Agregar FiO2 y edición en gasometrías

- Agregar campo fio2 en interface AcidoBase
- Agregar columna fio2 en SQLite
- Nuevo campo FiO2 en modal nueva gasometría
- Mostrar FiO2 en lista de gasometrías
- Agregar botón edición (lápiz) en registros
- Agregar función actualizarAcidoBase en store
This commit is contained in:
2026-04-16 01:28:31 -03:00
parent 97adfd08b7
commit 0b77297c3d
5 changed files with 84 additions and 8 deletions
+65 -6
View File
@@ -59,6 +59,7 @@ interface HistoriaClinicaProps {
onActualizarLaboratorio: (id: string, datos: Partial<Laboratorio>) => void;
onEliminarLaboratorio: (id: string) => void;
onAgregarAcidoBase: (acidoBase: Omit<AcidoBase, 'id'>) => void;
onActualizarAcidoBase: (id: string, datos: Partial<AcidoBase>) => void;
onEliminarAcidoBase: (id: string) => void;
onAgregarCultivo: (cultivo: Omit<Cultivo, 'id'>) => void;
onActualizarCultivo: (id: string, datos: Partial<Cultivo>) => void;
@@ -159,6 +160,7 @@ export function HistoriaClinica({
onActualizarLaboratorio,
onEliminarLaboratorio,
onAgregarAcidoBase,
onActualizarAcidoBase,
onEliminarAcidoBase,
onAgregarCultivo,
onActualizarCultivo,
@@ -532,7 +534,7 @@ export function HistoriaClinica({
</TabsContent>
<TabsContent value="acidobase" className="mt-4">
<SeccionAcidosBase ab={acidosBase} patientId={paciente.id} add={onAgregarAcidoBase} del={onEliminarAcidoBase} />
<SeccionAcidosBase ab={acidosBase} patientId={paciente.id} add={onAgregarAcidoBase} update={onActualizarAcidoBase} del={onEliminarAcidoBase} />
</TabsContent>
<TabsContent value="cultivos" className="mt-4">
@@ -1295,13 +1297,16 @@ function SeccionEvoluciones({ evos, internacionId, add, update, del }: {
);
}
function SeccionAcidosBase({ ab, patientId, add, del }: {
function SeccionAcidosBase({ ab, patientId, add, update, del }: {
ab: AcidoBase[];
patientId: string;
add: (a: Omit<AcidoBase, 'id'>) => void;
update: (id: string, datos: Partial<AcidoBase>) => void;
del: (id: string) => void;
}) {
const [dialog, setDialog] = useState(false);
const [editDialog, setEditDialog] = useState(false);
const [selected, setSelected] = useState<AcidoBase | null>(null);
const [fecha, setFecha] = useState(new Date().toISOString().split('T')[0]);
const [hora, setHora] = useState(new Date().toTimeString().slice(0, 5));
const [ph, setPh] = useState('');
@@ -1311,12 +1316,30 @@ function SeccionAcidosBase({ ab, patientId, add, del }: {
const [be, setBe] = useState('');
const [sato2, setSato2] = useState('');
const [lactato, setLactato] = useState('');
const [fio2, setFio2] = useState('');
const [interpretacion, setInterpretacion] = useState('');
const reset = () => {
setFecha(new Date().toISOString().split('T')[0]);
setHora(new Date().toTimeString().slice(0, 5));
setPh(''); setPco2(''); setPo2(''); setHco3(''); setBe(''); setSato2(''); setLactato(''); setInterpretacion('');
setPh(''); setPco2(''); setPo2(''); setHco3(''); setBe(''); setSato2(''); setLactato(''); setFio2(''); setInterpretacion('');
setSelected(null);
};
const loadEdit = (a: AcidoBase) => {
setSelected(a);
setFecha(a.fecha);
setHora(a.hora);
setPh(String(a.ph));
setPco2(String(a.pco2));
setPo2(String(a.po2));
setHco3(String(a.hco3));
setBe(String(a.be));
setSato2(String(a.sato2));
setLactato(a.lactato ? String(a.lactato) : '');
setFio2(a.fio2 ? String(a.fio2) : '');
setInterpretacion(a.interpretacion || '');
setEditDialog(true);
};
const abFiltered = ab.filter(a => a.pacienteId === patientId).sort((a, b) => new Date(b.fecha + 'T' + b.hora).getTime() - new Date(a.fecha + 'T' + a.hora).getTime());
@@ -1350,11 +1373,19 @@ function SeccionAcidosBase({ ab, patientId, add, del }: {
const handle = () => {
if (!ph || !pco2 || !po2 || !hco3 || !be || !sato2) return;
const interpretacionAuto = interpretarGasometria();
add({ pacienteId: patientId, fecha, hora, ph: parseFloat(ph), pco2: parseFloat(pco2), po2: parseFloat(po2), hco3: parseFloat(hco3), be: parseFloat(be), sato2: parseFloat(sato2), lactato: lactato ? parseFloat(lactato) : undefined, interpretacion: interpretacion || interpretacionAuto });
add({ pacienteId: patientId, fecha, hora, ph: parseFloat(ph), pco2: parseFloat(pco2), po2: parseFloat(po2), hco3: parseFloat(hco3), be: parseFloat(be), sato2: parseFloat(sato2), lactato: lactato ? parseFloat(lactato) : undefined, fio2: fio2 ? parseFloat(fio2) : undefined, interpretacion: interpretacion || interpretacionAuto });
setDialog(false);
reset();
};
const handleEdit = () => {
if (!selected || !ph || !pco2 || !po2 || !hco3 || !be || !sato2) return;
const interpretacionAuto = interpretarGasometria();
update(selected.id, { fecha, hora, ph: parseFloat(ph), pco2: parseFloat(pco2), po2: parseFloat(po2), hco3: parseFloat(hco3), be: parseFloat(be), sato2: parseFloat(sato2), lactato: lactato ? parseFloat(lactato) : undefined, fio2: fio2 ? parseFloat(fio2) : undefined, interpretacion: interpretacion || interpretacionAuto });
setEditDialog(false);
reset();
};
return (
<div className="space-y-4">
<div className="flex">
@@ -1368,7 +1399,7 @@ function SeccionAcidosBase({ ab, patientId, add, del }: {
<div><Label>Fecha *</Label><Input type="date" value={fecha} onChange={e => setFecha(e.target.value)} /></div>
<div><Label>Hora *</Label><Input type="time" value={hora} onChange={e => setHora(e.target.value)} /></div>
</div>
<div className="grid grid-cols-7 gap-2">
<div className="grid grid-cols-4 sm:grid-cols-8 gap-2">
<div><Label>pH *</Label><Input type="number" step="0.01" value={ph} onChange={e => setPh(e.target.value)} placeholder="7.40" /></div>
<div><Label>pCO2 *</Label><Input type="number" value={pco2} onChange={e => setPco2(e.target.value)} placeholder="40" /></div>
<div><Label>pO2 *</Label><Input type="number" value={po2} onChange={e => setPo2(e.target.value)} placeholder="85" /></div>
@@ -1376,6 +1407,7 @@ function SeccionAcidosBase({ ab, patientId, add, del }: {
<div><Label>BE *</Label><Input type="number" step="0.1" value={be} onChange={e => setBe(e.target.value)} placeholder="0" /></div>
<div><Label>SatO2 *</Label><Input type="number" value={sato2} onChange={e => setSato2(e.target.value)} placeholder="97" /></div>
<div><Label>Lactato</Label><Input type="number" step="0.1" value={lactato} onChange={e => setLactato(e.target.value)} placeholder="1.0" /></div>
<div><Label>FiO2</Label><Input type="number" value={fio2} onChange={e => setFio2(e.target.value)} placeholder="21" /></div>
</div>
{ph && pco2 && hco3 && <div className="bg-blue-50 p-3 rounded-lg border border-blue-200"><p className="text-sm font-medium text-blue-800 flex items-center gap-2"><Activity className="h-4 w-4" />Interpretación automática: {interpretarGasometria()}</p></div>}
<div><Label>Interpretación / Comentarios</Label><textarea className="w-full p-2 border rounded-md text-sm min-h-[80px]" value={interpretacion} onChange={e => setInterpretacion(e.target.value)} placeholder="Interpretación clínica..." /></div>
@@ -1383,6 +1415,30 @@ function SeccionAcidosBase({ ab, patientId, add, del }: {
<div className="flex justify-end gap-2 mt-4"><Button variant="outline" onClick={() => setDialog(false)}><X className="h-4 w-4 mr-2" />Cancelar</Button><Button onClick={handle} disabled={!ph || !pco2 || !po2 || !hco3 || !be || !sato2}><Plus className="h-4 w-4 mr-2" />Guardar Gasometría</Button></div>
</DialogContent>
</Dialog>
<Dialog open={editDialog} onOpenChange={setEditDialog}>
<DialogContent className="sm:max-w-2xl max-h-[90vh] overflow-y-auto">
<DialogHeader><DialogTitle>Editar Gasometría Arterial</DialogTitle></DialogHeader>
<div className="space-y-4">
<div className="grid grid-cols-2 gap-4">
<div><Label>Fecha *</Label><Input type="date" value={fecha} onChange={e => setFecha(e.target.value)} /></div>
<div><Label>Hora *</Label><Input type="time" value={hora} onChange={e => setHora(e.target.value)} /></div>
</div>
<div className="grid grid-cols-4 sm:grid-cols-8 gap-2">
<div><Label>pH *</Label><Input type="number" step="0.01" value={ph} onChange={e => setPh(e.target.value)} placeholder="7.40" /></div>
<div><Label>pCO2 *</Label><Input type="number" value={pco2} onChange={e => setPco2(e.target.value)} placeholder="40" /></div>
<div><Label>pO2 *</Label><Input type="number" value={po2} onChange={e => setPo2(e.target.value)} placeholder="85" /></div>
<div><Label>HCO3 *</Label><Input type="number" step="0.1" value={hco3} onChange={e => setHco3(e.target.value)} placeholder="24" /></div>
<div><Label>BE *</Label><Input type="number" step="0.1" value={be} onChange={e => setBe(e.target.value)} placeholder="0" /></div>
<div><Label>SatO2 *</Label><Input type="number" value={sato2} onChange={e => setSato2(e.target.value)} placeholder="97" /></div>
<div><Label>Lactato</Label><Input type="number" step="0.1" value={lactato} onChange={e => setLactato(e.target.value)} placeholder="1.0" /></div>
<div><Label>FiO2</Label><Input type="number" value={fio2} onChange={e => setFio2(e.target.value)} placeholder="21" /></div>
</div>
{ph && pco2 && hco3 && <div className="bg-blue-50 p-3 rounded-lg border border-blue-200"><p className="text-sm font-medium text-blue-800 flex items-center gap-2"><Activity className="h-4 w-4" />Interpretación automática: {interpretarGasometria()}</p></div>}
<div><Label>Interpretación / Comentarios</Label><textarea className="w-full p-2 border rounded-md text-sm min-h-[80px]" value={interpretacion} onChange={e => setInterpretacion(e.target.value)} placeholder="Interpretación clínica..." /></div>
</div>
<div className="flex justify-end gap-2 mt-4"><Button variant="outline" onClick={() => setEditDialog(false)}><X className="h-4 w-4 mr-2" />Cancelar</Button><Button onClick={handleEdit} disabled={!ph || !pco2 || !po2 || !hco3 || !be || !sato2}><Save className="h-4 w-4 mr-2" />Guardar Cambios</Button></div>
</DialogContent>
</Dialog>
{abFiltered.length === 0 ? <div className="text-center py-8 text-gray-400"><Activity className="h-12 w-12 mx-auto mb-2 opacity-50" /><p>No hay gasometrías</p></div> :
abFiltered.map(a => {
const phSt = getEstadoParametro('ph', a.ph);
@@ -1392,11 +1448,13 @@ function SeccionAcidosBase({ ab, patientId, add, del }: {
<div className="flex items-start justify-between">
<div><p className="font-medium">{a.fecha} {a.hora}</p></div>
<div className="flex items-center gap-2">
<Badge variant="outline" className="text-xs">{a.fio2 && <span className="mr-1">FiO:{a.fio2}</span>}</Badge>
<Badge className={getColorPh(a.ph)}>pH: {a.ph}</Badge>
<Button size="sm" variant="ghost" className="text-blue-600" onClick={() => loadEdit(a)}><Edit /></Button>
<Button size="sm" variant="ghost" className="text-red-600" onClick={() => del(a.id)}><Trash2 /></Button>
</div>
</div>
<div className="grid grid-cols-3 sm:grid-cols-7 gap-2">
<div className="grid grid-cols-3 sm:grid-cols-8 gap-2">
<div className="bg-gray-50 p-2 rounded text-center"><p className="text-xs text-gray-500">pH</p><p className={`font-bold ${phSt.color}`}>{a.ph}</p></div>
<div className="bg-gray-50 p-2 rounded text-center"><p className="text-xs text-gray-500">pCO2</p><p className="font-bold">{a.pco2}</p></div>
<div className="bg-gray-50 p-2 rounded text-center"><p className="text-xs text-gray-500">pO2</p><p className="font-bold">{a.po2}</p></div>
@@ -1404,6 +1462,7 @@ function SeccionAcidosBase({ ab, patientId, add, del }: {
<div className="bg-gray-50 p-2 rounded text-center"><p className="text-xs text-gray-500">BE</p><p className="font-bold">{a.be}</p></div>
<div className="bg-gray-50 p-2 rounded text-center"><p className="text-xs text-gray-500">SatO2</p><p className="font-bold">{a.sato2}%</p></div>
{a.lactato && <div className="bg-gray-50 p-2 rounded text-center"><p className="text-xs text-gray-500">Lactato</p><p className="font-bold">{a.lactato}</p></div>}
{a.fio2 && <div className="bg-gray-50 p-2 rounded text-center"><p className="text-xs text-gray-500">FiO2</p><p className="font-bold">{a.fio2}%</p></div>}
</div>
{a.interpretacion && <div className="bg-teal-50 p-3 rounded-lg border border-teal-200"><p className="text-sm font-medium text-teal-800">Interpretación: {a.interpretacion}</p></div>}
</div>