Implementar lógica de cálculo automático del sector (En Área / Fuera de Área) para Camas según su numeración y almacenar en la BD

This commit is contained in:
2026-08-09 20:17:44 +00:00
parent dc108a9699
commit 4ae43e713a
12 changed files with 319 additions and 47 deletions
+5 -1
View File
@@ -1,6 +1,6 @@
import { useState, useEffect, useCallback } from 'react';
import { toast } from 'sonner';
import { getNombreProfesional, isCamaFueraDeGrupo } from '@/lib/utils';
import { getNombreProfesional, isCamaFueraDeGrupo, computeSector } from '@/lib/utils';
import type {
Paciente,
Cama,
@@ -291,6 +291,9 @@ export function useHospitalStore() {
return;
}
try {
if (datos.numero !== undefined) {
datos.sector = computeSector(datos.numero);
}
await apiCall('PUT', `/camas/${id}`, datos);
setState(prev => ({
...prev,
@@ -306,6 +309,7 @@ const agregarCama = useCallback(async (cama: Omit<Cama, 'id'>) => {
const nuevaCama: Cama = {
...cama,
id: generateUUID(),
sector: computeSector(cama.numero),
} as Cama;
try {
await apiCall('POST', '/camas', nuevaCama);
+22 -35
View File
@@ -38,42 +38,29 @@ export function calcularEdad(fechaNacimiento?: string): string | number {
return edad;
}
export function isCamaFueraDeGrupo(
cama: { numero: string; grupoId?: string; areaId?: string },
gruposOrAreas?: { id: string; nombre: string }[]
cama: { numero: string; grupoId?: string; areaId?: string; sector?: string },
_gruposOrAreas?: { id: string; nombre: string }[]
): boolean {
if (cama.grupoId === 'Fuera de Area' || cama.areaId === 'Fuera de Area') {
return true;
}
if (gruposOrAreas) {
const targetId = cama.grupoId || cama.areaId;
if (targetId) {
const g = gruposOrAreas.find(a => (a.nombre || '').toLowerCase().trim() === 'fuera de area');
if (g && targetId === g.id) {
return true;
}
}
}
const numero = cama.numero;
if (!numero) return false;
const parts = numero.trim().split('-');
if (parts.length === 0) return false;
const salaStr = parts[0].trim();
const salaNum = parseInt(salaStr, 10);
if (isNaN(salaNum)) return false;
// Formato 3XX que sean impares (301, 303, 305, etc.)
if (salaNum >= 300 && salaNum < 400 && salaNum % 2 !== 0) {
return true;
}
// Formato 4XX (todas las 4XX, pares o impares)
if (salaNum >= 400 && salaNum < 500) {
return true;
}
return false;
if (cama.sector === 'Fuera de Área') return true;
if (cama.sector === 'En Área') return false;
return computeSector(cama.numero) === 'Fuera de Área';
}
export function computeSector(numero: string): "En Área" | "Fuera de Área" {
if (!numero) return 'En Área';
const parts = String(numero).trim().split('-');
if (parts.length === 0) return 'En Área';
const salaStr = parts[0].trim();
const salaNum = parseInt(salaStr, 10);
if (isNaN(salaNum)) return 'En Área';
if (salaNum >= 300 && salaNum < 400 && salaNum % 2 !== 0) {
return 'Fuera de Área';
}
if (salaNum >= 400 && salaNum < 500) {
return 'Fuera de Área';
}
return 'En Área';
}
+1 -1
View File
@@ -284,7 +284,7 @@ export function MapaCamas({
{getEstadoIcono(cama)}
</div>
<p className="font-bold text-sm sm:text-lg">{cama.numero}</p>
<p className="text-xs opacity-75 truncate">{cama.grupoId ? grupoById[cama.grupoId] ?? 'Grupo desconocido' : 'Sin grupo'}</p>
<p className="text-xs opacity-75 truncate">{cama.grupoId ? grupoById[cama.grupoId] ?? 'Grupo desconocido' : 'Sin grupo'} - {cama.sector || 'En Área'}</p>
<Badge variant="outline" className="mt-1 sm:mt-2 text-xs bg-white/50 dark:bg-gray-800 dark:text-gray-300">
{cama.tipo}
</Badge>
+6
View File
@@ -37,6 +37,7 @@ export interface Cama {
estado: 'Disponible' | 'Ocupada' | 'Reparacion' | 'Reservada';
pacienteId?: string;
internacionId?: string;
sector?: "En Área" | "Fuera de Área";
}
export interface Internacion {
@@ -100,6 +101,7 @@ export interface Laboratorio {
id: string;
pacienteId: string;
internacionId?: string;
sector?: "En Área" | "Fuera de Área";
fecha: string;
hora: string;
tipo?: 'Hemograma' | 'Química sanguínea' | 'Urianálisis' | 'Coagulación' | 'Microbiología' | 'Inmunología' | 'Otros';
@@ -120,6 +122,7 @@ export interface Glucemia {
id: string;
pacienteId: string;
internacionId?: string;
sector?: "En Área" | "Fuera de Área";
fecha: string;
hora: string;
valor: number; // in mg%
@@ -130,6 +133,7 @@ export interface AcidoBase {
id: string;
pacienteId: string;
internacionId?: string;
sector?: "En Área" | "Fuera de Área";
fecha: string;
hora: string;
ph: number;
@@ -147,6 +151,7 @@ export interface Cultivo {
id: string;
pacienteId: string;
internacionId?: string;
sector?: "En Área" | "Fuera de Área";
fechaToma: string;
protocolo?: string;
fechaResultado?: string;
@@ -162,6 +167,7 @@ export interface EstudioComplementario {
id: string;
pacienteId: string;
internacionId?: string;
sector?: "En Área" | "Fuera de Área";
fecha: string;
tipo: string;
resultado: string;