@primocaredentgroup/chat-ui
v2.1.0
Published
Typed API references, shared types, and React utilities for PrimoUp chat orchestrator
Readme
@primocaredentgroup/chat-ui
Batteries Included - Componente chat React per Software B (Laboratorio Odontotecnico) che si connette al backend di Software A (PrimoUp Core).
✨ Approccio "Batteries Included"
Questo pacchetto è completamente self-contained:
- Crea internamente un
ConvexReactClientisolato che si connette a Software A - Non interferisce con l'eventuale client Convex esistente di Software B
- Include tutte le definizioni di tipo necessarie
- Richiede solo
convexUrleauthToken
// Semplicissimo - nessun provider esterno necessario!
<LabChatWidget
convexUrl="https://software-a.convex.cloud"
authToken={token}
/>📦 Installazione
npm install @primocaredentgroup/chat-ui🔧 Requisiti
- React 18+ o 19+
- Auth0 React SDK (@auth0/auth0-react)
- Convex (come peer dependency - per i tipi)
- Tailwind CSS (per lo stile)
🏗️ Architettura Interna
Il componente crea un ConvexReactClient isolato internamente:
Software B App
├── Software B's Convex Client (esistente, non toccato)
│ └── Connesso a: Software B's Convex Backend
│
└── LabChatWidget
└── ChatConvexProvider (isolato)
└── ConvexReactClient (nuovo, isolato)
└── Connesso a: Software A's Convex BackendQuesto significa:
- ✅ Zero conflitti con l'esistente setup Convex di Software B
- ✅ Autenticazione indipendente verso Software A
- ✅ Nessun provider esterno richiesto
🚀 Utilizzo
1. Configurazione Auth0
Nel tuo Software B, devi configurare Auth0 per richiedere un token valido anche per l'audience di Software A:
// App.tsx di Software B
import { Auth0Provider } from '@auth0/auth0-react';
<Auth0Provider
domain="tuo-auth0-domain.auth0.com"
clientId="tuo-client-id-software-b"
authorizationParams={{
redirect_uri: window.location.origin,
audience: "https://api.primoup-core.com", // <-- Audience di Software A!
scope: "openid profile email"
}}
>
<App />
</Auth0Provider>2. Utilizzo del Componente
import { LabChatWidget } from '@primocaredentgroup/chat-ui';
import { useAuth0 } from '@auth0/auth0-react';
function App() {
const { getAccessTokenSilently } = useAuth0();
const [token, setToken] = useState<string>('');
useEffect(() => {
const getToken = async () => {
try {
const accessToken = await getAccessTokenSilently();
setToken(accessToken);
} catch (error) {
console.error('Error getting token:', error);
}
};
getToken();
}, [getAccessTokenSilently]);
return (
<div>
{/* Il resto della tua app */}
{token && (
<LabChatWidget
convexUrl="https://tuo-deployment.convex.cloud" // URL Convex di Software A
authToken={token}
/>
)}
</div>
);
}⚙️ Props
| Prop | Tipo | Obbligatorio | Descrizione |
|------|------|--------------|-------------|
| convexUrl | string | ✅ | URL del deployment Convex di Software A |
| authToken | string | ✅ | Auth0 access token (deve avere audience di Software A) |
| className | string | ❌ | Classi CSS aggiuntive per il widget |
| onClose | () => void | ❌ | Callback quando il widget viene chiuso |
🔐 Autenticazione Cross-Domain
Opzione 1: Shared Audience (Consigliata)
Configura Software B per usare la stessa audience API di Software A:
// auth0.com Dashboard -> Applications -> Software B
// Settings -> Advanced Settings -> OAuth
// audience: "https://api.primoup-core.com"Opzione 2: Token Exchange
Se non puoi condividere l'audience, crea un endpoint su Software A per scambiare il token:
// Su Software A (backend)
export const exchangeToken = mutation({
args: { token: v.string() },
handler: async (ctx, args) => {
// Verifica token Software B con Auth0
// Genera nuovo token per audience di Software A
// Restituisci nuovo token
}
});Opzione 3: Trusted Clients
Configura Software A per accettare clientId di Software B come trusted:
// convex/auth.config.ts
export default {
providers: [
{
domain: "https://tuo-auth0-domain.auth0.com",
applicationID: ["software-a-client-id", "software-b-client-id"], // <-- Aggiungi entrambi!
},
],
};🎨 Styling
Il componente usa Tailwind CSS. Assicurati che le seguenti classi siano disponibili nel tuo progetto:
- Colori:
bg-blue-600,text-white,bg-gray-50, ecc. - Layout:
flex,grid,fixed,absolute - Spaziature:
p-4,m-2,gap-3, ecc. - Bordi:
rounded-lg,border,shadow-lg
🎣 Hooks e Provider (Avanzato)
Per casi d'uso avanzati, puoi usare i provider e gli hook esposti:
import {
ChatConvexProvider,
useChatConvex,
useListAllChannels,
useGetPatientChatStructure,
useListMessages,
useSendMessage,
useChatQuery,
useChatMutation
} from '@primocaredentgroup/chat-ui';
// Provider isolato
function MyCustomChat() {
return (
<ChatConvexProvider
convexUrl="https://software-a.convex.cloud"
authToken={token}
>
<CustomChatUI />
</ChatConvexProvider>
);
}
// Hook personalizzato per query
function CustomChatUI() {
const { data: channels } = useListAllChannels();
const { data: structure } = useGetPatientChatStructure("patient-id");
const { data: messages } = useListMessages("subchannel-id");
const { mutate: sendMessage } = useSendMessage();
// ... la tua UI personalizzata
}📁 Struttura Chat
Paziente (Macro Canale)
├── Generale (sub-canale)
│ └── Messaggi generali
├── Laboratorio (sub-canale)
│ ├── Prescrizione 1
│ ├── Prescrizione 2
│ └── Prescrizione 3
└── Abaddon (sub-canale)
└── Messaggi per Abaddon📐 Tipi Esportati
Il pacchetto include tutte le definizioni di tipo per l'API di Software A:
import type {
Patient,
ChatMessage,
ChatStructure,
Channel,
Subchannel,
PrescriptionSubchannel,
// ... e altri tipi
} from '@primocaredentgroup/chat-ui';🐛 Debug
Il widget non si connette
- Verifica che
convexUrlsia corretto - Verifica che
authTokensia valido e non scaduto - Controlla console per errori CORS
- Verifica che Software A accetti il tuo clientId Auth0
"Unauthorized" error
- Verifica che l'audience nel token corrisponda a quello di Software A
- Verifica che l'utente esista nel database di Software A
- Controlla che il token non sia scaduto
📄 Licenza
MIT
🔗 Link Utili
💬 Supporto
Per domande o problemi, contatta il team di sviluppo PrimoCare.
