import React, { type ReactNode, useState, useEffect, useMemo } from 'react'; import { Box, AppBar, Toolbar, Typography, Tabs, Tab, Paper, IconButton, Menu, MenuItem, ListItemIcon, ListItemText, Divider, Button, Badge } from '@mui/material'; import AccountCircle from '@mui/icons-material/AccountCircle'; import LockResetIcon from '@mui/icons-material/LockReset'; import LogoutIcon from '@mui/icons-material/Logout'; import NotificationsIcon from '@mui/icons-material/Notifications'; import { useAuth } from '../contexts/AuthContext'; import ChangePasswordModal from '../components/Modals/Usuarios/ChangePasswordModal'; import { useNavigate, useLocation } from 'react-router-dom'; import { usePermissions } from '../hooks/usePermissions'; interface MainLayoutProps { children: ReactNode; } // --- Helper para dar nombres legibles a los tipos de alerta --- const getTipoAlertaLabel = (tipoAlerta: string): string => { switch (tipoAlerta) { case 'DevolucionAnomala': return 'Devoluciones Anómalas'; case 'ComportamientoSistema': return 'Anomalías del Sistema'; case 'FaltaDeDatos': return 'Falta de Datos'; default: return tipoAlerta; } }; // Definición original de módulos const allAppModules = [ { label: 'Inicio', path: '/', requiredPermission: null }, // Inicio siempre visible { label: 'Distribución', path: '/distribucion', requiredPermission: 'SS001' }, { label: 'Contables', path: '/contables', requiredPermission: 'SS002' }, { label: 'Impresión', path: '/impresion', requiredPermission: 'SS003' }, { label: 'Reportes', path: '/reportes', requiredPermission: 'SS004' }, { label: 'Radios', path: '/radios', requiredPermission: 'SS005' }, { label: 'Usuarios', path: '/usuarios', requiredPermission: 'SS006' }, { label: 'Auditoría', path: '/auditoria', requiredPermission: null, onlySuperAdmin: true }, ]; const MainLayout: React.FC = ({ children }) => { // Obtenemos todo lo necesario del AuthContext, INCLUYENDO LAS ALERTAS const { user, logout, isAuthenticated, isPasswordChangeForced, showForcedPasswordChangeModal, setShowForcedPasswordChangeModal, passwordChangeCompleted, alertas } = useAuth(); // El resto de los hooks locales no cambian const { tienePermiso, isSuperAdmin } = usePermissions(); const navigate = useNavigate(); const location = useLocation(); const [selectedTab, setSelectedTab] = useState(false); const [anchorElUserMenu, setAnchorElUserMenu] = useState(null); const [anchorElAlertasMenu, setAnchorElAlertasMenu] = useState(null); // --- Agrupación de alertas para el menú --- const gruposDeAlertas = useMemo(() => { if (!alertas || !Array.isArray(alertas)) return []; const groups = alertas.reduce((acc, alerta) => { const label = getTipoAlertaLabel(alerta.tipoAlerta); acc[label] = (acc[label] || 0) + 1; return acc; }, {} as Record); return Object.entries(groups); // Devuelve [['Devoluciones Anómalas', 5], ...] }, [alertas]); const numAlertas = alertas.length; const accessibleModules = useMemo(() => { if (!isAuthenticated) return []; return allAppModules.filter(module => { if (module.onlySuperAdmin) { // Si el módulo es solo para SuperAdmin return isSuperAdmin; } if (module.requiredPermission === null) return true; return isSuperAdmin || tienePermiso(module.requiredPermission); }); }, [isAuthenticated, isSuperAdmin, tienePermiso]); useEffect(() => { const currentModulePath = accessibleModules.findIndex(module => location.pathname === module.path || (module.path !== '/' && location.pathname.startsWith(module.path + '/')) ); if (currentModulePath !== -1) { setSelectedTab(currentModulePath); } else if (location.pathname === '/') { const inicioIndex = accessibleModules.findIndex(m => m.path === '/'); if (inicioIndex !== -1) setSelectedTab(inicioIndex); else setSelectedTab(false); } else { // Si la ruta actual no coincide con ningún módulo accesible, // y no es la raíz, podría ser una subruta de un módulo no accesible. // O podría ser una ruta inválida. // Podríamos intentar encontrar el módulo base y ver si es accesible. const basePath = "/" + (location.pathname.split('/')[1] || ""); const parentModuleIndex = accessibleModules.findIndex(m => m.path === basePath); if (parentModuleIndex !== -1) { setSelectedTab(parentModuleIndex); } else { setSelectedTab(false); } } }, [location.pathname, accessibleModules]); const handleOpenUserMenu = (event: React.MouseEvent) => { setAnchorElUserMenu(event.currentTarget); }; const handleCloseUserMenu = () => { setAnchorElUserMenu(null); }; // Handlers para el nuevo menú de alertas const handleOpenAlertasMenu = (event: React.MouseEvent) => { setAnchorElAlertasMenu(event.currentTarget); }; const handleCloseAlertasMenu = () => { setAnchorElAlertasMenu(null); }; const handleNavigateToAlertas = () => { navigate('/anomalias/alertas'); handleCloseAlertasMenu(); }; const handleChangePasswordClick = () => { setShowForcedPasswordChangeModal(true); handleCloseUserMenu(); }; const handleLogoutClick = () => { logout(); handleCloseUserMenu(); }; const handleModalClose = (passwordChangedSuccessfully: boolean) => { if (passwordChangedSuccessfully) { passwordChangeCompleted(); } else { if (isPasswordChangeForced) { logout(); // Si es forzado y cancela/falla, desloguear } else { setShowForcedPasswordChangeModal(false); // Si no es forzado, solo cerrar modal } } }; const handleTabChange = (_event: React.SyntheticEvent, newValue: number) => { if (accessibleModules[newValue]) { setSelectedTab(newValue); navigate(accessibleModules[newValue].path); } }; if (showForcedPasswordChangeModal && isPasswordChangeForced) { return ( ); } // Si no hay módulos accesibles después del login (y no es el cambio de clave forzado) // Esto podría pasar si un usuario no tiene permiso para NINGUNA sección, ni siquiera Inicio. // Deberías redirigir a login o mostrar un mensaje de "Sin acceso". if (isAuthenticated && !isPasswordChangeForced && accessibleModules.length === 0) { return ( No tiene acceso a ninguna sección del sistema. ); } return ( navigate('/')}> Sistema de Gestión - El Día {user && ( Hola, {user.nombreCompleto} )} {isAuthenticated && ( <> setAnchorElAlertasMenu(null)} > {gruposDeAlertas.map(([label, count]) => ( {label} ))} {numAlertas > 0 && } Ver Todas las Alertas {user && ( {user.nombreCompleto} {user.username} )} {user && } {!isPasswordChangeForced && ( Cambiar Contraseña )} Cerrar Sesión )} {isAuthenticated && accessibleModules.length > 0 && ( {accessibleModules.map((module) => ( ))} )} {children} `1px solid ${theme.palette.divider}` }}> Usuario: {user?.username} | Acceso: {user?.esSuperAdmin ? 'Super Administrador' : (user?.perfil || `ID ${user?.idPerfil}`)} handleModalClose(false)} isFirstLogin={false} /> ); }; export default MainLayout;