feat: implement tracking for medical indication changes with a new database table and management hooks
This commit is contained in:
+38
-8
@@ -251,33 +251,54 @@ try {
|
||||
// column may already exist
|
||||
}
|
||||
try {
|
||||
db.exec("ALTER TABLE recomendaciones ADD COLUMN fechaModificacion TEXT");
|
||||
db.exec("ALTER TABLE indicaciones ADD COLUMN fechaModificacion TEXT");
|
||||
} catch (e) {
|
||||
// column may already exist
|
||||
}
|
||||
try {
|
||||
db.exec("ALTER TABLE recomendaciones ADD COLUMN tipoInsulina TEXT");
|
||||
db.exec("ALTER TABLE indicaciones ADD COLUMN tipoInsulina TEXT");
|
||||
} catch (e) {
|
||||
// column may already exist
|
||||
}
|
||||
try {
|
||||
db.exec("ALTER TABLE recomendaciones ADD COLUMN unidadesDesayuno INTEGER");
|
||||
db.exec("ALTER TABLE indicaciones ADD COLUMN unidadesDesayuno INTEGER");
|
||||
} catch (e) {
|
||||
// column may already exist
|
||||
}
|
||||
try {
|
||||
db.exec("ALTER TABLE recomendaciones ADD COLUMN unidadesAlmuerzo INTEGER");
|
||||
db.exec("ALTER TABLE indicaciones ADD COLUMN unidadesAlmuerzo INTEGER");
|
||||
} catch (e) {
|
||||
// column may already exist
|
||||
}
|
||||
try {
|
||||
db.exec("ALTER TABLE recomendaciones ADD COLUMN unidadesNoche INTEGER");
|
||||
db.exec("ALTER TABLE indicaciones ADD COLUMN unidadesNoche INTEGER");
|
||||
} catch (e) {
|
||||
// column may already exist
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('Error tabla recomendaciones:', e.message);
|
||||
console.log('Error tabla indicaciones:', e.message);
|
||||
}
|
||||
|
||||
try {
|
||||
const exists = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='movimientos_indicaciones'").get();
|
||||
if (!exists) {
|
||||
db.exec(`
|
||||
CREATE TABLE movimientos_indicaciones (
|
||||
id TEXT PRIMARY KEY,
|
||||
indicacionId TEXT NOT NULL,
|
||||
internacionId TEXT NOT NULL,
|
||||
tipo TEXT NOT NULL,
|
||||
fecha TEXT NOT NULL,
|
||||
profesional TEXT NOT NULL,
|
||||
indicacionPrevia TEXT,
|
||||
indicacionNueva TEXT
|
||||
)
|
||||
`);
|
||||
console.log('Tabla movimientos_indicaciones creada');
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('Tabla movimientos_indicaciones:', e.message);
|
||||
}
|
||||
|
||||
const app = express();
|
||||
@@ -332,6 +353,7 @@ app.get('/api/state', (req, res) => {
|
||||
interconsultas: queryAll('SELECT * FROM interconsultas').map(ic => ({ ...ic, realizada: !!ic.realizada })),
|
||||
atb: queryAll('SELECT * FROM atb'),
|
||||
indicaciones: queryAll('SELECT * FROM indicaciones'),
|
||||
movimientosIndicaciones: queryAll('SELECT * FROM movimientos_indicaciones'),
|
||||
vistaActual: 'dashboard',
|
||||
currentInternacionId: null
|
||||
};
|
||||
@@ -432,9 +454,17 @@ if (state.laboratorios?.length) {
|
||||
|
||||
run('DELETE FROM indicaciones');
|
||||
if (state.indicaciones?.length) {
|
||||
const stmt = db.prepare('INSERT INTO indicaciones (id, internacionId, tipo, droga, dosis, frecuenciaHoras, via, descripcion, tipoPlan, tipoPlan2, cantidadMl, cantidadMl2, tiempoHoras, estado, medicoCrea, fechaCrea, medicoModifica, fechaModificacion, medicoSuspende, fechaSuspension) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)');
|
||||
const stmt = db.prepare('INSERT INTO recomendaciones (id, internacionId, tipo, droga, dosis, frecuenciaHoras, via, descripcion, tipoPlan, tipoPlan2, cantidadMl, cantidadMl2, tiempoHoras, estado, medicoCrea, fechaCrea, medicoModifica, medicoSuspende, fechaSuspension, tipoInsulina, unidadesDesayuno, unidadesAlmuerzo, unidadesNoche) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)');
|
||||
for (const ind of state.indicaciones) {
|
||||
stmt.run(ind.id, ind.internacionId, ind.tipo, ind.droga || null, ind.dosis || null, ind.frecuenciaHoras || null, ind.via || null, ind.descripcion || null, ind.tipoPlan || null, ind.tipoPlan2 || null, ind.cantidadMl || null, ind.cantidadMl2 || null, ind.tiempoHoras || null, ind.estado, ind.medicoCrea, ind.fechaCrea, ind.medicoModifica || null, ind.fechaModificacion || null, ind.medicoSuspende || null, ind.fechaSuspension || null);
|
||||
stmt.run(ind.id, ind.internacionId, ind.tipo, ind.droga || null, ind.dosis || null, ind.frecuenciaHoras || null, ind.via || null, ind.descripcion || null, ind.tipoPlan || null, ind.tipoPlan2 || null, ind.cantidadMl || null, ind.cantidadMl2 || null, ind.tiempoHoras || null, ind.estado, ind.medicoCrea, ind.fechaCrea, ind.medicoModifica || null, ind.medicoSuspende || null, ind.fechaSuspension || null, ind.tipoInsulina || null, ind.unidadesDesayuno || null, ind.unidadesAlmuerzo || null, ind.unidadesNoche || null);
|
||||
}
|
||||
}
|
||||
|
||||
run('DELETE FROM movimientos_indicaciones');
|
||||
if (state.movimientosIndicaciones?.length) {
|
||||
const stmt = db.prepare('INSERT INTO movimientos_indicaciones (id, indicacionId, internacionId, tipo, fecha, profesional, indicacionPrevia, indicacionNueva) VALUES (?, ?, ?, ?, ?, ?, ?, ?)');
|
||||
for (const mov of state.movimientosIndicaciones) {
|
||||
stmt.run(mov.id, mov.indicacionId, mov.internacionId, mov.tipo, mov.fecha, mov.profesional, mov.indicacionPrevia || null, mov.indicacionNueva || null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -168,9 +168,11 @@ function AppContent() {
|
||||
onActualizarATB={store.actualizarATB}
|
||||
onEliminarATB={store.eliminarATB}
|
||||
indicadores={(Array.isArray(store.indicaciones) ? store.indicaciones : []).filter((i: any) => i.internacionId === internacion.id)}
|
||||
movimientos={store.getMovimientosByInternacion ? store.getMovimientosByInternacion(internacion.id) : []}
|
||||
onAgregarIndicacion={(i) => store.agregarIndicacion({ ...i, internacionId: internacion.id })}
|
||||
onActualizarIndicacion={store.actualizarIndicacion}
|
||||
onEliminarIndicacion={store.eliminarIndicacion}
|
||||
onAgregarMovimiento={(m: any) => store.agregarMovimientoIndicacion ? store.agregarMovimientoIndicacion({ ...m, internacionId: internacion.id }) : null}
|
||||
onActualizarInternacion={store.actualizarInternacion}
|
||||
onActualizarCama={store.actualizarCama}
|
||||
onVolver={() => store.setVista('internaciones')}
|
||||
|
||||
@@ -41,6 +41,7 @@ interface HospitalState {
|
||||
interconsultas: Interconsulta[];
|
||||
atb: ATB[];
|
||||
indicaciones: Indicacion[];
|
||||
movimientosIndicaciones: any[];
|
||||
vistaActual: Vista;
|
||||
currentInternacionId?: string | null;
|
||||
}
|
||||
@@ -61,6 +62,7 @@ const defaultState = (): HospitalState => ({
|
||||
atb: [],
|
||||
vistaActual: 'dashboard',
|
||||
indicaciones: [],
|
||||
movimientosIndicaciones: [],
|
||||
camas: []
|
||||
});
|
||||
|
||||
@@ -77,7 +79,9 @@ export function useHospitalStore() {
|
||||
if (!res.ok) throw new Error('no state');
|
||||
const body = await res.json();
|
||||
if (mounted && body) {
|
||||
setState(body as HospitalState);
|
||||
const normalized = body as HospitalState;
|
||||
normalized.movimientosIndicaciones = normalized.movimientosIndicaciones || [];
|
||||
setState(normalized);
|
||||
}
|
||||
} catch (err) {
|
||||
// no remote state or unreachable — keep defaults
|
||||
@@ -428,6 +432,19 @@ const finalizarInternacion = useCallback((internacionId: string, datos: {
|
||||
}));
|
||||
}, []);
|
||||
|
||||
const agregarMovimientoIndicacion = useCallback((movimiento: any) => {
|
||||
setState(prev => ({
|
||||
...prev,
|
||||
movimientosIndicaciones: [...(prev.movimientosIndicaciones || []), { ...movimiento, id: generateUUID() }],
|
||||
}));
|
||||
}, []);
|
||||
|
||||
const getMovimientosByInternacion = useCallback((internacionId: string) => {
|
||||
return (state.movimientosIndicaciones || [])
|
||||
.filter((m: any) => m.internacionId === internacionId)
|
||||
.sort((a: any, b: any) => new Date(b.fecha).getTime() - new Date(a.fecha).getTime());
|
||||
}, [state.movimientosIndicaciones]);
|
||||
|
||||
// Acciones de areas
|
||||
const agregarArea = useCallback((area: Omit<Area, 'id'>) => {
|
||||
const nuevaArea: Area = { ...area, id: generateUUID() };
|
||||
@@ -560,6 +577,8 @@ const getEstadisticas = useCallback(() => {
|
||||
agregarIndicacion,
|
||||
actualizarIndicacion,
|
||||
eliminarIndicacion,
|
||||
agregarMovimientoIndicacion,
|
||||
getMovimientosByInternacion,
|
||||
agregarArea,
|
||||
actualizarArea,
|
||||
eliminarArea,
|
||||
|
||||
@@ -93,6 +93,8 @@ interface HistoriaClinicaProps {
|
||||
onAgregarIndicacion: (indicacion: Omit<Indicacion, 'id'>) => void;
|
||||
onActualizarIndicacion: (id: string, datos: Partial<Indicacion>) => void;
|
||||
onEliminarIndicacion: (id: string) => void;
|
||||
movimientos?: any[];
|
||||
onAgregarMovimiento?: (m: any) => void;
|
||||
onActualizarInternacion: (id: string, datos: Partial<Internacion>) => void;
|
||||
onActualizarCama: (id: string, datos: Partial<Cama>) => void;
|
||||
onVolver: () => void;
|
||||
@@ -209,6 +211,8 @@ export function HistoriaClinica({
|
||||
onAgregarIndicacion,
|
||||
onActualizarIndicacion,
|
||||
onEliminarIndicacion,
|
||||
movimientos,
|
||||
onAgregarMovimiento,
|
||||
onActualizarInternacion,
|
||||
onActualizarCama,
|
||||
onVolver,
|
||||
@@ -559,6 +563,8 @@ export function HistoriaClinica({
|
||||
add={onAgregarIndicacion}
|
||||
update={onActualizarIndicacion}
|
||||
del={onEliminarIndicacion}
|
||||
movimientos={movimientos}
|
||||
onAgregarMovimiento={onAgregarMovimiento}
|
||||
/>
|
||||
</TabsContent>
|
||||
|
||||
|
||||
@@ -10,17 +10,50 @@ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@
|
||||
import { Plus, Pencil, Trash2, X } from 'lucide-react';
|
||||
import type { Indicacion, IndicacionTipo, ViaAdministracion, TipoPlanHidratacion, TipoInsulina } from '@/types';
|
||||
|
||||
export function SeccionIndicaciones({ recomendaciones, internacionId, add, update, del }: {
|
||||
export function SeccionIndicaciones({ recomendaciones, internacionId, add, update, del, movimientos, onAgregarMovimiento }: {
|
||||
recomendaciones: Indicacion[];
|
||||
internacionId: string;
|
||||
add: (i: Omit<Indicacion, 'id'>) => void;
|
||||
update: (id: string, datos: Partial<Indicacion>) => void;
|
||||
del: (id: string) => void;
|
||||
movimientos?: any[];
|
||||
onAgregarMovimiento?: (m: any) => void;
|
||||
}) {
|
||||
const list: Indicacion[] = Array.isArray(recomendaciones) ? recomendaciones : [];
|
||||
const movs: any[] = Array.isArray(movimientos) ? movimientos : [];
|
||||
const [dialog, setDialog] = useState(false);
|
||||
const [edit, setEdit] = useState<Indicacion | null>(null);
|
||||
|
||||
const formatIndicacion = (i: Indicacion): string => {
|
||||
if (i.tipo === 'Farmacologica') return `${i.droga || ''} ${i.dosis || ''} ${i.frecuenciaHoras ? `c/${i.frecuenciaHoras}hs` : ''} ${i.via || ''}`.trim();
|
||||
if (i.tipo === 'Farmacologica Insulina') return `${i.tipoInsulina || ''}${i.unidadesDesayuno ? ` - Desayuno: ${i.unidadesDesayuno}U` : ''}${i.unidadesAlmuerzo ? ` - Almuerzo: ${i.unidadesAlmuerzo}U` : ''}${i.unidadesNoche ? ` - 23hs: ${i.unidadesNoche}U` : ''}`.trim();
|
||||
if (i.tipo === 'No Farmacologica') return i.descripcion || '';
|
||||
if (i.tipo === 'PHP' || i.tipo === 'PHP Paralelo') return `${i.tipoPlan || ''} ${i.cantidadMl || ''}ml en ${i.tiempoHoras || ''}hs`;
|
||||
if (i.tipo === 'PHP Alterno') return `${i.tipoPlan || ''} ${i.cantidadMl || ''}ml + ${i.tipoPlan2 || ''} ${i.cantidadMl2 || ''}ml en ${i.tiempoHoras || ''}hs`;
|
||||
return '';
|
||||
};
|
||||
const [tipo, setTipo] = useState<IndicacionTipo>('Farmacologica');
|
||||
const [sortField, setSortField] = useState<'fecha' | 'profesional' | 'tipo'>('fecha');
|
||||
const [sortDir, setSortDir] = useState<'asc' | 'desc'>('desc');
|
||||
|
||||
const handleSort = (field: 'fecha' | 'profesional' | 'tipo') => {
|
||||
if (sortField === field) {
|
||||
setSortDir(sortDir === 'asc' ? 'desc' : 'asc');
|
||||
} else {
|
||||
setSortField(field);
|
||||
setSortDir('desc');
|
||||
}
|
||||
};
|
||||
|
||||
const sortedMovs = [...movs].sort((a, b) => {
|
||||
let aVal: any = a[sortField] || '';
|
||||
let bVal: any = b[sortField] || '';
|
||||
if (sortField === 'fecha') {
|
||||
aVal = new Date(aVal.replace(' ', 'T')).getTime();
|
||||
bVal = new Date(bVal.replace(' ', 'T')).getTime();
|
||||
}
|
||||
return sortDir === 'asc' ? (aVal > bVal ? 1 : -1) : (aVal < bVal ? 1 : -1);
|
||||
});
|
||||
const [droga, setDroga] = useState('');
|
||||
const [dosis, setDosis] = useState('');
|
||||
const [frecuenciaHoras, setFrecuenciaHoras] = useState<number | ''>('');
|
||||
@@ -38,10 +71,10 @@ export function SeccionIndicaciones({ recomendaciones, internacionId, add, updat
|
||||
const [medico, setMedico] = useState('');
|
||||
const [showHistorial, setShowHistorial] = useState(false);
|
||||
|
||||
const vias: ViaAdministracion[] = ['Oral', 'EV', 'IM', 'SC', 'Por GGT', 'Por SNG'];
|
||||
const vias: ViaAdministracion[] = ['Via Oral', 'EV', 'IM', 'SC', 'Por GGT', 'Por SNG'];
|
||||
const planes: TipoPlanHidratacion[] = ['SF 0.9%', 'Dextrosa 5%', 'Dextrosa 10%', 'Dextrosa 25%', 'Ringer Lactato'];
|
||||
const tiposInsulina: TipoInsulina[] = ['NPH', 'Glargina'];
|
||||
const tipos: IndicacionTipo[] = ['Farmacologica', 'Farmacologica Insulina', 'No Farmacologica', 'PHP', 'Paralelo', 'Alterno'];
|
||||
const tipos: IndicacionTipo[] = ['Farmacologica', 'Farmacologica Profilactica', 'Farmacologica Insulina', 'No Farmacologica', 'PHP', 'PHP Paralelo', 'PHP Alterno'];
|
||||
|
||||
const reset = () => {
|
||||
setEdit(null);
|
||||
@@ -86,11 +119,11 @@ export function SeccionIndicaciones({ recomendaciones, internacionId, add, updat
|
||||
|
||||
const handleGuardar = () => {
|
||||
if (!medico.trim()) return;
|
||||
if (tipo === 'Farmacologica' && (!droga.trim() || !dosis.trim())) return;
|
||||
if ((tipo === 'Farmacologica' || tipo === 'Farmacologica Profilactica') && (!droga.trim() || !dosis.trim())) return;
|
||||
if (tipo === 'Farmacologica Insulina' && (!unidadesDesayuno && !unidadesAlmuerzo && !unidadesNoche)) return;
|
||||
if (tipo === 'No Farmacologica' && !descripcion.trim()) return;
|
||||
if ((tipo === 'PHP' || tipo === 'Paralelo') && !cantidadMl) return;
|
||||
if (tipo === 'Alterno' && (!cantidadMl || !cantidadMl2)) return;
|
||||
if ((tipo === 'PHP' || tipo === 'PHP Paralelo') && !cantidadMl) return;
|
||||
if (tipo === 'PHP Alterno' && (!cantidadMl || !cantidadMl2)) return;
|
||||
|
||||
const data: any = {
|
||||
internacionId,
|
||||
@@ -100,7 +133,7 @@ export function SeccionIndicaciones({ recomendaciones, internacionId, add, updat
|
||||
fechaCrea: new Date().toISOString().split('T')[0],
|
||||
};
|
||||
|
||||
if (tipo === 'Farmacologica') {
|
||||
if (tipo === 'Farmacologica' || tipo === 'Farmacologica Profilactica') {
|
||||
data.droga = droga;
|
||||
data.dosis = dosis;
|
||||
data.frecuenciaHoras = frecuenciaHoras || undefined;
|
||||
@@ -110,13 +143,14 @@ export function SeccionIndicaciones({ recomendaciones, internacionId, add, updat
|
||||
data.unidadesDesayuno = unidadesDesayuno || undefined;
|
||||
data.unidadesAlmuerzo = unidadesAlmuerzo || undefined;
|
||||
data.unidadesNoche = unidadesNoche || undefined;
|
||||
console.log('Guardando insulina:', tipoInsulina, unidadesDesayuno, unidadesAlmuerzo, unidadesNoche);
|
||||
} else if (tipo === 'No Farmacologica') {
|
||||
data.descripcion = descripcion;
|
||||
} else if (tipo === 'PHP' || tipo === 'Paralelo') {
|
||||
} else if (tipo === 'PHP' || tipo === 'PHP Paralelo') {
|
||||
data.tipoPlan = tipoPlan;
|
||||
data.cantidadMl = cantidadMl;
|
||||
data.tiempoHoras = tiempoHoras;
|
||||
} else if (tipo === 'Alterno') {
|
||||
} else if (tipo === 'PHP Alterno') {
|
||||
data.tipoPlan = tipoPlan;
|
||||
data.cantidadMl = cantidadMl;
|
||||
data.tipoPlan2 = tipoPlan2;
|
||||
@@ -124,27 +158,61 @@ export function SeccionIndicaciones({ recomendaciones, internacionId, add, updat
|
||||
data.tiempoHoras = tiempoHoras;
|
||||
}
|
||||
|
||||
const now = new Date();
|
||||
const fecha = now.toISOString().split('T')[0] + ' ' + now.toTimeString().split(' ')[0].substring(0, 5);
|
||||
if (edit) {
|
||||
if (onAgregarMovimiento) {
|
||||
onAgregarMovimiento({
|
||||
indicacionId: edit.id,
|
||||
internacionId,
|
||||
tipo: 'Modificacion',
|
||||
fecha,
|
||||
profesional: medico,
|
||||
indicacionPrevia: formatIndicacion(edit),
|
||||
indicacionNueva: formatIndicacion({ ...edit, ...data } as Indicacion),
|
||||
});
|
||||
}
|
||||
update(edit.id, data);
|
||||
} else {
|
||||
add(data);
|
||||
const newId = add(data);
|
||||
if (onAgregarMovimiento && newId) {
|
||||
onAgregarMovimiento({
|
||||
indicacionId: newId,
|
||||
internacionId,
|
||||
tipo: 'Indicacion',
|
||||
fecha,
|
||||
profesional: medico,
|
||||
indicacionNueva: formatIndicacion({ ...data, id: newId } as Indicacion),
|
||||
});
|
||||
}
|
||||
}
|
||||
setDialog(false);
|
||||
reset();
|
||||
};
|
||||
|
||||
const handleSuspender = (i: Indicacion, suspendioMedico: string) => {
|
||||
const now = new Date();
|
||||
const fecha = now.toISOString().split('T')[0] + ' ' + now.toTimeString().split(' ')[0].substring(0, 5);
|
||||
update(i.id, {
|
||||
estado: 'Suspendida',
|
||||
medicoSuspende: suspendioMedico,
|
||||
fechaSuspension: new Date().toISOString().split('T')[0],
|
||||
fechaSuspension: fecha,
|
||||
});
|
||||
if (onAgregarMovimiento) {
|
||||
onAgregarMovimiento({
|
||||
indicacionId: i.id,
|
||||
internacionId,
|
||||
tipo: 'Suspencion',
|
||||
fecha,
|
||||
profesional: suspendioMedico,
|
||||
indicacionPrevia: formatIndicacion(i),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleModificar = (i: Indicacion, modificoMedico: string) => {
|
||||
update(i.id, {
|
||||
medicoModifica: modificoMedico,
|
||||
fechaModificacion: new Date().toISOString().split('T')[0],
|
||||
});
|
||||
};
|
||||
|
||||
@@ -159,7 +227,7 @@ export function SeccionIndicaciones({ recomendaciones, internacionId, add, updat
|
||||
<Plus className="h-4 w-4 mr-2" />Nueva Indicación
|
||||
</Button>
|
||||
<Button variant="ghost" onClick={() => setShowHistorial(!showHistorial)}>
|
||||
{showHistorial ? 'Ocultar Historial' : `Ver Historial (${historial.length})`}
|
||||
{showHistorial ? 'Ocultar Historial' : `Ver Historial (${movs.length})`}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -184,7 +252,17 @@ export function SeccionIndicaciones({ recomendaciones, internacionId, add, updat
|
||||
<Input value={medico} onChange={e => setMedico(e.target.value)} placeholder="Nombre del médico" />
|
||||
</div>
|
||||
|
||||
{tipo === 'Farmacologica' && (
|
||||
{tipo === 'Farmacologica' && (
|
||||
<>
|
||||
<div><Label>Droga *</Label><Input value={droga} onChange={e => setDroga(e.target.value)} placeholder="Nombre del medicamento" /></div>
|
||||
<div><Label>Dosis *</Label><Input value={dosis} onChange={e => setDosis(e.target.value)} placeholder="Ej: 500mg, 1g, 10ml" /></div>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div><Label>Frecuencia (hs)</Label><Input type="number" value={frecuenciaHoras} onChange={e => setFrecuenciaHoras(e.target.value ? parseInt(e.target.value) : '')} placeholder="Cada X horas" /></div>
|
||||
<div><Label>Vía</Label><Select value={via} onValueChange={(v: ViaAdministracion) => setVia(v)}><SelectTrigger><SelectValue /></SelectTrigger><SelectContent>{vias.map(v => <SelectItem key={v} value={v}>{v}</SelectItem>)}</SelectContent></Select></div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{tipo === 'Farmacologica Profilactica' && (
|
||||
<>
|
||||
<div><Label>Droga *</Label><Input value={droga} onChange={e => setDroga(e.target.value)} placeholder="Nombre del medicamento" /></div>
|
||||
<div><Label>Dosis *</Label><Input value={dosis} onChange={e => setDosis(e.target.value)} placeholder="Ej: 500mg, 1g, 10ml" /></div>
|
||||
@@ -194,7 +272,6 @@ export function SeccionIndicaciones({ recomendaciones, internacionId, add, updat
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
{tipo === 'Farmacologica Insulina' && (
|
||||
<>
|
||||
<div><Label>Tipo de Insulina</Label><Select value={tipoInsulina} onValueChange={(v: TipoInsulina) => setTipoInsulina(v)}><SelectTrigger><SelectValue /></SelectTrigger><SelectContent>{tiposInsulina.map(t => <SelectItem key={t} value={t}>{t}</SelectItem>)}</SelectContent></Select></div>
|
||||
@@ -210,7 +287,7 @@ export function SeccionIndicaciones({ recomendaciones, internacionId, add, updat
|
||||
<div><Label>Descripción *</Label><textarea className="w-full p-2 border rounded-md text-sm min-h-[80px] bg-transparent dark:bg-input/30" value={descripcion} onChange={e => setDescripcion(e.target.value)} placeholder="Ej: Control de signos vitales, Dieta, etc." /></div>
|
||||
)}
|
||||
|
||||
{(tipo === 'PHP' || tipo === 'Paralelo') && (
|
||||
{(tipo === 'PHP' || tipo === 'PHP Paralelo') && (
|
||||
<>
|
||||
<div><Label>Tipo de Plan</Label><Select value={tipoPlan} onValueChange={(v: TipoPlanHidratacion) => setTipoPlan(v)}><SelectTrigger><SelectValue /></SelectTrigger><SelectContent>{planes.map(p => <SelectItem key={p} value={p}>{p}</SelectItem>)}</SelectContent></Select></div>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
@@ -220,7 +297,7 @@ export function SeccionIndicaciones({ recomendaciones, internacionId, add, updat
|
||||
</>
|
||||
)}
|
||||
|
||||
{tipo === 'Alterno' && (
|
||||
{tipo === 'PHP Alterno' && (
|
||||
<>
|
||||
<div><Label>Plan 1</Label><Select value={tipoPlan} onValueChange={(v: TipoPlanHidratacion) => setTipoPlan(v)}><SelectTrigger><SelectValue /></SelectTrigger><SelectContent>{planes.map(p => <SelectItem key={p} value={p}>{p}</SelectItem>)}</SelectContent></Select></div>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
@@ -256,6 +333,9 @@ export function SeccionIndicaciones({ recomendaciones, internacionId, add, updat
|
||||
{ind.tipo === 'Farmacologica' && (
|
||||
<div className="font-medium">{ind.droga} {ind.dosis} {ind.frecuenciaHoras ? `c/${ind.frecuenciaHoras}hs` : ''} {ind.via}</div>
|
||||
)}
|
||||
{ind.tipo === 'Farmacologica Profilactica' && (
|
||||
<div className="font-medium">{ind.droga} {ind.dosis} {ind.frecuenciaHoras ? `c/${ind.frecuenciaHoras}hs` : ''} {ind.via}</div>
|
||||
)}
|
||||
{ind.tipo === 'Farmacologica Insulina' && (
|
||||
<div className="font-medium">{ind.tipoInsulina}
|
||||
{ind.unidadesDesayuno && ` - Desayuno: ${ind.unidadesDesayuno}U`}
|
||||
@@ -266,13 +346,10 @@ export function SeccionIndicaciones({ recomendaciones, internacionId, add, updat
|
||||
{ind.tipo === 'No Farmacologica' && (
|
||||
<div className="font-medium">{ind.descripcion}</div>
|
||||
)}
|
||||
{(ind.tipo === 'PHP' || ind.tipo === 'Paralelo') && (
|
||||
{(ind.tipo === 'PHP' || ind.tipo === 'PHP Paralelo') && (
|
||||
<div className="font-medium">{ind.tipoPlan} {ind.cantidadMl}ml en {ind.tiempoHoras}hs</div>
|
||||
)}
|
||||
{ind.tipo === 'Alterno' && (
|
||||
<div className="font-medium">{ind.tipoPlan} {ind.cantidadMl}ml + {ind.tipoPlan2} {ind.cantidadMl2}ml en {ind.tiempoHoras}hs</div>
|
||||
)}
|
||||
{ind.tipo === 'Alterno' && (
|
||||
{ind.tipo === 'PHP Alterno' && (
|
||||
<div className="font-medium">{ind.tipoPlan} {ind.cantidadMl}ml + {ind.tipoPlan2} {ind.cantidadMl2}ml en {ind.tiempoHoras}hs</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -302,42 +379,55 @@ export function SeccionIndicaciones({ recomendaciones, internacionId, add, updat
|
||||
</div>
|
||||
)}
|
||||
|
||||
{showHistorial && historial.length > 0 && (
|
||||
<div className="mt-6">
|
||||
<h3 className="font-bold mb-2">Historial de Indicaciones</h3>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>Fecha Creación</TableHead>
|
||||
<TableHead>Creado por</TableHead>
|
||||
<TableHead>Última Modificación</TableHead>
|
||||
<TableHead>Modificado por</TableHead>
|
||||
<TableHead>Fecha Suspensión</TableHead>
|
||||
<TableHead>Suspendido por</TableHead>
|
||||
<TableHead>Indicación</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{historial.map(ind => (
|
||||
<TableRow key={ind.id}>
|
||||
<TableCell>{ind.fechaCrea}</TableCell>
|
||||
<TableCell>{ind.medicoCrea}</TableCell>
|
||||
<TableCell>{ind.fechaModificacion || '-'}</TableCell>
|
||||
<TableCell>{ind.medicoModifica || '-'}</TableCell>
|
||||
<TableCell>{ind.fechaSuspension || '-'}</TableCell>
|
||||
<TableCell>{ind.medicoSuspende || '-'}</TableCell>
|
||||
<TableCell>
|
||||
{ind.tipo === 'Farmacologica' && `${ind.droga} ${ind.dosis} ${ind.frecuenciaHoras ? `c/${ind.frecuenciaHoras}hs` : ''} ${ind.via}`}
|
||||
{ind.tipo === 'Farmacologica Insulina' && `${ind.tipoInsulina}${ind.unidadesDesayuno ? ` - Desayuno: ${ind.unidadesDesayuno}U` : ''}${ind.unidadesAlmuerzo ? ` - Almuerzo: ${ind.unidadesAlmuerzo}U` : ''}${ind.unidadesNoche ? ` - 23hs: ${ind.unidadesNoche}U` : ''}`}
|
||||
{ind.tipo === 'No Farmacologica' && ind.descripcion}
|
||||
{(ind.tipo === 'PHP' || ind.tipo === 'Paralelo') && `${ind.tipoPlan} ${ind.cantidadMl}ml en ${ind.tiempoHoras}hs`}
|
||||
{ind.tipo === 'Alterno' && `${ind.tipoPlan} ${ind.cantidadMl}ml + ${ind.tipoPlan2} ${ind.cantidadMl2}ml en ${ind.tiempoHoras}hs`}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
{showHistorial && (
|
||||
<Dialog open={showHistorial} onOpenChange={setShowHistorial}>
|
||||
<DialogContent className="max-w-4xl max-h-[80vh] overflow-auto">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Historial de Indicaciones</DialogTitle>
|
||||
</DialogHeader>
|
||||
{movs.length === 0 ? (
|
||||
<p className="text-gray-500 py-4">Sin movimientos registrados</p>
|
||||
) : (
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead className="cursor-pointer hover:bg-gray-100" onClick={() => handleSort('fecha')}>
|
||||
Fecha {sortField === 'fecha' && (sortDir === 'asc' ? '↑' : '↓')}
|
||||
</TableHead>
|
||||
<TableHead className="cursor-pointer hover:bg-gray-100" onClick={() => handleSort('profesional')}>
|
||||
Profesional {sortField === 'profesional' && (sortDir === 'asc' ? '↑' : '↓')}
|
||||
</TableHead>
|
||||
<TableHead className="cursor-pointer hover:bg-gray-100" onClick={() => handleSort('tipo')}>
|
||||
Tipo {sortField === 'tipo' && (sortDir === 'asc' ? '↑' : '↓')}
|
||||
</TableHead>
|
||||
<TableHead>Indicación</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{sortedMovs.map(mov => (
|
||||
<TableRow key={mov.id}>
|
||||
<TableCell>{mov.fecha}</TableCell>
|
||||
<TableCell>{mov.profesional}</TableCell>
|
||||
<TableCell>
|
||||
<Badge className={mov.tipo === 'Indicacion' ? 'bg-green-500' : mov.tipo === 'Suspencion' ? 'bg-red-500' : 'bg-orange-500'}>
|
||||
{mov.tipo === 'Indicacion' ? 'Indicación' : mov.tipo === 'Suspencion' ? 'Suspensión' : 'Modificación'}
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
{mov.tipo === 'Modificacion' ? (
|
||||
<div className="text-sm">
|
||||
<div className="text-red-500 line-through">{mov.indicacionPrevia}</div>
|
||||
<div className="text-green-500">{mov.indicacionNueva}</div>
|
||||
</div>
|
||||
) : mov.tipo === 'Suspencion' ? mov.indicacionPrevia : mov.indicacionNueva}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
)}
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
+2
-2
@@ -172,9 +172,9 @@ export interface ATB {
|
||||
fechaFinalizacion?: string;
|
||||
}
|
||||
|
||||
export type IndicacionTipo = 'Farmacologica' | 'Farmacologica Insulina' | 'No Farmacologica' | 'PHP' | 'Paralelo' | 'Alterno';
|
||||
export type IndicacionTipo = 'Farmacologica' | 'Farmacologica Profilactica' | 'Farmacologica Insulina' | 'No Farmacologica' | 'PHP' | 'PHP Paralelo' | 'PHP Alterno';
|
||||
export type TipoInsulina = 'NPH' | 'Glargina';
|
||||
export type ViaAdministracion = 'Oral' | 'EV' | 'IM' | 'SC' | 'Por GGT' | 'Por SNG';
|
||||
export type ViaAdministracion = 'Via Oral' | 'EV' | 'IM' | 'SC' | 'Por GGT' | 'Por SNG';
|
||||
export type TipoPlanHidratacion = 'SF 0.9%' | 'Dextrosa 5%' | 'Dextrosa 10%' | 'Dextrosa 25%' | 'Ringer Lactato';
|
||||
|
||||
export interface Indicacion {
|
||||
|
||||
Reference in New Issue
Block a user