Restringir operaciones de grupos al administrador y permitir a usuarios regulares solo modificar el Tipo de camas de su grupo de trabajo

This commit is contained in:
2026-08-11 23:47:45 +00:00
parent e869d6a19e
commit da7a82502f
2 changed files with 66 additions and 30 deletions
+32 -8
View File
@@ -305,11 +305,15 @@ export function useHospitalStore() {
const cama = state.camas.find(c => c.id === id); const cama = state.camas.find(c => c.id === id);
if (!cama) return; if (!cama) return;
const user = state.currentUser; const user = state.currentUser;
const grupoId = cama.grupoId || null; if (user && user.rol !== 'admin') {
if (user && user.rol !== 'admin' && grupoId && user.grupoId !== grupoId) { // Must have a working group and the bed must belong to it
console.warn('No tiene permisos para actualizar cama en esta área'); if (!user.grupoId || cama.grupoId !== user.grupoId) {
toast.error('No tiene permisos para modificar camas fuera de su grupo de trabajo');
return; return;
} }
// A regular user can ONLY modify the "Tipo" of the bed.
datos = { tipo: datos.tipo };
}
try { try {
if (datos.numero !== undefined) { if (datos.numero !== undefined) {
datos.sector = computeSector(datos.numero); datos.sector = computeSector(datos.numero);
@@ -326,6 +330,10 @@ export function useHospitalStore() {
}, [state, apiCall]); }, [state, apiCall]);
const agregarCama = useCallback(async (cama: Omit<Cama, 'id'>) => { const agregarCama = useCallback(async (cama: Omit<Cama, 'id'>) => {
if (state.currentUser?.rol !== 'admin') {
toast.error('Solo el usuario administrador puede agregar camas');
return;
}
const nuevaCama: Cama = { const nuevaCama: Cama = {
...cama, ...cama,
id: generateUUID(), id: generateUUID(),
@@ -342,9 +350,13 @@ const agregarCama = useCallback(async (cama: Omit<Cama, 'id'>) => {
console.error('Error al agregar cama:', err); console.error('Error al agregar cama:', err);
throw err; throw err;
} }
}, [apiCall]); }, [state.currentUser, apiCall]);
const eliminarCama = useCallback(async (id: string) => { const eliminarCama = useCallback(async (id: string) => {
if (state.currentUser?.rol !== 'admin') {
toast.error('Solo el usuario administrador puede eliminar camas');
return;
}
try { try {
await apiCall('DELETE', `/camas/${id}`); await apiCall('DELETE', `/camas/${id}`);
setState(prev => ({ setState(prev => ({
@@ -356,7 +368,7 @@ const agregarCama = useCallback(async (cama: Omit<Cama, 'id'>) => {
console.error('Error al eliminar cama:', err); console.error('Error al eliminar cama:', err);
throw err; throw err;
} }
}, [apiCall]); }, [state.currentUser, 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'>) => {
@@ -1211,6 +1223,10 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
// Acciones de grupos // Acciones de grupos
const agregarGrupo = useCallback(async (grupo: Omit<Grupo, 'id'>) => { const agregarGrupo = useCallback(async (grupo: Omit<Grupo, 'id'>) => {
if (state.currentUser?.rol !== 'admin') {
toast.error('Solo el usuario administrador puede agregar grupos de trabajo');
return;
}
const nuevaGrupo: Grupo = { ...grupo, id: generateUUID() }; const nuevaGrupo: Grupo = { ...grupo, id: generateUUID() };
try { try {
await apiCall('POST', '/grupos', nuevaGrupo); await apiCall('POST', '/grupos', nuevaGrupo);
@@ -1223,9 +1239,13 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
console.error('Error al agregar área:', err); console.error('Error al agregar área:', err);
throw err; throw err;
} }
}, [apiCall]); }, [state.currentUser, apiCall]);
const actualizarGrupo = useCallback(async (id: string, datos: Partial<Grupo>) => { const actualizarGrupo = useCallback(async (id: string, datos: Partial<Grupo>) => {
if (state.currentUser?.rol !== 'admin') {
toast.error('Solo el usuario administrador puede modificar grupos de trabajo');
return;
}
try { try {
await apiCall('PUT', `/grupos/${id}`, datos); await apiCall('PUT', `/grupos/${id}`, datos);
setState(prev => ({ setState(prev => ({
@@ -1236,9 +1256,13 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
console.error('Error al actualizar área:', err); console.error('Error al actualizar área:', err);
throw err; throw err;
} }
}, [apiCall]); }, [state.currentUser, apiCall]);
const eliminarGrupo = useCallback(async (id: string) => { const eliminarGrupo = useCallback(async (id: string) => {
if (state.currentUser?.rol !== 'admin') {
toast.error('Solo el usuario administrador puede eliminar grupos de trabajo');
return;
}
try { try {
await apiCall('DELETE', `/grupos/${id}`); await apiCall('DELETE', `/grupos/${id}`);
setState(prev => ({ setState(prev => ({
@@ -1250,7 +1274,7 @@ const actualizarInternacion = useCallback(async (internacionId: string, datos: P
console.error('Error al eliminar área:', err); console.error('Error al eliminar área:', err);
throw err; throw err;
} }
}, [apiCall]); }, [state.currentUser, apiCall]);
// Funciones de utilidad para consultas // Funciones de utilidad para consultas
const getPacienteById = useCallback((id: string) => { const getPacienteById = useCallback((id: string) => {
+16 -4
View File
@@ -157,6 +157,7 @@ export function MapaCamas({
{camas.filter(c => isCamaFueraDeGrupo(c)).length} Fuera de Área {camas.filter(c => isCamaFueraDeGrupo(c)).length} Fuera de Área
</Badge> </Badge>
<div className="ml-0 sm:ml-4 flex items-center gap-2 flex-wrap sm:flex-nowrap"> <div className="ml-0 sm:ml-4 flex items-center gap-2 flex-wrap sm:flex-nowrap">
{currentUser?.rol === 'admin' && (
<Button variant="outline" onClick={() => { <Button variant="outline" onClick={() => {
setEditingGrupoId(null); setEditingGrupoId(null);
setGrupoNombre(''); setGrupoNombre('');
@@ -164,6 +165,8 @@ export function MapaCamas({
}} className="text-xs px-2 py-1 sm:text-sm sm:px-4 sm:py-2"> }} className="text-xs px-2 py-1 sm:text-sm sm:px-4 sm:py-2">
Administrar Grupos Administrar Grupos
</Button> </Button>
)}
{currentUser?.rol === 'admin' && (
<Button variant="outline" onClick={() => { <Button variant="outline" onClick={() => {
setEditingBed(null); setEditingBed(null);
setBedNumero(''); setBedNumero('');
@@ -174,6 +177,7 @@ export function MapaCamas({
<Plus className="h-3 w-3 sm:h-4 sm:w-4 sm:mr-1" /> <Plus className="h-3 w-3 sm:h-4 sm:w-4 sm:mr-1" />
<span className="hidden sm:inline">Agregar Cama</span> <span className="hidden sm:inline">Agregar Cama</span>
</Button> </Button>
)}
</div> </div>
</div> </div>
</div> </div>
@@ -441,7 +445,7 @@ export function MapaCamas({
<Edit2 className="h-4 w-4 mr-1" />Editar <Edit2 className="h-4 w-4 mr-1" />Editar
</Button> </Button>
)} )}
{canEditCama(cama.id) && ( {canEditCama(cama.id) && currentUser?.rol === 'admin' && (
<Button variant="destructive" onClick={() => { <Button variant="destructive" onClick={() => {
onEliminarCama(cama.id); onEliminarCama(cama.id);
}}> }}>
@@ -518,7 +522,11 @@ export function MapaCamas({
<div className="space-y-4"> <div className="space-y-4">
<div> <div>
<Label>Número</Label> <Label>Número</Label>
<Input value={bedNumero} onChange={(e) => setBedNumero(e.target.value)} /> <Input
value={bedNumero}
onChange={(e) => setBedNumero(e.target.value)}
disabled={currentUser?.rol !== 'admin'}
/>
</div> </div>
<div> <div>
<Label>Tipo</Label> <Label>Tipo</Label>
@@ -539,7 +547,11 @@ export function MapaCamas({
</div> </div>
<div> <div>
<Label>Grupo</Label> <Label>Grupo</Label>
<Select value={bedGrupoId ?? '__none'} onValueChange={(v) => setBedGrupoId(v === '__none' ? undefined : v)}> <Select
value={bedGrupoId ?? '__none'}
onValueChange={(v) => setBedGrupoId(v === '__none' ? undefined : v)}
disabled={currentUser?.rol !== 'admin'}
>
<SelectTrigger> <SelectTrigger>
<SelectValue placeholder="Seleccione grupo" /> <SelectValue placeholder="Seleccione grupo" />
</SelectTrigger> </SelectTrigger>
@@ -552,7 +564,7 @@ export function MapaCamas({
</Select> </Select>
</div> </div>
<div className="flex gap-2 justify-end"> <div className="flex gap-2 justify-end">
{editingBed && ( {editingBed && currentUser?.rol === 'admin' && (
<Button variant="destructive" onClick={() => { onEliminarCama(editingBed.id); setBedDialogOpen(false); }}> <Button variant="destructive" onClick={() => { onEliminarCama(editingBed.id); setBedDialogOpen(false); }}>
Eliminar Eliminar
</Button> </Button>