diff --git a/historia_clinica_generator.html b/historia_clinica_generator.html new file mode 100644 index 0000000..2aee996 --- /dev/null +++ b/historia_clinica_generator.html @@ -0,0 +1,753 @@ + + + + + Generador HC Ingreso – Santojanni + + + + +

Historia Clínica de Ingreso – Hospital Donación F. Santojanni

+

Hace clic en el botón para generar el PDF con las 5 páginas del formulario en blanco.

+ +
+ + + + diff --git a/server/server.js b/server/server.js index a296592..beb88a8 100644 --- a/server/server.js +++ b/server/server.js @@ -157,6 +157,22 @@ try { // La columna ya existe } +try { + db.exec(` + CREATE TABLE IF NOT EXISTS interconsultas ( + id TEXT PRIMARY KEY, + pacienteId TEXT NOT NULL, + internacionId TEXT NOT NULL, + fecha TEXT, + servicioInterconsultado TEXT, + realizada INTEGER DEFAULT 0, + respuestaInterconsulta TEXT + ) + `); +} catch (e) { + console.log('Tabla interconsultas ya existe o error:', e.message); +} + const app = express(); app.use(cors()); app.use(express.json({ limit: '50mb' })); @@ -206,6 +222,7 @@ app.get('/api/state', (req, res) => { acidosBase: queryAll('SELECT * FROM acidosbase'), cultivos: queryAll('SELECT * FROM cultivos'), estudiosComplementarios: queryAll('SELECT * FROM estudiosComplementarios'), + interconsultas: queryAll('SELECT * FROM interconsultas').map(ic => ({ ...ic, realizada: !!ic.realizada })), vistaActual: 'dashboard', currentInternacionId: null }; @@ -288,6 +305,14 @@ if (state.laboratorios?.length) { } } + run('DELETE FROM interconsultas'); + if (state.interconsultas?.length) { + const stmt = db.prepare('INSERT INTO interconsultas (id, pacienteId, internacionId, fecha, servicioInterconsultado, realizada, respuestaInterconsulta) VALUES (?, ?, ?, ?, ?, ?, ?)'); + for (const ic of state.interconsultas) { + stmt.run(ic.id, ic.pacienteId, ic.internacionId, ic.fecha, ic.servicioInterconsultado, ic.realizada ? 1 : 0, ic.respuestaInterconsulta || null); + } + } + res.json({ ok: true }); }); diff --git a/src/App.tsx b/src/App.tsx index 6d2877b..a1217db 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -144,6 +144,7 @@ function AppContent() { acidosBase={store.getAcidosBaseByPaciente(paciente.id)} cultivos={store.getCultivosByPaciente(paciente.id)} estudiosComplementarios={store.estudiosComplementarios.filter(e => e.pacienteId === paciente.id)} + interconsultas={store.interconsultas.filter(ic => ic.internacionId === internacion.id)} onAgregarEvolucion={store.agregarEvolucion} onActualizarEvolucion={store.actualizarEvolucion} onEliminarEvolucion={store.eliminarEvolucion} @@ -159,6 +160,9 @@ function AppContent() { onAgregarEstudioComplementario={(e) => store.agregarEstudioComplementario({ ...e, internacionId: internacion.id })} onActualizarEstudioComplementario={store.actualizarEstudioComplementario} onEliminarEstudioComplementario={store.eliminarEstudioComplementario} + onAgregarInterconsulta={(ic) => store.agregarInterconsulta({ ...ic, internacionId: internacion.id })} + onActualizarInterconsulta={store.actualizarInterconsulta} + onEliminarInterconsulta={store.eliminarInterconsulta} onActualizarInternacion={store.actualizarInternacion} onActualizarCama={store.actualizarCama} onVolver={() => store.setVista('internaciones')} diff --git a/src/hooks/useHospitalStore.ts b/src/hooks/useHospitalStore.ts index 4007457..62d3822 100644 --- a/src/hooks/useHospitalStore.ts +++ b/src/hooks/useHospitalStore.ts @@ -9,6 +9,7 @@ import type { AcidoBase, Cultivo, EstudioComplementario, + Interconsulta, Vista } from '@/types'; @@ -35,6 +36,7 @@ interface HospitalState { acidosBase: AcidoBase[]; cultivos: Cultivo[]; estudiosComplementarios: EstudioComplementario[]; + interconsultas: Interconsulta[]; vistaActual: Vista; currentInternacionId?: string | null; } @@ -51,6 +53,7 @@ const defaultState = (): HospitalState => ({ acidosBase: [], cultivos: [], estudiosComplementarios: [], + interconsultas: [], vistaActual: 'dashboard', camas: [] }); @@ -349,6 +352,30 @@ const finalizarInternacion = useCallback((internacionId: string, datos: { })); }, []); + // Acciones de interconsultas + const agregarInterconsulta = useCallback((interconsulta: Omit) => { + const nuevaInterconsulta: Interconsulta = { ...interconsulta, id: generateUUID() }; + setState(prev => ({ + ...prev, + interconsultas: [...prev.interconsultas, nuevaInterconsulta], + })); + return nuevaInterconsulta.id; + }, []); + + const actualizarInterconsulta = useCallback((id: string, datos: Partial) => { + setState(prev => ({ + ...prev, + interconsultas: prev.interconsultas.map(ic => ic.id === id ? { ...ic, ...datos } : ic), + })); + }, []); + + const eliminarInterconsulta = useCallback((id: string) => { + setState(prev => ({ + ...prev, + interconsultas: prev.interconsultas.filter(ic => ic.id !== id), + })); + }, []); + // Acciones de areas const agregarArea = useCallback((area: Omit) => { const nuevaArea: Area = { ...area, id: generateUUID() }; @@ -472,6 +499,9 @@ const getEstadisticas = useCallback(() => { agregarEstudioComplementario, actualizarEstudioComplementario, eliminarEstudioComplementario, + agregarInterconsulta, + actualizarInterconsulta, + eliminarInterconsulta, agregarArea, actualizarArea, eliminarArea, diff --git a/src/sections/HistoriaClinica.tsx b/src/sections/HistoriaClinica.tsx index 8d2967e..92c99a1 100644 --- a/src/sections/HistoriaClinica.tsx +++ b/src/sections/HistoriaClinica.tsx @@ -50,7 +50,7 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@/components/ui/dropdown-menu'; import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts'; -import type { Laboratorio, AcidoBase, Cultivo, Paciente, ResultadoLaboratorio, Internacion, Evolucion, Cama, EstudioComplementario } from '@/types'; +import type { Laboratorio, AcidoBase, Cultivo, Paciente, ResultadoLaboratorio, Internacion, Evolucion, Cama, EstudioComplementario, Interconsulta } from '@/types'; import { formatDateDDMMYYYY } from '@/lib/utils'; interface HistoriaClinicaProps { @@ -63,6 +63,7 @@ interface HistoriaClinicaProps { acidosBase: AcidoBase[]; cultivos: Cultivo[]; estudiosComplementarios: EstudioComplementario[]; + interconsultas: Interconsulta[]; onAgregarEvolucion: (evolucion: Omit) => void; onActualizarEvolucion: (id: string, datos: Partial) => void; onEliminarEvolucion: (id: string) => void; @@ -79,6 +80,9 @@ interface HistoriaClinicaProps { onAgregarEstudioComplementario: (estudio: Omit) => void; onActualizarEstudioComplementario: (id: string, datos: Partial) => void; onEliminarEstudioComplementario: (id: string) => void; + onAgregarInterconsulta: (interconsulta: Omit) => void; + onActualizarInterconsulta: (id: string, datos: Partial) => void; + onEliminarInterconsulta: (id: string) => void; onActualizarInternacion: (id: string, datos: Partial) => void; onActualizarCama: (id: string, datos: Partial) => void; onVolver: () => void; @@ -168,6 +172,7 @@ export function HistoriaClinica({ acidosBase, cultivos, estudiosComplementarios, + interconsultas, onAgregarEvolucion, onActualizarEvolucion, onEliminarEvolucion, @@ -183,6 +188,9 @@ export function HistoriaClinica({ onAgregarEstudioComplementario, onActualizarEstudioComplementario, onEliminarEstudioComplementario, + onAgregarInterconsulta, + onActualizarInterconsulta, + onEliminarInterconsulta, onActualizarInternacion, onActualizarCama, onVolver, @@ -538,10 +546,14 @@ export function HistoriaClinica({ -
- -

Sección Interconsultas en desarrollo

-
+
@@ -2006,4 +2018,148 @@ function SeccionEstudiosComplementarios({ estudios, internacionId, pacienteId, a )} ); +} + +function SeccionInterconsultas({ interconsultas, pacienteId, internacionId, add, update, del }: { + interconsultas: Interconsulta[]; + pacienteId: string; + internacionId: string; + add: (ic: Omit) => void; + update: (id: string, datos: Partial) => void; + del: (id: string) => void; +}) { + const [dialog, setDialog] = useState(false); + const [fecha, setFecha] = useState(new Date().toISOString().split('T')[0]); + const [servicioInterconsultado, setServicioInterconsultado] = useState(''); + const [realizada, setRealizada] = useState(false); + const [respuestaInterconsulta, setRespuestaInterconsulta] = useState(''); + const [edit, setEdit] = useState(null); + + const reset = () => { + setFecha(new Date().toISOString().split('T')[0]); + setServicioInterconsultado(''); + setRealizada(false); + setRespuestaInterconsulta(''); + setEdit(null); + }; + + const handleGuardar = () => { + if (!servicioInterconsultado) return; + if (edit) { + update(edit.id, { fecha, servicioInterconsultado, realizada, respuestaInterconsulta }); + } else { + add({ pacienteId, internacionId, fecha, servicioInterconsultado, realizada, respuestaInterconsulta }); + } + setDialog(false); + reset(); + }; + + const loadEdit = (ic: Interconsulta) => { + setEdit(ic); + setFecha(ic.fecha); + setServicioInterconsultado(ic.servicioInterconsultado); + setRealizada(ic.realizada); + setRespuestaInterconsulta(ic.respuestaInterconsulta || ''); + setDialog(true); + }; + + const icsFiltrados = interconsultas.filter(ic => ic.internacionId === internacionId); + + return ( +
+
+ +
+ + + + + {edit ? 'Editar' : 'Nueva'} Interconsulta + +
+
+ + setFecha(e.target.value)} /> +
+
+ + setServicioInterconsultado(e.target.value)} + placeholder="Ej: Cardiología, Neurología, Infectología, etc." + /> +
+
+ setRealizada(e.target.checked)} + className="w-4 h-4" + /> + +
+
+ +