113 lines
3.4 KiB
TypeScript
113 lines
3.4 KiB
TypeScript
|
import * as React from "react";
|
||
|
import { styled, Theme, CSSObject } from "@mui/material/styles";
|
||
|
import MuiDrawer from "@mui/material/Drawer";
|
||
|
import List from "@mui/material/List";
|
||
|
import Divider from "@mui/material/Divider";
|
||
|
import IconButton from "@mui/material/IconButton";
|
||
|
import ChevronLeftIcon from "@mui/icons-material/ChevronLeft";
|
||
|
import ChevronRightIcon from "@mui/icons-material/ChevronRight";
|
||
|
import { useNavigate } from "react-router-dom";
|
||
|
import { drawerWidth } from "./constants";
|
||
|
import MenuItem from "./MenuItem";
|
||
|
import { useTranslation } from "react-i18next";
|
||
|
import { menu } from "./constants";
|
||
|
|
||
|
const openedMixin = (theme: Theme): CSSObject => ({
|
||
|
width: drawerWidth,
|
||
|
transition: theme.transitions.create("width", {
|
||
|
easing: theme.transitions.easing.sharp,
|
||
|
duration: theme.transitions.duration.enteringScreen
|
||
|
}),
|
||
|
overflowX: "hidden"
|
||
|
});
|
||
|
|
||
|
const closedMixin = (theme: Theme): CSSObject => ({
|
||
|
transition: theme.transitions.create("width", {
|
||
|
easing: theme.transitions.easing.sharp,
|
||
|
duration: theme.transitions.duration.leavingScreen
|
||
|
}),
|
||
|
overflowX: "hidden",
|
||
|
width: `calc(${theme.spacing(7)} + 1px)`,
|
||
|
[theme.breakpoints.up("sm")]: {
|
||
|
width: `calc(${theme.spacing(8)} + 1px)`
|
||
|
}
|
||
|
});
|
||
|
|
||
|
const DrawerHeader = styled("div")(({ theme }) => ({
|
||
|
display: "flex",
|
||
|
alignItems: "center",
|
||
|
justifyContent: "flex-end",
|
||
|
padding: theme.spacing(0, 1),
|
||
|
// necessary for content to be below app bar
|
||
|
...theme.mixins.toolbar
|
||
|
}));
|
||
|
|
||
|
const Drawer = styled(MuiDrawer, { shouldForwardProp: prop => prop !== "open" })(({ theme, open }) => ({
|
||
|
width: drawerWidth,
|
||
|
flexShrink: 0,
|
||
|
whiteSpace: "nowrap",
|
||
|
boxSizing: "border-box",
|
||
|
...(open && {
|
||
|
...openedMixin(theme),
|
||
|
"& .MuiDrawer-paper": openedMixin(theme)
|
||
|
}),
|
||
|
...(!open && {
|
||
|
...closedMixin(theme),
|
||
|
"& .MuiDrawer-paper": closedMixin(theme)
|
||
|
})
|
||
|
}));
|
||
|
|
||
|
type SideBarProps = {
|
||
|
open: boolean;
|
||
|
onDrawerOpen: () => void;
|
||
|
onDrawerClose: () => void;
|
||
|
};
|
||
|
|
||
|
const SideBar: React.FC<SideBarProps> = ({ open, onDrawerOpen, onDrawerClose }) => {
|
||
|
const navigate = useNavigate();
|
||
|
const { t } = useTranslation();
|
||
|
|
||
|
menu.sort((a, b) => (a.order || 0) - (b.order || 0));
|
||
|
|
||
|
return (
|
||
|
<Drawer variant="permanent" open={open}>
|
||
|
<DrawerHeader>
|
||
|
<IconButton onClick={open ? onDrawerClose : onDrawerOpen}>
|
||
|
{open ? <ChevronLeftIcon /> : <ChevronRightIcon />}
|
||
|
</IconButton>
|
||
|
</DrawerHeader>
|
||
|
<Divider />
|
||
|
|
||
|
{menu.map((section, index) => {
|
||
|
const isLast = index === menu.length - 1;
|
||
|
return (
|
||
|
<React.Fragment key={`section-${section.order}`}>
|
||
|
<List>
|
||
|
{section.items
|
||
|
.sort((i1, i2) => i1.order - i2.order)
|
||
|
.map(item => (
|
||
|
<MenuItem
|
||
|
key={`${item.code}-${index}`}
|
||
|
open={open}
|
||
|
icon={item.icon}
|
||
|
label={t(item.name)}
|
||
|
onClick={item.subMenus ? undefined : () => navigate(item.route)}
|
||
|
subMenus={item.subMenus?.map(si => ({
|
||
|
open,
|
||
|
icon: si.icon,
|
||
|
label: t(si.name),
|
||
|
onClick: () => navigate(si.route)
|
||
|
}))}
|
||
|
/>
|
||
|
))}
|
||
|
</List>
|
||
|
{!isLast && <Divider />}
|
||
|
</React.Fragment>
|
||
|
);
|
||
|
})}
|
||
|
</Drawer>
|
||
|
);
|
||
|
};
|
||
|
|
||
|
export default SideBar;
|