Actualizar control de permisos de área y gestión de usuarios

This commit is contained in:
2026-08-09 19:34:36 +00:00
parent 4617c3c1a0
commit 8eb071e31f
3 changed files with 129 additions and 63 deletions
+16 -1
View File
@@ -1,5 +1,6 @@
import { useHospitalStore } from '@/hooks/useHospitalStore'; import { useHospitalStore } from '@/hooks/useHospitalStore';
import { Layout } from '@/sections/Layout'; import { Layout } from '@/sections/Layout';
import { toast } from 'sonner';
import { Dashboard } from '@/sections/Dashboard'; import { Dashboard } from '@/sections/Dashboard';
import { MapaCamas } from '@/sections/MapaCamas'; import { MapaCamas } from '@/sections/MapaCamas';
import { Pacientes } from '@/sections/Pacientes'; import { Pacientes } from '@/sections/Pacientes';
@@ -190,7 +191,13 @@ function AppContent() {
onActualizarInternacion={store.actualizarInternacion} onActualizarInternacion={store.actualizarInternacion}
onActualizarCama={store.actualizarCama} onActualizarCama={store.actualizarCama}
onVolver={() => store.setVista('internaciones')} onVolver={() => store.setVista('internaciones')}
onEditarIngreso={() => { store.setVista('editaringreso'); }} onEditarIngreso={() => {
if (store.canEditIngreso(internacion.id)) {
store.setVista('editaringreso');
} else {
toast.error(`Solo el usuario que creó esta internación (${internacion.medicoIngresante}) puede modificar el ingreso.`);
}
}}
canEdit={store.canEditInternacion(internacion.id)} canEdit={store.canEditInternacion(internacion.id)}
/> />
); );
@@ -236,6 +243,14 @@ function AppContent() {
); );
} }
case 'usuarios': case 'usuarios':
if (store.currentUser?.rol !== 'admin') {
return (
<div className="p-8 text-center text-red-500 font-semibold">
<p>No tiene permisos para acceder a esta sección.</p>
<Button className="mt-4" onClick={() => store.setVista('dashboard')}>Volver al Dashboard</Button>
</div>
);
}
return ( return (
<GestionUsuarios /> <GestionUsuarios />
); );
+103 -60
View File
@@ -1,4 +1,6 @@
import { useState, useEffect, useCallback } from 'react'; import { useState, useEffect, useCallback } from 'react';
import { toast } from 'sonner';
import { getNombreProfesional } from '@/lib/utils';
import type { import type {
Paciente, Paciente,
Cama, Cama,
@@ -168,6 +170,14 @@ export function useHospitalStore() {
return user.areaId === areaId; return user.areaId === areaId;
}, [state.currentUser]); }, [state.currentUser]);
const checkAreaPermission = useCallback((areaId: string | null | undefined): boolean => {
const allowed = canAccessArea(areaId);
if (!allowed) {
toast.error("no pertenecen al area de trabajo por la que se encuentra internado el paciente");
}
return allowed;
}, [canAccessArea]);
const canChangeBed = useCallback((internacionId: string): boolean => { const canChangeBed = useCallback((internacionId: string): boolean => {
const internacion = state.internaciones.find(i => i.id === internacionId); const internacion = state.internaciones.find(i => i.id === internacionId);
if (!internacion) return false; if (!internacion) return false;
@@ -179,6 +189,17 @@ export function useHospitalStore() {
return canAccessArea(areaId); return canAccessArea(areaId);
}, [getInternacionAreaId, canAccessArea]); }, [getInternacionAreaId, canAccessArea]);
const canEditIngreso = useCallback((internacionId: string): boolean => {
const internacion = state.internaciones.find(i => i.id === internacionId);
if (!internacion) return false;
const normalizeMedicoName = (name?: string) => {
return (name || '').trim().toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '');
};
const userProfesionalName = getNombreProfesional(state.currentUser);
return state.currentUser?.rol === 'admin' ||
(normalizeMedicoName(internacion.medicoIngresante) === normalizeMedicoName(userProfesionalName));
}, [state.internaciones, state.currentUser]);
const canEditCama = useCallback((camaId: string): boolean => { const canEditCama = useCallback((camaId: string): boolean => {
const areaId = getCamaAreaId(camaId); const areaId = getCamaAreaId(camaId);
return canAccessArea(areaId); return canAccessArea(areaId);
@@ -230,6 +251,8 @@ export function useHospitalStore() {
}, [apiCall]); }, [apiCall]);
const actualizarPaciente = useCallback(async (id: string, datos: Partial<Paciente>) => { const actualizarPaciente = useCallback(async (id: string, datos: Partial<Paciente>) => {
const areaId = getPacienteAreaId(id);
if (!checkAreaPermission(areaId)) return;
try { try {
await apiCall('PUT', `/pacientes/${id}`, datos); await apiCall('PUT', `/pacientes/${id}`, datos);
setState(prev => ({ setState(prev => ({
@@ -240,9 +263,11 @@ export function useHospitalStore() {
console.error('Error al actualizar paciente:', err); console.error('Error al actualizar paciente:', err);
throw err; throw err;
} }
}, [apiCall]); }, [apiCall, checkAreaPermission, getPacienteAreaId]);
const eliminarPaciente = useCallback(async (id: string) => { const eliminarPaciente = useCallback(async (id: string) => {
const areaId = getPacienteAreaId(id);
if (!checkAreaPermission(areaId)) return;
try { try {
await apiCall('DELETE', `/pacientes/${id}`); await apiCall('DELETE', `/pacientes/${id}`);
setState(prev => ({ setState(prev => ({
@@ -253,7 +278,7 @@ export function useHospitalStore() {
console.error('Error al eliminar paciente:', err); console.error('Error al eliminar paciente:', err);
throw err; throw err;
} }
}, [apiCall]); }, [apiCall, checkAreaPermission, getPacienteAreaId]);
// Acciones de camas // Acciones de camas
const actualizarCama = useCallback(async (id: string, datos: Partial<Cama>) => { const actualizarCama = useCallback(async (id: string, datos: Partial<Cama>) => {
@@ -311,6 +336,9 @@ const agregarCama = useCallback(async (cama: Omit<Cama, 'id'>) => {
// Acciones de internaciones // Acciones de internaciones
const iniciarInternacion = useCallback(async (internacion: Omit<Internacion, 'id' | 'activa'>) => { const iniciarInternacion = useCallback(async (internacion: Omit<Internacion, 'id' | 'activa'>) => {
if (!checkAreaPermission(internacion.areaId)) {
return null;
}
const nuevaInternacion: Internacion = { const nuevaInternacion: Internacion = {
...internacion, ...internacion,
id: generateUUID(), id: generateUUID(),
@@ -402,16 +430,30 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
const internacion = state.internaciones.find(i => i.id === internacionId); const internacion = state.internaciones.find(i => i.id === internacionId);
if (!internacion) return; if (!internacion) return;
// Check creator permission first
const normalizeMedicoName = (name?: string) => {
return (name || '').trim().toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '');
};
const userProfesionalName = getNombreProfesional(state.currentUser);
const isCreator = state.currentUser?.rol === 'admin' ||
(normalizeMedicoName(internacion.medicoIngresante) === normalizeMedicoName(userProfesionalName));
if (!isCreator) {
toast.error(`Solo el usuario que creó esta internación (${internacion.medicoIngresante}) puede modificar el ingreso.`);
return;
}
const oldCamaId = internacion.camaId; const oldCamaId = internacion.camaId;
const newCamaId = datos.camaId; const newCamaId = datos.camaId;
const cambioDeCama = newCamaId && newCamaId !== oldCamaId; const cambioDeCama = newCamaId && newCamaId !== oldCamaId;
if (cambioDeCama && !canChangeBed(internacionId)) { if (cambioDeCama && !canChangeBed(internacionId)) {
console.warn('No tiene permisos para cambiar la cama de esta internación'); console.warn('No tiene permisos para cambiar la cama de esta internación');
checkAreaPermission(null); // triggers toast
return; return;
} }
if (!cambioDeCama && !canAccessArea(internacion.areaId)) { if (!cambioDeCama && !checkAreaPermission(internacion.areaId)) {
console.warn('No tiene permisos para actualizar esta internación'); console.warn('No tiene permisos para actualizar esta internación');
return; return;
} }
@@ -455,13 +497,13 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
console.error('Error al actualizar internación:', err); console.error('Error al actualizar internación:', err);
throw err; throw err;
} }
}, [state, canAccessArea, apiCall]); }, [state, canAccessArea, checkAreaPermission, apiCall]);
// Acciones de evoluciones // Acciones de evoluciones
const agregarEvolucion = useCallback(async (evolucion: Omit<Evolucion, 'id'>) => { const agregarEvolucion = useCallback(async (evolucion: Omit<Evolucion, 'id'>) => {
const internacion = state.internaciones.find(i => i.id === evolucion.internacionId); const internacion = state.internaciones.find(i => i.id === evolucion.internacionId);
const areaId = internacion?.areaId || null; const areaId = internacion?.areaId || null;
if (!canAccessArea(areaId)) { if (!checkAreaPermission(areaId)) {
console.warn('No tiene permisos para agregar evolución en esta área'); console.warn('No tiene permisos para agregar evolución en esta área');
return null; return null;
} }
@@ -481,14 +523,14 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
console.error('Error al agregar evolución:', err); console.error('Error al agregar evolución:', err);
throw err; throw err;
} }
}, [state, canAccessArea, apiCall]); }, [state, canAccessArea, checkAreaPermission, apiCall]);
const eliminarEvolucion = useCallback(async (id: string) => { const eliminarEvolucion = useCallback(async (id: string) => {
const evolucion = state.evoluciones.find(e => e.id === id); const evolucion = state.evoluciones.find(e => e.id === id);
if (!evolucion) return; if (!evolucion) return;
const internacion = state.internaciones.find(i => i.id === evolucion.internacionId); const internacion = state.internaciones.find(i => i.id === evolucion.internacionId);
const areaId = internacion?.areaId || null; const areaId = internacion?.areaId || null;
if (!canAccessArea(areaId)) { if (!checkAreaPermission(areaId)) {
console.warn('No tiene permisos para eliminar evolución en esta área'); console.warn('No tiene permisos para eliminar evolución en esta área');
return; return;
} }
@@ -503,14 +545,14 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
console.error('Error al eliminar evolución:', err); console.error('Error al eliminar evolución:', err);
throw err; throw err;
} }
}, [state, canAccessArea, apiCall]); }, [state, canAccessArea, checkAreaPermission, apiCall]);
const actualizarEvolucion = useCallback(async (id: string, datos: Partial<Evolucion>) => { const actualizarEvolucion = useCallback(async (id: string, datos: Partial<Evolucion>) => {
const evolucion = state.evoluciones.find(e => e.id === id); const evolucion = state.evoluciones.find(e => e.id === id);
if (!evolucion) return; if (!evolucion) return;
const internacion = state.internaciones.find(i => i.id === evolucion.internacionId); const internacion = state.internaciones.find(i => i.id === evolucion.internacionId);
const areaId = internacion?.areaId || null; const areaId = internacion?.areaId || null;
if (!canAccessArea(areaId)) { if (!checkAreaPermission(areaId)) {
console.warn('No tiene permisos para actualizar evolución en esta área'); console.warn('No tiene permisos para actualizar evolución en esta área');
return; return;
} }
@@ -525,13 +567,13 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
console.error('Error al actualizar evolución:', err); console.error('Error al actualizar evolución:', err);
throw err; throw err;
} }
}, [state, canAccessArea, apiCall]); }, [state, canAccessArea, checkAreaPermission, apiCall]);
// Acciones de laboratorios // Acciones de laboratorios
const agregarLaboratorio = useCallback(async (laboratorio: Omit<Laboratorio, 'id'>) => { const agregarLaboratorio = useCallback(async (laboratorio: Omit<Laboratorio, 'id'>) => {
const internacion = state.internaciones.find(i => i.id === laboratorio.internacionId); const internacion = state.internaciones.find(i => i.id === laboratorio.internacionId);
const areaId = internacion?.areaId || null; const areaId = internacion?.areaId || null;
if (!canAccessArea(areaId)) { if (!checkAreaPermission(areaId)) {
console.warn('No tiene permisos para agregar laboratorio en esta área'); console.warn('No tiene permisos para agregar laboratorio en esta área');
return null; return null;
} }
@@ -550,14 +592,14 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
console.error('Error al agregar laboratorio:', err); console.error('Error al agregar laboratorio:', err);
throw err; throw err;
} }
}, [state, canAccessArea, apiCall]); }, [state, canAccessArea, checkAreaPermission, apiCall]);
const eliminarLaboratorio = useCallback(async (id: string) => { const eliminarLaboratorio = useCallback(async (id: string) => {
const laboratorio = state.laboratorios.find(l => l.id === id); const laboratorio = state.laboratorios.find(l => l.id === id);
if (!laboratorio) return; if (!laboratorio) return;
const internacion = state.internaciones.find(i => i.id === laboratorio.internacionId); const internacion = state.internaciones.find(i => i.id === laboratorio.internacionId);
const areaId = internacion?.areaId || null; const areaId = internacion?.areaId || null;
if (!canAccessArea(areaId)) { if (!checkAreaPermission(areaId)) {
console.warn('No tiene permisos para eliminar laboratorio en esta área'); console.warn('No tiene permisos para eliminar laboratorio en esta área');
return; return;
} }
@@ -571,14 +613,14 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
console.error('Error al eliminar laboratorio:', err); console.error('Error al eliminar laboratorio:', err);
throw err; throw err;
} }
}, [state, canAccessArea, apiCall]); }, [state, canAccessArea, checkAreaPermission, apiCall]);
const actualizarLaboratorio = useCallback(async (id: string, datos: Partial<Laboratorio>) => { const actualizarLaboratorio = useCallback(async (id: string, datos: Partial<Laboratorio>) => {
const laboratorio = state.laboratorios.find(l => l.id === id); const laboratorio = state.laboratorios.find(l => l.id === id);
if (!laboratorio) return; if (!laboratorio) return;
const internacion = state.internaciones.find(i => i.id === laboratorio.internacionId); const internacion = state.internaciones.find(i => i.id === laboratorio.internacionId);
const areaId = internacion?.areaId || null; const areaId = internacion?.areaId || null;
if (!canAccessArea(areaId)) { if (!checkAreaPermission(areaId)) {
console.warn('No tiene permisos para actualizar laboratorio en esta área'); console.warn('No tiene permisos para actualizar laboratorio en esta área');
return; return;
} }
@@ -592,13 +634,13 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
console.error('Error al actualizar laboratorio:', err); console.error('Error al actualizar laboratorio:', err);
throw err; throw err;
} }
}, [state, canAccessArea, apiCall]); }, [state, canAccessArea, checkAreaPermission, apiCall]);
// Acciones de glucemias // Acciones de glucemias
const agregarGlucemia = useCallback(async (glucemia: Omit<Glucemia, 'id'>) => { const agregarGlucemia = useCallback(async (glucemia: Omit<Glucemia, 'id'>) => {
const internacion = state.internaciones.find(i => i.id === glucemia.internacionId); const internacion = state.internaciones.find(i => i.id === glucemia.internacionId);
const areaId = internacion?.areaId || null; const areaId = internacion?.areaId || null;
if (!canAccessArea(areaId)) { if (!checkAreaPermission(areaId)) {
console.warn('No tiene permisos para agregar glucemia en esta área'); console.warn('No tiene permisos para agregar glucemia en esta área');
return null; return null;
} }
@@ -617,14 +659,14 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
console.error('Error al agregar glucemia:', err); console.error('Error al agregar glucemia:', err);
throw err; throw err;
} }
}, [state, canAccessArea, apiCall]); }, [state, canAccessArea, checkAreaPermission, apiCall]);
const eliminarGlucemia = useCallback(async (id: string) => { const eliminarGlucemia = useCallback(async (id: string) => {
const glucemia = state.glucemias.find(g => g.id === id); const glucemia = state.glucemias.find(g => g.id === id);
if (!glucemia) return; if (!glucemia) return;
const internacion = state.internaciones.find(i => i.id === glucemia.internacionId); const internacion = state.internaciones.find(i => i.id === glucemia.internacionId);
const areaId = internacion?.areaId || null; const areaId = internacion?.areaId || null;
if (!canAccessArea(areaId)) { if (!checkAreaPermission(areaId)) {
console.warn('No tiene permisos para eliminar glucemia en esta área'); console.warn('No tiene permisos para eliminar glucemia en esta área');
return; return;
} }
@@ -638,14 +680,14 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
console.error('Error al eliminar glucemia:', err); console.error('Error al eliminar glucemia:', err);
throw err; throw err;
} }
}, [state, canAccessArea, apiCall]); }, [state, canAccessArea, checkAreaPermission, apiCall]);
const actualizarGlucemia = useCallback(async (id: string, datos: Partial<Glucemia>) => { const actualizarGlucemia = useCallback(async (id: string, datos: Partial<Glucemia>) => {
const glucemia = state.glucemias.find(g => g.id === id); const glucemia = state.glucemias.find(g => g.id === id);
if (!glucemia) return; if (!glucemia) return;
const internacion = state.internaciones.find(i => i.id === glucemia.internacionId); const internacion = state.internaciones.find(i => i.id === glucemia.internacionId);
const areaId = internacion?.areaId || null; const areaId = internacion?.areaId || null;
if (!canAccessArea(areaId)) { if (!checkAreaPermission(areaId)) {
console.warn('No tiene permisos para actualizar glucemia en esta área'); console.warn('No tiene permisos para actualizar glucemia en esta área');
return; return;
} }
@@ -659,13 +701,13 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
console.error('Error al actualizar glucemia:', err); console.error('Error al actualizar glucemia:', err);
throw err; throw err;
} }
}, [state, canAccessArea, apiCall]); }, [state, canAccessArea, checkAreaPermission, apiCall]);
// Acciones de ácido-base // Acciones de ácido-base
const agregarAcidoBase = useCallback(async (acidoBase: Omit<AcidoBase, 'id'>) => { const agregarAcidoBase = useCallback(async (acidoBase: Omit<AcidoBase, 'id'>) => {
const internacion = state.internaciones.find(i => i.id === acidoBase.internacionId); const internacion = state.internaciones.find(i => i.id === acidoBase.internacionId);
const areaId = internacion?.areaId || null; const areaId = internacion?.areaId || null;
if (!canAccessArea(areaId)) { if (!checkAreaPermission(areaId)) {
console.warn('No tiene permisos para agregar ácido-base en esta área'); console.warn('No tiene permisos para agregar ácido-base en esta área');
return null; return null;
} }
@@ -684,14 +726,14 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
console.error('Error al agregar ácido-base:', err); console.error('Error al agregar ácido-base:', err);
throw err; throw err;
} }
}, [state, canAccessArea, apiCall]); }, [state, canAccessArea, checkAreaPermission, apiCall]);
const actualizarAcidoBase = useCallback(async (id: string, datos: Partial<AcidoBase>) => { const actualizarAcidoBase = useCallback(async (id: string, datos: Partial<AcidoBase>) => {
const acidoBase = state.acidosBase.find(a => a.id === id); const acidoBase = state.acidosBase.find(a => a.id === id);
if (!acidoBase) return; if (!acidoBase) return;
const internacion = state.internaciones.find(i => i.id === acidoBase.internacionId); const internacion = state.internaciones.find(i => i.id === acidoBase.internacionId);
const areaId = internacion?.areaId || null; const areaId = internacion?.areaId || null;
if (!canAccessArea(areaId)) { if (!checkAreaPermission(areaId)) {
console.warn('No tiene permisos para actualizar ácido-base en esta área'); console.warn('No tiene permisos para actualizar ácido-base en esta área');
return; return;
} }
@@ -705,14 +747,14 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
console.error('Error al actualizar ácido-base:', err); console.error('Error al actualizar ácido-base:', err);
throw err; throw err;
} }
}, [state, canAccessArea, apiCall]); }, [state, canAccessArea, checkAreaPermission, apiCall]);
const eliminarAcidoBase = useCallback(async (id: string) => { const eliminarAcidoBase = useCallback(async (id: string) => {
const acidoBase = state.acidosBase.find(a => a.id === id); const acidoBase = state.acidosBase.find(a => a.id === id);
if (!acidoBase) return; if (!acidoBase) return;
const internacion = state.internaciones.find(i => i.id === acidoBase.internacionId); const internacion = state.internaciones.find(i => i.id === acidoBase.internacionId);
const areaId = internacion?.areaId || null; const areaId = internacion?.areaId || null;
if (!canAccessArea(areaId)) { if (!checkAreaPermission(areaId)) {
console.warn('No tiene permisos para eliminar ácido-base en esta área'); console.warn('No tiene permisos para eliminar ácido-base en esta área');
return; return;
} }
@@ -726,13 +768,13 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
console.error('Error al eliminar ácido-base:', err); console.error('Error al eliminar ácido-base:', err);
throw err; throw err;
} }
}, [state, canAccessArea, apiCall]); }, [state, canAccessArea, checkAreaPermission, apiCall]);
// Acciones de cultivos // Acciones de cultivos
const agregarCultivo = useCallback(async (cultivo: Omit<Cultivo, 'id'>) => { const agregarCultivo = useCallback(async (cultivo: Omit<Cultivo, 'id'>) => {
const internacion = state.internaciones.find(i => i.id === cultivo.internacionId); const internacion = state.internaciones.find(i => i.id === cultivo.internacionId);
const areaId = internacion?.areaId || null; const areaId = internacion?.areaId || null;
if (!canAccessArea(areaId)) { if (!checkAreaPermission(areaId)) {
console.warn('No tiene permisos para agregar cultivo en esta área'); console.warn('No tiene permisos para agregar cultivo en esta área');
return null; return null;
} }
@@ -751,14 +793,14 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
console.error('Error al agregar cultivo:', err); console.error('Error al agregar cultivo:', err);
throw err; throw err;
} }
}, [state, canAccessArea, apiCall]); }, [state, canAccessArea, checkAreaPermission, apiCall]);
const actualizarCultivo = useCallback(async (id: string, datos: Partial<Cultivo>) => { const actualizarCultivo = useCallback(async (id: string, datos: Partial<Cultivo>) => {
const cultivo = state.cultivos.find(c => c.id === id); const cultivo = state.cultivos.find(c => c.id === id);
if (!cultivo) return; if (!cultivo) return;
const internacion = state.internaciones.find(i => i.id === cultivo.internacionId); const internacion = state.internaciones.find(i => i.id === cultivo.internacionId);
const areaId = internacion?.areaId || null; const areaId = internacion?.areaId || null;
if (!canAccessArea(areaId)) { if (!checkAreaPermission(areaId)) {
console.warn('No tiene permisos para actualizar cultivo en esta área'); console.warn('No tiene permisos para actualizar cultivo en esta área');
return; return;
} }
@@ -772,14 +814,14 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
console.error('Error al actualizar cultivo:', err); console.error('Error al actualizar cultivo:', err);
throw err; throw err;
} }
}, [state, canAccessArea, apiCall]); }, [state, canAccessArea, checkAreaPermission, apiCall]);
const eliminarCultivo = useCallback(async (id: string) => { const eliminarCultivo = useCallback(async (id: string) => {
const cultivo = state.cultivos.find(c => c.id === id); const cultivo = state.cultivos.find(c => c.id === id);
if (!cultivo) return; if (!cultivo) return;
const internacion = state.internaciones.find(i => i.id === cultivo.internacionId); const internacion = state.internaciones.find(i => i.id === cultivo.internacionId);
const areaId = internacion?.areaId || null; const areaId = internacion?.areaId || null;
if (!canAccessArea(areaId)) { if (!checkAreaPermission(areaId)) {
console.warn('No tiene permisos para eliminar cultivo en esta área'); console.warn('No tiene permisos para eliminar cultivo en esta área');
return; return;
} }
@@ -793,13 +835,13 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
console.error('Error al eliminar cultivo:', err); console.error('Error al eliminar cultivo:', err);
throw err; throw err;
} }
}, [state, canAccessArea, apiCall]); }, [state, canAccessArea, checkAreaPermission, apiCall]);
// Acciones de estudios complementarios // Acciones de estudios complementarios
const agregarEstudioComplementario = useCallback(async (estudio: Omit<EstudioComplementario, 'id'>) => { const agregarEstudioComplementario = useCallback(async (estudio: Omit<EstudioComplementario, 'id'>) => {
const internacion = state.internaciones.find(i => i.id === estudio.internacionId); const internacion = state.internaciones.find(i => i.id === estudio.internacionId);
const areaId = internacion?.areaId || null; const areaId = internacion?.areaId || null;
if (!canAccessArea(areaId)) { if (!checkAreaPermission(areaId)) {
console.warn('No tiene permisos para agregar estudio complementario en esta área'); console.warn('No tiene permisos para agregar estudio complementario en esta área');
return null; return null;
} }
@@ -818,14 +860,14 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
console.error('Error al agregar estudio:', err); console.error('Error al agregar estudio:', err);
throw err; throw err;
} }
}, [state, canAccessArea, apiCall]); }, [state, canAccessArea, checkAreaPermission, apiCall]);
const actualizarEstudioComplementario = useCallback(async (id: string, datos: Partial<EstudioComplementario>) => { const actualizarEstudioComplementario = useCallback(async (id: string, datos: Partial<EstudioComplementario>) => {
const estudio = state.estudiosComplementarios.find(e => e.id === id); const estudio = state.estudiosComplementarios.find(e => e.id === id);
if (!estudio) return; if (!estudio) return;
const internacion = state.internaciones.find(i => i.id === estudio.internacionId); const internacion = state.internaciones.find(i => i.id === estudio.internacionId);
const areaId = internacion?.areaId || null; const areaId = internacion?.areaId || null;
if (!canAccessArea(areaId)) { if (!checkAreaPermission(areaId)) {
console.warn('No tiene permisos para actualizar estudio complementario en esta área'); console.warn('No tiene permisos para actualizar estudio complementario en esta área');
return; return;
} }
@@ -839,14 +881,14 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
console.error('Error al actualizar estudio:', err); console.error('Error al actualizar estudio:', err);
throw err; throw err;
} }
}, [state, canAccessArea, apiCall]); }, [state, canAccessArea, checkAreaPermission, apiCall]);
const eliminarEstudioComplementario = useCallback(async (id: string) => { const eliminarEstudioComplementario = useCallback(async (id: string) => {
const estudio = state.estudiosComplementarios.find(e => e.id === id); const estudio = state.estudiosComplementarios.find(e => e.id === id);
if (!estudio) return; if (!estudio) return;
const internacion = state.internaciones.find(i => i.id === estudio.internacionId); const internacion = state.internaciones.find(i => i.id === estudio.internacionId);
const areaId = internacion?.areaId || null; const areaId = internacion?.areaId || null;
if (!canAccessArea(areaId)) { if (!checkAreaPermission(areaId)) {
console.warn('No tiene permisos para eliminar estudio complementario en esta área'); console.warn('No tiene permisos para eliminar estudio complementario en esta área');
return; return;
} }
@@ -860,13 +902,13 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
console.error('Error al eliminar estudio:', err); console.error('Error al eliminar estudio:', err);
throw err; throw err;
} }
}, [state, canAccessArea, apiCall]); }, [state, canAccessArea, checkAreaPermission, apiCall]);
// Acciones de interconsultas // Acciones de interconsultas
const agregarInterconsulta = useCallback(async (interconsulta: Omit<Interconsulta, 'id'>) => { const agregarInterconsulta = useCallback(async (interconsulta: Omit<Interconsulta, 'id'>) => {
const internacion = state.internaciones.find(i => i.id === interconsulta.internacionId); const internacion = state.internaciones.find(i => i.id === interconsulta.internacionId);
const areaId = internacion?.areaId || null; const areaId = internacion?.areaId || null;
if (!canAccessArea(areaId)) { if (!checkAreaPermission(areaId)) {
console.warn('No tiene permisos para agregar interconsulta en esta área'); console.warn('No tiene permisos para agregar interconsulta en esta área');
return null; return null;
} }
@@ -882,14 +924,14 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
console.error('Error al agregar interconsulta:', err); console.error('Error al agregar interconsulta:', err);
throw err; throw err;
} }
}, [state, canAccessArea, apiCall]); }, [state, canAccessArea, checkAreaPermission, apiCall]);
const actualizarInterconsulta = useCallback(async (id: string, datos: Partial<Interconsulta>) => { const actualizarInterconsulta = useCallback(async (id: string, datos: Partial<Interconsulta>) => {
const interconsulta = (state.interconsultas || []).find(ic => ic.id === id); const interconsulta = (state.interconsultas || []).find(ic => ic.id === id);
if (!interconsulta) return; if (!interconsulta) return;
const internacion = state.internaciones.find(i => i.id === interconsulta.internacionId); const internacion = state.internaciones.find(i => i.id === interconsulta.internacionId);
const areaId = internacion?.areaId || null; const areaId = internacion?.areaId || null;
if (!canAccessArea(areaId)) { if (!checkAreaPermission(areaId)) {
console.warn('No tiene permisos para actualizar interconsulta en esta área'); console.warn('No tiene permisos para actualizar interconsulta en esta área');
return; return;
} }
@@ -903,14 +945,14 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
console.error('Error al actualizar interconsulta:', err); console.error('Error al actualizar interconsulta:', err);
throw err; throw err;
} }
}, [state, canAccessArea, apiCall]); }, [state, canAccessArea, checkAreaPermission, apiCall]);
const eliminarInterconsulta = useCallback(async (id: string) => { const eliminarInterconsulta = useCallback(async (id: string) => {
const interconsulta = (state.interconsultas || []).find(ic => ic.id === id); const interconsulta = (state.interconsultas || []).find(ic => ic.id === id);
if (!interconsulta) return; if (!interconsulta) return;
const internacion = state.internaciones.find(i => i.id === interconsulta.internacionId); const internacion = state.internaciones.find(i => i.id === interconsulta.internacionId);
const areaId = internacion?.areaId || null; const areaId = internacion?.areaId || null;
if (!canAccessArea(areaId)) { if (!checkAreaPermission(areaId)) {
console.warn('No tiene permisos para eliminar interconsulta en esta área'); console.warn('No tiene permisos para eliminar interconsulta en esta área');
return; return;
} }
@@ -924,12 +966,12 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
console.error('Error al eliminar interconsulta:', err); console.error('Error al eliminar interconsulta:', err);
throw err; throw err;
} }
}, [state, canAccessArea, apiCall]); }, [state, canAccessArea, checkAreaPermission, apiCall]);
const agregarATB = useCallback(async (atb: Omit<ATB, 'id'>) => { const agregarATB = useCallback(async (atb: Omit<ATB, 'id'>) => {
const internacion = state.internaciones.find(i => i.id === atb.internacionId); const internacion = state.internaciones.find(i => i.id === atb.internacionId);
const areaId = internacion?.areaId || null; const areaId = internacion?.areaId || null;
if (!canAccessArea(areaId)) { if (!checkAreaPermission(areaId)) {
console.warn('No tiene permisos para agregar ATB en esta área'); console.warn('No tiene permisos para agregar ATB en esta área');
return null; return null;
} }
@@ -945,14 +987,14 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
console.error('Error al agregar ATB:', err); console.error('Error al agregar ATB:', err);
throw err; throw err;
} }
}, [state, canAccessArea, apiCall]); }, [state, canAccessArea, checkAreaPermission, apiCall]);
const actualizarATB = useCallback(async (id: string, datos: Partial<ATB>) => { const actualizarATB = useCallback(async (id: string, datos: Partial<ATB>) => {
const atb = state.atb.find(a => a.id === id); const atb = state.atb.find(a => a.id === id);
if (!atb) return; if (!atb) return;
const internacion = state.internaciones.find(i => i.id === atb.internacionId); const internacion = state.internaciones.find(i => i.id === atb.internacionId);
const areaId = internacion?.areaId || null; const areaId = internacion?.areaId || null;
if (!canAccessArea(areaId)) { if (!checkAreaPermission(areaId)) {
console.warn('No tiene permisos para actualizar ATB en esta área'); console.warn('No tiene permisos para actualizar ATB en esta área');
return; return;
} }
@@ -966,14 +1008,14 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
console.error('Error al actualizar ATB:', err); console.error('Error al actualizar ATB:', err);
throw err; throw err;
} }
}, [state, canAccessArea, apiCall]); }, [state, canAccessArea, checkAreaPermission, apiCall]);
const eliminarATB = useCallback(async (id: string) => { const eliminarATB = useCallback(async (id: string) => {
const atb = state.atb.find(a => a.id === id); const atb = state.atb.find(a => a.id === id);
if (!atb) return; if (!atb) return;
const internacion = state.internaciones.find(i => i.id === atb.internacionId); const internacion = state.internaciones.find(i => i.id === atb.internacionId);
const areaId = internacion?.areaId || null; const areaId = internacion?.areaId || null;
if (!canAccessArea(areaId)) { if (!checkAreaPermission(areaId)) {
console.warn('No tiene permisos para eliminar ATB en esta área'); console.warn('No tiene permisos para eliminar ATB en esta área');
return; return;
} }
@@ -987,12 +1029,12 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
console.error('Error al eliminar ATB:', err); console.error('Error al eliminar ATB:', err);
throw err; throw err;
} }
}, [state, canAccessArea, apiCall]); }, [state, canAccessArea, checkAreaPermission, apiCall]);
const agregarIndicacion = useCallback(async (indicacion: Omit<Indicacion, 'id'>) => { const agregarIndicacion = useCallback(async (indicacion: Omit<Indicacion, 'id'>) => {
const internacion = state.internaciones.find(i => i.id === indicacion.internacionId); const internacion = state.internaciones.find(i => i.id === indicacion.internacionId);
const areaId = internacion?.areaId || null; const areaId = internacion?.areaId || null;
if (!canAccessArea(areaId)) { if (!checkAreaPermission(areaId)) {
console.warn('No tiene permisos para agregar indicación en esta área'); console.warn('No tiene permisos para agregar indicación en esta área');
return null; return null;
} }
@@ -1008,14 +1050,14 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
console.error('Error al agregar indicación:', err); console.error('Error al agregar indicación:', err);
throw err; throw err;
} }
}, [state.internaciones, canAccessArea, apiCall]); }, [state.internaciones, canAccessArea, checkAreaPermission, apiCall]);
const actualizarIndicacion = useCallback(async (id: string, datos: Partial<Indicacion>) => { const actualizarIndicacion = useCallback(async (id: string, datos: Partial<Indicacion>) => {
const indicacion = state.indicaciones.find(i => i.id === id); const indicacion = state.indicaciones.find(i => i.id === id);
if (!indicacion) return; if (!indicacion) return;
const internacion = state.internaciones.find(i => i.id === indicacion.internacionId); const internacion = state.internaciones.find(i => i.id === indicacion.internacionId);
const areaId = internacion?.areaId || null; const areaId = internacion?.areaId || null;
if (!canAccessArea(areaId)) { if (!checkAreaPermission(areaId)) {
console.warn('No tiene permisos para actualizar indicación en esta área'); console.warn('No tiene permisos para actualizar indicación en esta área');
return; return;
} }
@@ -1029,14 +1071,14 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
console.error('Error al actualizar indicación:', err); console.error('Error al actualizar indicación:', err);
throw err; throw err;
} }
}, [state.indicaciones, state.internaciones, canAccessArea, apiCall]); }, [state.indicaciones, state.internaciones, canAccessArea, checkAreaPermission, apiCall]);
const eliminarIndicacion = useCallback(async (id: string) => { const eliminarIndicacion = useCallback(async (id: string) => {
const indicacion = state.indicaciones.find(i => i.id === id); const indicacion = state.indicaciones.find(i => i.id === id);
if (!indicacion) return; if (!indicacion) return;
const internacion = state.internaciones.find(i => i.id === indicacion.internacionId); const internacion = state.internaciones.find(i => i.id === indicacion.internacionId);
const areaId = internacion?.areaId || null; const areaId = internacion?.areaId || null;
if (!canAccessArea(areaId)) { if (!checkAreaPermission(areaId)) {
console.warn('No tiene permisos para eliminar indicación en esta área'); console.warn('No tiene permisos para eliminar indicación en esta área');
return; return;
} }
@@ -1050,12 +1092,12 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
console.error('Error al eliminar indicación:', err); console.error('Error al eliminar indicación:', err);
throw err; throw err;
} }
}, [state.indicaciones, state.internaciones, canAccessArea, apiCall]); }, [state.indicaciones, state.internaciones, canAccessArea, checkAreaPermission, apiCall]);
const agregarMovimientoIndicacion = useCallback(async (movimiento: any) => { const agregarMovimientoIndicacion = useCallback(async (movimiento: any) => {
const internacion = state.internaciones.find(i => i.id === movimiento.internacionId); const internacion = state.internaciones.find(i => i.id === movimiento.internacionId);
const areaId = internacion?.areaId || null; const areaId = internacion?.areaId || null;
if (!canAccessArea(areaId)) { if (!checkAreaPermission(areaId)) {
console.warn('No tiene permisos para agregar movimiento de indicación en esta área'); console.warn('No tiene permisos para agregar movimiento de indicación en esta área');
return; return;
} }
@@ -1070,7 +1112,7 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
console.error('Error al agregar movimiento:', err); console.error('Error al agregar movimiento:', err);
throw err; throw err;
} }
}, [state, canAccessArea, apiCall]); }, [state, canAccessArea, checkAreaPermission, apiCall]);
const getMovimientosByInternacion = useCallback((internacionId: string) => { const getMovimientosByInternacion = useCallback((internacionId: string) => {
return (state.movimientosIndicaciones || []) return (state.movimientosIndicaciones || [])
@@ -1318,6 +1360,7 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
canAccessArea, canAccessArea,
canChangeBed, canChangeBed,
canEditInternacion, canEditInternacion,
canEditIngreso,
canEditCama, canEditCama,
canEditPaciente, canEditPaciente,
getCamaAreaId, getCamaAreaId,
+10 -2
View File
@@ -14,7 +14,7 @@ import { Plus, Pencil, Trash2 } from 'lucide-react';
const API_BASE = import.meta.env.VITE_API_URL || '/api'; const API_BASE = import.meta.env.VITE_API_URL || '/api';
export function GestionUsuarios() { export function GestionUsuarios() {
const { logout } = useHospitalStore(); const { currentUser } = useHospitalStore();
const [usuarios, setUsuarios] = useState<Usuario[]>([]); const [usuarios, setUsuarios] = useState<Usuario[]>([]);
const [areas, setAreas] = useState<Area[]>([]); const [areas, setAreas] = useState<Area[]>([]);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
@@ -157,6 +157,14 @@ export function GestionUsuarios() {
return areas.find(a => a.id === areaId)?.nombre || '-'; return areas.find(a => a.id === areaId)?.nombre || '-';
}; };
if (!currentUser || currentUser.rol !== 'admin') {
return (
<div className="p-8 text-center text-red-500 font-semibold">
No tiene permisos para acceder al módulo de gestión de usuarios.
</div>
);
}
if (loading) { if (loading) {
return <div>Cargando...</div>; return <div>Cargando...</div>;
} }
@@ -319,7 +327,7 @@ export function GestionUsuarios() {
</div> </div>
</div> </div>
{form.rol === 'medico' && ( {form.rol !== 'admin' && (
<div className="space-y-2"> <div className="space-y-2">
<Label>Área Asignada</Label> <Label>Área Asignada</Label>
<Select value={form.areaId} onValueChange={(v) => setForm({ ...form, areaId: v })}> <Select value={form.areaId} onValueChange={(v) => setForm({ ...form, areaId: v })}>