Actualizacion de tabla de internaciones y evoluciones
This commit is contained in:
@@ -96,6 +96,8 @@ function AppContent() {
|
|||||||
evoluciones={store.evoluciones}
|
evoluciones={store.evoluciones}
|
||||||
internaciones={store.internaciones}
|
internaciones={store.internaciones}
|
||||||
pacientes={store.pacientes}
|
pacientes={store.pacientes}
|
||||||
|
camas={store.camas}
|
||||||
|
getCamaById={store.getCamaById}
|
||||||
onAgregarEvolucion={store.agregarEvolucion}
|
onAgregarEvolucion={store.agregarEvolucion}
|
||||||
onActualizarEvolucion={store.actualizarEvolucion}
|
onActualizarEvolucion={store.actualizarEvolucion}
|
||||||
onEliminarEvolucion={store.eliminarEvolucion}
|
onEliminarEvolucion={store.eliminarEvolucion}
|
||||||
|
|||||||
+182
-117
@@ -1,19 +1,22 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { FileText, Plus, Search, Calendar, Clock, Thermometer, Heart, Activity, Wind, Droplets, Pencil, Trash2, ChevronDown, ChevronUp, X, Save } from 'lucide-react';
|
import { FileText, Plus, Search, Eye, MoreHorizontal, Pencil, Trash2, X, Save, Activity, Heart, Wind, Thermometer, Droplets } from 'lucide-react';
|
||||||
import { Card, CardContent } from '@/components/ui/card';
|
import { Card, CardContent } from '@/components/ui/card';
|
||||||
import { Badge } from '@/components/ui/badge';
|
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Input } from '@/components/ui/input';
|
import { Input } from '@/components/ui/input';
|
||||||
import { Label } from '@/components/ui/label';
|
import { Label } from '@/components/ui/label';
|
||||||
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog';
|
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog';
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
||||||
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
|
||||||
|
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@/components/ui/dropdown-menu';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import type { Evolucion, Internacion, Paciente, SignosVitales, ExamenFisico } from '@/types';
|
import type { Evolucion, Internacion, Paciente, Cama, SignosVitales, ExamenFisico } from '@/types';
|
||||||
|
|
||||||
interface EvolucionesProps {
|
interface EvolucionesProps {
|
||||||
evoluciones: Evolucion[];
|
evoluciones: Evolucion[];
|
||||||
internaciones: Internacion[];
|
internaciones: Internacion[];
|
||||||
pacientes: Paciente[];
|
pacientes: Paciente[];
|
||||||
|
camas?: Cama[];
|
||||||
|
getCamaById?: (id: string) => Cama | undefined;
|
||||||
onAgregarEvolucion: (evolucion: Omit<Evolucion, 'id'>) => Promise<unknown> | void;
|
onAgregarEvolucion: (evolucion: Omit<Evolucion, 'id'>) => Promise<unknown> | void;
|
||||||
onActualizarEvolucion?: (id: string, datos: Partial<Evolucion>) => Promise<unknown> | void;
|
onActualizarEvolucion?: (id: string, datos: Partial<Evolucion>) => Promise<unknown> | void;
|
||||||
onEliminarEvolucion: (id: string) => Promise<unknown> | void;
|
onEliminarEvolucion: (id: string) => Promise<unknown> | void;
|
||||||
@@ -25,6 +28,8 @@ export function Evoluciones({
|
|||||||
evoluciones,
|
evoluciones,
|
||||||
internaciones,
|
internaciones,
|
||||||
pacientes,
|
pacientes,
|
||||||
|
camas,
|
||||||
|
getCamaById,
|
||||||
onAgregarEvolucion,
|
onAgregarEvolucion,
|
||||||
onActualizarEvolucion,
|
onActualizarEvolucion,
|
||||||
onEliminarEvolucion,
|
onEliminarEvolucion,
|
||||||
@@ -34,7 +39,7 @@ export function Evoluciones({
|
|||||||
const [busqueda, setBusqueda] = useState('');
|
const [busqueda, setBusqueda] = useState('');
|
||||||
const [pacienteSeleccionado, setPacienteSeleccionado] = useState<string>('');
|
const [pacienteSeleccionado, setPacienteSeleccionado] = useState<string>('');
|
||||||
const [dialogoAbierto, setDialogoAbierto] = useState(false);
|
const [dialogoAbierto, setDialogoAbierto] = useState(false);
|
||||||
const [evolucionExpandida, setEvolucionExpandida] = useState<string | null>(null);
|
const [evolucionDetalle, setEvolucionDetalle] = useState<Evolucion | null>(null);
|
||||||
const [evolucionEditando, setEvolucionEditando] = useState<Evolucion | null>(null);
|
const [evolucionEditando, setEvolucionEditando] = useState<Evolucion | null>(null);
|
||||||
|
|
||||||
const [fecha, setFecha] = useState(new Date().toISOString().split('T')[0]);
|
const [fecha, setFecha] = useState(new Date().toISOString().split('T')[0]);
|
||||||
@@ -439,120 +444,83 @@ export function Evoluciones({
|
|||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<div className="space-y-4">
|
{evolucionesFiltradas.length > 0 ? (
|
||||||
{evolucionesFiltradas.map((evolucion) => {
|
<div className="rounded-md border overflow-x-auto bg-card">
|
||||||
const internacion = internaciones.find(i => i.id === evolucion.internacionId);
|
<Table className="w-full min-w-max text-sm">
|
||||||
const paciente = internacion ? getPacienteById(internacion.pacienteId) : null;
|
<TableHeader>
|
||||||
const signosTexto = getSignosVitalesTexto(evolucion.signosVitales);
|
<TableRow>
|
||||||
const estaExpandida = evolucionExpandida === evolucion.id;
|
<TableHead>Fecha</TableHead>
|
||||||
|
<TableHead>Cama</TableHead>
|
||||||
|
<TableHead>Paciente</TableHead>
|
||||||
|
<TableHead>Profesional</TableHead>
|
||||||
|
<TableHead className="text-center">TAS</TableHead>
|
||||||
|
<TableHead className="text-center">TAD</TableHead>
|
||||||
|
<TableHead className="text-center">FC</TableHead>
|
||||||
|
<TableHead className="text-center">FR</TableHead>
|
||||||
|
<TableHead className="text-center">Tº</TableHead>
|
||||||
|
<TableHead className="text-center">Sat</TableHead>
|
||||||
|
<TableHead className="text-center w-[60px]">Acciones</TableHead>
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
<TableBody>
|
||||||
|
{evolucionesFiltradas.map((evolucion) => {
|
||||||
|
const internacion = internaciones.find(i => i.id === evolucion.internacionId);
|
||||||
|
const paciente = internacion ? getPacienteById(internacion.pacienteId) : null;
|
||||||
|
const cama = internacion ? (getCamaById ? getCamaById(internacion.camaId) : camas?.find(c => c.id === internacion.camaId)) : null;
|
||||||
|
const sv = evolucion.signosVitales;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card key={evolucion.id} className="hover:shadow-md transition-shadow">
|
<TableRow key={evolucion.id} className="hover:bg-muted/50">
|
||||||
<CardContent className="p-4">
|
<TableCell className="whitespace-nowrap font-medium text-xs">
|
||||||
<div className="flex flex-col gap-4">
|
{evolucion.fecha} {evolucion.hora || ''}
|
||||||
{/* Patient Info */}
|
</TableCell>
|
||||||
<div className="flex flex-col gap-3">
|
<TableCell className="text-xs whitespace-nowrap">
|
||||||
<div className="flex items-center gap-3">
|
{cama ? cama.numero : '-'}
|
||||||
<div className="h-10 w-10 bg-blue-100 rounded-full flex items-center justify-center">
|
</TableCell>
|
||||||
<FileText className="h-5 w-5 text-blue-600" />
|
<TableCell className="font-medium text-xs whitespace-nowrap">
|
||||||
</div>
|
{paciente ? `${paciente.apellido}, ${paciente.nombre}` : 'Sin paciente'}
|
||||||
<div>
|
</TableCell>
|
||||||
<h3 className="font-bold">
|
<TableCell className="text-xs whitespace-nowrap">
|
||||||
{paciente ? `${paciente.apellido}, ${paciente.nombre}` : 'Paciente no encontrado'}
|
{evolucion.medico || '-'}
|
||||||
</h3>
|
</TableCell>
|
||||||
<div className="flex flex-wrap items-center gap-x-3 gap-y-1 text-sm text-gray-500">
|
<TableCell className="text-center text-xs">{sv?.presionSistolica ?? '-'}</TableCell>
|
||||||
<span className="flex items-center gap-1">
|
<TableCell className="text-center text-xs">{sv?.presionDiastolica ?? '-'}</TableCell>
|
||||||
<Calendar className="h-3 w-3" />
|
<TableCell className="text-center text-xs">{sv?.frecuenciaCardiaca ?? '-'}</TableCell>
|
||||||
{evolucion.fecha}
|
<TableCell className="text-center text-xs">{sv?.frecuenciaRespiratoria ?? '-'}</TableCell>
|
||||||
</span>
|
<TableCell className="text-center text-xs">{sv?.temperatura !== undefined ? `${sv.temperatura}°C` : '-'}</TableCell>
|
||||||
<span className="flex items-center gap-1">
|
<TableCell className="text-center text-xs">{sv?.saturacionO2 !== undefined ? `${sv.saturacionO2}%` : '-'}</TableCell>
|
||||||
<Clock className="h-3 w-3" />
|
<TableCell className="text-center p-1">
|
||||||
{evolucion.hora}
|
<DropdownMenu>
|
||||||
</span>
|
<DropdownMenuTrigger asChild>
|
||||||
<Badge variant="outline">{evolucion.medico}</Badge>
|
<Button size="sm" variant="ghost" className="h-8 w-8 p-0">
|
||||||
</div>
|
<MoreHorizontal className="h-4 w-4" />
|
||||||
</div>
|
</Button>
|
||||||
</div>
|
</DropdownMenuTrigger>
|
||||||
<div className="flex flex-wrap items-center gap-2">
|
<DropdownMenuContent align="end">
|
||||||
<Button
|
<DropdownMenuItem onClick={() => setEvolucionDetalle(evolucion)}>
|
||||||
size="sm"
|
<Eye className="mr-2 h-4 w-4" />
|
||||||
variant="outline"
|
Detalles
|
||||||
onClick={() => setEvolucionExpandida(estaExpandida ? null : evolucion.id)}
|
</DropdownMenuItem>
|
||||||
>
|
{onActualizarEvolucion && (
|
||||||
{estaExpandida ? <ChevronUp className="h-4 w-4" /> : <ChevronDown className="h-4 w-4" />}
|
<DropdownMenuItem onClick={() => abrirEditar(evolucion)}>
|
||||||
</Button>
|
<Pencil className="mr-2 h-4 w-4" />
|
||||||
{onActualizarEvolucion && (
|
Editar
|
||||||
<Button size="sm" variant="outline" onClick={() => abrirEditar(evolucion)}>
|
</DropdownMenuItem>
|
||||||
<Pencil className="h-4 w-4" />
|
)}
|
||||||
</Button>
|
<DropdownMenuItem onClick={() => onEliminarEvolucion(evolucion.id)} className="text-red-600 focus:text-red-600">
|
||||||
)}
|
<Trash2 className="mr-2 h-4 w-4" />
|
||||||
<Button variant="outline"
|
Eliminar
|
||||||
size="sm"
|
</DropdownMenuItem>
|
||||||
className="text-red-600"
|
</DropdownMenuContent>
|
||||||
onClick={() => onEliminarEvolucion(evolucion.id)}
|
</DropdownMenu>
|
||||||
>
|
</TableCell>
|
||||||
<Trash2 className="h-4 w-4" />
|
</TableRow>
|
||||||
Eliminar
|
);
|
||||||
</Button>
|
})}
|
||||||
</div>
|
</TableBody>
|
||||||
</div>
|
</Table>
|
||||||
|
</div>
|
||||||
{signosTexto && (
|
) : (
|
||||||
<div className="bg-blue-50 p-3 rounded-lg">
|
|
||||||
<p className="text-sm font-medium text-blue-800 flex items-center gap-2">
|
|
||||||
<Activity className="h-4 w-4" />
|
|
||||||
Signos Vitales: {signosTexto}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{estaExpandida && (
|
|
||||||
<>
|
|
||||||
{evolucion.examenFisico && (
|
|
||||||
<div className="bg-green-50 p-3 rounded-lg border border-green-200">
|
|
||||||
<p className="text-sm font-medium text-green-800 mb-2">Examen Físico:</p>
|
|
||||||
<div className="grid grid-cols-1 sm:grid-cols-4 gap-2 text-xs">
|
|
||||||
{evolucion.examenFisico.SNC && <div><span className="font-medium">SNC:</span> {evolucion.examenFisico.SNC}</div>}
|
|
||||||
{evolucion.examenFisico.Cardiovascular && <div><span className="font-medium">CV:</span> {evolucion.examenFisico.Cardiovascular}</div>}
|
|
||||||
{evolucion.examenFisico.Respiratorio && <div><span className="font-medium">Resp:</span> {evolucion.examenFisico.Respiratorio}</div>}
|
|
||||||
{evolucion.examenFisico.Abdominal && <div><span className="font-medium">Abd:</span> {evolucion.examenFisico.Abdominal}</div>}
|
|
||||||
{evolucion.examenFisico.Genitourinario && <div><span className="font-medium">GU:</span> {evolucion.examenFisico.Genitourinario}</div>}
|
|
||||||
{evolucion.examenFisico.PielAnexos && <div><span className="font-medium">Piel:</span> {evolucion.examenFisico.PielAnexos}</div>}
|
|
||||||
{evolucion.examenFisico.SOMA && <div><span className="font-medium">SOMA:</span> {evolucion.examenFisico.SOMA}</div>}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{evolucion.novedades && (
|
|
||||||
<div className="bg-red-50 p-3 rounded-lg border border-red-200 mt-3">
|
|
||||||
<p className="text-sm font-medium text-red-800 mb-1">Novedades:</p>
|
|
||||||
<p className="text-sm text-gray-800 whitespace-pre-wrap">{evolucion.novedades}</p>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{evolucion.comentario && (
|
|
||||||
<div>
|
|
||||||
<p className="text-sm font-medium text-gray-700">Comentario:</p>
|
|
||||||
<p className="text-sm text-gray-600 whitespace-pre-wrap">{evolucion.comentario}</p>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{evolucion.pendientes && (
|
|
||||||
<div className="bg-amber-50 p-3 rounded-lg border border-amber-200">
|
|
||||||
<p className="text-sm font-medium text-amber-800 mb-1">Pendientes:</p>
|
|
||||||
<p className="text-sm text-amber-700 whitespace-pre-wrap">{evolucion.pendientes}</p>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{evolucionesFiltradas.length === 0 && (
|
|
||||||
<div className="text-center py-12 text-gray-400">
|
<div className="text-center py-12 text-gray-400">
|
||||||
<FileText className="h-16 w-16 mx-auto mb-4 opacity-50" />
|
<FileText className="h-16 w-16 mx-auto mb-4 opacity-50" />
|
||||||
<p className="text-lg">
|
<p className="text-lg">
|
||||||
@@ -560,6 +528,103 @@ return (
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Modal de Detalle de Evolución */}
|
||||||
|
<Dialog open={!!evolucionDetalle} onOpenChange={(open) => { if (!open) setEvolucionDetalle(null); }}>
|
||||||
|
<DialogContent className="sm:max-w-2xl max-h-[90vh] overflow-y-auto">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle className="flex items-center gap-2">
|
||||||
|
<FileText className="h-5 w-5 text-blue-600" />
|
||||||
|
Detalle de Evolución
|
||||||
|
</DialogTitle>
|
||||||
|
</DialogHeader>
|
||||||
|
{evolucionDetalle && (() => {
|
||||||
|
const internacionDet = internaciones.find(i => i.id === evolucionDetalle.internacionId);
|
||||||
|
const pacienteDet = internacionDet ? getPacienteById(internacionDet.pacienteId) : null;
|
||||||
|
const camaDet = internacionDet ? (getCamaById ? getCamaById(internacionDet.camaId) : camas?.find(c => c.id === internacionDet.camaId)) : null;
|
||||||
|
const svDet = evolucionDetalle.signosVitales;
|
||||||
|
const efDet = evolucionDetalle.examenFisico;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-4 text-sm">
|
||||||
|
<div className="flex flex-wrap items-center justify-between gap-2 p-3 bg-muted/40 rounded-lg border">
|
||||||
|
<div>
|
||||||
|
{pacienteDet && (
|
||||||
|
<p className="font-bold text-base text-gray-900 dark:text-white mb-1">
|
||||||
|
{pacienteDet.apellido}, {pacienteDet.nombre} <span className="text-xs font-normal text-muted-foreground">(DNI: {pacienteDet.dni}{camaDet ? ` | Cama: ${camaDet.numero}` : ''})</span>
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
<p className="text-xs text-muted-foreground">
|
||||||
|
<span className="font-medium text-foreground">Fecha:</span> {evolucionDetalle.fecha} | <span className="font-medium text-foreground">Hora:</span> {evolucionDetalle.hora}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="text-right text-xs text-muted-foreground">
|
||||||
|
<p><span className="font-medium text-foreground">Médico:</span> {evolucionDetalle.medico}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Signos Vitales */}
|
||||||
|
{svDet && (
|
||||||
|
<div className="bg-blue-50 dark:bg-blue-950/60 p-3 rounded-lg border border-blue-200 dark:border-blue-800/50">
|
||||||
|
<p className="text-xs font-semibold text-blue-800 dark:text-blue-300 mb-2 flex items-center gap-1.5">
|
||||||
|
<Activity className="h-4 w-4" />
|
||||||
|
Signos Vitales
|
||||||
|
</p>
|
||||||
|
<div className="grid grid-cols-2 sm:grid-cols-3 gap-2 text-xs">
|
||||||
|
<div><span className="font-medium">TAS:</span> {svDet.presionSistolica ?? '-'} mmHg</div>
|
||||||
|
<div><span className="font-medium">TAD:</span> {svDet.presionDiastolica ?? '-'} mmHg</div>
|
||||||
|
<div><span className="font-medium">FC:</span> {svDet.frecuenciaCardiaca ?? '-'} lpm</div>
|
||||||
|
<div><span className="font-medium">FR:</span> {svDet.frecuenciaRespiratoria ?? '-'} rpm</div>
|
||||||
|
<div><span className="font-medium">Tº:</span> {svDet.temperatura !== undefined ? `${svDet.temperatura}°C` : '-'}</div>
|
||||||
|
<div><span className="font-medium">SatO2:</span> {svDet.saturacionO2 !== undefined ? `${svDet.saturacionO2}%` : '-'}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Examen Físico */}
|
||||||
|
{efDet && (
|
||||||
|
<div className="bg-green-50 dark:bg-green-950/60 p-3 rounded-lg border border-green-200 dark:border-green-800/50">
|
||||||
|
<p className="text-xs font-semibold text-green-800 dark:text-green-300 mb-2">Examen Físico:</p>
|
||||||
|
<div className="grid grid-cols-1 sm:grid-cols-2 gap-2 text-xs">
|
||||||
|
{efDet.SNC && <div><span className="font-semibold">SNC:</span> {efDet.SNC}</div>}
|
||||||
|
{efDet.Cardiovascular && <div><span className="font-semibold">Cardiovascular:</span> {efDet.Cardiovascular}</div>}
|
||||||
|
{efDet.Respiratorio && <div><span className="font-semibold">Respiratorio:</span> {efDet.Respiratorio}</div>}
|
||||||
|
{efDet.Abdominal && <div><span className="font-semibold">Abdominal:</span> {efDet.Abdominal}</div>}
|
||||||
|
{efDet.Genitourinario && <div><span className="font-semibold">Genitourinario:</span> {efDet.Genitourinario}</div>}
|
||||||
|
{efDet.PielAnexos && <div><span className="font-semibold">Piel y Anexos:</span> {efDet.PielAnexos}</div>}
|
||||||
|
{efDet.SOMA && <div><span className="font-semibold">SOMA:</span> {efDet.SOMA}</div>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Novedades */}
|
||||||
|
{evolucionDetalle.novedades && (
|
||||||
|
<div className="bg-red-50 dark:bg-red-950/60 p-3 rounded-lg border border-red-200 dark:border-red-800/50">
|
||||||
|
<p className="text-xs font-semibold text-red-800 dark:text-red-300 mb-1">Novedades:</p>
|
||||||
|
<p className="text-xs text-gray-800 dark:text-gray-200 whitespace-pre-wrap">{evolucionDetalle.novedades}</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Comentario */}
|
||||||
|
{evolucionDetalle.comentario && (
|
||||||
|
<div className="bg-slate-100 dark:bg-slate-800/60 p-3 rounded-lg border border-slate-200 dark:border-slate-700/50">
|
||||||
|
<p className="text-xs font-semibold text-slate-800 dark:text-slate-200 mb-1">Comentario:</p>
|
||||||
|
<p className="text-xs text-slate-700 dark:text-slate-300 whitespace-pre-wrap">{evolucionDetalle.comentario}</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Pendientes */}
|
||||||
|
{evolucionDetalle.pendientes && (
|
||||||
|
<div className="bg-amber-50 dark:bg-amber-950/60 p-3 rounded-lg border border-amber-200 dark:border-amber-800/50">
|
||||||
|
<p className="text-xs font-semibold text-amber-800 dark:text-amber-300 mb-1">Pendientes:</p>
|
||||||
|
<p className="text-xs text-amber-700 dark:text-amber-300 whitespace-pre-wrap">{evolucionDetalle.pendientes}</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})()}
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import {
|
|||||||
Save,
|
Save,
|
||||||
X,
|
X,
|
||||||
MoreHorizontal,
|
MoreHorizontal,
|
||||||
|
Eye,
|
||||||
Edit,
|
Edit,
|
||||||
ClipboardList,
|
ClipboardList,
|
||||||
TrendingUp,
|
TrendingUp,
|
||||||
@@ -269,6 +270,7 @@ export function HistoriaClinica({
|
|||||||
canEdit,
|
canEdit,
|
||||||
}: HistoriaClinicaProps) {
|
}: HistoriaClinicaProps) {
|
||||||
const [tabActivo, setTabActivo] = useState('evoluciones');
|
const [tabActivo, setTabActivo] = useState('evoluciones');
|
||||||
|
const indicacionesActivas = (indicadores || []).filter(i => i.estado === 'Activa');
|
||||||
|
|
||||||
|
|
||||||
const calcularEdad = (fechaNacimiento: string) => {
|
const calcularEdad = (fechaNacimiento: string) => {
|
||||||
@@ -544,7 +546,7 @@ export function HistoriaClinica({
|
|||||||
<TabsTrigger value="indicaciones">
|
<TabsTrigger value="indicaciones">
|
||||||
<List className="h-3 w-3 sm:h-4 sm:w-4" />
|
<List className="h-3 w-3 sm:h-4 sm:w-4" />
|
||||||
<span>Indicaciones</span>
|
<span>Indicaciones</span>
|
||||||
|
({indicacionesActivas.length})
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
<TabsTrigger value="glucemias">
|
<TabsTrigger value="glucemias">
|
||||||
<Droplet className="h-3 w-3 sm:h-4 sm:w-4" />
|
<Droplet className="h-3 w-3 sm:h-4 sm:w-4" />
|
||||||
@@ -1755,6 +1757,7 @@ function SeccionEvoluciones({ evos, internacionId, add, update, del, canEdit }:
|
|||||||
}) {
|
}) {
|
||||||
const [dialog, setDialog] = useState(false);
|
const [dialog, setDialog] = useState(false);
|
||||||
const [edit, setEdit] = useState<Evolucion | null>(null);
|
const [edit, setEdit] = useState<Evolucion | null>(null);
|
||||||
|
const [evoDetalle, setEvoDetalle] = useState<Evolucion | null>(null);
|
||||||
const [expanded, setExpanded] = useState<string | null>(null);
|
const [expanded, setExpanded] = useState<string | null>(null);
|
||||||
const [fecha, setFecha] = useState(new Date().toISOString().split('T')[0]);
|
const [fecha, setFecha] = useState(new Date().toISOString().split('T')[0]);
|
||||||
const [hora, setHora] = useState(new Date().toTimeString().slice(0, 5));
|
const [hora, setHora] = useState(new Date().toTimeString().slice(0, 5));
|
||||||
@@ -1900,42 +1903,165 @@ function SeccionEvoluciones({ evos, internacionId, add, update, del, canEdit }:
|
|||||||
<div className="flex justify-end gap-2 mt-4"><Button variant="outline" onClick={() => { reset(); setDialog(false); }}><X className="h-4 w-4 mr-2" />Cancelar</Button><Button onClick={handle} disabled={!medico}><Save className="h-4 w-4 mr-2" />Guardar Evolución</Button></div>
|
<div className="flex justify-end gap-2 mt-4"><Button variant="outline" onClick={() => { reset(); setDialog(false); }}><X className="h-4 w-4 mr-2" />Cancelar</Button><Button onClick={handle} disabled={!medico}><Save className="h-4 w-4 mr-2" />Guardar Evolución</Button></div>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
{evosFiltered.length === 0 ? <div className="text-center py-8 text-gray-400"><FileText className="h-12 w-12 mx-auto mb-2 opacity-50" /><p>No hay evoluciones</p></div> :
|
{evosFiltered.length === 0 ? (
|
||||||
evosFiltered.map(e => {
|
<div className="text-center py-8 text-gray-400">
|
||||||
const isExpanded = expanded === e.id;
|
<FileText className="h-12 w-12 mx-auto mb-2 opacity-50" />
|
||||||
const sv = e.signosVitales;
|
<p>No hay evoluciones</p>
|
||||||
const svText = sv ? [sv.presionSistolica && sv.presionDiastolica ? `PA: ${sv.presionSistolica}/${sv.presionDiastolica}` : null, sv.frecuenciaCardiaca ? `FC: ${sv.frecuenciaCardiaca}` : null, sv.frecuenciaRespiratoria ? `FR: ${sv.frecuenciaRespiratoria}` : null, sv.temperatura ? `T: ${sv.temperatura}°C` : null, sv.saturacionO2 ? `SatO2: ${sv.saturacionO2}%` : null].filter(Boolean).join(' | ') : null;
|
</div>
|
||||||
return (
|
) : (
|
||||||
<Card key={e.id} className="mb-2"><CardContent className="p-4">
|
<div className="rounded-md border overflow-x-auto bg-card">
|
||||||
<div className="flex flex-col gap-3">
|
<Table className="w-full min-w-max text-sm">
|
||||||
<div className="flex items-start justify-between">
|
<TableHeader>
|
||||||
<div><p className="font-medium">{e.fecha} {e.hora}</p><p className="text-sm text-gray-600">Médico: {e.medico}</p></div>
|
<TableRow>
|
||||||
<div className="flex gap-1">
|
<TableHead>Fecha</TableHead>
|
||||||
<Button size="sm" variant="outline" onClick={() => setExpanded(isExpanded ? null : e.id)}>{isExpanded ? <ChevronUp className="h-4 w-4" /> : <ChevronDown className="h-4 w-4" />}</Button>
|
<TableHead>Profesional</TableHead>
|
||||||
{canEdit && <Button size="sm" variant="outline" onClick={() => openEdit(e)}><Pencil /></Button>}
|
<TableHead className="text-center">TAS</TableHead>
|
||||||
{canEdit && <Button size="sm" variant="outline" className="text-red-600" onClick={() => del(e.id)}><Trash2 /></Button>}
|
<TableHead className="text-center">TAD</TableHead>
|
||||||
|
<TableHead className="text-center">FC</TableHead>
|
||||||
|
<TableHead className="text-center">FR</TableHead>
|
||||||
|
<TableHead className="text-center">Tº</TableHead>
|
||||||
|
<TableHead className="text-center">Sat</TableHead>
|
||||||
|
<TableHead className="text-center w-[60px]">Acciones</TableHead>
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
<TableBody>
|
||||||
|
{evosFiltered.map((e) => {
|
||||||
|
const sv = e.signosVitales;
|
||||||
|
return (
|
||||||
|
<TableRow key={e.id} className="hover:bg-muted/50">
|
||||||
|
<TableCell className="whitespace-nowrap font-medium text-xs">
|
||||||
|
{e.fecha} {e.hora || ''}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-xs whitespace-nowrap">
|
||||||
|
{e.medico || '-'}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-center text-xs">{sv?.presionSistolica ?? '-'}</TableCell>
|
||||||
|
<TableCell className="text-center text-xs">{sv?.presionDiastolica ?? '-'}</TableCell>
|
||||||
|
<TableCell className="text-center text-xs">{sv?.frecuenciaCardiaca ?? '-'}</TableCell>
|
||||||
|
<TableCell className="text-center text-xs">{sv?.frecuenciaRespiratoria ?? '-'}</TableCell>
|
||||||
|
<TableCell className="text-center text-xs">{sv?.temperatura !== undefined ? `${sv.temperatura}°C` : '-'}</TableCell>
|
||||||
|
<TableCell className="text-center text-xs">{sv?.saturacionO2 !== undefined ? `${sv.saturacionO2}%` : '-'}</TableCell>
|
||||||
|
<TableCell className="text-center p-1">
|
||||||
|
<DropdownMenu>
|
||||||
|
<DropdownMenuTrigger asChild>
|
||||||
|
<Button size="sm" variant="ghost" className="h-8 w-8 p-0">
|
||||||
|
<MoreHorizontal className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
<DropdownMenuContent align="end">
|
||||||
|
<DropdownMenuItem onClick={() => setEvoDetalle(e)}>
|
||||||
|
<Eye className="mr-2 h-4 w-4" />
|
||||||
|
Detalles
|
||||||
|
</DropdownMenuItem>
|
||||||
|
{canEdit && (
|
||||||
|
<DropdownMenuItem onClick={() => openEdit(e)}>
|
||||||
|
<Pencil className="mr-2 h-4 w-4" />
|
||||||
|
Editar
|
||||||
|
</DropdownMenuItem>
|
||||||
|
)}
|
||||||
|
{canEdit && (
|
||||||
|
<DropdownMenuItem onClick={() => del(e.id)} className="text-red-600 focus:text-red-600">
|
||||||
|
<Trash2 className="mr-2 h-4 w-4" />
|
||||||
|
Eliminar
|
||||||
|
</DropdownMenuItem>
|
||||||
|
)}
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Modal Detalles Evolucion */}
|
||||||
|
<Dialog open={!!evoDetalle} onOpenChange={(open) => { if (!open) setEvoDetalle(null); }}>
|
||||||
|
<DialogContent className="sm:max-w-2xl max-h-[90vh] overflow-y-auto">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle className="flex items-center gap-2">
|
||||||
|
<FileText className="h-5 w-5 text-blue-600" />
|
||||||
|
Detalle de Evolución
|
||||||
|
</DialogTitle>
|
||||||
|
</DialogHeader>
|
||||||
|
{evoDetalle && (() => {
|
||||||
|
const svDet = evoDetalle.signosVitales;
|
||||||
|
const efDet = evoDetalle.examenFisico;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-4 text-sm">
|
||||||
|
<div className="flex flex-wrap items-center justify-between gap-2 p-3 bg-muted/40 rounded-lg border">
|
||||||
|
<div className="text-xs text-muted-foreground">
|
||||||
|
<p><span className="font-medium text-foreground">Fecha:</span> {evoDetalle.fecha} | <span className="font-medium text-foreground">Hora:</span> {evoDetalle.hora}</p>
|
||||||
|
</div>
|
||||||
|
<div className="text-right text-xs text-muted-foreground">
|
||||||
|
<p><span className="font-medium text-foreground">Médico:</span> {evoDetalle.medico}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{svText && <div className="bg-blue-50 dark:bg-blue-950/60 p-2 rounded-lg border border-transparent dark:border-blue-800/50"><p className="text-sm font-medium text-blue-800 dark:text-blue-300 flex items-center gap-2"><Activity className="h-4 w-4" />Signos Vitales: {svText}</p></div>}
|
|
||||||
{isExpanded && <>
|
{/* Signos Vitales */}
|
||||||
{e.examenFisico && <div className="bg-green-50 dark:bg-green-950/60 p-3 rounded-lg border border-green-200 dark:border-green-800/50"><p className="text-sm font-medium text-green-800 dark:text-green-300 mb-2">Examen Físico:</p><div className="grid grid-cols-2 sm:grid-cols-4 gap-2 text-xs">
|
{svDet && (
|
||||||
{e.examenFisico.SNC && <div><span className="font-medium">SNC:</span> {e.examenFisico.SNC}</div>}
|
<div className="bg-blue-50 dark:bg-blue-950/60 p-3 rounded-lg border border-blue-200 dark:border-blue-800/50">
|
||||||
{e.examenFisico.Cardiovascular && <div><span className="font-medium">CV:</span> {e.examenFisico.Cardiovascular}</div>}
|
<p className="text-xs font-semibold text-blue-800 dark:text-blue-300 mb-2 flex items-center gap-1.5">
|
||||||
{e.examenFisico.Respiratorio && <div><span className="font-medium">Resp:</span> {e.examenFisico.Respiratorio}</div>}
|
<Activity className="h-4 w-4" />
|
||||||
{e.examenFisico.Abdominal && <div><span className="font-medium">Abd:</span> {e.examenFisico.Abdominal}</div>}
|
Signos Vitales
|
||||||
{e.examenFisico.Genitourinario && <div><span className="font-medium">GU:</span> {e.examenFisico.Genitourinario}</div>}
|
</p>
|
||||||
{e.examenFisico.PielAnexos && <div><span className="font-medium">Piel:</span> {e.examenFisico.PielAnexos}</div>}
|
<div className="grid grid-cols-2 sm:grid-cols-3 gap-2 text-xs">
|
||||||
{e.examenFisico.SOMA && <div><span className="font-medium">SOMA:</span> {e.examenFisico.SOMA}</div>}
|
<div><span className="font-medium">TAS:</span> {svDet.presionSistolica ?? '-'} mmHg</div>
|
||||||
</div></div>}
|
<div><span className="font-medium">TAD:</span> {svDet.presionDiastolica ?? '-'} mmHg</div>
|
||||||
{e.novedades && <div className="bg-red-50 dark:bg-red-950/60 p-3 rounded-lg border border-red-200 dark:border-red-800/50 mt-3"><p className="text-sm font-medium text-red-800 dark:text-red-300 mb-1">Novedades:</p><p className="text-sm text-gray-800 dark:text-gray-200 whitespace-pre-wrap">{e.novedades}</p></div>}
|
<div><span className="font-medium">FC:</span> {svDet.frecuenciaCardiaca ?? '-'} lpm</div>
|
||||||
{e.comentario && <div><p className="text-sm font-medium text-gray-700 dark:text-gray-300">Comentario:</p><p className="text-sm text-gray-600 dark:text-gray-400 whitespace-pre-wrap">{e.comentario}</p></div>}
|
<div><span className="font-medium">FR:</span> {svDet.frecuenciaRespiratoria ?? '-'} rpm</div>
|
||||||
{e.pendientes && <div className="bg-amber-50 dark:bg-amber-950/60 p-3 rounded-lg border border-amber-200 dark:border-amber-800/50"><p className="text-sm font-medium text-amber-800 dark:text-amber-300 mb-1">Pendientes:</p><p className="text-sm text-amber-700 dark:text-amber-300 whitespace-pre-wrap">{e.pendientes}</p></div>}
|
<div><span className="font-medium">Tº:</span> {svDet.temperatura !== undefined ? `${svDet.temperatura}°C` : '-'}</div>
|
||||||
</>}
|
<div><span className="font-medium">SatO2:</span> {svDet.saturacionO2 !== undefined ? `${svDet.saturacionO2}%` : '-'}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Examen Físico */}
|
||||||
|
{efDet && (
|
||||||
|
<div className="bg-green-50 dark:bg-green-950/60 p-3 rounded-lg border border-green-200 dark:border-green-800/50">
|
||||||
|
<p className="text-xs font-semibold text-green-800 dark:text-green-300 mb-2">Examen Físico:</p>
|
||||||
|
<div className="grid grid-cols-1 sm:grid-cols-2 gap-2 text-xs">
|
||||||
|
{efDet.SNC && <div><span className="font-semibold">SNC:</span> {efDet.SNC}</div>}
|
||||||
|
{efDet.Cardiovascular && <div><span className="font-semibold">Cardiovascular:</span> {efDet.Cardiovascular}</div>}
|
||||||
|
{efDet.Respiratorio && <div><span className="font-semibold">Respiratorio:</span> {efDet.Respiratorio}</div>}
|
||||||
|
{efDet.Abdominal && <div><span className="font-semibold">Abdominal:</span> {efDet.Abdominal}</div>}
|
||||||
|
{efDet.Genitourinario && <div><span className="font-semibold">Genitourinario:</span> {efDet.Genitourinario}</div>}
|
||||||
|
{efDet.PielAnexos && <div><span className="font-semibold">Piel y Anexos:</span> {efDet.PielAnexos}</div>}
|
||||||
|
{efDet.SOMA && <div><span className="font-semibold">SOMA:</span> {efDet.SOMA}</div>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Novedades */}
|
||||||
|
{evoDetalle.novedades && (
|
||||||
|
<div className="bg-red-50 dark:bg-red-950/60 p-3 rounded-lg border border-red-200 dark:border-red-800/50">
|
||||||
|
<p className="text-xs font-semibold text-red-800 dark:text-red-300 mb-1">Novedades:</p>
|
||||||
|
<p className="text-xs text-gray-800 dark:text-gray-200 whitespace-pre-wrap">{evoDetalle.novedades}</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Comentario */}
|
||||||
|
{evoDetalle.comentario && (
|
||||||
|
<div className="bg-slate-100 dark:bg-slate-800/60 p-3 rounded-lg border border-slate-200 dark:border-slate-700/50">
|
||||||
|
<p className="text-xs font-semibold text-slate-800 dark:text-slate-200 mb-1">Comentario:</p>
|
||||||
|
<p className="text-xs text-slate-700 dark:text-slate-300 whitespace-pre-wrap">{evoDetalle.comentario}</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Pendientes */}
|
||||||
|
{evoDetalle.pendientes && (
|
||||||
|
<div className="bg-amber-50 dark:bg-amber-950/60 p-3 rounded-lg border border-amber-200 dark:border-amber-800/50">
|
||||||
|
<p className="text-xs font-semibold text-amber-800 dark:text-amber-300 mb-1">Pendientes:</p>
|
||||||
|
<p className="text-xs text-amber-700 dark:text-amber-300 whitespace-pre-wrap">{evoDetalle.pendientes}</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</CardContent></Card>
|
);
|
||||||
);
|
})()}
|
||||||
})
|
</DialogContent>
|
||||||
}
|
</Dialog>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+205
-148
@@ -1,5 +1,5 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { ClipboardList, Plus, Search, Bed, Calendar, Stethoscope, LogOut, CheckCircle2 } from 'lucide-react';
|
import { ClipboardList, Plus, Search, LogOut, CheckCircle2, MoreHorizontal, FileText } from 'lucide-react';
|
||||||
import { Card, CardContent } from '@/components/ui/card';
|
import { Card, CardContent } from '@/components/ui/card';
|
||||||
import { Badge } from '@/components/ui/badge';
|
import { Badge } from '@/components/ui/badge';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
@@ -7,6 +7,8 @@ import { Input } from '@/components/ui/input';
|
|||||||
import { Label } from '@/components/ui/label';
|
import { Label } from '@/components/ui/label';
|
||||||
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog';
|
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog';
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
||||||
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
|
||||||
|
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@/components/ui/dropdown-menu';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import type { Internacion, Paciente, Cama, Area, Evolucion, Laboratorio, Cultivo } from '@/types';
|
import type { Internacion, Paciente, Cama, Area, Evolucion, Laboratorio, Cultivo } from '@/types';
|
||||||
import { formatDateDDMMYYYY } from '@/lib/utils';
|
import { formatDateDDMMYYYY } from '@/lib/utils';
|
||||||
@@ -165,6 +167,44 @@ export function Internaciones({
|
|||||||
|
|
||||||
const getAreaName = (areaId?: string) => areas.find(a => a.id === areaId)?.nombre;
|
const getAreaName = (areaId?: string) => areas.find(a => a.id === areaId)?.nombre;
|
||||||
|
|
||||||
|
const calcularEdad = (fechaNacimiento?: string) => {
|
||||||
|
if (!fechaNacimiento) return '-';
|
||||||
|
const hoy = new Date();
|
||||||
|
const nacimiento = new Date(fechaNacimiento);
|
||||||
|
if (isNaN(nacimiento.getTime())) return '-';
|
||||||
|
let edad = hoy.getFullYear() - nacimiento.getFullYear();
|
||||||
|
const m = hoy.getMonth() - nacimiento.getMonth();
|
||||||
|
if (m < 0 || (m === 0 && hoy.getDate() < nacimiento.getDate())) {
|
||||||
|
edad--;
|
||||||
|
}
|
||||||
|
return edad >= 0 ? `${edad} años` : '-';
|
||||||
|
};
|
||||||
|
|
||||||
|
const calcularDiasDuracion = (internacion: Internacion) => {
|
||||||
|
const fechaStr = internacion.fechaIngresoClinica || internacion.fechaIngreso;
|
||||||
|
if (!fechaStr) return null;
|
||||||
|
|
||||||
|
const hoy = new Date();
|
||||||
|
let fechaFin = hoy;
|
||||||
|
|
||||||
|
if (!internacion.activa && internacion.fechaEgreso) {
|
||||||
|
const egreso = new Date(internacion.fechaEgreso.includes('T') ? internacion.fechaEgreso : `${internacion.fechaEgreso}T00:00:00`);
|
||||||
|
if (!isNaN(egreso.getTime())) {
|
||||||
|
fechaFin = egreso;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ingreso = new Date(fechaStr.includes('T') ? fechaStr : `${fechaStr}T00:00:00`);
|
||||||
|
if (isNaN(ingreso.getTime())) return null;
|
||||||
|
|
||||||
|
const inicioD = new Date(ingreso.getFullYear(), ingreso.getMonth(), ingreso.getDate());
|
||||||
|
const finD = new Date(fechaFin.getFullYear(), fechaFin.getMonth(), fechaFin.getDate());
|
||||||
|
|
||||||
|
const diffMs = finD.getTime() - inicioD.getTime();
|
||||||
|
const dias = Math.floor(diffMs / (1000 * 60 * 60 * 24));
|
||||||
|
return dias < 0 ? 0 : dias;
|
||||||
|
};
|
||||||
|
|
||||||
const abrirDialogoEgreso = (internacion: Internacion) => {
|
const abrirDialogoEgreso = (internacion: Internacion) => {
|
||||||
setInternacionSeleccionada(internacion);
|
setInternacionSeleccionada(internacion);
|
||||||
setFechaEgreso(new Date().toISOString().split('T')[0]);
|
setFechaEgreso(new Date().toISOString().split('T')[0]);
|
||||||
@@ -351,153 +391,8 @@ export function Internaciones({
|
|||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
{/* Lista de Internaciones */}
|
{/* Lista de Internaciones en Tabla */}
|
||||||
<div className="space-y-4">
|
{internacionesFiltradas.length === 0 ? (
|
||||||
{internacionesFiltradas.map((internacion) => {
|
|
||||||
const paciente = getPacienteById(internacion.pacienteId);
|
|
||||||
const cama = getCamaById(internacion.camaId);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Card key={internacion.id} className="hover:shadow-md transition-shadow">
|
|
||||||
<CardContent className="p-4">
|
|
||||||
<div className="flex flex-col lg:flex-row lg:items-start lg:justify-between gap-4">
|
|
||||||
<div className="flex items-start gap-4">
|
|
||||||
<div className={`h-12 w-12 rounded-full flex items-center justify-center flex-shrink-0 ${internacion.activa ? 'bg-purple-100' : 'bg-gray-100'
|
|
||||||
}`}>
|
|
||||||
{internacion.activa ? (
|
|
||||||
<ClipboardList className="h-6 w-6 text-purple-600" />
|
|
||||||
) : (
|
|
||||||
<CheckCircle2 className="h-6 w-6 text-gray-600" />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div className="flex items-center gap-2 flex-wrap">
|
|
||||||
<h3 className="font-bold text-lg">
|
|
||||||
{paciente ? `${paciente.apellido}, ${paciente.nombre}` : 'Paciente no encontrado'}
|
|
||||||
</h3>
|
|
||||||
<Badge className={internacion.activa ? 'bg-purple-100 text-purple-800' : 'bg-gray-100 text-gray-800'}>
|
|
||||||
{internacion.activa ? 'Activa' : 'Finalizada'}
|
|
||||||
</Badge>
|
|
||||||
</div>
|
|
||||||
<div className="grid grid-cols-2 sm:grid-cols-3 gap-x-4 gap-y-2 mt-3 text-sm">
|
|
||||||
<div className="flex items-center gap-2 text-gray-600">
|
|
||||||
<Bed className="h-4 w-4" />
|
|
||||||
<span>Cama {cama?.numero || '-'} ({getAreaName(cama?.areaId) || 'Sin área'})
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center gap-2 text-gray-600">
|
|
||||||
<Calendar className="h-4 w-4" />
|
|
||||||
<span>Ingreso: {internacion.fechaIngresoClinica ? formatDateDDMMYYYY(internacion.fechaIngresoClinica) : 'N/A'}</span>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center gap-2 text-gray-600">
|
|
||||||
<Stethoscope className="h-4 w-4" />
|
|
||||||
<span className="truncate">{internacion.medicoIngresante}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="mt-2">
|
|
||||||
<p className="text-sm text-gray-600">
|
|
||||||
<span className="font-medium">Diagnóstico de ingreso:</span>{' '}
|
|
||||||
{internacion.diagnosticoIngreso}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
{!internacion.activa && internacion.fechaEgreso && (
|
|
||||||
<div className="mt-2 space-y-1">
|
|
||||||
<div className="flex items-center gap-2 text-sm text-gray-600">
|
|
||||||
<LogOut className="h-4 w-4" />
|
|
||||||
<span>Egreso: {internacion.fechaEgreso}</span>
|
|
||||||
</div>
|
|
||||||
<p className="text-sm text-gray-600">
|
|
||||||
<span className="font-medium">Diagnóstico de egreso:</span>{' '}
|
|
||||||
{internacion.diagnosticoEgreso}
|
|
||||||
</p>
|
|
||||||
<p className="text-sm text-gray-600">
|
|
||||||
<span className="font-medium">Motivo:</span>{' '}
|
|
||||||
{internacion.motivoEgreso}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
{internacion.activa && (
|
|
||||||
<Dialog open={dialogoEgresoAbierto && internacionSeleccionada?.id === internacion.id} onOpenChange={setDialogoEgresoAbierto}>
|
|
||||||
<DialogTrigger asChild>
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
className="whitespace-nowrap"
|
|
||||||
onClick={() => abrirDialogoEgreso(internacion)}
|
|
||||||
>
|
|
||||||
<LogOut className="h-4 w-4 mr-2" />
|
|
||||||
Registrar Egreso
|
|
||||||
</Button>
|
|
||||||
</DialogTrigger>
|
|
||||||
<DialogContent className="sm:max-w-lg">
|
|
||||||
<DialogHeader>
|
|
||||||
<DialogTitle>Dar Alta</DialogTitle>
|
|
||||||
</DialogHeader>
|
|
||||||
<div className="space-y-4">
|
|
||||||
<div>
|
|
||||||
<Label>Paciente</Label>
|
|
||||||
<Input
|
|
||||||
value={paciente ? `${paciente.apellido}, ${paciente.nombre}` : ''}
|
|
||||||
disabled
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<Label>Fecha de Egreso *</Label>
|
|
||||||
<Input
|
|
||||||
type="date"
|
|
||||||
value={fechaEgreso}
|
|
||||||
onChange={(e) => setFechaEgreso(e.target.value)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<Label>Motivo de Egreso *</Label>
|
|
||||||
<Select value={motivoEgreso} onValueChange={(v) => setMotivoEgreso(v as Internacion['motivoEgreso'])}>
|
|
||||||
<SelectTrigger>
|
|
||||||
<SelectValue />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
<SelectItem value="Alta médica">Alta médica</SelectItem>
|
|
||||||
<SelectItem value="Alta voluntaria">Alta voluntaria</SelectItem>
|
|
||||||
<SelectItem value="Derivación">Derivación</SelectItem>
|
|
||||||
<SelectItem value="Fallecimiento">Fallecimiento</SelectItem>
|
|
||||||
<SelectItem value="Otro">Otro</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<Label>Diagnóstico de Egreso *</Label>
|
|
||||||
<textarea
|
|
||||||
className="w-full p-2 border rounded-md text-sm min-h-[80px]"
|
|
||||||
value={diagnosticoEgreso}
|
|
||||||
onChange={(e) => setDiagnosticoEgreso(e.target.value)}
|
|
||||||
placeholder="Ingrese el diagnóstico de egreso..."
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<Button variant="outline"
|
|
||||||
className="w-full"
|
|
||||||
onClick={handleFinalizarInternacion}
|
|
||||||
disabled={!fechaEgreso || !diagnosticoEgreso || !motivoEgreso}
|
|
||||||
>
|
|
||||||
<CheckCircle2 className="h-4 w-4 mr-2" />
|
|
||||||
Confirmar Egreso
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</DialogContent>
|
|
||||||
</Dialog>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Button variant="outline" onClick={() => { if (typeof onVerHC === 'function') onVerHC(internacion.id); }}>Ver HC</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{internacionesFiltradas.length === 0 && (
|
|
||||||
<div className="text-center py-12 text-gray-400">
|
<div className="text-center py-12 text-gray-400">
|
||||||
<ClipboardList className="h-16 w-16 mx-auto mb-4 opacity-50" />
|
<ClipboardList className="h-16 w-16 mx-auto mb-4 opacity-50" />
|
||||||
<p className="text-lg">
|
<p className="text-lg">
|
||||||
@@ -506,7 +401,169 @@ export function Internaciones({
|
|||||||
: 'No hay internaciones registradas'}
|
: 'No hay internaciones registradas'}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="rounded-md border overflow-x-auto bg-card">
|
||||||
|
<Table className="w-full min-w-max text-sm">
|
||||||
|
<TableHeader>
|
||||||
|
<TableRow>
|
||||||
|
<TableHead>Cama</TableHead>
|
||||||
|
<TableHead>Apellido</TableHead>
|
||||||
|
<TableHead>Nombre</TableHead>
|
||||||
|
<TableHead className="text-center">Edad</TableHead>
|
||||||
|
<TableHead className="text-center">DNI</TableHead>
|
||||||
|
<TableHead className="text-center">Estado</TableHead>
|
||||||
|
<TableHead className="text-center">Fecha Ingreso</TableHead>
|
||||||
|
<TableHead className="text-center">Duración</TableHead>
|
||||||
|
<TableHead className="text-center w-[60px]">Acciones</TableHead>
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
<TableBody>
|
||||||
|
{internacionesFiltradas.map((internacion) => {
|
||||||
|
const paciente = getPacienteById(internacion.pacienteId);
|
||||||
|
const cama = getCamaById(internacion.camaId);
|
||||||
|
const fechaIng = internacion.fechaIngresoClinica
|
||||||
|
? formatDateDDMMYYYY(internacion.fechaIngresoClinica)
|
||||||
|
: (internacion.fechaIngreso ? formatDateDDMMYYYY(internacion.fechaIngreso) : '-');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TableRow key={internacion.id} className="hover:bg-muted/50">
|
||||||
|
<TableCell className="font-medium text-xs whitespace-nowrap">
|
||||||
|
{cama ? cama.numero : '-'}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-xs font-medium whitespace-nowrap">
|
||||||
|
{paciente?.apellido || '-'}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-xs font-medium whitespace-nowrap">
|
||||||
|
{paciente?.nombre || '-'}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-center text-xs whitespace-nowrap">
|
||||||
|
{calcularEdad(paciente?.fechaNacimiento)}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-center text-xs whitespace-nowrap font-mono">
|
||||||
|
{paciente?.dni || '-'}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-center">
|
||||||
|
{internacion.activa ? (
|
||||||
|
<Badge className="bg-purple-100 text-purple-800 dark:bg-purple-950/80 dark:text-purple-300 border-purple-200 hover:bg-purple-100">
|
||||||
|
Activa
|
||||||
|
</Badge>
|
||||||
|
) : (
|
||||||
|
<Badge variant="outline" className="bg-gray-100 text-gray-700 dark:bg-gray-800 dark:text-gray-300 border-gray-300">
|
||||||
|
Alta
|
||||||
|
</Badge>
|
||||||
|
)}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-center text-xs whitespace-nowrap">
|
||||||
|
{fechaIng}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-center text-xs whitespace-nowrap">
|
||||||
|
{(() => {
|
||||||
|
const dias = calcularDiasDuracion(internacion);
|
||||||
|
if (dias === null) return '-';
|
||||||
|
const esMenorOIgual10 = dias <= 10;
|
||||||
|
return (
|
||||||
|
<Badge
|
||||||
|
className={
|
||||||
|
esMenorOIgual10
|
||||||
|
? 'bg-emerald-100 text-emerald-800 dark:bg-emerald-950/80 dark:text-emerald-300 border-emerald-200 hover:bg-emerald-100'
|
||||||
|
: 'bg-red-100 text-red-800 dark:bg-red-950/80 dark:text-red-300 border-red-200 hover:bg-red-100'
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{dias} {dias === 1 ? 'día' : 'días'}
|
||||||
|
</Badge>
|
||||||
|
);
|
||||||
|
})()}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-center p-1">
|
||||||
|
<DropdownMenu>
|
||||||
|
<DropdownMenuTrigger asChild>
|
||||||
|
<Button size="sm" variant="ghost" className="h-8 w-8 p-0">
|
||||||
|
<MoreHorizontal className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
<DropdownMenuContent align="end">
|
||||||
|
<DropdownMenuItem onClick={() => { if (typeof onVerHC === 'function') onVerHC(internacion.id); }}>
|
||||||
|
<FileText className="mr-2 h-4 w-4" />
|
||||||
|
Ver HC
|
||||||
|
</DropdownMenuItem>
|
||||||
|
{internacion.activa && (
|
||||||
|
<DropdownMenuItem onClick={() => abrirDialogoEgreso(internacion)}>
|
||||||
|
<LogOut className="mr-2 h-4 w-4" />
|
||||||
|
Registrar Egreso
|
||||||
|
</DropdownMenuItem>
|
||||||
|
)}
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Modal Registrar Egreso */}
|
||||||
|
<Dialog open={dialogoEgresoAbierto} onOpenChange={(open) => { if (!open) resetFormularioEgreso(); setDialogoEgresoAbierto(open); }}>
|
||||||
|
<DialogContent className="sm:max-w-lg">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Dar Alta</DialogTitle>
|
||||||
|
</DialogHeader>
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div>
|
||||||
|
<Label>Paciente</Label>
|
||||||
|
<Input
|
||||||
|
value={(() => {
|
||||||
|
if (!internacionSeleccionada) return '';
|
||||||
|
const p = getPacienteById(internacionSeleccionada.pacienteId);
|
||||||
|
return p ? `${p.apellido}, ${p.nombre}` : '';
|
||||||
|
})()}
|
||||||
|
disabled
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Label>Fecha de Egreso *</Label>
|
||||||
|
<Input
|
||||||
|
type="date"
|
||||||
|
value={fechaEgreso}
|
||||||
|
onChange={(e) => setFechaEgreso(e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Label>Motivo de Egreso *</Label>
|
||||||
|
<Select value={motivoEgreso} onValueChange={(v) => setMotivoEgreso(v as Internacion['motivoEgreso'])}>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="Alta médica">Alta médica</SelectItem>
|
||||||
|
<SelectItem value="Alta voluntaria">Alta voluntaria</SelectItem>
|
||||||
|
<SelectItem value="Derivación">Derivación</SelectItem>
|
||||||
|
<SelectItem value="Fallecimiento">Fallecimiento</SelectItem>
|
||||||
|
<SelectItem value="Otro">Otro</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Label>Diagnóstico de Egreso *</Label>
|
||||||
|
<textarea
|
||||||
|
className="w-full p-2 border rounded-md text-sm min-h-[80px]"
|
||||||
|
value={diagnosticoEgreso}
|
||||||
|
onChange={(e) => setDiagnosticoEgreso(e.target.value)}
|
||||||
|
placeholder="Ingrese el diagnóstico de egreso..."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Button variant="outline"
|
||||||
|
className="w-full"
|
||||||
|
onClick={handleFinalizarInternacion}
|
||||||
|
disabled={!fechaEgreso || !diagnosticoEgreso || !motivoEgreso}
|
||||||
|
>
|
||||||
|
<CheckCircle2 className="h-4 w-4 mr-2" />
|
||||||
|
Confirmar Egreso
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
{/* Historia Clínica ahora es una página separada */}
|
{/* Historia Clínica ahora es una página separada */}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -255,12 +255,12 @@ export function SeccionIndicaciones({ recomendaciones, internacionId, pacienteId
|
|||||||
const activas = indsFilter.filter(ind => ind.estado === 'Activa');
|
const activas = indsFilter.filter(ind => ind.estado === 'Activa');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-2.5">
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between items-center">
|
||||||
{canEdit && <Button variant="outline" onClick={() => { reset(); setDialog(true); }}>
|
{canEdit && <Button size="sm" variant="outline" onClick={() => { reset(); setDialog(true); }}>
|
||||||
<Plus className="h-4 w-4 mr-2" />Nueva Indicación
|
<Plus className="h-4 w-4 mr-1.5" />Nueva Indicación
|
||||||
</Button>}
|
</Button>}
|
||||||
<Button variant="ghost" onClick={() => setShowHistorial(!showHistorial)}>
|
<Button size="sm" variant="ghost" onClick={() => setShowHistorial(!showHistorial)}>
|
||||||
{showHistorial ? 'Ocultar Historial' : `Ver Historial (${movs.length})`}
|
{showHistorial ? 'Ocultar Historial' : `Ver Historial (${movs.length})`}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
@@ -362,52 +362,52 @@ export function SeccionIndicaciones({ recomendaciones, internacionId, pacienteId
|
|||||||
</Dialog>
|
</Dialog>
|
||||||
|
|
||||||
{activas.length === 0 ? (
|
{activas.length === 0 ? (
|
||||||
<div className="text-center py-8 text-gray-500">No hay indicaciones activas</div>
|
<div className="text-center py-6 text-gray-500 text-sm">No hay indicaciones activas</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="space-y-2">
|
<div className="space-y-1.5">
|
||||||
{activas.map(ind => (
|
{activas.map(ind => (
|
||||||
<Card key={ind.id}>
|
<Card key={ind.id}>
|
||||||
<CardContent className="p-4 flex flex-col sm:flex-row sm:items-center justify-between gap-4">
|
<CardContent className="py-2 px-3 flex flex-col sm:flex-row sm:items-center justify-between gap-2">
|
||||||
<div className="flex-1">
|
<div className="flex-1 min-w-0">
|
||||||
<div className="flex items-center gap-2 mb-1">
|
<div className="flex items-center gap-1.5 mb-0.5">
|
||||||
<Badge variant="outline">{ind.tipo}</Badge>
|
<Badge variant="outline" className="text-xs py-0 px-1.5 h-5">{ind.tipo}</Badge>
|
||||||
{ind.medicoCrea && <span className="text-xs text-gray-500">Dr: {ind.medicoCrea}</span>}
|
{ind.medicoCrea && <span className="text-xs text-muted-foreground">Dr: {ind.medicoCrea}</span>}
|
||||||
</div>
|
</div>
|
||||||
{ind.tipo === 'Farmacologica' && (
|
{ind.tipo === 'Farmacologica' && (
|
||||||
<div className="font-medium">{ind.droga} {ind.dosis} {ind.frecuenciaHoras ? `c/${ind.frecuenciaHoras}hs` : ''} {ind.via}</div>
|
<div className="font-medium text-sm leading-tight">{ind.droga} {ind.dosis} {ind.frecuenciaHoras ? `c/${ind.frecuenciaHoras}hs` : ''} {ind.via}</div>
|
||||||
)}
|
)}
|
||||||
{ind.tipo === 'Farmacologica Antibiótico' && (
|
{ind.tipo === 'Farmacologica Antibiótico' && (
|
||||||
<div className="font-medium">{ind.droga} {ind.dosis} {ind.frecuenciaHoras ? `c/${ind.frecuenciaHoras}hs` : ''} {ind.via} <Badge className="ml-2 bg-purple-100 text-purple-800 dark:bg-purple-950 dark:text-purple-300 hover:bg-purple-100">Antibiótico</Badge></div>
|
<div className="font-medium text-sm leading-tight">{ind.droga} {ind.dosis} {ind.frecuenciaHoras ? `c/${ind.frecuenciaHoras}hs` : ''} {ind.via} <Badge className="ml-1.5 py-0 px-1.5 h-5 text-xs bg-purple-100 text-purple-800 dark:bg-purple-950 dark:text-purple-300 hover:bg-purple-100">Antibiótico</Badge></div>
|
||||||
)}
|
)}
|
||||||
{ind.tipo === 'Farmacologica Profilactica' && (
|
{ind.tipo === 'Farmacologica Profilactica' && (
|
||||||
<div className="font-medium">{ind.droga} {ind.dosis} {ind.frecuenciaHoras ? `c/${ind.frecuenciaHoras}hs` : ''} {ind.via}</div>
|
<div className="font-medium text-sm leading-tight">{ind.droga} {ind.dosis} {ind.frecuenciaHoras ? `c/${ind.frecuenciaHoras}hs` : ''} {ind.via}</div>
|
||||||
)}
|
)}
|
||||||
{ind.tipo === 'Farmacologica Insulina' && (
|
{ind.tipo === 'Farmacologica Insulina' && (
|
||||||
<div className="font-medium">{ind.tipoInsulina}
|
<div className="font-medium text-sm leading-tight">{ind.tipoInsulina}
|
||||||
{ind.unidadesDesayuno && ` - PreDesayuno: ${ind.unidadesDesayuno}U`}
|
{ind.unidadesDesayuno && ` - PreDesayuno: ${ind.unidadesDesayuno}U`}
|
||||||
{ind.unidadesAlmuerzo && ` - PreAlmuerzo: ${ind.unidadesAlmuerzo}U`}
|
{ind.unidadesAlmuerzo && ` - PreAlmuerzo: ${ind.unidadesAlmuerzo}U`}
|
||||||
{ind.unidadesNoche && ` - 23hs: ${ind.unidadesNoche}U`}
|
{ind.unidadesNoche && ` - 23hs: ${ind.unidadesNoche}U`}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{ind.tipo === 'No Farmacologica' && (
|
{ind.tipo === 'No Farmacologica' && (
|
||||||
<div className="font-medium">{ind.indicacionNoFco}</div>
|
<div className="font-medium text-sm leading-tight">{ind.indicacionNoFco}</div>
|
||||||
)}
|
)}
|
||||||
{(ind.tipo === 'PHP' || ind.tipo === 'PHP Paralelo') && (
|
{(ind.tipo === 'PHP' || ind.tipo === 'PHP Paralelo') && (
|
||||||
<div className="font-medium">{ind.tipoPlan} {ind.cantidadMl}ml en {ind.tiempoHoras}hs</div>
|
<div className="font-medium text-sm leading-tight">{ind.tipoPlan} {ind.cantidadMl}ml en {ind.tiempoHoras}hs</div>
|
||||||
)}
|
)}
|
||||||
{ind.tipo === 'PHP 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 className="font-medium text-sm leading-tight">{ind.tipoPlan} {ind.cantidadMl}ml + {ind.tipoPlan2} {ind.cantidadMl2}ml en {ind.tiempoHoras}hs</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-1">
|
<div className="flex gap-1 shrink-0">
|
||||||
{canEdit && <Button size="sm" variant="outline" title="Editar" onClick={() => loadEdit(ind)}>
|
{canEdit && <Button size="sm" variant="outline" className="h-7 w-7 p-0" title="Editar" onClick={() => loadEdit(ind)}>
|
||||||
<Pencil className="h-4 w-4" />
|
<Pencil className="h-3.5 w-3.5" />
|
||||||
</Button>}
|
</Button>}
|
||||||
{canEdit && <Button size="sm" variant="outline" className="text-red-600 hover:text-red-700 hover:bg-red-50 dark:hover:bg-red-950/30" title="Eliminar" onClick={() => {
|
{canEdit && <Button size="sm" variant="outline" className="h-7 w-7 p-0 text-red-600 hover:text-red-700 hover:bg-red-50 dark:hover:bg-red-950/30" title="Eliminar" onClick={() => {
|
||||||
setDeleteConfirmInd(ind);
|
setDeleteConfirmInd(ind);
|
||||||
setDeleteMedico(ind.medicoCrea || '');
|
setDeleteMedico(ind.medicoCrea || '');
|
||||||
}}>
|
}}>
|
||||||
<Trash2 className="h-4 w-4" />
|
<Trash2 className="h-3.5 w-3.5" />
|
||||||
</Button>}
|
</Button>}
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|||||||
Reference in New Issue
Block a user