Spaces:
Sleeping
Sleeping
| import Inventory2OutlinedIcon from '@mui/icons-material/Inventory2Outlined'; | |
| import LogoutIcon from '@mui/icons-material/Logout'; | |
| import ReceiptLongOutlinedIcon from '@mui/icons-material/ReceiptLongOutlined'; | |
| import SpaceDashboardOutlinedIcon from '@mui/icons-material/SpaceDashboardOutlined'; | |
| import { | |
| AppBar, | |
| Box, | |
| Button, | |
| Chip, | |
| Container, | |
| Divider, | |
| Drawer, | |
| List, | |
| ListItemButton, | |
| ListItemIcon, | |
| ListItemText, | |
| Toolbar, | |
| Typography | |
| } from '@mui/material'; | |
| import { NavLink, Outlet, useLocation } from 'react-router-dom'; | |
| import { useAuth } from '../context/AuthContext'; | |
| const drawerWidth = 260; | |
| const navItems = [ | |
| { label: 'Dashboard', path: '/app', icon: <SpaceDashboardOutlinedIcon /> }, | |
| { label: 'Products', path: '/app/products', icon: <Inventory2OutlinedIcon /> }, | |
| { label: 'Orders', path: '/app/orders', icon: <ReceiptLongOutlinedIcon /> } | |
| ]; | |
| export function AppShell() { | |
| const { role, logout } = useAuth(); | |
| const location = useLocation(); | |
| const drawer = ( | |
| <Box sx={{ height: '100%', display: 'flex', flexDirection: 'column' }}> | |
| <Box sx={{ p: 3 }}> | |
| <Typography variant="h5" fontWeight={800}> | |
| RTOPP | |
| </Typography> | |
| <Typography variant="body2" color="text.secondary"> | |
| Real-Time Order Processing | |
| </Typography> | |
| </Box> | |
| <Divider /> | |
| <List sx={{ px: 1.5, flex: 1 }}> | |
| {navItems.map((item) => ( | |
| <ListItemButton | |
| key={item.path} | |
| component={NavLink} | |
| to={item.path} | |
| selected={location.pathname === item.path} | |
| sx={{ borderRadius: 2, mb: 0.5 }} | |
| > | |
| <ListItemIcon>{item.icon}</ListItemIcon> | |
| <ListItemText primary={item.label} /> | |
| </ListItemButton> | |
| ))} | |
| </List> | |
| <Box sx={{ p: 2 }}> | |
| <Button fullWidth variant="outlined" startIcon={<LogoutIcon />} onClick={logout}> | |
| Logout | |
| </Button> | |
| </Box> | |
| </Box> | |
| ); | |
| return ( | |
| <Box sx={{ display: 'flex', minHeight: '100vh', bgcolor: 'background.default' }}> | |
| <AppBar | |
| position="fixed" | |
| color="inherit" | |
| elevation={0} | |
| sx={{ width: { md: `calc(100% - ${drawerWidth}px)` }, ml: { md: `${drawerWidth}px` }, borderBottom: 1, borderColor: 'divider' }} | |
| > | |
| <Toolbar sx={{ justifyContent: 'space-between' }}> | |
| <Box> | |
| <Typography variant="h6" fontWeight={700}> | |
| Operations Dashboard | |
| </Typography> | |
| <Typography variant="caption" color="text.secondary"> | |
| Manage products, orders and live fulfilment updates | |
| </Typography> | |
| </Box> | |
| <Chip label={role ?? 'GUEST'} color={role === 'ADMIN' ? 'primary' : 'secondary'} /> | |
| </Toolbar> | |
| </AppBar> | |
| <Drawer | |
| variant="permanent" | |
| sx={{ | |
| width: drawerWidth, | |
| flexShrink: 0, | |
| display: { xs: 'none', md: 'block' }, | |
| '& .MuiDrawer-paper': { width: drawerWidth, boxSizing: 'border-box' } | |
| }} | |
| > | |
| {drawer} | |
| </Drawer> | |
| <Box component="main" sx={{ flexGrow: 1, pt: 11, pb: 5 }}> | |
| <Container maxWidth="xl"> | |
| <Outlet /> | |
| </Container> | |
| </Box> | |
| </Box> | |
| ); | |
| } | |