Add area assignment to internaciones and permission controls

- Add areaId field to Internacion type and database schema
- Add area selection in NuevoIngreso, EditIngreso, and Internaciones forms
- Filter out 'Fuera de area' from area selection dropdowns
- Add permission controls for users to only edit internaciones in their area
- Add canEdit check to hide 'Editar Ingreso' button in HistoriaClinica
- Fix getInternacionAreaId to use new areaId field first, fallback to cama area
- Add INSERT OR IGNORE to prevent duplicate errors
This commit is contained in:
2026-04-23 17:49:07 -03:00
parent 6611258ce9
commit 56402563fb
9 changed files with 345 additions and 47 deletions
+236 -29
View File
@@ -172,13 +172,21 @@ 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;
const user = state.currentUser;
const areaId = cama.areaId || null;
if (user && user.rol !== 'admin' && areaId && user.areaId !== areaId) {
console.warn('No tiene permisos para actualizar cama en esta área');
return;
}
setState(prev => ({
...prev,
camas: prev.camas.map(c => c.id === id ? { ...c, ...datos } : c),
}));
}, []);
}, [state.camas, state.currentUser]);
const agregarCama = useCallback((cama: Omit<Cama, 'id'>) => {
const nuevaCama: Cama = {
@@ -202,6 +210,12 @@ export function useHospitalStore() {
// Acciones de internaciones
const iniciarInternacion = useCallback((internacion: Omit<Internacion, 'id' | 'activa'>) => {
const user = state.currentUser;
const areaId = internacion.areaId || null;
if (user && user.rol !== 'admin' && areaId && user.areaId !== areaId) {
console.warn('No tiene permisos para iniciar internación en esta área');
return null;
}
const nuevaInternacion: Internacion = {
...internacion,
id: generateUUID(),
@@ -217,7 +231,7 @@ export function useHospitalStore() {
),
}));
return nuevaInternacion.id;
}, []);
}, [state.currentUser]);
const finalizarInternacion = useCallback((internacionId: string, datos: {
fechaEgreso: string;
@@ -245,6 +259,14 @@ 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;
if (user && user.rol !== 'admin' && areaId && user.areaId !== areaId) {
console.warn('No tiene permisos para actualizar internación en esta área');
return;
}
setState(prev => ({
...prev,
internaciones: prev.internaciones.map(i =>
@@ -253,10 +275,16 @@ const finalizarInternacion = useCallback((internacionId: string, datos: {
: i
),
}));
}, []);
}, [state.internaciones, state.currentUser]);
// Acciones de evoluciones
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)) {
console.warn('No tiene permisos para agregar evolución en esta área');
return null;
}
const nuevaEvolucion: Evolucion = {
...evolucion,
id: generateUUID(),
@@ -266,9 +294,17 @@ const finalizarInternacion = useCallback((internacionId: string, datos: {
evoluciones: [...prev.evoluciones, nuevaEvolucion],
}));
return nuevaEvolucion.id;
}, []);
}, [state.internaciones, state.currentUser]);
const eliminarEvolucion = useCallback((id: string) => {
const evolucion = state.evoluciones.find(e => e.id === id);
if (!evolucion) return;
const internacion = state.internaciones.find(i => i.id === evolucion.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
console.warn('No tiene permisos para eliminar evolución en esta área');
return;
}
setState(prev => ({
...prev,
evoluciones: prev.evoluciones.filter(e => e.id !== id),
@@ -276,14 +312,28 @@ const finalizarInternacion = useCallback((internacionId: string, datos: {
}, []);
const actualizarEvolucion = useCallback((id: string, datos: Partial<Evolucion>) => {
const evolucion = state.evoluciones.find(e => e.id === id);
if (!evolucion) return;
const internacion = state.internaciones.find(i => i.id === evolucion.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
console.warn('No tiene permisos para actualizar evolución en esta área');
return;
}
setState(prev => ({
...prev,
evoluciones: prev.evoluciones.map(e => e.id === id ? { ...e, ...datos } : e),
}));
}, []);
}, [state.internaciones, state.currentUser]);
// Acciones de laboratorios
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)) {
console.warn('No tiene permisos para agregar laboratorio en esta área');
return null;
}
const nuevoLaboratorio: Laboratorio = {
...laboratorio,
id: generateUUID(),
@@ -293,24 +343,46 @@ const finalizarInternacion = useCallback((internacionId: string, datos: {
laboratorios: [...prev.laboratorios, nuevoLaboratorio],
}));
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)) {
console.warn('No tiene permisos para eliminar laboratorio en esta área');
return;
}
setState(prev => ({
...prev,
laboratorios: prev.laboratorios.filter(l => l.id !== id),
}));
}, []);
}, [state.internaciones, state.currentUser]);
const actualizarLaboratorio = useCallback((id: string, datos: Partial<Laboratorio>) => {
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)) {
console.warn('No tiene permisos para actualizar laboratorio en esta área');
return;
}
setState(prev => ({
...prev,
laboratorios: prev.laboratorios.map(l => l.id === id ? { ...l, ...datos } : l),
}));
}, []);
}, [state.internaciones, state.currentUser]);
// Acciones de ácido-base
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)) {
console.warn('No tiene permisos para agregar ácido-base en esta área');
return null;
}
const nuevoAcidoBase: AcidoBase = {
...acidoBase,
id: generateUUID(),
@@ -320,24 +392,46 @@ const finalizarInternacion = useCallback((internacionId: string, datos: {
acidosBase: [...prev.acidosBase, nuevoAcidoBase],
}));
return nuevoAcidoBase.id;
}, []);
}, [state.internaciones, state.currentUser]);
const actualizarAcidoBase = useCallback((id: string, datos: Partial<AcidoBase>) => {
const acidoBase = state.acidosBase.find(a => a.id === id);
if (!acidoBase) return;
const internacion = state.internaciones.find(i => i.id === acidoBase.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
console.warn('No tiene permisos para actualizar ácido-base en esta área');
return;
}
setState(prev => ({
...prev,
acidosBase: prev.acidosBase.map(a => a.id === id ? { ...a, ...datos } : a),
}));
}, []);
}, [state.internaciones, state.currentUser]);
const eliminarAcidoBase = useCallback((id: string) => {
const acidoBase = state.acidosBase.find(a => a.id === id);
if (!acidoBase) return;
const internacion = state.internaciones.find(i => i.id === acidoBase.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
console.warn('No tiene permisos para eliminar ácido-base en esta área');
return;
}
setState(prev => ({
...prev,
acidosBase: prev.acidosBase.filter(a => a.id !== id),
}));
}, []);
}, [state.internaciones, state.currentUser]);
// Acciones de cultivos
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)) {
console.warn('No tiene permisos para agregar cultivo en esta área');
return null;
}
const nuevoCultivo: Cultivo = {
...cultivo,
id: generateUUID(),
@@ -347,24 +441,46 @@ const finalizarInternacion = useCallback((internacionId: string, datos: {
cultivos: [...prev.cultivos, nuevoCultivo],
}));
return nuevoCultivo.id;
}, []);
}, [state.internaciones, state.currentUser]);
const actualizarCultivo = useCallback((id: string, datos: Partial<Cultivo>) => {
const cultivo = state.cultivos.find(c => c.id === id);
if (!cultivo) return;
const internacion = state.internaciones.find(i => i.id === cultivo.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
console.warn('No tiene permisos para actualizar cultivo en esta área');
return;
}
setState(prev => ({
...prev,
cultivos: prev.cultivos.map(c => c.id === id ? { ...c, ...datos } : c),
}));
}, []);
}, [state.internaciones, state.currentUser]);
const eliminarCultivo = useCallback((id: string) => {
const cultivo = state.cultivos.find(c => c.id === id);
if (!cultivo) return;
const internacion = state.internaciones.find(i => i.id === cultivo.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
console.warn('No tiene permisos para eliminar cultivo en esta área');
return;
}
setState(prev => ({
...prev,
cultivos: prev.cultivos.filter(c => c.id !== id),
}));
}, []);
}, [state.internaciones, state.currentUser]);
// Acciones de estudios complementarios
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)) {
console.warn('No tiene permisos para agregar estudio complementario en esta área');
return null;
}
const nuevoEstudio: EstudioComplementario = {
...estudio,
id: generateUUID(),
@@ -374,98 +490,186 @@ const finalizarInternacion = useCallback((internacionId: string, datos: {
estudiosComplementarios: [...prev.estudiosComplementarios, nuevoEstudio],
}));
return nuevoEstudio.id;
}, []);
}, [state.internaciones, state.currentUser]);
const actualizarEstudioComplementario = useCallback((id: string, datos: Partial<EstudioComplementario>) => {
const estudio = state.estudiosComplementarios.find(e => e.id === id);
if (!estudio) return;
const internacion = state.internaciones.find(i => i.id === estudio.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
console.warn('No tiene permisos para actualizar estudio complementario en esta área');
return;
}
setState(prev => ({
...prev,
estudiosComplementarios: prev.estudiosComplementarios.map(e => e.id === id ? { ...e, ...datos } : e),
}));
}, []);
}, [state.internaciones, state.currentUser]);
const eliminarEstudioComplementario = useCallback((id: string) => {
const estudio = state.estudiosComplementarios.find(e => e.id === id);
if (!estudio) return;
const internacion = state.internaciones.find(i => i.id === estudio.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
console.warn('No tiene permisos para eliminar estudio complementario en esta área');
return;
}
setState(prev => ({
...prev,
estudiosComplementarios: prev.estudiosComplementarios.filter(e => e.id !== id),
}));
}, []);
}, [state.internaciones, state.currentUser]);
// Acciones de interconsultas
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)) {
console.warn('No tiene permisos para agregar interconsulta en esta área');
return null;
}
const nuevaInterconsulta: Interconsulta = { ...interconsulta, id: generateUUID() };
setState(prev => ({
...prev,
interconsultas: [...(prev.interconsultas || []), nuevaInterconsulta],
}));
return nuevaInterconsulta.id;
}, []);
}, [state.internaciones, state.currentUser]);
const actualizarInterconsulta = useCallback((id: string, datos: Partial<Interconsulta>) => {
const interconsulta = (state.interconsultas || []).find(ic => ic.id === id);
if (!interconsulta) return;
const internacion = state.internaciones.find(i => i.id === interconsulta.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
console.warn('No tiene permisos para actualizar interconsulta en esta área');
return;
}
setState(prev => ({
...prev,
interconsultas: (prev.interconsultas || []).map(ic => ic.id === id ? { ...ic, ...datos } : ic),
}));
}, []);
}, [state.internaciones, state.currentUser]);
const eliminarInterconsulta = useCallback((id: string) => {
const interconsulta = (state.interconsultas || []).find(ic => ic.id === id);
if (!interconsulta) return;
const internacion = state.internaciones.find(i => i.id === interconsulta.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
console.warn('No tiene permisos para eliminar interconsulta en esta área');
return;
}
setState(prev => ({
...prev,
interconsultas: (prev.interconsultas || []).filter(ic => ic.id !== id),
}));
}, []);
}, [state.internaciones, state.currentUser]);
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)) {
console.warn('No tiene permisos para agregar ATB en esta área');
return null;
}
const nuevoATB: ATB = { ...atb, id: generateUUID() };
setState(prev => ({
...prev,
atb: [...prev.atb, nuevoATB],
}));
return nuevoATB.id;
}, []);
}, [state.internaciones, state.currentUser]);
const actualizarATB = useCallback((id: string, datos: Partial<ATB>) => {
const atb = state.atb.find(a => a.id === id);
if (!atb) return;
const internacion = state.internaciones.find(i => i.id === atb.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
console.warn('No tiene permisos para actualizar ATB en esta área');
return;
}
setState(prev => ({
...prev,
atb: prev.atb.map(a => a.id === id ? { ...a, ...datos } : a),
}));
}, []);
}, [state.internaciones, state.currentUser]);
const eliminarATB = useCallback((id: string) => {
const atb = state.atb.find(a => a.id === id);
if (!atb) return;
const internacion = state.internaciones.find(i => i.id === atb.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
console.warn('No tiene permisos para eliminar ATB en esta área');
return;
}
setState(prev => ({
...prev,
atb: prev.atb.filter(a => a.id !== id),
}));
}, []);
}, [state.internaciones, state.currentUser]);
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)) {
console.warn('No tiene permisos para agregar indicación en esta área');
return null;
}
const nuevaIndicacion: Indicacion = { ...indicacion, id: generateUUID() };
setState(prev => ({
...prev,
indicaciones: [...prev.indicaciones, nuevaIndicacion],
}));
return nuevaIndicacion.id;
}, []);
}, [state.internaciones, state.currentUser]);
const actualizarIndicacion = useCallback((id: string, datos: Partial<Indicacion>) => {
const indicacion = state.indicaciones.find(i => i.id === id);
if (!indicacion) return;
const internacion = state.internaciones.find(i => i.id === indicacion.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
console.warn('No tiene permisos para actualizar indicación en esta área');
return;
}
setState(prev => ({
...prev,
indicaciones: prev.indicaciones.map(i => i.id === id ? { ...i, ...datos } : i),
}));
}, []);
}, [state.internaciones, state.currentUser]);
const eliminarIndicacion = useCallback((id: string) => {
const indicacion = state.indicaciones.find(i => i.id === id);
if (!indicacion) return;
const internacion = state.internaciones.find(i => i.id === indicacion.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
console.warn('No tiene permisos para eliminar indicación en esta área');
return;
}
setState(prev => ({
...prev,
indicaciones: prev.indicaciones.filter(i => i.id !== id),
}));
}, []);
}, [state.internaciones, state.currentUser]);
const agregarMovimientoIndicacion = useCallback((movimiento: any) => {
const internacion = state.internaciones.find(i => i.id === movimiento.internacionId);
const areaId = internacion?.areaId || null;
if (!canEditInArea(areaId)) {
console.warn('No tiene permisos para agregar movimiento de indicación en esta área');
return;
}
setState(prev => ({
...prev,
movimientosIndicaciones: [...(prev.movimientosIndicaciones || []), { ...movimiento, id: generateUUID() }],
}));
}, []);
}, [state.internaciones, state.currentUser]);
const getMovimientosByInternacion = useCallback((internacionId: string) => {
return (state.movimientosIndicaciones || [])
@@ -662,6 +866,9 @@ const getEstadisticas = useCallback(() => {
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]);