diff --git a/src/hooks/useHospitalStore.ts b/src/hooks/useHospitalStore.ts index f7055a1..6186817 100644 --- a/src/hooks/useHospitalStore.ts +++ b/src/hooks/useHospitalStore.ts @@ -1,6 +1,6 @@ import { useState, useEffect, useCallback } from 'react'; import { toast } from 'sonner'; -import { getNombreProfesional, isCamaFueraDeGrupo, computeSector } from '@/lib/utils'; +import { getNombreProfesional, isCamaFueraDeGrupo, computeSector, sortCamas } from '@/lib/utils'; import type { Paciente, Cama, @@ -109,6 +109,7 @@ export function useHospitalStore() { movimientosIndicaciones: body.movimientosIndicaciones || [], pendientes: body.pendientes || [], currentInternacionId: storedInternacionId || body.currentInternacionId || null, + camas: sortCamas(body.camas || []), currentUser, isAuthenticated: !!currentUser, }; @@ -316,7 +317,7 @@ export function useHospitalStore() { await apiCall('PUT', `/camas/${id}`, datos); setState(prev => ({ ...prev, - camas: prev.camas.map(c => c.id === id ? { ...c, ...datos } : c), + camas: sortCamas(prev.camas.map(c => c.id === id ? { ...c, ...datos } : c)), })); } catch (err) { console.error('Error al actualizar cama:', err); @@ -334,7 +335,7 @@ const agregarCama = useCallback(async (cama: Omit) => { await apiCall('POST', '/camas', nuevaCama); setState(prev => ({ ...prev, - camas: [...prev.camas, nuevaCama], + camas: sortCamas([...prev.camas, nuevaCama]), })); return nuevaCama.id; } catch (err) { diff --git a/src/lib/utils.ts b/src/lib/utils.ts index 4d2f04f..295020d 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -44,6 +44,58 @@ export function isCamaFueraDeGrupo( return computeSector(cama?.numero || '') === 'Fuera de Área'; } +export function sortCamas(camas: T[]): T[] { + const parseBedNumber = (numero: string) => { + const match = (numero || '').match(/^(\d{3})-(\d+)$/); + if (!match) return { sala: 0, cama: 0 }; + return { + sala: parseInt(match[1], 10), + cama: parseInt(match[2], 10) + }; + }; + + return [...camas].sort((a, b) => { + const pa = parseBedNumber(a.numero); + const pb = parseBedNumber(b.numero); + + const getOrden = (sala: number) => { + const grupo = Math.floor(sala / 100); + const esPar = sala % 2 === 0; + + if (grupo === 2) { + if (!esPar) return { weight: 1, order: 'desc', sala }; // 2XX impares, mayor a menor + return { weight: 2, order: 'asc', sala }; // 2XX pares, menor a mayor + } + if (grupo === 3) { + if (esPar) return { weight: 3, order: 'asc', sala }; // 3XX pares, menor a mayor + return { weight: 4, order: 'desc', sala }; // 3XX impares, mayor a menor + } + if (grupo === 4) { + if (!esPar) return { weight: 5, order: 'desc', sala }; // 4XX impares, mayor a menor + return { weight: 6, order: 'asc', sala }; // 4XX pares, menor a mayor + } + return { weight: 10, order: 'asc', sala }; + }; + + const oa = getOrden(pa.sala); + const ob = getOrden(pb.sala); + + if (oa.weight !== ob.weight) { + return oa.weight - ob.weight; + } + + if (oa.sala !== ob.sala) { + if (oa.order === 'desc') { + return ob.sala - oa.sala; + } else { + return oa.sala - ob.sala; + } + } + + return pa.cama - pb.cama; + }); +} + export function computeSector(numero: string): "En Área" | "Fuera de Área" { if (!numero) return 'En Área'; const cleanNumero = String(numero).trim(); diff --git a/src/sections/EditIngreso.tsx b/src/sections/EditIngreso.tsx index 103a999..3119832 100644 --- a/src/sections/EditIngreso.tsx +++ b/src/sections/EditIngreso.tsx @@ -8,7 +8,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@ import { Badge } from '@/components/ui/badge'; import { toast } from 'sonner'; import type { Paciente, Cama, Grupo, Internacion } from '@/types'; -import { getNombreProfesional, calcularEdad, computeSector } from '@/lib/utils'; +import { getNombreProfesional, calcularEdad, computeSector, sortCamas } from '@/lib/utils'; import { useHospitalStore } from '@/hooks/useHospitalStore'; interface EditIngresoProps { @@ -57,48 +57,7 @@ export function EditIngreso({ const grupoFueraDeGrupo = grupos.find(a => normalizeStr(a.nombre) === 'fuera de grupo'); const grupoFueraDeGrupoId = grupoFueraDeGrupo?.id || grupos[0]?.id || 'fuera-de-grupo'; - const parseBedNumber = (numero: string) => { - const match = numero.match(/^(\d{3})-(\d+)$/); - if (!match) return { sala: 0, cama: 0 }; - return { - sala: parseInt(match[1]), - cama: parseInt(match[2]) - }; - }; - - const sortedCamas = [...camas].sort((a, b) => { - const pa = parseBedNumber(a.numero); - const pb = parseBedNumber(b.numero); - - const getOrden = (sala: number) => { - const grupo = Math.floor(sala / 100); - const esPar = sala % 2 === 0; - - if (grupo === 2) { - if (esPar) return { grupo: 2, suborden: 0, sala }; - return { grupo: 1, suborden: 1, sala }; - } - if (grupo === 3) { - if (esPar) return { grupo: 3, suborden: 0, sala }; - return { grupo: 4, suborden: 1, sala }; - } - if (grupo === 4) { - if (esPar) return { grupo: 6, suborden: 0, sala }; - return { grupo: 5, suborden: 1, sala }; - } - return { grupo: 10, suborden: 1, sala }; - }; - - const oa = getOrden(pa.sala); - const ob = getOrden(pb.sala); - - if (oa.grupo !== ob.grupo) return oa.grupo - ob.grupo; - if (oa.suborden === ob.suborden) { - if (oa.suborden === 0) return (oa.sala || pa.sala) - (ob.sala || pb.sala); - return (ob.sala || 0) - (oa.sala || 0); - } - return oa.suborden - ob.suborden; - }); + const sortedCamas = sortCamas(camas); const handleSubmit = async () => { if (!pacienteSeleccionado) { diff --git a/src/sections/Internaciones.tsx b/src/sections/Internaciones.tsx index 2ed9aab..1b08270 100644 --- a/src/sections/Internaciones.tsx +++ b/src/sections/Internaciones.tsx @@ -11,7 +11,7 @@ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@ import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@/components/ui/dropdown-menu'; import { toast } from 'sonner'; import type { Internacion, Paciente, Cama, Grupo, Evolucion, Laboratorio, Cultivo } from '@/types'; -import { formatDateDDMMYYYY, getNombreProfesional } from '@/lib/utils'; +import { formatDateDDMMYYYY, getNombreProfesional, sortCamas } from '@/lib/utils'; import { useHospitalStore } from '@/hooks/useHospitalStore'; interface InternacionesProps { @@ -150,31 +150,7 @@ export function Internaciones({ return !internacionActiva; }); - const parseBedNumber = (numero: string) => { - const match = numero.match(/^(\d{3})-(\d+)$/); - if (!match) return { sala: 0, cama: 0 }; - return { sala: parseInt(match[1]), cama: parseInt(match[2]) }; - }; - - const sortedCamas = [...camas].sort((a, b) => { - const pa = parseBedNumber(a.numero); - const pb = parseBedNumber(b.numero); - const getOrden = (sala: number) => { - const grupo = Math.floor(sala / 100); - const esPar = sala % 2 === 0; - if (grupo === 2) return esPar ? { grupo: 2, suborden: 0, sala } : { grupo: 1, suborden: 1, sala }; - if (grupo === 3) return esPar ? { grupo: 3, suborden: 0, sala } : { grupo: 4, suborden: 1, sala }; - if (grupo === 4) return esPar ? { grupo: 6, suborden: 0, sala } : { grupo: 5, suborden: 1, sala }; - return { grupo: 10, suborden: 1, sala }; - }; - const oa = getOrden(pa.sala); - const ob = getOrden(pb.sala); - if (oa.grupo !== ob.grupo) return oa.grupo - ob.grupo; - if (oa.suborden === ob.suborden) { - return oa.suborden === 0 ? (oa.sala - ob.sala) : (ob.sala - oa.sala); - } - return oa.suborden - ob.suborden; - }); + const sortedCamas = sortCamas(camas); const getGrupoName = (grupoId?: string) => grupos.find(a => a.id === grupoId)?.nombre; diff --git a/src/sections/MapaCamas.tsx b/src/sections/MapaCamas.tsx index 3b5d4a7..346a693 100644 --- a/src/sections/MapaCamas.tsx +++ b/src/sections/MapaCamas.tsx @@ -3,7 +3,7 @@ import { Bed, CheckCircle2, Clock, Wrench, User, Plus, Trash, Edit2, Save, X } f import { Card, CardContent } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; -import { formatDateDDMMYYYY, getNombreProfesional, isCamaFueraDeGrupo, computeSector } from '@/lib/utils'; +import { formatDateDDMMYYYY, getNombreProfesional, isCamaFueraDeGrupo, computeSector, sortCamas } from '@/lib/utils'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; @@ -104,48 +104,7 @@ export function MapaCamas({ } }; - const parseBedNumber = (numero: string) => { - const match = numero.match(/^(\d{3})-(\d+)$/); - if (!match) return { sala: 0, cama: 0 }; - return { - sala: parseInt(match[1]), - cama: parseInt(match[2]) - }; - }; - - const sortedCamas = [...camasFiltradas].sort((a, b) => { - const pa = parseBedNumber(a.numero); - const pb = parseBedNumber(b.numero); - - const getOrden = (sala: number) => { - const grupo = Math.floor(sala / 100); - const esPar = sala % 2 === 0; - - if (grupo === 2) { - if (esPar) return { grupo: 2, suborden: 0, sala }; // 2XX pares, menor a mayor - return { grupo: 1, suborden: 1, sala }; // 2XX impares, mayor a menor - } - if (grupo === 3) { - if (esPar) return { grupo: 3, suborden: 0, sala }; // 3XX pares, menor a mayor - return { grupo: 4, suborden: 1, sala }; // 3XX impares, mayor a menor - } - if (grupo === 4) { - if (esPar) return { grupo: 6, suborden: 0, sala }; // 4XX pares, menor a mayor - return { grupo: 5, suborden: 1, sala }; // 4XX impares, mayor a menor - } - return { grupo: 10, suborden: 1, sala }; - }; - - const oa = getOrden(pa.sala); - const ob = getOrden(pb.sala); - - if (oa.grupo !== ob.grupo) return oa.grupo - ob.grupo; - if (oa.suborden === ob.suborden) { - if (oa.suborden === 0) return (oa.sala || pa.sala) - (ob.sala || pb.sala); - return (ob.sala || 0) - (oa.sala || 0); - } - return oa.suborden - ob.suborden; - }); + const sortedCamas = sortCamas(camasFiltradas); const handleOcuparCama = () => { if (camaSeleccionada && grupoSeleccionada && pacienteSeleccionado && diagnostico && enfermedadActual && effectiveMedico) { diff --git a/src/sections/NuevoIngreso.tsx b/src/sections/NuevoIngreso.tsx index 0297504..e4b31cf 100644 --- a/src/sections/NuevoIngreso.tsx +++ b/src/sections/NuevoIngreso.tsx @@ -8,7 +8,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@ import { Badge } from '@/components/ui/badge'; import { toast } from 'sonner'; import type { Paciente, Cama, Grupo, Internacion } from '@/types'; -import { getNombreProfesional, computeSector } from '@/lib/utils'; +import { getNombreProfesional, computeSector, sortCamas } from '@/lib/utils'; import { useHospitalStore } from '@/hooks/useHospitalStore'; interface NuevoIngresoProps { @@ -64,48 +64,7 @@ export function NuevoIngreso({ pacientes, camas, grupos, onIniciarInternacion, o return !internacionActiva; }); - const parseBedNumber = (numero: string) => { - const match = numero.match(/^(\d{3})-(\d+)$/); - if (!match) return { sala: 0, cama: 0 }; - return { - sala: parseInt(match[1]), - cama: parseInt(match[2]) - }; - }; - - const sortedCamas = [...camas].sort((a, b) => { - const pa = parseBedNumber(a.numero); - const pb = parseBedNumber(b.numero); - - const getOrden = (sala: number) => { - const grupo = Math.floor(sala / 100); - const esPar = sala % 2 === 0; - - if (grupo === 2) { - if (esPar) return { grupo: 2, suborden: 0, sala }; - return { grupo: 1, suborden: 1, sala }; - } - if (grupo === 3) { - if (esPar) return { grupo: 3, suborden: 0, sala }; - return { grupo: 4, suborden: 1, sala }; - } - if (grupo === 4) { - if (esPar) return { grupo: 6, suborden: 0, sala }; - return { grupo: 5, suborden: 1, sala }; - } - return { grupo: 10, suborden: 1, sala }; - }; - - const oa = getOrden(pa.sala); - const ob = getOrden(pb.sala); - - if (oa.grupo !== ob.grupo) return oa.grupo - ob.grupo; - if (oa.suborden === ob.suborden) { - if (oa.suborden === 0) return (oa.sala || pa.sala) - (ob.sala || pb.sala); - return (ob.sala || 0) - (oa.sala || 0); - } - return oa.suborden - ob.suborden; - }); + const sortedCamas = sortCamas(camas); const handleSubmit = async () => { // Validaciones explícitas con feedback claro