111 lines
2.7 KiB
TypeScript
111 lines
2.7 KiB
TypeScript
import React from "react";
|
|
import { useNavigate, useLocation } from "react-router-dom";
|
|
import {
|
|
Drawer,
|
|
List,
|
|
ListItemButton,
|
|
ListItemIcon,
|
|
ListItemText,
|
|
Toolbar,
|
|
Typography,
|
|
Box,
|
|
useMediaQuery,
|
|
useTheme,
|
|
} from "@mui/material";
|
|
import CircleIcon from "@mui/icons-material/Circle";
|
|
import type { ResourceConfig } from "../types";
|
|
|
|
interface SideMenuProps {
|
|
resources: ResourceConfig[];
|
|
basePath: string;
|
|
mobileOpen: boolean;
|
|
onClose: () => void;
|
|
}
|
|
|
|
const drawerWidth = 260;
|
|
|
|
export function SideMenu({ resources, basePath, mobileOpen, onClose }: SideMenuProps) {
|
|
const navigate = useNavigate();
|
|
const location = useLocation();
|
|
const theme = useTheme();
|
|
const isMobile = useMediaQuery(theme.breakpoints.down("md"));
|
|
|
|
const colors = [
|
|
"#6366f1", "#10b981", "#f59e0b", "#ef4444", "#8b5cf6",
|
|
"#ec4899", "#14b8a6", "#f97316", "#06b6d4", "#84cc16",
|
|
];
|
|
|
|
const content = (
|
|
<Box>
|
|
<Toolbar>
|
|
<Typography variant="h6" fontWeight={700} noWrap>
|
|
Admin Panel
|
|
</Typography>
|
|
</Toolbar>
|
|
<List sx={{ px: 1 }}>
|
|
{resources.map((r, i) => {
|
|
const listPath = `${basePath}/${r.name}`;
|
|
const active = location.pathname.startsWith(listPath);
|
|
return (
|
|
<ListItemButton
|
|
key={r.name}
|
|
selected={active}
|
|
onClick={() => {
|
|
navigate(listPath);
|
|
if (isMobile) onClose();
|
|
}}
|
|
sx={{
|
|
borderRadius: 2,
|
|
mb: 0.5,
|
|
"&.Mui-selected": {
|
|
bgcolor: `${colors[i % colors.length]}15`,
|
|
"&:hover": { bgcolor: `${colors[i % colors.length]}20` },
|
|
},
|
|
}}
|
|
>
|
|
<ListItemIcon sx={{ minWidth: 36 }}>
|
|
<CircleIcon sx={{ color: colors[i % colors.length], fontSize: 12 }} />
|
|
</ListItemIcon>
|
|
<ListItemText
|
|
primary={r.displayName}
|
|
primaryTypographyProps={{ fontWeight: active ? 700 : 500, fontSize: 14 }}
|
|
/>
|
|
</ListItemButton>
|
|
);
|
|
})}
|
|
</List>
|
|
</Box>
|
|
);
|
|
|
|
if (isMobile) {
|
|
return (
|
|
<Drawer
|
|
variant="temporary"
|
|
open={mobileOpen}
|
|
onClose={onClose}
|
|
ModalProps={{ keepMounted: true }}
|
|
sx={{
|
|
"& .MuiDrawer-paper": { boxSizing: "border-box", width: drawerWidth },
|
|
}}
|
|
>
|
|
{content}
|
|
</Drawer>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<Drawer
|
|
variant="permanent"
|
|
sx={{
|
|
width: drawerWidth,
|
|
flexShrink: 0,
|
|
"& .MuiDrawer-paper": { width: drawerWidth, boxSizing: "border-box" },
|
|
}}
|
|
>
|
|
{content}
|
|
</Drawer>
|
|
);
|
|
}
|
|
|
|
export { drawerWidth };
|