2026-05-16 19:19:34 -04:00
|
|
|
import { useLocation, useNavigate } from 'react-router-dom';
|
|
|
|
|
import { useSelector } from 'react-redux';
|
|
|
|
|
import {
|
|
|
|
|
Drawer,
|
|
|
|
|
List,
|
|
|
|
|
ListItemButton,
|
|
|
|
|
ListItemIcon,
|
|
|
|
|
ListItemText,
|
|
|
|
|
Toolbar,
|
|
|
|
|
Box,
|
2026-05-16 19:42:47 -04:00
|
|
|
Divider,
|
|
|
|
|
Typography,
|
2026-05-16 19:19:34 -04:00
|
|
|
} from '@mui/material';
|
|
|
|
|
import DashboardIcon from '@mui/icons-material/Dashboard';
|
|
|
|
|
import DescriptionIcon from '@mui/icons-material/Description';
|
|
|
|
|
import AddCircleIcon from '@mui/icons-material/AddCircle';
|
2026-05-16 19:42:47 -04:00
|
|
|
import AdminPanelSettingsIcon from '@mui/icons-material/AdminPanelSettings';
|
|
|
|
|
import AssignmentIcon from '@mui/icons-material/Assignment';
|
|
|
|
|
import PeopleIcon from '@mui/icons-material/People';
|
2026-05-16 19:19:34 -04:00
|
|
|
import { selectSidebarOpen } from '../app/slices/uiSlice';
|
|
|
|
|
import { selectUser } from '../app/slices/authSlice';
|
|
|
|
|
import type { RootState } from '../app/store';
|
|
|
|
|
|
|
|
|
|
const DRAWER_WIDTH = 240;
|
|
|
|
|
|
|
|
|
|
const dispatcherNav = [
|
|
|
|
|
{ label: 'Dashboard', path: '/', icon: <DashboardIcon /> },
|
|
|
|
|
{ label: 'My Proposals', path: '/proposals', icon: <DescriptionIcon /> },
|
|
|
|
|
{ label: 'New Proposal', path: '/proposals/new', icon: <AddCircleIcon /> },
|
|
|
|
|
];
|
|
|
|
|
|
2026-05-16 19:42:47 -04:00
|
|
|
const adminNav = [
|
|
|
|
|
{ label: 'Admin Queue', path: '/admin', icon: <AdminPanelSettingsIcon /> },
|
|
|
|
|
{ label: 'All Proposals', path: '/admin/proposals', icon: <AssignmentIcon /> },
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const sysadminNav = [
|
|
|
|
|
{ label: 'Users', path: '/admin/users', icon: <PeopleIcon /> },
|
|
|
|
|
];
|
|
|
|
|
|
2026-05-16 19:19:34 -04:00
|
|
|
export default function Sidebar() {
|
|
|
|
|
const navigate = useNavigate();
|
|
|
|
|
const location = useLocation();
|
|
|
|
|
const open = useSelector((state: RootState) => selectSidebarOpen(state));
|
|
|
|
|
const user = useSelector((state: RootState) => selectUser(state));
|
|
|
|
|
|
2026-05-16 19:42:47 -04:00
|
|
|
const isAdmin = user?.role === 'Admin' || user?.role === 'SysAdmin';
|
|
|
|
|
const isSysAdmin = user?.role === 'SysAdmin';
|
2026-05-16 19:19:34 -04:00
|
|
|
const navItems = dispatcherNav;
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<Drawer
|
|
|
|
|
variant="persistent"
|
|
|
|
|
open={open}
|
|
|
|
|
sx={{
|
|
|
|
|
width: open ? DRAWER_WIDTH : 0,
|
|
|
|
|
flexShrink: 0,
|
|
|
|
|
'& .MuiDrawer-paper': {
|
|
|
|
|
width: DRAWER_WIDTH,
|
|
|
|
|
boxSizing: 'border-box',
|
|
|
|
|
},
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<Toolbar />
|
2026-05-16 19:42:47 -04:00
|
|
|
<Box sx={{ overflow: 'auto', flexGrow: 1 }}>
|
2026-05-16 19:19:34 -04:00
|
|
|
<List>
|
|
|
|
|
{navItems.map((item) => (
|
|
|
|
|
<ListItemButton
|
|
|
|
|
key={item.path}
|
|
|
|
|
selected={location.pathname === item.path}
|
|
|
|
|
onClick={() => navigate(item.path)}
|
|
|
|
|
>
|
|
|
|
|
<ListItemIcon>{item.icon}</ListItemIcon>
|
|
|
|
|
<ListItemText primary={item.label} />
|
|
|
|
|
</ListItemButton>
|
|
|
|
|
))}
|
|
|
|
|
</List>
|
2026-05-16 19:42:47 -04:00
|
|
|
|
|
|
|
|
{isAdmin && (
|
|
|
|
|
<>
|
|
|
|
|
<Divider />
|
|
|
|
|
<Typography variant="overline" sx={{ px: 2, pt: 1, display: 'block', color: 'text.secondary' }}>
|
|
|
|
|
Admin
|
|
|
|
|
</Typography>
|
|
|
|
|
<List>
|
|
|
|
|
{adminNav.map((item) => (
|
|
|
|
|
<ListItemButton
|
|
|
|
|
key={item.path}
|
|
|
|
|
selected={location.pathname === item.path || location.pathname.startsWith(item.path + '/')}
|
|
|
|
|
onClick={() => navigate(item.path)}
|
|
|
|
|
>
|
|
|
|
|
<ListItemIcon>{item.icon}</ListItemIcon>
|
|
|
|
|
<ListItemText primary={item.label} />
|
|
|
|
|
</ListItemButton>
|
|
|
|
|
))}
|
|
|
|
|
{isSysAdmin && sysadminNav.map((item) => (
|
|
|
|
|
<ListItemButton
|
|
|
|
|
key={item.path}
|
|
|
|
|
selected={location.pathname === item.path}
|
|
|
|
|
onClick={() => navigate(item.path)}
|
|
|
|
|
>
|
|
|
|
|
<ListItemIcon>{item.icon}</ListItemIcon>
|
|
|
|
|
<ListItemText primary={item.label} />
|
|
|
|
|
</ListItemButton>
|
|
|
|
|
))}
|
|
|
|
|
</List>
|
|
|
|
|
</>
|
|
|
|
|
)}
|
2026-05-16 19:19:34 -04:00
|
|
|
</Box>
|
|
|
|
|
{user && (
|
|
|
|
|
<Box sx={{ p: 2, mt: 'auto', borderTop: 1, borderColor: 'divider' }}>
|
|
|
|
|
<Box sx={{ fontSize: '0.85rem', fontWeight: 500 }}>{user.displayName}</Box>
|
|
|
|
|
<Box sx={{ fontSize: '0.75rem', color: 'text.secondary' }}>{user.role}</Box>
|
|
|
|
|
</Box>
|
|
|
|
|
)}
|
|
|
|
|
</Drawer>
|
|
|
|
|
);
|
|
|
|
|
}
|