158 lines
4.4 KiB
TypeScript
158 lines
4.4 KiB
TypeScript
import * as React from "react";
|
||
import Box from "@mui/material/Box";
|
||
import Toolbar from "@mui/material/Toolbar";
|
||
import IconButton from "@mui/material/IconButton";
|
||
import { Menu, ChevronLeftIcon, ChevronRightIcon, User } from "lucide-react";
|
||
import { useTheme } from "@mui/material/styles";
|
||
import { AppBar } from "./ui/AppBar";
|
||
import { Drawer } from "./ui/Drawer";
|
||
import { DrawerHeader } from "./ui/DrawerHeader";
|
||
import { NavigationList } from "@features";
|
||
import { authStore, userStore, menuStore } from "@shared";
|
||
import { observer } from "mobx-react-lite";
|
||
import { useEffect } from "react";
|
||
import { Typography } from "@mui/material";
|
||
import { CitySelector } from "@widgets";
|
||
|
||
interface LayoutProps {
|
||
children: React.ReactNode;
|
||
}
|
||
|
||
export const Layout: React.FC<LayoutProps> = observer(({ children }) => {
|
||
const theme = useTheme();
|
||
const [open, setOpen] = React.useState(true);
|
||
const { setIsMenuOpen } = menuStore;
|
||
|
||
React.useEffect(() => {
|
||
setIsMenuOpen(open);
|
||
}, [open]);
|
||
|
||
const { getUsers, users } = userStore;
|
||
|
||
useEffect(() => {
|
||
const fetchUsers = async () => {
|
||
await getUsers();
|
||
};
|
||
fetchUsers();
|
||
}, []);
|
||
|
||
const handleDrawerOpen = () => {
|
||
setOpen(true);
|
||
};
|
||
|
||
const handleDrawerClose = () => {
|
||
setOpen(false);
|
||
};
|
||
|
||
return (
|
||
<Box sx={{ display: "flex" }}>
|
||
<AppBar position="fixed" open={open}>
|
||
<Toolbar className="flex justify-between">
|
||
<div className="flex items-center">
|
||
<IconButton
|
||
color="inherit"
|
||
aria-label="open drawer"
|
||
onClick={handleDrawerOpen}
|
||
edge="start"
|
||
sx={[
|
||
{
|
||
marginRight: 5,
|
||
},
|
||
open && { display: "none" },
|
||
]}
|
||
>
|
||
<Menu />
|
||
</IconButton>
|
||
<CitySelector />
|
||
</div>
|
||
|
||
<div className="flex gap-2 items-center">
|
||
<div className="flex flex-col gap-1">
|
||
{(() => {
|
||
return (
|
||
<>
|
||
<p className=" text-white">
|
||
{
|
||
users?.data?.find(
|
||
// @ts-ignore
|
||
(user) => user.id === authStore.payload?.user_id
|
||
)?.name
|
||
}
|
||
</p>
|
||
<div
|
||
className="text-center text-xs"
|
||
style={{
|
||
backgroundColor: "#877361",
|
||
borderRadius: "4px",
|
||
color: "white",
|
||
padding: "2px 10px",
|
||
}}
|
||
>
|
||
{/* @ts-ignore */}
|
||
{authStore.payload?.is_admin
|
||
? "Администратор"
|
||
: "Режим пользователя"}
|
||
</div>
|
||
</>
|
||
);
|
||
})()}
|
||
</div>
|
||
<div className="w-10 h-10 bg-gray-600 rounded-full flex items-center justify-center">
|
||
<User />
|
||
</div>
|
||
</div>
|
||
</Toolbar>
|
||
</AppBar>
|
||
<Drawer variant="permanent" open={open}>
|
||
<DrawerHeader>
|
||
<Box
|
||
sx={{
|
||
display: "flex",
|
||
alignItems: "center",
|
||
gap: 2,
|
||
cursor: "pointer",
|
||
}}
|
||
onClick={() => {
|
||
setOpen(!open);
|
||
}}
|
||
>
|
||
<img
|
||
src="/favicon_ship.svg"
|
||
alt="logo"
|
||
width={40}
|
||
height={40}
|
||
style={{ filter: "brightness(0)", marginLeft: "-5px" }}
|
||
/>
|
||
<Typography variant="h6" component="h1">
|
||
Белые ночи
|
||
</Typography>
|
||
</Box>
|
||
{open && (
|
||
<IconButton onClick={handleDrawerClose}>
|
||
{theme.direction === "rtl" ? (
|
||
<ChevronRightIcon />
|
||
) : (
|
||
<ChevronLeftIcon />
|
||
)}
|
||
</IconButton>
|
||
)}
|
||
</DrawerHeader>
|
||
<NavigationList open={open} onDrawerOpen={handleDrawerOpen} />
|
||
</Drawer>
|
||
<Box
|
||
component="main"
|
||
sx={{
|
||
width: "100%",
|
||
flexGrow: 1,
|
||
p: 3,
|
||
overflow: "auto",
|
||
maxWidth: "100vw",
|
||
}}
|
||
>
|
||
<div className="mt-16"></div>
|
||
{children}
|
||
</Box>
|
||
</Box>
|
||
);
|
||
});
|