109 lines
2.9 KiB
TypeScript
109 lines
2.9 KiB
TypeScript
import * as React from 'react';
|
|
import {
|
|
Box,
|
|
Drawer,
|
|
AppBar,
|
|
Toolbar,
|
|
List,
|
|
Typography,
|
|
Divider,
|
|
ListItem,
|
|
ListItemButton,
|
|
ListItemIcon,
|
|
ListItemText,
|
|
CssBaseline,
|
|
IconButton
|
|
} from '@mui/material';
|
|
import TableViewIcon from '@mui/icons-material/TableView';
|
|
import DashboardIcon from '@mui/icons-material/Dashboard';
|
|
import LogoutIcon from '@mui/icons-material/Logout';
|
|
import { ResourceConfig } from '../types/config';
|
|
import { useLocation, useNavigate } from 'react-router-dom';
|
|
|
|
const drawerWidth = 240;
|
|
|
|
interface AdminLayoutProps {
|
|
children: React.ReactNode;
|
|
onSelectResource: (resourceName: string | null) => void;
|
|
onLogout: () => void;
|
|
username?: string;
|
|
resources: ResourceConfig[];
|
|
}
|
|
|
|
export default function AdminLayout({
|
|
children,
|
|
onSelectResource,
|
|
onLogout,
|
|
username,
|
|
resources,
|
|
}: AdminLayoutProps) {
|
|
const location = useLocation();
|
|
const navigate = useNavigate();
|
|
const activeResourceName = location.pathname.split('/')[1] || null;
|
|
|
|
return (
|
|
<Box sx={{ display: 'flex' }}>
|
|
<CssBaseline />
|
|
<AppBar position="fixed" sx={{ zIndex: (theme) => theme.zIndex.drawer + 1 }}>
|
|
<Toolbar>
|
|
<Typography variant="h6" noWrap component="div" sx={{ flexGrow: 1 }}>
|
|
Admin Panel
|
|
</Typography>
|
|
<Typography variant="body1" sx={{ mr: 2 }}>
|
|
{username}
|
|
</Typography>
|
|
<IconButton color="inherit" onClick={onLogout}>
|
|
<LogoutIcon />
|
|
</IconButton>
|
|
</Toolbar>
|
|
</AppBar>
|
|
<Drawer
|
|
variant="permanent"
|
|
sx={{
|
|
width: drawerWidth,
|
|
flexShrink: 0,
|
|
[`& .MuiDrawer-paper`]: { width: drawerWidth, boxSizing: 'border-box' },
|
|
}}
|
|
>
|
|
<Toolbar />
|
|
<Box sx={{ overflow: 'auto' }}>
|
|
<List>
|
|
<ListItem disablePadding>
|
|
<ListItemButton
|
|
selected={location.pathname === '/'}
|
|
onClick={() => navigate('/')}
|
|
>
|
|
<ListItemIcon>
|
|
<DashboardIcon />
|
|
</ListItemIcon>
|
|
<ListItemText primary="Dashboard" />
|
|
</ListItemButton>
|
|
</ListItem>
|
|
</List>
|
|
<Divider />
|
|
<List>
|
|
{resources.map((res) => (
|
|
<ListItem key={res.name} disablePadding>
|
|
<ListItemButton
|
|
selected={activeResourceName === res.name}
|
|
onClick={() => onSelectResource(res.name)}
|
|
>
|
|
<ListItemIcon>
|
|
<TableViewIcon />
|
|
</ListItemIcon>
|
|
<ListItemText primary={res.pluralLabel} />
|
|
</ListItemButton>
|
|
</ListItem>
|
|
))}
|
|
</List>
|
|
<Divider />
|
|
</Box>
|
|
</Drawer>
|
|
<Box component="main" sx={{ flexGrow: 1, p: 3 }}>
|
|
<Toolbar />
|
|
{children}
|
|
</Box>
|
|
</Box>
|
|
);
|
|
}
|