Fix bed management: preserve camaId from frontend to backend

- Use camaId generated in frontend instead of generating new one in backend API
- Remove patientId and internacionId from cama table (use internaciones table instead)
- Fix discharge: delete cama if fuera de area, mark available otherwise
- Fix MapaCamas to find patient via internaciones table
This commit is contained in:
2026-04-24 11:46:01 -03:00
parent 705c200f1b
commit 96058f5275
4 changed files with 37 additions and 30 deletions
+4 -1
View File
@@ -239,7 +239,10 @@ app.put('/api/camas/:id', async (req, res) => {
app.post('/api/camas', async (req, res) => { app.post('/api/camas', async (req, res) => {
try { try {
const cama = { ...req.body, id: generateUUID() }; const cama = req.body;
if (!cama.id) {
cama.id = generateUUID();
}
await createCama(cama); await createCama(cama);
res.json(cama); res.json(cama);
} catch (err) { } catch (err) {
+14 -1
View File
@@ -1,6 +1,18 @@
import * as mariadb from 'mariadb'; import * as mariadb from 'mariadb';
import * as bcrypt from 'bcryptjs'; import * as bcrypt from 'bcryptjs';
// UUID generator
export function generateUUID() {
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
return crypto.randomUUID();
}
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
const r = (Math.random() * 16) | 0;
const v = c === 'x' ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
}
// MariaDB connection pool // MariaDB connection pool
const pool = mariadb.createPool({ const pool = mariadb.createPool({
host: process.env.DB_HOST || '10.9.8.135', host: process.env.DB_HOST || '10.9.8.135',
@@ -350,9 +362,10 @@ export async function getCamaById(id) {
} }
export async function createCama(cama) { export async function createCama(cama) {
const id = cama.id || generateUUID();
await query( await query(
'INSERT INTO camas (id, numero, areaId, tipo, estado) VALUES (?, ?, ?, ?, ?)', 'INSERT INTO camas (id, numero, areaId, tipo, estado) VALUES (?, ?, ?, ?, ?)',
[cama.id, cama.numero, cama.areaId, cama.tipo, cama.estado] [id, cama.numero, cama.areaId, cama.tipo, cama.estado]
); );
} }
+15 -25
View File
@@ -271,7 +271,7 @@ export function useHospitalStore() {
} }
}, [state.camas, state.currentUser, apiCall]); }, [state.camas, state.currentUser, apiCall]);
const agregarCama = useCallback(async (cama: Omit<Cama, 'id'>) => { const agregarCama = useCallback(async (cama: Omit<Cama, 'id'>) => {
const nuevaCama: Cama = { const nuevaCama: Cama = {
...cama, ...cama,
id: generateUUID(), id: generateUUID(),
@@ -303,7 +303,7 @@ export function useHospitalStore() {
} }
}, [apiCall]); }, [apiCall]);
// Acciones de internaciones // Acciones de internaciones
const iniciarInternacion = useCallback(async (internacion: Omit<Internacion, 'id' | 'activa'>) => { const iniciarInternacion = useCallback(async (internacion: Omit<Internacion, 'id' | 'activa'>) => {
const nuevaInternacion: Internacion = { const nuevaInternacion: Internacion = {
...internacion, ...internacion,
@@ -315,11 +315,9 @@ export function useHospitalStore() {
// API call inmediata para crear internación // API call inmediata para crear internación
await apiCall('POST', '/internaciones', nuevaInternacion); await apiCall('POST', '/internaciones', nuevaInternacion);
// Actualizar estado de la cama en la base de datos // Actualizar estado de la cama en la base de datos (solo estado)
await apiCall('PUT', `/camas/${internacion.camaId}`, { await apiCall('PUT', `/camas/${internacion.camaId}`, {
estado: 'Ocupada', estado: 'Ocupada'
pacienteId: internacion.pacienteId,
internacionId: nuevaInternacion.id
}); });
// Actualizar estado local después del éxito // Actualizar estado local después del éxito
@@ -328,7 +326,7 @@ export function useHospitalStore() {
internaciones: [...prev.internaciones, nuevaInternacion], internaciones: [...prev.internaciones, nuevaInternacion],
camas: prev.camas.map(c => camas: prev.camas.map(c =>
c.id === internacion.camaId c.id === internacion.camaId
? { ...c, estado: 'Ocupada' as const, pacienteId: internacion.pacienteId, internacionId: nuevaInternacion.id } ? { ...c, estado: 'Ocupada' as const }
: c : c
), ),
})); }));
@@ -348,9 +346,9 @@ const finalizarInternacion = useCallback(async (internacionId: string, datos: {
const internacion = state.internaciones.find(i => i.id === internacionId); const internacion = state.internaciones.find(i => i.id === internacionId);
if (!internacion) return; if (!internacion) return;
const areaFueraDeArea = state.areas.find(a => (a.nombre || '').trim().toLowerCase() === 'fuera de area'); const areaFueraDeArea = state.areas.find(a => (a.nombre || '').toLowerCase().trim() === 'fuera de area');
const areaFueraDeAreaId = areaFueraDeArea?.id; const areaFueraDeAreaId = areaFueraDeArea?.id;
const esFueraDeArea = internacion.areaId === areaFueraDeAreaId; const esFueraDeArea = !internacion.areaId || !areaFueraDeAreaId || internacion.areaId === areaFueraDeAreaId;
const camaId = internacion.camaId; const camaId = internacion.camaId;
try { try {
@@ -365,9 +363,7 @@ const finalizarInternacion = useCallback(async (internacionId: string, datos: {
} else { } else {
// Marcar como disponible si es un área normal // Marcar como disponible si es un área normal
await apiCall('PUT', `/camas/${camaId}`, { await apiCall('PUT', `/camas/${camaId}`, {
estado: 'Disponible', estado: 'Disponible'
pacienteId: null,
internacionId: null
}); });
} }
} }
@@ -385,7 +381,7 @@ const finalizarInternacion = useCallback(async (internacionId: string, datos: {
? prev.camas.filter(c => c.id !== camaId) ? prev.camas.filter(c => c.id !== camaId)
: prev.camas.map(c => : prev.camas.map(c =>
c.id === camaId c.id === camaId
? { ...c, estado: 'Disponible' as const, pacienteId: undefined, internacionId: undefined } ? { ...c, estado: 'Disponible' as const }
: c : c
), ),
}; };
@@ -414,8 +410,6 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
return; return;
} }
const pacienteId = datos.pacienteId || internacion.pacienteId;
try { try {
// API call inmediata // API call inmediata
await apiCall('PUT', `/internaciones/${internacionId}`, datos); await apiCall('PUT', `/internaciones/${internacionId}`, datos);
@@ -423,18 +417,14 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
// Si hay cambio de cama, actualizar estados en la base de datos // Si hay cambio de cama, actualizar estados en la base de datos
if (cambioDeCama && newCamaId && oldCamaId) { if (cambioDeCama && newCamaId && oldCamaId) {
await apiCall('PUT', `/camas/${newCamaId}`, { await apiCall('PUT', `/camas/${newCamaId}`, {
estado: 'Ocupada', estado: 'Ocupada'
pacienteId,
internacionId
}); });
await apiCall('PUT', `/camas/${oldCamaId}`, { await apiCall('PUT', `/camas/${oldCamaId}`, {
estado: 'Disponible', estado: 'Disponible'
pacienteId: null,
internacionId: null
}); });
} }
// Actualizar estado local después del éxito // Actualizar estado local después del éxito
setState(prev => { setState(prev => {
const result = { const result = {
...prev, ...prev,
@@ -443,12 +433,12 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
? { ...i, ...datos } ? { ...i, ...datos }
: i : i
), ),
camas: prev.camas.map(c => { cams: prev.camas.map(c => {
if (c.id === newCamaId && newCamaId !== oldCamaId) { if (c.id === newCamaId && newCamaId !== oldCamaId) {
return { ...c, estado: 'Ocupada' as const, pacienteId, internacionId }; return { ...c, estado: 'Ocupada' as const };
} }
if (c.id === oldCamaId && oldCamaId !== newCamaId) { if (c.id === oldCamaId && oldCamaId !== newCamaId) {
return { ...c, estado: 'Disponible' as const, pacienteId: undefined, internacionId: undefined }; return { ...c, estado: 'Disponible' as const };
} }
return c; return c;
}), }),
+4 -3
View File
@@ -265,11 +265,11 @@ export function MapaCamas({
</CardContent> </CardContent>
</Card> </Card>
{/* Mapa de Camas */} {/* Mapa de Camas */}
<div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-2 sm:gap-4"> <div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-2 sm:gap-4">
{sortedCamas.map((cama) => { {sortedCamas.map((cama) => {
const paciente = cama.pacienteId ? getPacienteById(cama.pacienteId) : null; const internacion = internaciones.find(i => i.camaId === cama.id && i.activa);
const internacion = cama.internacionId ? getInternacionById(cama.internacionId) : null; const paciente = internacion ? getPacienteById(internacion.pacienteId) : null;
return ( return (
<Dialog key={cama.id}> <Dialog key={cama.id}>
@@ -297,6 +297,7 @@ export function MapaCamas({
)} )}
</CardContent> </CardContent>
</Card> </Card>
</DialogTrigger> </DialogTrigger>