Initial commit

This commit is contained in:
Kayashov.SM
2025-03-12 17:54:16 +04:00
commit b6d8a3cebd
254 changed files with 29963 additions and 0 deletions

View File

@@ -0,0 +1,65 @@
import * as React from 'react';
import Avatar from '@mui/material/Avatar';
import Box from '@mui/material/Box';
import IconButton from '@mui/material/IconButton';
import Stack from '@mui/material/Stack';
import {List as ListIcon} from '@phosphor-icons/react/dist/ssr/List';
// import NotificationsIcon from '@mui/icons-material/Notifications';
import {usePopover} from "../../hooks/usePopover";
import {MobileNav} from "./MobileNav";
import {UserPopover} from "../core/UserPopover";
// import Tooltip from "@mui/material/Tooltip";
// import {Badge} from "@mui/material";
// import {useAlert} from "../../hooks/useAlert";
export function MainNav() {
const [openNav, setOpenNav] = React.useState(false);
// const {notImplement} = useAlert();
const userPopover = usePopover();
return (
<>
<Box
component="header"
sx={{
borderBottom: '1px solid var(--mui-palette-divider)',
backgroundColor: 'var(--mui-palette-background-paper)',
position: 'sticky',
top: 0,
zIndex: 'var(--mui-zIndex-appBar)',
height: '64px'
}}
>
<Stack direction="row" spacing={3}
sx={{alignItems: 'center', justifyContent: 'space-between', minHeight: '64px', px: 2}}>
<Stack sx={{alignItems: 'center'}} direction="row" spacing={3}>
<IconButton onClick={() => setOpenNav(true)} sx={{display: {xl: 'none'}}}>
<ListIcon/>
</IconButton>
</Stack>
<Stack sx={{alignItems: 'center'}} direction="row" spacing={2}>
{/*<Tooltip title="Уведомления" onClick={() => notImplement()}>*/}
{/* <Badge badgeContent={10} color="success" variant="standart">*/}
{/* <IconButton>*/}
{/* <NotificationsIcon/>*/}
{/* </IconButton>*/}
{/* </Badge>*/}
{/*</Tooltip>*/}
<Avatar onClick={userPopover.handleOpen} ref={userPopover.anchorRef} src="/assets/avatar.png"
sx={{cursor: 'pointer'}}/>
</Stack>
</Stack>
</Box>
<UserPopover anchorEl={userPopover.anchorRef.current} onClose={userPopover.handleClose}
open={userPopover.open}/>
<MobileNav
onClose={() => {
setOpenNav(false);
}}
open={openNav}
/>
</>
);
}

View File

@@ -0,0 +1,38 @@
import * as React from 'react';
import Drawer from '@mui/material/Drawer';
import {NavigationMenu} from "./NavigationMenu";
//Боковое меню
export function MobileNav({open, onClose}) {
return (
<Drawer
PaperProps={{
sx: {
'--MobileNav-background': 'var(--mui-palette-neutral-950)',
'--MobileNav-color': 'var(--mui-palette-common-white)',
'--NavItem-color': 'var(--mui-palette-neutral-300)',
'--NavItem-hover-background': 'rgba(255, 255, 255, 0.04)',
'--NavItem-active-background': 'var(--mui-palette-primary-main)',
'--NavItem-active-color': 'var(--mui-palette-primary-contrastText)',
'--NavItem-disabled-color': 'var(--mui-palette-neutral-500)',
'--NavItem-icon-color': 'var(--mui-palette-neutral-400)',
'--NavItem-icon-active-color': 'var(--mui-palette-primary-contrastText)',
'--NavItem-icon-disabled-color': 'var(--mui-palette-neutral-600)',
bgcolor: 'var(--MobileNav-background)',
color: 'var(--MobileNav-color)',
display: 'flex',
flexDirection: 'column',
maxWidth: '100%',
scrollbarWidth: 'none',
width: 'var(--MobileNav-width)',
zIndex: 'var(--MobileNav-zIndex)',
'&::-webkit-scrollbar': {display: 'none'},
},
}}
onClose={onClose}
open={open}
>
<NavigationMenu/>
</Drawer>
);
}

View File

@@ -0,0 +1,74 @@
import Stack from "@mui/material/Stack";
import {isNavItemActive} from "../../lib/isNavItemActive";
import {navIcons} from "../core/navIcons";
import Box from "@mui/material/Box";
import Typography from "@mui/material/Typography";
import {Link} from "react-router-dom";
export function renderNavItems({items = [], pathname}) {
const children = items.reduce((acc, curr) => {
const {key, ...item} = curr;
acc.push(<NavItem key={key} pathname={pathname} {...item} />);
return acc;
}, []);
return (
<Stack key={"stack-NavItem-key"} component="ul" spacing={1} sx={{listStyle: 'none', m: 0, p: 0}}>
{children}
</Stack>
);
}
function NavItem({disabled, external, href, icon, matcher, pathname, title}) {
const active = isNavItemActive({disabled, external, href, matcher, pathname});
const Icon = icon ? navIcons[icon] : null;
return (
<li>
<Link to={href} style={{ textDecoration: 'none' }}>
<Box
sx={{
alignItems: 'center',
borderRadius: 1,
color: 'var(--NavItem-color)',
cursor: 'pointer',
display: 'flex',
flex: '0 0 auto',
gap: 1,
p: '6px 16px',
position: 'relative',
textDecoration: 'none',
whiteSpace: 'nowrap',
...(disabled && {
bgcolor: 'var(--NavItem-disabled-background)',
color: 'var(--NavItem-disabled-color)',
cursor: 'not-allowed',
}),
...(active && {
bgcolor: 'var(--NavItem-active-background)',
color: 'var(--NavItem-active-color)'
}),
}}
>
<Box sx={{alignItems: 'center', display: 'flex', justifyContent: 'center', flex: '0 0 auto'}}>
{Icon ? (
<Icon
fill={active ? 'var(--NavItem-icon-active-color)' : 'var(--NavItem-icon-color)'}
fontSize="var(--icon-fontSize-md)"
weight={active ? 'fill' : undefined}
/>
) : null}
</Box>
<Box sx={{flex: '1 1 auto'}}>
<Typography
component="span"
sx={{color: 'inherit', fontSize: '0.875rem', fontWeight: 500, lineHeight: '28px'}}
>
{title}
</Typography>
</Box>
</Box>
</Link>
</li>
);
}

View File

@@ -0,0 +1,56 @@
import Stack from "@mui/material/Stack";
import Box from "@mui/material/Box";
import {ThemeSwitch} from "../core/ThemeSwitch";
import Divider from "@mui/material/Divider";
import {renderNavItems} from "./NavItem";
import {navItems} from "../../navItems";
import React, {useEffect, useState} from "react";
import {useLocation} from "react-router-dom";
import {useUser} from "../../hooks/useUser";
import Typography from "@mui/material/Typography";
function renderSpecialItems(items, label, pathname) {
return (
<Box>
<hr/>
<Typography pl={"20px"} pb={1} variant="subtitle2" color="textSecondary">{label}</Typography>
{renderNavItems({items: items, pathname: pathname})}
</Box>
)
}
export function NavigationMenu() {
const location = useLocation();
const pathname = location.pathname;
const {user} = useUser();
const [items, setItems] = useState(null)
const userChild = navItems.filter((item) => !item.forBarmen && !item.forAdmin)
const barmenChild = navItems.filter((item) => item.forBarmen)
const adminChild = navItems.filter((item) => item.forAdmin)
useEffect(() => {
const role = !user ? "USER" : Object.keys(user).length === 0 ? "USER" : user.role
const newState = (
<Box component="nav" sx={{flex: '1 1 auto', p: '12px'}}>
{renderNavItems({items: userChild, pathname: pathname})}
{role !== "USER" && renderSpecialItems(barmenChild, "Для бармена:", pathname)}
{role === "ADMIN" && renderSpecialItems(adminChild, "Для админа", pathname)}
</Box>
)
setItems(newState)
// eslint-disable-next-line
}, [user, pathname]);
return (
<>
{/*верхняя стопка*/}
<Stack spacing={2} sx={{p: 2, height: '63px'}}>
<ThemeSwitch/>
</Stack>
<Divider sx={{borderColor: 'var(--mui-palette-neutral-700)'}}/>
{/*меню навигации*/}
{items}
</>
)
}

View File

@@ -0,0 +1,37 @@
import * as React from 'react';
import Box from '@mui/material/Box';
import {NavigationMenu} from "./NavigationMenu";
export function SideNav() {
return (
<Box
sx={{
'--SideNav-background': 'var(--mui-palette-neutral-950)',
'--SideNav-color': 'var(--mui-palette-common-white)',
'--NavItem-color': 'var(--mui-palette-neutral-300)',
'--NavItem-hover-background': 'rgba(255, 255, 255, 0.04)',
'--NavItem-active-background': 'var(--mui-palette-primary-main)',
'--NavItem-active-color': 'var(--mui-palette-primary-contrastText)',
'--NavItem-disabled-color': 'var(--mui-palette-neutral-500)',
'--NavItem-icon-color': 'var(--mui-palette-neutral-400)',
'--NavItem-icon-active-color': 'var(--mui-palette-primary-contrastText)',
'--NavItem-icon-disabled-color': 'var(--mui-palette-neutral-600)',
bgcolor: 'var(--SideNav-background)',
color: 'var(--SideNav-color)',
display: {xs: 'none', xl: 'flex'},
flexDirection: 'column',
height: '100%',
left: 0,
maxWidth: '100%',
position: 'fixed',
scrollbarWidth: 'none',
top: 0,
width: 'var(--SideNav-width)',
zIndex: 'var(--SideNav-zIndex)',
'&::-webkit-scrollbar': {display: 'none'},
}}
>
<NavigationMenu/>
</Box>
);
}