Fix: Organizacion de Editar Ingreso igual a Nuevo Ingreso, corregido formato de fecha
This commit is contained in:
@@ -210,7 +210,7 @@ export function Dashboard({
|
||||
{paciente ? `${paciente.apellido}, ${paciente.nombre}` : 'Paciente no encontrado'}
|
||||
</p>
|
||||
<p className="text-sm text-gray-500">
|
||||
Ingreso: {formatDateDDMMYYYY(internacion.fechaIngreso)}
|
||||
Ingreso: {internacion.fechaIngresoClinica ? formatDateDDMMYYYY(internacion.fechaIngresoClinica) : 'N/A'}
|
||||
</p>
|
||||
</div>
|
||||
<Badge variant="outline" className="bg-purple-50 text-purple-700">
|
||||
|
||||
@@ -0,0 +1,323 @@
|
||||
import { useState } from 'react';
|
||||
import { ArrowLeft, Save, X, Bed, Calendar, Stethoscope, User, ClipboardList } from 'lucide-react';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import type { Paciente, Cama, Area, Internacion } from '@/types';
|
||||
|
||||
interface EditIngresoProps {
|
||||
internacion: Internacion;
|
||||
paciente: Paciente;
|
||||
cama: Cama | undefined;
|
||||
pacientes: Paciente[];
|
||||
camas: Cama[];
|
||||
areas: Area[];
|
||||
onActualizarInternacion: (id: string, datos: Partial<Internacion>) => void;
|
||||
onVolver: () => void;
|
||||
getAreaName: (areaId: string | undefined) => string;
|
||||
}
|
||||
|
||||
export function EditIngreso({
|
||||
internacion,
|
||||
paciente: pacienteOriginal,
|
||||
cama: camaOriginal,
|
||||
pacientes,
|
||||
camas,
|
||||
areas,
|
||||
onActualizarInternacion,
|
||||
onVolver,
|
||||
getAreaName
|
||||
}: EditIngresoProps) {
|
||||
const [pacienteSeleccionado, setPacienteSeleccionado] = useState(internacion.pacienteId);
|
||||
const [busqueda, setBusqueda] = useState('');
|
||||
const [camaSeleccionada, setCamaSeleccionada] = useState(internacion.camaId);
|
||||
const [medico, setMedico] = useState(internacion.medicoIngresante);
|
||||
const [fechaIngresoHospital, setFechaIngresoHospital] = useState(internacion.fechaIngresoHospital || '');
|
||||
const [fechaIngresoClinica, setFechaIngresoClinica] = useState(internacion.fechaIngresoClinica || '');
|
||||
const [motivoConsulta, setMotivoConsulta] = useState(internacion.motivoConsulta || '');
|
||||
const [diagnosticoIngreso, setDiagnosticoIngreso] = useState(internacion.diagnosticoIngreso);
|
||||
const [enfermedadActual, setEnfermedadActual] = useState(internacion.enfermedadActual);
|
||||
const [antecedentesEnfermedadActual, setAntecedentesEnfermedadActual] = useState(internacion.antecedentesEnfermedadActual || '');
|
||||
const [apache, setApache] = useState(internacion.apache || '');
|
||||
const [derivacion, setDerivacion] = useState(internacion.derivacion || '');
|
||||
|
||||
const selectedPaciente = pacientes.find(p => p.id === pacienteSeleccionado);
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (!pacienteSeleccionado || !camaSeleccionada || !medico || !diagnosticoIngreso || !enfermedadActual) {
|
||||
alert('Por favor complete los campos obligatorios');
|
||||
return;
|
||||
}
|
||||
|
||||
onActualizarInternacion(internacion.id, {
|
||||
pacienteId: pacienteSeleccionado,
|
||||
camaId: camaSeleccionada,
|
||||
medicoIngresante: medico,
|
||||
diagnosticoIngreso,
|
||||
motivoConsulta: motivoConsulta || undefined,
|
||||
enfermedadActual,
|
||||
antecedentesEnfermedadActual: antecedentesEnfermedadActual || undefined,
|
||||
fechaIngresoHospital: fechaIngresoHospital || undefined,
|
||||
fechaIngresoClinica: fechaIngresoClinica || undefined,
|
||||
apache: apache || undefined,
|
||||
derivacion: derivacion || undefined,
|
||||
});
|
||||
|
||||
onVolver();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-4">
|
||||
<Button variant="ghost" size="icon" onClick={onVolver}>
|
||||
<ArrowLeft className="h-5 w-5" />
|
||||
</Button>
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold text-gray-900 flex items-center gap-2">
|
||||
<User className="h-6 w-6 text-blue-600" />
|
||||
Editar Ingreso
|
||||
</h1>
|
||||
<p className="text-gray-500">Modificar datos de internación</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<Button variant="outline" onClick={() => onVolver()}>
|
||||
<X className="h-4 w-4 mr-2" />
|
||||
Cancelar
|
||||
</Button>
|
||||
<Button className="bg-blue-600 hover:bg-blue-700" onClick={handleSubmit}>
|
||||
<Save className="h-4 w-4 mr-2" />
|
||||
Guardar Cambios
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
||||
{/* Columna 1: Datos del Paciente, Cama y Datos Adicionales */}
|
||||
<div className="space-y-6">
|
||||
<Card>
|
||||
<CardContent className="pt-6 space-y-4">
|
||||
<h3 className="font-semibold text-gray-900 flex items-center gap-2">
|
||||
<User className="h-4 w-4" />
|
||||
Datos del Paciente
|
||||
</h3>
|
||||
|
||||
{selectedPaciente ? (
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
<Badge className="bg-blue-100 text-blue-800">
|
||||
{selectedPaciente?.apellido}, {selectedPaciente?.nombre}
|
||||
</Badge>
|
||||
<Badge variant="outline">DNI: {selectedPaciente?.dni}</Badge>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<Label>Buscar Paciente *</Label>
|
||||
<Input
|
||||
placeholder="Apellido, nombre o DNI"
|
||||
value={busqueda}
|
||||
onChange={(e) => setBusqueda(e.target.value)}
|
||||
/>
|
||||
<div className="max-h-48 overflow-auto border rounded-md">
|
||||
{(() => {
|
||||
const q = busqueda.trim().toLowerCase();
|
||||
if (!q) {
|
||||
return <div className="p-2 text-sm text-gray-500">Escriba para buscar</div>;
|
||||
}
|
||||
const matches = pacientes.filter(p =>
|
||||
p.apellido.toLowerCase().includes(q) ||
|
||||
p.nombre.toLowerCase().includes(q) ||
|
||||
p.dni.includes(q)
|
||||
);
|
||||
if (matches.length === 0) {
|
||||
return <div className="p-2 text-sm text-gray-500">Sin resultados</div>;
|
||||
}
|
||||
return matches.map(p => (
|
||||
<button
|
||||
key={p.id}
|
||||
type="button"
|
||||
onClick={() => setPacienteSeleccionado(p.id)}
|
||||
className="w-full text-left p-2 hover:bg-gray-50 text-sm"
|
||||
>
|
||||
{p.apellido}, {p.nombre} — DNI: {p.dni}
|
||||
</button>
|
||||
));
|
||||
})()}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<CardContent className="pt-6 space-y-4">
|
||||
<h3 className="font-semibold text-gray-900 flex items-center gap-2">
|
||||
<Bed className="h-4 w-4" />
|
||||
Asignación de Cama
|
||||
</h3>
|
||||
|
||||
<div>
|
||||
<Label>Cama *</Label>
|
||||
<Select value={camaSeleccionada} onValueChange={setCamaSeleccionada}>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Seleccionar cama" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{camas.map(c => (
|
||||
<SelectItem key={c.id} value={c.id}>
|
||||
{c.numero} - {getAreaName(c.areaId)} ({c.tipo})
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<CardContent className="pt-6 space-y-4">
|
||||
<h3 className="font-semibold text-gray-900 flex items-center gap-2">
|
||||
<ClipboardList className="h-4 w-4" />
|
||||
Datos Adicionales
|
||||
</h3>
|
||||
|
||||
<div>
|
||||
<Label>Apache / Mortalidad</Label>
|
||||
<Input
|
||||
placeholder="Valor Apache o riesgo"
|
||||
value={apache}
|
||||
onChange={(e) => setApache(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Label>Derivado de</Label>
|
||||
<Input
|
||||
placeholder="Hospital o clínica de derivación"
|
||||
value={derivacion}
|
||||
onChange={(e) => setDerivacion(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
{/* Columna 2: Datos de Ingreso */}
|
||||
<div className="space-y-6">
|
||||
<Card>
|
||||
<CardContent className="pt-6 space-y-4">
|
||||
<h3 className="font-semibold text-gray-900 flex items-center gap-2">
|
||||
<ClipboardList className="h-4 w-4" />
|
||||
Datos de Ingreso
|
||||
</h3>
|
||||
|
||||
<div>
|
||||
<Label>Fecha Ingreso al Hospital</Label>
|
||||
<Input
|
||||
type="date"
|
||||
value={fechaIngresoHospital}
|
||||
onChange={(e) => setFechaIngresoHospital(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Label>Fecha Ingreso a Clínica Médica</Label>
|
||||
<Input
|
||||
type="date"
|
||||
value={fechaIngresoClinica}
|
||||
onChange={(e) => setFechaIngresoClinica(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Label>Apache / Mortalidad</Label>
|
||||
<Input
|
||||
placeholder="Valor Apache o riesgo"
|
||||
value={apache}
|
||||
onChange={(e) => setApache(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Label>Derivado de</Label>
|
||||
<Input
|
||||
placeholder="Hospital o clínica de derivación"
|
||||
value={derivacion}
|
||||
onChange={(e) => setDerivacion(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<CardContent className="pt-6 space-y-4">
|
||||
<h3 className="font-semibold text-gray-900 flex items-center gap-2">
|
||||
<Stethoscope className="h-4 w-4" />
|
||||
Médico Ingresante
|
||||
</h3>
|
||||
|
||||
<div>
|
||||
<Label>Médico Ingresante *</Label>
|
||||
<Input
|
||||
placeholder="Nombre del médico"
|
||||
value={medico}
|
||||
onChange={(e) => setMedico(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
{/* Columna 3: Datos Clínicos */}
|
||||
<div className="space-y-6">
|
||||
<Card>
|
||||
<CardContent className="pt-6 space-y-4">
|
||||
<h3 className="font-semibold text-gray-900">
|
||||
Datos Clínicos
|
||||
</h3>
|
||||
|
||||
<div>
|
||||
<Label>Motivo de Consulta *</Label>
|
||||
<textarea
|
||||
className="w-full p-2 border rounded-md text-sm min-h-[80px]"
|
||||
placeholder="Motivo por el cual consulta"
|
||||
value={motivoConsulta}
|
||||
onChange={(e) => setMotivoConsulta(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label>Diagnóstico de Ingreso *</Label>
|
||||
<textarea
|
||||
className="w-full p-2 border rounded-md text-sm min-h-[80px]"
|
||||
placeholder="Diagnóstico principal"
|
||||
value={diagnosticoIngreso}
|
||||
onChange={(e) => setDiagnosticoIngreso(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label>Enfermedad Actual *</Label>
|
||||
<textarea
|
||||
className="w-full p-2 border rounded-md text-sm min-h-[100px]"
|
||||
placeholder="Descripción de la enfermedad actual"
|
||||
value={enfermedadActual}
|
||||
onChange={(e) => setEnfermedadActual(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label>Antecedentes de la Enfermedad Actual</Label>
|
||||
<textarea
|
||||
className="w-full p-2 border rounded-md text-sm min-h-[80px]"
|
||||
placeholder="Antecedentes relevantes"
|
||||
value={antecedentesEnfermedadActual}
|
||||
onChange={(e) => setAntecedentesEnfermedadActual(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -58,6 +58,7 @@ interface HistoriaClinicaProps {
|
||||
onActualizarInternacion: (id: string, datos: Partial<Internacion>) => void;
|
||||
onActualizarCama: (id: string, datos: Partial<Cama>) => void;
|
||||
onVolver: () => void;
|
||||
onEditarIngreso?: () => void;
|
||||
}
|
||||
|
||||
const PARAMETROS_COMUNES: Record<string, { unidad: string; referencia: string }> = {
|
||||
@@ -154,11 +155,12 @@ export function HistoriaClinica({
|
||||
onActualizarInternacion,
|
||||
onActualizarCama,
|
||||
onVolver,
|
||||
onEditarIngreso,
|
||||
}: HistoriaClinicaProps) {
|
||||
const [tabActivo, setTabActivo] = useState('evoluciones');
|
||||
const [detalleExpandido, setDetalleExpandido] = useState(false);
|
||||
const [editIngresoDialog, setEditIngresoDialog] = useState(false);
|
||||
const [editFechaIngreso, setEditFechaIngreso] = useState(internacion.fechaIngreso);
|
||||
const [editFechaIngreso, setEditFechaIngreso] = useState(internacion.fechaIngresoClinica);
|
||||
const [editMotivoConsulta, setEditMotivoConsulta] = useState(internacion.motivoConsulta || '');
|
||||
const [editDiagnostico, setEditDiagnostico] = useState(internacion.diagnosticoIngreso || '');
|
||||
const [editEnfermedadActual, setEditEnfermedadActual] = useState(internacion.enfermedadActual || '');
|
||||
@@ -192,7 +194,7 @@ export function HistoriaClinica({
|
||||
onActualizarCama(editCamaId, { estado: 'Ocupada', pacienteId: paciente.id, internacionId: internacion.id });
|
||||
}
|
||||
onActualizarInternacion(internacion.id, {
|
||||
fechaIngreso: editFechaIngreso,
|
||||
fechaIngresoClinica: editFechaIngreso,
|
||||
motivoConsulta: editMotivoConsulta,
|
||||
diagnosticoIngreso: editDiagnostico,
|
||||
enfermedadActual: editEnfermedadActual,
|
||||
@@ -222,7 +224,7 @@ export function HistoriaClinica({
|
||||
<ArrowLeft className="h-4 w-4 mr-2" />
|
||||
Volver
|
||||
</Button>
|
||||
<Button variant="outline" onClick={() => setEditIngresoDialog(true)}>
|
||||
<Button variant="outline" onClick={onEditarIngreso}>
|
||||
<Pencil className="h-4 w-4 mr-2" />
|
||||
Editar Ingreso
|
||||
</Button>
|
||||
@@ -292,12 +294,12 @@ export function HistoriaClinica({
|
||||
|
||||
<div>
|
||||
<p className="text-gray-500">Antecedentes</p>
|
||||
<p className="font-medium truncate">{paciente.antecedentes || 'Sin registrados'}</p>
|
||||
<p className="font-medium truncate">{paciente.antecedentes || 'No constan'}</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p className="text-gray-500">Fecha de Ingreso</p>
|
||||
<p className="font-medium">{formatDateDDMMYYYY(internacion.fechaIngreso)}</p>
|
||||
<p className="font-medium">{internacion.fechaIngresoClinica ? formatDateDDMMYYYY(internacion.fechaIngresoClinica) : 'N/A'}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-gray-500">Diagnóstico de Ingreso</p>
|
||||
@@ -305,8 +307,8 @@ export function HistoriaClinica({
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-gray-500">Días de Internación</p>
|
||||
<Badge className={calcularDiasInternado(internacion.fechaIngreso) > 7 ? 'bg-red-100 text-red-800' : 'bg-blue-100 text-blue-800'}>
|
||||
{calcularDiasInternado(internacion.fechaIngreso)} días
|
||||
<Badge className={internacion.fechaIngresoClinica && calcularDiasInternado(internacion.fechaIngresoClinica) > 7 ? 'bg-red-100 text-red-800' : 'bg-blue-100 text-blue-800'}>
|
||||
{internacion.fechaIngresoClinica ? calcularDiasInternado(internacion.fechaIngresoClinica) : 0} días
|
||||
</Badge>
|
||||
</div>
|
||||
|
||||
@@ -344,7 +346,7 @@ export function HistoriaClinica({
|
||||
const colorLightGray = rgb(0.92, 0.92, 0.92);
|
||||
|
||||
const edad = paciente.fechaNacimiento ? calcularEdad(paciente.fechaNacimiento) : '';
|
||||
const fechaFormateada = formatDateDDMMYYYY(internacion.fechaIngreso);
|
||||
const fechaFormateada = internacion.fechaIngresoClinica ? formatDateDDMMYYYY(internacion.fechaIngresoClinica) : 'N/A';
|
||||
|
||||
// Header
|
||||
page.drawRectangle({ x: 0, y: height - 80, width, height: 80, color: colorPrimary });
|
||||
|
||||
@@ -18,7 +18,7 @@ interface InternacionesProps {
|
||||
laboratorios?: Laboratorio[];
|
||||
cultivos?: Cultivo[];
|
||||
areas: Area[];
|
||||
onIniciarInternacion: (internacion: Omit<Internacion, 'id' | 'fechaIngreso' | 'activa'>) => void;
|
||||
onIniciarInternacion: (internacion: Omit<Internacion, 'id' | 'activa'>) => void;
|
||||
onFinalizarInternacion: (internacionId: string, datos: {
|
||||
fechaEgreso: string;
|
||||
diagnosticoEgreso: string;
|
||||
@@ -27,6 +27,7 @@ interface InternacionesProps {
|
||||
getPacienteById: (id: string) => Paciente | undefined;
|
||||
getCamaById: (id: string) => Cama | undefined;
|
||||
onVerHC?: (internacionId: string) => void;
|
||||
onNuevoIngreso?: () => void;
|
||||
}
|
||||
|
||||
export function Internaciones({
|
||||
@@ -39,6 +40,7 @@ export function Internaciones({
|
||||
getCamaById,
|
||||
areas,
|
||||
onVerHC,
|
||||
onNuevoIngreso,
|
||||
}: InternacionesProps) {
|
||||
const [filtroEstado, setFiltroEstado] = useState<'todas' | 'activas' | 'finalizadas'>('todas');
|
||||
const [dialogoNuevaAbierto, setDialogoNuevaAbierto] = useState(false);
|
||||
@@ -116,7 +118,7 @@ export function Internaciones({
|
||||
(filtroEstado === 'finalizadas' && !i.activa);
|
||||
|
||||
return cumpleBusqueda && cumpleEstado;
|
||||
}).sort((a, b) => new Date(b.fechaIngreso).getTime() - new Date(a.fechaIngreso).getTime());
|
||||
}).sort((a, b) => new Date(b.fechaIngresoClinica || '').getTime() - new Date(a.fechaIngresoClinica || '').getTime());
|
||||
|
||||
const pacientesSinInternar = pacientes.filter(p => {
|
||||
const internacionActiva = internaciones.find(i => i.pacienteId === p.id && i.activa);
|
||||
@@ -143,7 +145,7 @@ export function Internaciones({
|
||||
</div>
|
||||
<Dialog open={dialogoNuevaAbierto} onOpenChange={setDialogoNuevaAbierto}>
|
||||
<DialogTrigger asChild>
|
||||
<Button onClick={resetFormularioNueva}>
|
||||
<Button onClick={() => onNuevoIngreso ? onNuevoIngreso() : setDialogoNuevaAbierto(true)}>
|
||||
<Plus className="h-4 w-4 mr-2" />
|
||||
Nuevo Ingreso
|
||||
</Button>
|
||||
@@ -334,7 +336,7 @@ export function Internaciones({
|
||||
</div>
|
||||
<div className="flex items-center gap-2 text-gray-600">
|
||||
<Calendar className="h-4 w-4" />
|
||||
<span>Ingreso: {formatDateDDMMYYYY(internacion.fechaIngreso)}</span>
|
||||
<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" />
|
||||
|
||||
@@ -18,7 +18,7 @@ interface MapaCamasProps {
|
||||
onActualizarCama: (id: string, datos: Partial<Cama>) => void;
|
||||
onAgregarCama: (cama: Omit<Cama, 'id'>) => string;
|
||||
onEliminarCama: (id: string) => void;
|
||||
onIniciarInternacion: (internacion: Omit<Internacion, 'id' | 'fechaIngreso' | 'activa'>) => void;
|
||||
onIniciarInternacion: (internacion: Omit<Internacion, 'id' | 'activa'>) => void;
|
||||
onAgregarArea: (area: Omit<Area, 'id'>) => string;
|
||||
onActualizarArea: (id: string, datos: Partial<Area>) => void;
|
||||
onEliminarArea: (id: string) => void;
|
||||
@@ -332,7 +332,7 @@ export function MapaCamas({
|
||||
<p className="font-medium">Paciente:</p>
|
||||
<p className="text-lg">{paciente.apellido}, {paciente.nombre}</p>
|
||||
<p className="text-sm text-gray-500">DNI: {paciente.dni}</p>
|
||||
<p className="text-sm text-gray-500">Ingreso: {formatDateDDMMYYYY(internacion.fechaIngreso)}</p>
|
||||
<p className="text-sm text-gray-500">Ingreso: {internacion.fechaIngresoClinica ? formatDateDDMMYYYY(internacion.fechaIngresoClinica) : 'N/A'}</p>
|
||||
<p className="text-sm text-gray-500">Diagnóstico: {internacion.diagnosticoIngreso}</p>
|
||||
<p className="text-sm text-gray-500">Médico: {internacion.medicoIngresante}</p>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,310 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { ArrowLeft, Save, X, Bed, Calendar, Stethoscope, User, ClipboardList } from 'lucide-react';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import type { Paciente, Cama, Area, Internacion } from '@/types';
|
||||
|
||||
interface NuevoIngresoProps {
|
||||
pacientes: Paciente[];
|
||||
camas: Cama[];
|
||||
areas: Area[];
|
||||
onIniciarInternacion: (internacion: Omit<Internacion, 'id' | 'activa'>) => void;
|
||||
onVolver: () => void;
|
||||
getAreaName: (areaId: string | undefined) => string;
|
||||
}
|
||||
|
||||
export function NuevoIngreso({ pacientes, camas, areas, onIniciarInternacion, onVolver, getAreaName }: NuevoIngresoProps) {
|
||||
const [pacienteSeleccionado, setPacienteSeleccionado] = useState<string>('');
|
||||
const [busqueda, setBusqueda] = useState('');
|
||||
const [camaSeleccionada, setCamaSeleccionada] = useState('');
|
||||
const [medico, setMedico] = useState('');
|
||||
const [fechaIngresoHospital, setFechaIngresoHospital] = useState('');
|
||||
const [fechaIngresoClinica, setFechaIngresoClinica] = useState('');
|
||||
const [motivoConsulta, setMotivoConsulta] = useState('');
|
||||
const [diagnosticoIngreso, setDiagnosticoIngreso] = useState('');
|
||||
const [enfermedadActual, setEnfermedadActual] = useState('');
|
||||
const [antecedentesEnfermedadActual, setAntecedentesEnfermedadActual] = useState('');
|
||||
const [apache, setApache] = useState('');
|
||||
const [derivacion, setDerivacion] = useState('');
|
||||
|
||||
const resetFormulario = () => {
|
||||
setPacienteSeleccionado('');
|
||||
setBusqueda('');
|
||||
setCamaSeleccionada('');
|
||||
setMedico('');
|
||||
setFechaIngresoHospital('');
|
||||
setFechaIngresoClinica('');
|
||||
setMotivoConsulta('');
|
||||
setDiagnosticoIngreso('');
|
||||
setEnfermedadActual('');
|
||||
setAntecedentesEnfermedadActual('');
|
||||
setApache('');
|
||||
setDerivacion('');
|
||||
};
|
||||
|
||||
const pacientesSinInternar = pacientes;
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (!pacienteSeleccionado || !camaSeleccionada || !medico || !diagnosticoIngreso || !enfermedadActual) {
|
||||
alert('Por favor complete los campos obligatorios');
|
||||
return;
|
||||
}
|
||||
|
||||
onIniciarInternacion({
|
||||
pacienteId: pacienteSeleccionado,
|
||||
camaId: camaSeleccionada,
|
||||
medicoIngresante: medico,
|
||||
diagnosticoIngreso,
|
||||
motivoConsulta: motivoConsulta || undefined,
|
||||
enfermedadActual,
|
||||
antecedentesEnfermedadActual: antecedentesEnfermedadActual || undefined,
|
||||
fechaIngresoHospital: fechaIngresoHospital || undefined,
|
||||
fechaIngresoClinica: fechaIngresoClinica || undefined,
|
||||
apache: apache || undefined,
|
||||
derivacion: derivacion || undefined,
|
||||
});
|
||||
|
||||
resetFormulario();
|
||||
onVolver();
|
||||
};
|
||||
|
||||
const selectedPaciente = pacientes.find(p => p.id === pacienteSeleccionado);
|
||||
const camasDisponibles = camaSeleccionada
|
||||
? []
|
||||
: camas.filter(c => c.estado === 'Disponible' && !c.pacienteId);
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-4">
|
||||
<Button variant="ghost" size="icon" onClick={onVolver}>
|
||||
<ArrowLeft className="h-5 w-5" />
|
||||
</Button>
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold text-gray-900 flex items-center gap-2">
|
||||
<User className="h-6 w-6 text-blue-600" />
|
||||
Nuevo Ingreso
|
||||
</h1>
|
||||
<p className="text-gray-500">Formulario de internación</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<Button variant="outline" onClick={() => { resetFormulario(); onVolver(); }}>
|
||||
<X className="h-4 w-4 mr-2" />
|
||||
Cancelar
|
||||
</Button>
|
||||
<Button className="bg-blue-600 hover:bg-blue-700" onClick={handleSubmit}>
|
||||
<Save className="h-4 w-4 mr-2" />
|
||||
Guardar Ingreso
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
||||
{/* Columna 1: Datos del Paciente, Cama y Datos Adicionales */}
|
||||
<div className="space-y-6">
|
||||
<Card>
|
||||
<CardContent className="pt-6 space-y-4">
|
||||
<h3 className="font-semibold text-gray-900 flex items-center gap-2">
|
||||
<User className="h-4 w-4" />
|
||||
Datos del Paciente
|
||||
</h3>
|
||||
|
||||
{!pacienteSeleccionado ? (
|
||||
<>
|
||||
<Label>Buscar Paciente *</Label>
|
||||
<Input
|
||||
placeholder="Apellido, nombre o DNI"
|
||||
value={busqueda}
|
||||
onChange={(e) => setBusqueda(e.target.value)}
|
||||
/>
|
||||
<div className="max-h-48 overflow-auto border rounded-md">
|
||||
{(() => {
|
||||
const q = busqueda.trim().toLowerCase();
|
||||
if (!q) {
|
||||
return <div className="p-2 text-sm text-gray-500">Escriba para buscar</div>;
|
||||
}
|
||||
const matches = pacientesSinInternar.filter(p =>
|
||||
p.apellido.toLowerCase().includes(q) ||
|
||||
p.nombre.toLowerCase().includes(q) ||
|
||||
p.dni.includes(q)
|
||||
);
|
||||
if (matches.length === 0) {
|
||||
return <div className="p-2 text-sm text-gray-500">Sin resultados</div>;
|
||||
}
|
||||
return matches.map(p => (
|
||||
<button
|
||||
key={p.id}
|
||||
type="button"
|
||||
onClick={() => setPacienteSeleccionado(p.id)}
|
||||
className="w-full text-left p-2 hover:bg-gray-50 text-sm"
|
||||
>
|
||||
{p.apellido}, {p.nombre} — DNI: {p.dni}
|
||||
</button>
|
||||
));
|
||||
})()}
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
<Badge className="bg-blue-100 text-blue-800">
|
||||
{selectedPaciente?.apellido}, {selectedPaciente?.nombre}
|
||||
</Badge>
|
||||
<Badge variant="outline">DNI: {selectedPaciente?.dni}</Badge>
|
||||
<Button size="sm" variant="ghost" onClick={() => { setPacienteSeleccionado(''); setBusqueda(''); }}>
|
||||
Cambiar
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<CardContent className="pt-6 space-y-4">
|
||||
<h3 className="font-semibold text-gray-900 flex items-center gap-2">
|
||||
<Bed className="h-4 w-4" />
|
||||
Asignación de Cama
|
||||
</h3>
|
||||
|
||||
<div>
|
||||
<Label>Cama *</Label>
|
||||
<Select value={camaSeleccionada} onValueChange={setCamaSeleccionada}>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Seleccionar cama" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{camas.map(c => (
|
||||
<SelectItem key={c.id} value={c.id}>
|
||||
{c.numero} - {getAreaName(c.areaId)} ({c.tipo})
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
{/* Columna 2: Fechas y Médico */}
|
||||
<div className="space-y-6">
|
||||
<Card>
|
||||
<CardContent className="pt-6 space-y-4">
|
||||
<h3 className="font-semibold text-gray-900 flex items-center gap-2">
|
||||
<Calendar className="h-4 w-4" />
|
||||
Datos de Ingreso
|
||||
</h3>
|
||||
|
||||
<div>
|
||||
<Label>Fecha Ingreso al Hospital</Label>
|
||||
<Input
|
||||
type="date"
|
||||
value={fechaIngresoHospital}
|
||||
onChange={(e) => setFechaIngresoHospital(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Label>Fecha Ingreso a Clínica Médica</Label>
|
||||
<Input
|
||||
type="date"
|
||||
value={fechaIngresoClinica}
|
||||
onChange={(e) => setFechaIngresoClinica(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Label>Apache / Mortalidad</Label>
|
||||
<Input
|
||||
placeholder="Valor Apache o riesgo"
|
||||
value={apache}
|
||||
onChange={(e) => setApache(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Label>Derivado de</Label>
|
||||
<Input
|
||||
placeholder="Hospital o clínica de derivación"
|
||||
value={derivacion}
|
||||
onChange={(e) => setDerivacion(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<CardContent className="pt-6 space-y-4">
|
||||
<h3 className="font-semibold text-gray-900 flex items-center gap-2">
|
||||
<Stethoscope className="h-4 w-4" />
|
||||
Médico Ingresante
|
||||
</h3>
|
||||
|
||||
<div>
|
||||
<Label>Médico Ingresante *</Label>
|
||||
<Input
|
||||
placeholder="Nombre del médico"
|
||||
value={medico}
|
||||
onChange={(e) => setMedico(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
{/* Columna 3: Datos Clínicos */}
|
||||
<div className="space-y-6">
|
||||
<Card>
|
||||
<CardContent className="pt-6 space-y-4">
|
||||
<h3 className="font-semibold text-gray-900">
|
||||
Datos Clínicos
|
||||
</h3>
|
||||
|
||||
<div>
|
||||
<Label>Motivo de Consulta *</Label>
|
||||
<textarea
|
||||
className="w-full p-2 border rounded-md text-sm min-h-[80px]"
|
||||
placeholder="Motivo por el cual consulta"
|
||||
value={motivoConsulta}
|
||||
onChange={(e) => setMotivoConsulta(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label>Diagnóstico de Ingreso *</Label>
|
||||
<textarea
|
||||
className="w-full p-2 border rounded-md text-sm min-h-[80px]"
|
||||
placeholder="Diagnóstico principal"
|
||||
value={diagnosticoIngreso}
|
||||
onChange={(e) => setDiagnosticoIngreso(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label>Enfermedad Actual *</Label>
|
||||
<textarea
|
||||
className="w-full p-2 border rounded-md text-sm min-h-[100px]"
|
||||
placeholder="Descripción de la enfermedad actual"
|
||||
value={enfermedadActual}
|
||||
onChange={(e) => setEnfermedadActual(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label>Antecedentes de la Enfermedad Actual</Label>
|
||||
<textarea
|
||||
className="w-full p-2 border rounded-md text-sm min-h-[80px]"
|
||||
placeholder="Antecedentes relevantes"
|
||||
value={antecedentesEnfermedadActual}
|
||||
onChange={(e) => setAntecedentesEnfermedadActual(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user