Configuración inicial
1. Instalación
Copiar
npm install @omniloy/sofia-sdk
2. Importación en su aplicación
Copiar
// En su App.tsx o archivo principal
import '@omniloy/sofia-sdk';
Componente React básico
Implementación con hooks
Copiar
import React, { useRef, useState, useEffect } from 'react';
interface SofiaComponentProps {
userId: string;
patientId: string;
apiKey: string;
baseUrl: string;
wssUrl: string;
}
const SofiaComponent: React.FC<SofiaComponentProps> = ({
userId,
patientId,
apiKey,
baseUrl,
wssUrl
}) => {
const sofiaRef = useRef<any>(null);
const [isOpen, setIsOpen] = useState(false);
const [lastReport, setLastReport] = useState<any>(null);
// Esquema de ejemplo para notas clínicas
const toolsArgs = {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "clinical_notes",
"type": "object",
"required": ["diagnosis"],
"properties": {
"diagnosis": {
"type": "string",
"description": "Diagnóstico principal"
},
"symptoms": {
"type": "array",
"items": {"type": "string"},
"description": "Síntomas observados"
}
}
};
// Configurar callbacks cuando el componente se monta
useEffect(() => {
if (sofiaRef.current) {
// Callback para recibir reportes
sofiaRef.current.handleReport = (report: any) => {
console.log('Reporte recibido:', report);
setLastReport(report);
// Procesar reporte (enviar a API, mostrar notificación, etc.)
processReport(report);
};
// Callback para cambios de visibilidad
sofiaRef.current.setIsOpen = (open: boolean) => {
setIsOpen(open);
};
}
}, []);
const processReport = async (report: any) => {
try {
// Enviar reporte a su backend
const response = await fetch('/api/clinical-reports', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(report)
});
if (response.ok) {
console.log('Reporte guardado exitosamente');
}
} catch (error) {
console.error('Error procesando reporte:', error);
}
};
const toggleSofia = () => {
if (sofiaRef.current) {
sofiaRef.current.isopen = !isOpen;
}
};
return (
<div className="sofia-container">
<sofia-sdk
ref={sofiaRef}
baseurl={baseUrl}
wssurl={wssUrl}
apikey={apiKey}
userid={userId}
patientid={patientId}
isopen={isOpen.toString()}
toolsargs={JSON.stringify(toolsArgs)}
/>
<div className="sofia-controls">
<button onClick={toggleSofia} className="toggle-button">
{isOpen ? 'Cerrar SofIA' : 'Abrir SofIA'}
</button>
{lastReport && (
<div className="last-report">
<h3>Último reporte:</h3>
<pre>{JSON.stringify(lastReport, null, 2)}</pre>
</div>
)}
</div>
</div>
);
};
export default SofiaComponent;
Hook personalizado
useSofia Hook
Copiar
import { useRef, useState, useCallback } from 'react';
interface UseSofiaOptions {
onReport?: (report: any) => void;
onVisibilityChange?: (isOpen: boolean) => void;
}
export const useSofia = (options: UseSofiaOptions = {}) => {
const sofiaRef = useRef<any>(null);
const [isOpen, setIsOpen] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const initializeSofia = useCallback(() => {
if (sofiaRef.current) {
sofiaRef.current.handleReport = (report: any) => {
setIsLoading(false);
options.onReport?.(report);
};
sofiaRef.current.setIsOpen = (open: boolean) => {
setIsOpen(open);
options.onVisibilityChange?.(open);
};
}
}, [options]);
const openSofia = useCallback(() => {
if (sofiaRef.current) {
sofiaRef.current.isopen = true;
}
}, []);
const closeSofia = useCallback(() => {
if (sofiaRef.current) {
sofiaRef.current.isopen = false;
}
}, []);
const generateReport = useCallback(() => {
if (sofiaRef.current) {
setIsLoading(true);
// Triggering report generation if supported
sofiaRef.current.dispatchEvent(new CustomEvent('generate'));
}
}, []);
return {
sofiaRef,
isOpen,
isLoading,
initializeSofia,
openSofia,
closeSofia,
generateReport
};
};
Uso del hook
Copiar
const MyComponent: React.FC = () => {
const {
sofiaRef,
isOpen,
isLoading,
initializeSofia,
openSofia,
closeSofia
} = useSofia({
onReport: (report) => {
console.log('Reporte procesado:', report);
},
onVisibilityChange: (isOpen) => {
console.log('Estado cambió:', isOpen);
}
});
useEffect(() => {
initializeSofia();
}, [initializeSofia]);
return (
<div>
<sofia-sdk
ref={sofiaRef}
baseurl="https://api.example.com/v1"
wssurl="wss://ws.example.com"
apikey="sk-your-api-key-here"
userid="user_12345"
patientid="patient_67890"
isopen={isOpen.toString()}
toolsargs={JSON.stringify(mySchema)}
/>
<button onClick={openSofia} disabled={isOpen}>
Abrir SofIA
</button>
<button onClick={closeSofia} disabled={!isOpen}>
Cerrar SofIA
</button>
{isLoading && <div>Generando reporte...</div>}
</div>
);
};
Gestión de estado con Context
Sofia Context Provider
Copiar
import React, { createContext, useContext, useState, ReactNode } from 'react';
interface SofiaContextType {
currentPatient: string | null;
setCurrentPatient: (patientId: string) => void;
reports: any[];
addReport: (report: any) => void;
}
const SofiaContext = createContext<SofiaContextType | undefined>(undefined);
export const SofiaProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
const [currentPatient, setCurrentPatient] = useState<string | null>(null);
const [reports, setReports] = useState<any[]>([]);
const addReport = (report: any) => {
setReports(prev => [...prev, { ...report, timestamp: new Date() }]);
};
return (
<SofiaContext.Provider value={{
currentPatient,
setCurrentPatient,
reports,
addReport
}}>
{children}
</SofiaContext.Provider>
);
};
export const useSofiaContext = () => {
const context = useContext(SofiaContext);
if (!context) {
throw new Error('useSofiaContext must be used within SofiaProvider');
}
return context;
};
TypeScript Support
Declaración de tipos
Copiar
// types/sofia.d.ts
declare global {
namespace JSX {
interface IntrinsicElements {
'sofia-sdk': React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement> & {
baseurl?: string;
wssurl?: string;
apikey?: string;
userid?: string;
patientid?: string;
isopen?: string;
toolsargs?: string;
patientdata?: string;
ref?: React.Ref<any>;
};
}
}
}
Ejemplo completo
Para ver una implementación completa con React y TypeScript, consulte nuestro repositorio de ejemplos: Ver ejemplo completo de React → El ejemplo incluye:- Configuración completa con TypeScript
- Estado global con Context API
- Componentes reutilizables
- Integración con React Router
- Testing con Jest y React Testing Library
Mejores prácticas
Performance
- Use
React.memo()para componentes que envuelven sofia-sdk - Implemente lazy loading para el componente en rutas no críticas
Estado
- Mantenga el estado de SofIA sincronizado con el estado de React
- Use useCallback para callbacks estables
Error Boundaries
Copiar
class SofiaErrorBoundary extends React.Component {
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
console.error('Error en SofIA SDK:', error, errorInfo);
}
render() {
return this.props.children;
}
}