import { useLocation, useNavigate } from 'react-router-dom'; import { useSelector, useDispatch } from 'react-redux'; import { Drawer, List, ListItemButton, ListItemIcon, ListItemText, Toolbar, Box, Typography, Tooltip, useMediaQuery, useTheme, } from '@mui/material'; import DashboardIcon from '@mui/icons-material/Dashboard'; import DescriptionIcon from '@mui/icons-material/Description'; import AddCircleIcon from '@mui/icons-material/AddCircle'; import AdminPanelSettingsIcon from '@mui/icons-material/AdminPanelSettings'; import AssignmentIcon from '@mui/icons-material/Assignment'; import PeopleIcon from '@mui/icons-material/People'; import { selectSidebarOpen, setSidebarOpen } from '../app/slices/uiSlice'; import { selectUser } from '../app/slices/authSlice'; import type { RootState } from '../app/store'; import { DRAWER_WIDTH } from '../constants'; const COLLAPSED_WIDTH = 72; const dispatcherNav = [ { label: 'Dashboard', path: '/', icon: }, { label: 'My Proposals', path: '/proposals', icon: }, { label: 'New Proposal', path: '/proposals/new', icon: }, ]; const adminNav = [ { label: 'Admin Queue', path: '/admin', icon: }, { label: 'All Proposals', path: '/admin/proposals', icon: }, ]; const sysadminNav = [ { label: 'Users', path: '/admin/users', icon: }, ]; const ALL_NAV_PATHS = new Set( [...dispatcherNav, ...adminNav, ...sysadminNav].map(n => n.path) ); function isNavActive(pathname: string, itemPath: string): boolean { if (pathname === itemPath) return true; if (ALL_NAV_PATHS.has(pathname)) return false; if (itemPath === '/' || itemPath === '/admin') return false; return pathname.startsWith(itemPath + '/'); } export default function Sidebar() { const navigate = useNavigate(); const location = useLocation(); const dispatch = useDispatch(); const theme = useTheme(); const open = useSelector((state: RootState) => selectSidebarOpen(state)); const user = useSelector((state: RootState) => selectUser(state)); const isMobile = useMediaQuery(theme.breakpoints.down('md')); // <900px const isCollapsed = useMediaQuery(theme.breakpoints.between('md', 'lg')); // 900–1200px const isAdmin = user?.role === 'Admin' || user?.role === 'SysAdmin'; const isSysAdmin = user?.role === 'SysAdmin'; const navItems = dispatcherNav; const drawerVariant = isMobile ? 'temporary' : 'persistent'; const effectiveWidth = isCollapsed ? COLLAPSED_WIDTH : DRAWER_WIDTH; const handleNavClick = (path: string) => { navigate(path); if (isMobile) { dispatch(setSidebarOpen(false)); } }; const handleDrawerClose = () => { dispatch(setSidebarOpen(false)); }; const renderNavItem = (item: { label: string; path: string; icon: React.ReactNode }) => { const button = ( handleNavClick(item.path)} sx={{ py: 1, justifyContent: isCollapsed ? 'center' : 'flex-start', minHeight: 40, }} > {item.icon} {!isCollapsed && ( )} ); if (isCollapsed) { return ( {button} ); } return button; }; return ( {isAdmin && ( <> {!isCollapsed && ( Admin )} {adminNav.map((item) => renderNavItem(item))} {isSysAdmin && sysadminNav.map((item) => renderNavItem(item))} )} {!isCollapsed && ( Proposals )} {navItems.map((item) => renderNavItem(item))} {user && !isCollapsed && ( {user.displayName} {user.role} )} ); }