Refactor: reorganizar arquitectura de permisos y corregir bug de camaS

- Mover funciones utilitarias y de permisos al principio del hook
- Corregir bug camaS -> camas en iniciarInternacion
- Limpiar funciones duplicadas
- Estructura de permisos clara según reglas:
  1. Cualquier usuario puede crear ingresos en cualquier cama
  2. Cualquier usuario puede ver todos los pacientes
  3. Solo usuarios del área pueden crear/modificar registros
  4. Solo usuarios del área pueden cambiar la cama
This commit is contained in:
2026-04-24 01:07:02 -03:00
parent 1d0065683e
commit 079e3bd82c
2 changed files with 111 additions and 118 deletions
+110 -117
View File
@@ -139,6 +139,72 @@ export function useHospitalStore() {
return () => clearTimeout(t);
}, [state, initialLoadComplete]);
// Utility functions
const getCamaAreaId = useCallback((camaId: string): string | null => {
const cama = state.camas.find(c => c.id === camaId);
return cama?.areaId || null;
}, [state.camas]);
const getInternacionAreaId = useCallback((internacionId: string): string | null => {
const internacion = state.internaciones.find(i => i.id === internacionId);
return internacion?.areaId || null;
}, [state.internaciones]);
const getPacienteAreaId = useCallback((pacienteId: string): string | null => {
const internacion = state.internaciones.find(i => i.pacienteId === pacienteId && i.activa);
if (!internacion) {
const anyInternacion = state.internaciones.find(i => i.pacienteId === pacienteId);
if (anyInternacion) return getCamaAreaId(anyInternacion.camaId);
return null;
}
return getCamaAreaId(internacion.camaId);
}, [state.internaciones, getCamaAreaId]);
// Permission functions
const canAccessArea = useCallback((areaId: string | null | undefined): boolean => {
const user = state.currentUser;
if (!user) return false;
if (user.rol === 'admin') return true;
if (!areaId) return false;
return user.areaId === areaId;
}, [state.currentUser]);
const canChangeBed = useCallback((internacionId: string): boolean => {
const internacion = state.internaciones.find(i => i.id === internacionId);
if (!internacion) return false;
return canAccessArea(internacion.areaId);
}, [state.internaciones, canAccessArea]);
const canEditInternacion = useCallback((internacionId: string): boolean => {
const areaId = getInternacionAreaId(internacionId);
return canAccessArea(areaId);
}, [getInternacionAreaId, canAccessArea]);
const canEditCama = useCallback((camaId: string): boolean => {
const areaId = getCamaAreaId(camaId);
return canAccessArea(areaId);
}, [getCamaAreaId, canAccessArea]);
const canEditPaciente = useCallback((pacienteId: string): boolean => {
const areaId = getPacienteAreaId(pacienteId);
return canAccessArea(areaId);
}, [getPacienteAreaId, canAccessArea]);
const hasPermission = useCallback((permission: 'read' | 'write', section: string): boolean => {
const user = state.currentUser;
if (!user) return false;
if (user.rol === 'admin') return true;
if (user.rol === 'enfermero') {
if (section === 'glucemias' || section === 'signosvitales') return permission === 'read' || permission === 'write';
return permission === 'read';
}
if (user.rol === 'medico') {
if (section === 'miArea') return permission === 'read' || permission === 'write';
return permission === 'read';
}
return false;
}, [state.currentUser]);
// Acciones de navegación
const setVista = useCallback((vista: Vista) => {
setState(prev => ({ ...prev, vistaActual: vista }));
@@ -172,7 +238,7 @@ export function useHospitalStore() {
}));
}, []);
// Acciones de camas
// Acciones de camas
const actualizarCama = useCallback((id: string, datos: Partial<Cama>) => {
const cama = state.camas.find(c => c.id === id);
if (!cama) return;
@@ -208,7 +274,7 @@ export function useHospitalStore() {
}));
}, []);
// Acciones de internaciones
// Acciones de internaciones
const iniciarInternacion = useCallback((internacion: Omit<Internacion, 'id' | 'activa'>) => {
const nuevaInternacion: Internacion = {
...internacion,
@@ -218,7 +284,7 @@ export function useHospitalStore() {
setState(prev => ({
...prev,
internaciones: [...prev.internaciones, nuevaInternacion],
camaS: prev.camas.map(c =>
camas: prev.camas.map(c =>
c.id === internacion.camaId
? { ...c, estado: 'Ocupada' as const, pacienteId: internacion.pacienteId, internacionId: nuevaInternacion.id }
: c
@@ -227,7 +293,7 @@ export function useHospitalStore() {
return nuevaInternacion.id;
}, []);
const finalizarInternacion = useCallback((internacionId: string, datos: {
const finalizarInternacion = useCallback((internacionId: string, datos: {
fechaEgreso: string;
diagnosticoEgreso: string;
motivoEgreso: Internacion['motivoEgreso']
@@ -247,7 +313,7 @@ const finalizarInternacion = useCallback((internacionId: string, datos: {
? { ...i, ...datos, activa: false }
: i
),
cams: esFueraDeArea
camas: esFueraDeArea
? prev.camas.filter(c => c.id !== internacion.camaId)
: prev.camas.map(c =>
c.id === internacion.camaId
@@ -261,18 +327,21 @@ const finalizarInternacion = useCallback((internacionId: string, datos: {
const actualizarInternacion = useCallback((internacionId: string, datos: Partial<Internacion>) => {
const internacion = state.internaciones.find(i => i.id === internacionId);
if (!internacion) return;
const user = state.currentUser;
const areaId = internacion.areaId || null;
const oldCamaId = internacion.camaId;
const newCamaId = datos.camaId;
const cambioDeCama = newCamaId && newCamaId !== oldCamaId;
if (cambioDeCama && user && user.rol !== 'admin' && areaId && user.areaId !== areaId) {
if (cambioDeCama && !canChangeBed(internacionId)) {
console.warn('No tiene permisos para cambiar la cama de esta internación');
return;
}
if (!cambioDeCama && !canAccessArea(internacion.areaId)) {
console.warn('No tiene permisos para actualizar esta internación');
return;
}
const pacienteId = datos.pacienteId || internacion.pacienteId;
setState(prev => {
@@ -318,7 +387,7 @@ const finalizarInternacion = useCallback((internacionId: string, datos: {
const agregarEvolucion = useCallback((evolucion: Omit<Evolucion, 'id'>) => {
const internacion = state.internaciones.find(i => i.id === evolucion.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
if (!canAccessArea(areaId)) {
console.warn('No tiene permisos para agregar evolución en esta área');
return null;
}
@@ -338,7 +407,7 @@ const finalizarInternacion = useCallback((internacionId: string, datos: {
if (!evolucion) return;
const internacion = state.internaciones.find(i => i.id === evolucion.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
if (!canAccessArea(areaId)) {
console.warn('No tiene permisos para eliminar evolución en esta área');
return;
}
@@ -353,7 +422,7 @@ const finalizarInternacion = useCallback((internacionId: string, datos: {
if (!evolucion) return;
const internacion = state.internaciones.find(i => i.id === evolucion.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
if (!canAccessArea(areaId)) {
console.warn('No tiene permisos para actualizar evolución en esta área');
return;
}
@@ -367,7 +436,7 @@ const finalizarInternacion = useCallback((internacionId: string, datos: {
const agregarLaboratorio = useCallback((laboratorio: Omit<Laboratorio, 'id'>) => {
const internacion = state.internaciones.find(i => i.id === laboratorio.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
if (!canAccessArea(areaId)) {
console.warn('No tiene permisos para agregar laboratorio en esta área');
return null;
}
@@ -382,12 +451,12 @@ const finalizarInternacion = useCallback((internacionId: string, datos: {
return nuevoLaboratorio.id;
}, [state.internaciones, state.currentUser]);
const eliminarLaboratorio = useCallback((id: string) => {
const eliminarLaboratorio = useCallback((id: string) => {
const laboratorio = state.laboratorios.find(l => l.id === id);
if (!laboratorio) return;
const internacion = state.internaciones.find(i => i.id === laboratorio.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
if (!canAccessArea(areaId)) {
console.warn('No tiene permisos para eliminar laboratorio en esta área');
return;
}
@@ -402,7 +471,7 @@ const eliminarLaboratorio = useCallback((id: string) => {
if (!laboratorio) return;
const internacion = state.internaciones.find(i => i.id === laboratorio.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
if (!canAccessArea(areaId)) {
console.warn('No tiene permisos para actualizar laboratorio en esta área');
return;
}
@@ -416,7 +485,7 @@ const eliminarLaboratorio = useCallback((id: string) => {
const agregarAcidoBase = useCallback((acidoBase: Omit<AcidoBase, 'id'>) => {
const internacion = state.internaciones.find(i => i.id === acidoBase.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
if (!canAccessArea(areaId)) {
console.warn('No tiene permisos para agregar ácido-base en esta área');
return null;
}
@@ -436,7 +505,7 @@ const eliminarLaboratorio = useCallback((id: string) => {
if (!acidoBase) return;
const internacion = state.internaciones.find(i => i.id === acidoBase.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
if (!canAccessArea(areaId)) {
console.warn('No tiene permisos para actualizar ácido-base en esta área');
return;
}
@@ -451,7 +520,7 @@ const eliminarLaboratorio = useCallback((id: string) => {
if (!acidoBase) return;
const internacion = state.internaciones.find(i => i.id === acidoBase.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
if (!canAccessArea(areaId)) {
console.warn('No tiene permisos para eliminar ácido-base en esta área');
return;
}
@@ -465,7 +534,7 @@ const eliminarLaboratorio = useCallback((id: string) => {
const agregarCultivo = useCallback((cultivo: Omit<Cultivo, 'id'>) => {
const internacion = state.internaciones.find(i => i.id === cultivo.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
if (!canAccessArea(areaId)) {
console.warn('No tiene permisos para agregar cultivo en esta área');
return null;
}
@@ -485,7 +554,7 @@ const eliminarLaboratorio = useCallback((id: string) => {
if (!cultivo) return;
const internacion = state.internaciones.find(i => i.id === cultivo.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
if (!canAccessArea(areaId)) {
console.warn('No tiene permisos para actualizar cultivo en esta área');
return;
}
@@ -500,7 +569,7 @@ const eliminarLaboratorio = useCallback((id: string) => {
if (!cultivo) return;
const internacion = state.internaciones.find(i => i.id === cultivo.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
if (!canAccessArea(areaId)) {
console.warn('No tiene permisos para eliminar cultivo en esta área');
return;
}
@@ -514,7 +583,7 @@ const eliminarLaboratorio = useCallback((id: string) => {
const agregarEstudioComplementario = useCallback((estudio: Omit<EstudioComplementario, 'id'>) => {
const internacion = state.internaciones.find(i => i.id === estudio.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
if (!canAccessArea(areaId)) {
console.warn('No tiene permisos para agregar estudio complementario en esta área');
return null;
}
@@ -534,7 +603,7 @@ const eliminarLaboratorio = useCallback((id: string) => {
if (!estudio) return;
const internacion = state.internaciones.find(i => i.id === estudio.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
if (!canAccessArea(areaId)) {
console.warn('No tiene permisos para actualizar estudio complementario en esta área');
return;
}
@@ -549,7 +618,7 @@ const eliminarLaboratorio = useCallback((id: string) => {
if (!estudio) return;
const internacion = state.internaciones.find(i => i.id === estudio.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
if (!canAccessArea(areaId)) {
console.warn('No tiene permisos para eliminar estudio complementario en esta área');
return;
}
@@ -563,7 +632,7 @@ const eliminarLaboratorio = useCallback((id: string) => {
const agregarInterconsulta = useCallback((interconsulta: Omit<Interconsulta, 'id'>) => {
const internacion = state.internaciones.find(i => i.id === interconsulta.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
if (!canAccessArea(areaId)) {
console.warn('No tiene permisos para agregar interconsulta en esta área');
return null;
}
@@ -580,7 +649,7 @@ const eliminarLaboratorio = useCallback((id: string) => {
if (!interconsulta) return;
const internacion = state.internaciones.find(i => i.id === interconsulta.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
if (!canAccessArea(areaId)) {
console.warn('No tiene permisos para actualizar interconsulta en esta área');
return;
}
@@ -595,7 +664,7 @@ const eliminarLaboratorio = useCallback((id: string) => {
if (!interconsulta) return;
const internacion = state.internaciones.find(i => i.id === interconsulta.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
if (!canAccessArea(areaId)) {
console.warn('No tiene permisos para eliminar interconsulta en esta área');
return;
}
@@ -608,7 +677,7 @@ const eliminarLaboratorio = useCallback((id: string) => {
const agregarATB = useCallback((atb: Omit<ATB, 'id'>) => {
const internacion = state.internaciones.find(i => i.id === atb.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
if (!canAccessArea(areaId)) {
console.warn('No tiene permisos para agregar ATB en esta área');
return null;
}
@@ -625,7 +694,7 @@ const eliminarLaboratorio = useCallback((id: string) => {
if (!atb) return;
const internacion = state.internaciones.find(i => i.id === atb.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
if (!canAccessArea(areaId)) {
console.warn('No tiene permisos para actualizar ATB en esta área');
return;
}
@@ -640,7 +709,7 @@ const eliminarLaboratorio = useCallback((id: string) => {
if (!atb) return;
const internacion = state.internaciones.find(i => i.id === atb.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
if (!canAccessArea(areaId)) {
console.warn('No tiene permisos para eliminar ATB en esta área');
return;
}
@@ -653,7 +722,7 @@ const eliminarLaboratorio = useCallback((id: string) => {
const agregarIndicacion = useCallback((indicacion: Omit<Indicacion, 'id'>) => {
const internacion = state.internaciones.find(i => i.id === indicacion.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
if (!canAccessArea(areaId)) {
console.warn('No tiene permisos para agregar indicación en esta área');
return null;
}
@@ -670,7 +739,7 @@ const eliminarLaboratorio = useCallback((id: string) => {
if (!indicacion) return;
const internacion = state.internaciones.find(i => i.id === indicacion.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
if (!canAccessArea(areaId)) {
console.warn('No tiene permisos para actualizar indicación en esta área');
return;
}
@@ -685,7 +754,7 @@ const eliminarLaboratorio = useCallback((id: string) => {
if (!indicacion) return;
const internacion = state.internaciones.find(i => i.id === indicacion.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
if (!canAccessArea(areaId)) {
console.warn('No tiene permisos para eliminar indicación en esta área');
return;
}
@@ -698,7 +767,7 @@ const eliminarLaboratorio = useCallback((id: string) => {
const agregarMovimientoIndicacion = useCallback((movimiento: any) => {
const internacion = state.internaciones.find(i => i.id === movimiento.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
if (!canAccessArea(areaId)) {
console.warn('No tiene permisos para agregar movimiento de indicación en esta área');
return;
}
@@ -739,7 +808,7 @@ const eliminarLaboratorio = useCallback((id: string) => {
}));
}, []);
// Funciones de utilidad
// Funciones de utilidad para consultas
const getPacienteById = useCallback((id: string) => {
return state.pacientes.find(p => p.id === id);
}, [state.pacientes]);
@@ -780,7 +849,7 @@ const eliminarLaboratorio = useCallback((id: string) => {
.sort((a, b) => new Date(b.fechaToma).getTime() - new Date(a.fechaToma).getTime());
}, [state.cultivos]);
const getEstadisticas = useCallback(() => {
const getEstadisticas = useCallback(() => {
const fueraDeAreaList = state.camas.filter(c => c.areaId === 'Fuera de Area');
const camasActivas = state.camas.filter(c => c.areaId !== 'Fuera de Area');
const camaPrincipal = state.camas.filter(c => c.areaId !== 'Fuera de Area');
@@ -866,82 +935,6 @@ const getEstadisticas = useCallback(() => {
return true;
}, []);
const hasPermission = useCallback((permission: 'read' | 'write', section: string): boolean => {
const user = state.currentUser;
if (!user) return false;
if (user.rol === 'admin') return true;
if (user.rol === 'enfermero') {
if (section === 'glucemias' || section === 'signosvitales') return permission === 'read' || permission === 'write';
return permission === 'read';
}
if (user.rol === 'medico') {
if (section === 'miArea') return permission === 'read' || permission === 'write';
return permission === 'read';
}
return false;
}, [state.currentUser]);
const canAccessInternacion = useCallback((internacionId: string): boolean => {
const user = state.currentUser;
if (!user) return false;
const rol = user.rol as string;
if (rol === 'admin') return true;
if (rol === 'medico' && user.areaId) {
const internacion = state.internaciones.find(i => i.id === internacionId);
if (!internacion) return false;
const cama = state.camas.find(c => c.id === internacion.camaId);
return cama?.areaId === user.areaId;
}
return rol === 'admin';
}, [state.currentUser, state.internaciones, state.camas]);
const getCamaAreaId = useCallback((camaId: string): string | null => {
const cama = state.camas.find(c => c.id === camaId);
return cama?.areaId || null;
}, [state.camas]);
const getInternacionAreaId = useCallback((internacionId: string): string | null => {
const internacion = state.internaciones.find(i => i.id === internacionId);
if (!internacion) return null;
// Use the new areaId field first
if (internacion.areaId) return internacion.areaId;
// Fallback to cama's area
return getCamaAreaId(internacion.camaId);
}, [state.internaciones, getCamaAreaId]);
const getPacienteAreaId = useCallback((pacienteId: string): string | null => {
const internacion = state.internaciones.find(i => i.pacienteId === pacienteId && i.activa);
if (!internacion) {
const anyInternacion = state.internaciones.find(i => i.pacienteId === pacienteId);
if (anyInternacion) return getCamaAreaId(anyInternacion.camaId);
return null;
}
return getCamaAreaId(internacion.camaId);
}, [state.internaciones, getCamaAreaId]);
const canEditInArea = useCallback((areaId: string | null | undefined): boolean => {
const user = state.currentUser;
if (!user) return false;
if (user.rol === 'admin') return true;
if (!areaId) return false;
return user.areaId === areaId;
}, [state.currentUser]);
const canEditCama = useCallback((camaId: string): boolean => {
const areaId = getCamaAreaId(camaId);
return canEditInArea(areaId);
}, [getCamaAreaId, canEditInArea]);
const canEditInternacion = useCallback((internacionId: string): boolean => {
const areaId = getInternacionAreaId(internacionId);
return canEditInArea(areaId);
}, [getInternacionAreaId, canEditInArea]);
const canEditPaciente = useCallback((pacienteId: string): boolean => {
const areaId = getPacienteAreaId(pacienteId);
return canEditInArea(areaId);
}, [getPacienteAreaId, canEditInArea]);
return {
...state,
isLoaded,
@@ -956,8 +949,10 @@ const getEstadisticas = useCallback(() => {
agregarCama,
eliminarCama,
agregarEvolucion,
actualizarEvolucion,
eliminarEvolucion,
agregarLaboratorio,
actualizarLaboratorio,
eliminarLaboratorio,
agregarAcidoBase,
actualizarAcidoBase,
@@ -990,8 +985,6 @@ const getEstadisticas = useCallback(() => {
getLaboratoriosByPaciente,
getAcidosBaseByPaciente,
getCultivosByPaciente,
actualizarEvolucion,
actualizarLaboratorio,
setCurrentInternacion,
getEstadisticas,
login,
@@ -999,10 +992,10 @@ const getEstadisticas = useCallback(() => {
changePassword,
updateEmail,
hasPermission,
canAccessInternacion,
canEditInArea,
canEditCama,
canAccessArea,
canChangeBed,
canEditInternacion,
canEditCama,
canEditPaciente,
getCamaAreaId,
getInternacionAreaId,