forked from VinokurovVE/tests
252 lines
7.8 KiB
TypeScript
252 lines
7.8 KiB
TypeScript
// Layout for dashboard with responsive drawer
|
|
|
|
import { Outlet, useLocation, useNavigate } from "react-router-dom"
|
|
import * as React from 'react';
|
|
import AppBar from '@mui/material/AppBar';
|
|
import Box from '@mui/material/Box';
|
|
import CssBaseline from '@mui/material/CssBaseline';
|
|
import Divider from '@mui/material/Divider';
|
|
import Drawer from '@mui/material/Drawer';
|
|
import IconButton from '@mui/material/IconButton';
|
|
import List from '@mui/material/List';
|
|
import ListItem from '@mui/material/ListItem';
|
|
import ListItemButton from '@mui/material/ListItemButton';
|
|
import ListItemIcon from '@mui/material/ListItemIcon';
|
|
import ListItemText from '@mui/material/ListItemText';
|
|
import MenuIcon from '@mui/icons-material/Menu';
|
|
import Toolbar from '@mui/material/Toolbar';
|
|
import Typography from '@mui/material/Typography';
|
|
import { Api, ExitToApp, Home, People, Settings, Shield } from "@mui/icons-material";
|
|
import { getUserData, useAuthStore } from "../store/auth";
|
|
import { UserData } from "../interfaces/auth";
|
|
|
|
const drawerWidth = 240;
|
|
|
|
export default function DashboardLayoutResponsive() {
|
|
const [open, setOpen] = React.useState(true);
|
|
|
|
const authStore = useAuthStore();
|
|
const [userData, setUserData] = React.useState<UserData>();
|
|
|
|
const location = useLocation()
|
|
|
|
const navigate = useNavigate()
|
|
|
|
//const { window } = props;
|
|
const [mobileOpen, setMobileOpen] = React.useState(false);
|
|
const [isClosing, setIsClosing] = React.useState(false);
|
|
|
|
const handleDrawerClose = () => {
|
|
setIsClosing(true);
|
|
setMobileOpen(false);
|
|
};
|
|
|
|
const handleDrawerTransitionEnd = () => {
|
|
setIsClosing(false);
|
|
};
|
|
|
|
const handleDrawerToggle = () => {
|
|
if (!isClosing) {
|
|
setMobileOpen(!mobileOpen);
|
|
}
|
|
};
|
|
|
|
const pages = [
|
|
{
|
|
label: "Главная",
|
|
path: "/",
|
|
icon: <Home />
|
|
},
|
|
{
|
|
label: "Пользователи",
|
|
path: "/user",
|
|
icon: <People />
|
|
},
|
|
{
|
|
label: "Роли",
|
|
path: "/role",
|
|
icon: <Shield />
|
|
},
|
|
{
|
|
label: "API Test",
|
|
path: "/api-test",
|
|
icon: <Api />
|
|
},
|
|
]
|
|
|
|
const misc = [
|
|
{
|
|
label: "Настройки",
|
|
path: "/settings",
|
|
icon: <Settings />
|
|
},
|
|
{
|
|
label: "Выход",
|
|
path: "/signOut",
|
|
icon: <ExitToApp />
|
|
}
|
|
]
|
|
|
|
const getPageTitle = () => {
|
|
const currentPath = location.pathname;
|
|
const allPages = [...pages, ...misc];
|
|
const currentPage = allPages.find(page => page.path === currentPath);
|
|
return currentPage ? currentPage.label : "Dashboard";
|
|
};
|
|
|
|
const toggleDrawer = () => {
|
|
setOpen(!open);
|
|
};
|
|
|
|
const drawer = (
|
|
<div>
|
|
<Toolbar>
|
|
<Box display="flex" justifyContent={'space-between'} width={"100%"}>
|
|
<Box>
|
|
<Typography>{userData?.name} {userData?.surname}</Typography>
|
|
<Divider />
|
|
<Typography variant="caption">{userData?.login}</Typography>
|
|
</Box>
|
|
|
|
<IconButton
|
|
edge="start"
|
|
color="inherit"
|
|
aria-label="open drawer"
|
|
onClick={toggleDrawer}
|
|
sx={{
|
|
...(open && { display: 'none' }),
|
|
}}
|
|
>
|
|
<MenuIcon />
|
|
</IconButton>
|
|
</Box>
|
|
</Toolbar>
|
|
|
|
<Divider />
|
|
|
|
<List>
|
|
{pages.map((item, index) => (
|
|
<ListItem key={index} disablePadding>
|
|
<ListItemButton
|
|
onClick={() => {
|
|
navigate(item.path)
|
|
}}
|
|
selected={location.pathname === item.path}
|
|
>
|
|
<ListItemIcon>
|
|
{item.icon}
|
|
</ListItemIcon>
|
|
<ListItemText primary={item.label} />
|
|
</ListItemButton>
|
|
</ListItem>
|
|
))}
|
|
</List>
|
|
|
|
<Divider />
|
|
|
|
<List>
|
|
{misc.map((item, index) => (
|
|
<ListItem key={index} disablePadding>
|
|
<ListItemButton
|
|
onClick={() => {
|
|
navigate(item.path)
|
|
}}
|
|
selected={location.pathname === item.path}
|
|
>
|
|
<ListItemIcon>
|
|
{item.icon}
|
|
</ListItemIcon>
|
|
<ListItemText primary={item.label} />
|
|
</ListItemButton>
|
|
</ListItem>
|
|
))}
|
|
</List>
|
|
</div >
|
|
);
|
|
|
|
React.useEffect(() => {
|
|
if (authStore) {
|
|
const stored = getUserData()
|
|
if (stored) {
|
|
setUserData(stored)
|
|
}
|
|
}
|
|
}, [authStore])
|
|
|
|
return (
|
|
<Box sx={{
|
|
display: 'flex',
|
|
flexGrow: 1,
|
|
height: "100vh"
|
|
}}>
|
|
<CssBaseline />
|
|
<AppBar
|
|
position="fixed"
|
|
sx={{
|
|
width: { sm: `calc(100% - ${drawerWidth}px)` },
|
|
ml: { sm: `${drawerWidth}px` },
|
|
}}
|
|
>
|
|
<Toolbar>
|
|
<IconButton
|
|
color="inherit"
|
|
aria-label="open drawer"
|
|
edge="start"
|
|
onClick={handleDrawerToggle}
|
|
sx={{ mr: 2, display: { sm: 'none' } }}
|
|
>
|
|
<MenuIcon />
|
|
</IconButton>
|
|
<Typography variant="h6" noWrap component="div">
|
|
{getPageTitle()}
|
|
</Typography>
|
|
</Toolbar>
|
|
</AppBar>
|
|
|
|
<Box
|
|
component="nav"
|
|
sx={{ width: { sm: drawerWidth }, flexShrink: { sm: 0 } }}
|
|
aria-label="mailbox folders"
|
|
>
|
|
{/* The implementation can be swapped with js to avoid SEO duplication of links. */}
|
|
<Drawer
|
|
variant="temporary"
|
|
open={mobileOpen}
|
|
onTransitionEnd={handleDrawerTransitionEnd}
|
|
onClose={handleDrawerClose}
|
|
ModalProps={{
|
|
keepMounted: true, // Better open performance on mobile.
|
|
}}
|
|
sx={{
|
|
display: { xs: 'block', sm: 'none' },
|
|
'& .MuiDrawer-paper': { boxSizing: 'border-box', width: drawerWidth },
|
|
}}
|
|
>
|
|
{drawer}
|
|
</Drawer>
|
|
<Drawer
|
|
variant="permanent"
|
|
sx={{
|
|
display: { xs: 'none', sm: 'block' },
|
|
'& .MuiDrawer-paper': { boxSizing: 'border-box', width: drawerWidth },
|
|
}}
|
|
open
|
|
>
|
|
{drawer}
|
|
</Drawer>
|
|
</Box>
|
|
|
|
<Box
|
|
component="main"
|
|
sx={{
|
|
flexGrow: 1,
|
|
p: 3,
|
|
width: { sm: `calc(100% - ${drawerWidth}px)` }
|
|
}}
|
|
>
|
|
<Toolbar />
|
|
<Outlet />
|
|
</Box>
|
|
</Box>
|
|
);
|
|
} |