diff --git a/src/App.tsx b/src/App.tsx index 8197b01..7fa7c64 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -13,6 +13,7 @@ import { EditIngreso } from '@/sections/EditIngreso'; import { Spinner } from '@/components/ui/spinner'; import { Button } from '@/components/ui/button'; import { ThemeProvider } from '@/contexts/ThemeContext'; +import { Toaster } from '@/components/ui/sonner'; function AppContent() { const store = useHospitalStore(); @@ -127,7 +128,7 @@ function AppContent() { if (!internacion || !paciente) { return (
-

Internación no encontrada

+

Internación no encontrada

); @@ -160,7 +161,7 @@ function AppContent() { /> ); } -case 'nuevoingreso': + case 'nuevoingreso': return ( -

Internación no encontrada

+

Internación no encontrada

); @@ -197,6 +198,7 @@ case 'nuevoingreso': /> ); } + default: return null; } }; @@ -210,10 +212,12 @@ case 'nuevoingreso': function App() { return ( - + // @ts-expect-error - next-themes types mismatch + + ); } -export default App; +export default App; \ No newline at end of file diff --git a/src/contexts/ThemeContext.tsx b/src/contexts/ThemeContext.tsx index 86a446c..0925d71 100644 --- a/src/contexts/ThemeContext.tsx +++ b/src/contexts/ThemeContext.tsx @@ -1,40 +1,19 @@ -import { createContext, useContext, useEffect, useState, type ReactNode } from 'react'; - -interface ThemeContextType { - isDarkMode: boolean; - toggleDarkMode: () => void; -} - -const ThemeContext = createContext(undefined); +import { ThemeProvider as NextThemesProvider, useTheme as useNextTheme } from 'next-themes'; +import type { ReactNode } from 'react'; export function ThemeProvider({ children }: { children: ReactNode }) { - const [isDarkMode, setIsDarkMode] = useState(() => { - const saved = localStorage.getItem('darkMode'); - return saved ? JSON.parse(saved) : false; - }); - - useEffect(() => { - localStorage.setItem('darkMode', JSON.stringify(isDarkMode)); - if (isDarkMode) { - document.documentElement.classList.add('dark'); - } else { - document.documentElement.classList.remove('dark'); - } - }, [isDarkMode]); - - const toggleDarkMode = () => setIsDarkMode((prev: boolean) => !prev); - return ( - + {children} - + ); } export function useTheme() { - const context = useContext(ThemeContext); - if (!context) { - throw new Error('useTheme must be used within ThemeProvider'); - } - return context; -} \ No newline at end of file + const { theme, setTheme } = useNextTheme(); + const isDarkMode = theme === 'dark'; + const toggleDarkMode = () => setTheme(theme === 'dark' ? 'light' : 'dark'); + return { isDarkMode, toggleDarkMode, theme, setTheme }; +} + +export { NextThemesProvider }; \ No newline at end of file diff --git a/src/sections/Cultivos.tsx b/src/sections/Cultivos.tsx index 62ac58c..79b4566 100644 --- a/src/sections/Cultivos.tsx +++ b/src/sections/Cultivos.tsx @@ -184,7 +184,7 @@ export function Cultivos({ - @@ -230,7 +230,7 @@ export function Cultivos({ return p ? `${p.apellido}, ${p.nombre} - DNI: ${p.dni}` : ''; })()} - + )}
@@ -269,7 +269,7 @@ export function Cultivos({
- @@ -310,7 +310,7 @@ export function Cultivos({ Cancelar - @@ -368,7 +368,7 @@ export function Cultivos({ Cancelar - @@ -452,11 +452,11 @@ export function Cultivos({
{onActualizarCultivo && cultivo.estado === 'NAF/Pendiente' && ( <> - - @@ -468,7 +468,7 @@ export function Cultivos({ Editar - @@ -479,7 +479,7 @@ export function Cultivos({ )} -
diff --git a/src/sections/EditIngreso.tsx b/src/sections/EditIngreso.tsx index 1398107..546340f 100644 --- a/src/sections/EditIngreso.tsx +++ b/src/sections/EditIngreso.tsx @@ -82,7 +82,7 @@ export function EditIngreso({ return (
-
+
-
+
@@ -390,13 +390,13 @@ export function Evoluciones({ Cancelar - +
@@ -462,13 +462,12 @@ export function Evoluciones({ )} - diff --git a/src/sections/HistoriaClinica.tsx b/src/sections/HistoriaClinica.tsx index 6721e68..90af0e5 100644 --- a/src/sections/HistoriaClinica.tsx +++ b/src/sections/HistoriaClinica.tsx @@ -22,7 +22,11 @@ import { Wind, Droplets, Save, - X + X, + MoreHorizontal, + Edit, + ClipboardList, + TrendingUp } from 'lucide-react'; import { Card, CardContent } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; @@ -33,6 +37,8 @@ import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; 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 } from '@/types'; import { formatDateDDMMYYYY } from '@/lib/utils'; @@ -212,7 +218,7 @@ export function HistoriaClinica({
-

Historia Clínica

+

Historia Clínica

Cama: {cama?.numero || 'N/A'} | {paciente.apellido}, {paciente.nombre} | {paciente.fechaNacimiento ? calcularEdad(paciente.fechaNacimiento) + ' años' : ''} | DNI: {paciente.dni}

@@ -534,6 +540,8 @@ function SeccionLaboratorios({ lab, patientId, add, update, del }: { }) { const [dialog, setDialog] = useState(false); const [obsDialog, setObsDialog] = useState(false); + const [evolDialog, setEvolDialog] = useState(false); + const [selectedLab, setSelectedLab] = useState(null); const [edit, setEdit] = useState(null); const [obsLab, setObsLab] = useState(null); const [fecha, setFecha] = useState(new Date().toISOString().split('T')[0]); @@ -556,6 +564,23 @@ function SeccionLaboratorios({ lab, patientId, add, update, del }: { const [tp, setTp] = useState(''); const [kptt, setKptt] = useState(''); const [rin, setRin] = useState(''); + const [parametroEvolucion, setParametroEvolucion] = useState(''); + + const parametrosLaboratorio = [ + 'Hematocrito', 'Hemoglobina', 'Leucocitos', 'Plaquetas', + 'Glucemia', 'Urea', 'Creatinina', + 'Sodio', 'Potasio', 'Cloro', + 'Bilirrubina Total', 'Bilirrubina Directa', 'GOT', 'GPT', + 'Tiempo de Protrombina', 'KPTT', 'INR' + ]; + + const datosEvolucion = lab + .filter(l => l.resultados.some(r => r.parametro === parametroEvolucion)) + .sort((a, b) => new Date(a.fecha).getTime() - new Date(b.fecha).getTime()) + .map(l => { + const r = l.resultados.find(r => r.parametro === parametroEvolucion); + return { fecha: l.fecha, valor: r ? parseFloat(String(r.valor)) : null }; + }); const getEstadoColor = (estado: ResultadoLaboratorio['estado']) => { switch (estado) { @@ -657,8 +682,11 @@ function SeccionLaboratorios({ lab, patientId, add, update, del }: { return (
-
- +
+
+ + +
@@ -725,7 +753,7 @@ function SeccionLaboratorios({ lab, patientId, add, update, del }: {

{obsLab?.fecha}

{obsLab?.tipo}

-
+

{obsLab?.observaciones}

@@ -733,6 +761,64 @@ function SeccionLaboratorios({ lab, patientId, add, update, del }: {
+ + + + + + Evolución de Laboratorio + + +
+
+ + +
+ {parametroEvolucion && datosEvolucion.length > 0 && ( +
+ + + + + + + + + +
+ )} + {parametroEvolucion && datosEvolucion.length === 0 && ( +
+ +

No hay datos para este parámetro

+
+ )} +
+
+ +
+
+
+ {labs.length === 0 ?

No hay laboratorios

:
@@ -756,7 +842,7 @@ function SeccionLaboratorios({ lab, patientId, add, update, del }: { TPKPTTRIN - + Acciones @@ -781,11 +867,27 @@ function SeccionLaboratorios({ lab, patientId, add, update, del }: { {getValor(l, 'KPTT')} {getValor(l, 'INR')} -
- {l.observaciones && } - - -
+ + + + + + loadEdit(l)}> + + Editar + + del(l.id)} className="text-red-600"> + + Eliminar + + { setObsLab(l); setObsDialog(true); }}> + + Ver Observaciones + + +
))} @@ -893,8 +995,8 @@ function SeccionEvoluciones({ evos, internacionId, add, update, del }: { return (
-
- +
+
@@ -1037,8 +1139,8 @@ function SeccionAcidosBase({ ab, patientId, add, del }: { return (
-
- +
+
@@ -1212,8 +1314,8 @@ const resetRes = () => { return (
-
- +
+
@@ -1242,7 +1344,7 @@ const resetRes = () => {