Files
universal_is/client/src/layouts/DashboardLayout.tsx

166 lines
6.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Outlet, useLocation, useNavigate } from 'react-router-dom';
import { IconLogout, IconSettings, IconMoon, IconSun, IconMenu2, IconUser, IconLogin } from '@tabler/icons-react';
import { getUserData, logout, useAuthStore } from '../store/auth';
import { useEffect, useState } from 'react';
import { UserData } from '../interfaces/auth';
import { pages } from '../constants/app';
import { Button, Image, makeStyles, Menu, MenuButton, MenuItem, MenuList, MenuPopover, MenuTrigger, Text } from '@fluentui/react-components';
import { setColorScheme, useAppStore } from '../store/app';
const useStyles = makeStyles({
root: {
display: 'grid',
gridTemplateRows: 'min-content auto',
height: '100vh',
maxHeight: '100vh',
overflow: 'hidden'
},
header: {
display: 'flex',
maxHeight: '3rem',
borderBottom: '1px solid var(--colorNeutralShadowKey)'
},
main: {
display: 'flex',
overflow: 'hidden',
width: '100%',
height: '100%',
},
navbar: {
overflow: 'auto',
display: 'flex',
flexDirection: 'column',
maxWidth: '200px',
position: 'relative',
width: '100%',
height: '100%',
transition: 'max-width .2s ease-in-out',
borderRight: '1px solid var(--colorNeutralShadowKey)'
},
content: {
overflow: 'auto',
display: 'flex',
position: 'relative',
width: '100%',
height: '100%'
}
})
function DashboardLayout() {
const navigate = useNavigate()
const location = useLocation()
const { colorScheme } = useAppStore()
const getPageTitle = () => {
const currentPath = location.pathname
const allPages = [...pages]
const currentPage = allPages.find(page => page.path === currentPath)
return currentPage ? currentPage.label : "Панель управления"
}
const authStore = useAuthStore()
const [userData, setUserData] = useState<UserData>()
useEffect(() => {
if (authStore) {
const stored = getUserData()
if (stored) {
setUserData(stored)
}
}
}, [authStore])
const classes = useStyles()
const [navbarOpen, setNavbarOpen] = useState(true)
useEffect(() => {
if (colorScheme === 'dark') {
document.body.dataset.agThemeMode = 'dark'
} else {
document.body.dataset.agThemeMode = 'light'
}
}, [colorScheme])
return (
<div className={classes.root}>
<div className={classes.header}>
<div style={{
display: 'flex',
width: '100%',
alignItems: 'center',
gap: '0.75rem',
padding: '0.5rem 0.5rem 0.5rem 0.25rem',
}}>
<Button appearance='subtle' onClick={() => setNavbarOpen(!navbarOpen)} icon={<IconMenu2 />} />
<Text weight='bold' size={400}>
{getPageTitle()}
</Text>
<div id='header-portal' style={{ marginLeft: 'auto' }}>
</div>
<Menu positioning={{ autoSize: true }}>
<MenuTrigger>
<MenuButton appearance='transparent' icon={authStore.isAuthenticated ? <IconUser /> : <IconSettings />}>{authStore.isAuthenticated && `${userData?.name} ${userData?.surname}`}</MenuButton>
</MenuTrigger>
<MenuPopover>
<MenuList>
{!authStore.isAuthenticated && <MenuItem icon={<IconLogin />} onClick={() => navigate('/auth/signin')}>Войти</MenuItem>}
<MenuItem icon={colorScheme === 'dark' ? <IconMoon /> : <IconSun />} onClick={() => colorScheme === 'dark' ? setColorScheme('light') : setColorScheme('dark')}>Тема: {colorScheme === 'dark' ? 'тёмная' : 'светлая'}</MenuItem>
{authStore.isAuthenticated && <MenuItem icon={<IconSettings />} onClick={() => navigate('/settings')}>Настройки профиля</MenuItem>}
{authStore.isAuthenticated && <MenuItem icon={<IconLogout />} onClick={() => {
logout()
if (pages.find(page => page.path === '/auth/signin')?.enabled) {
navigate("/auth/signin")
}
}}>Выход</MenuItem>}
<MenuItem icon={<Image src={'/logo2.svg'} width={24} />}>
0.1.0
</MenuItem>
</MenuList>
</MenuPopover>
</Menu>
</div>
</div>
<div className={classes.main}>
<div className={classes.navbar} style={{
maxWidth: navbarOpen ? '200px' : '2.70rem',
}}>
{pages.filter((page) => page.drawer).filter((page) => page.enabled).map((item) => (
<Button key={item.path} style={{ paddingLeft: '0.5rem', flexShrink: 0, flexWrap: 'nowrap', textWrap: 'nowrap', borderRadius: 0 }} appearance={location.pathname === item.path ? 'primary' : 'subtle'} onClick={() => navigate(item.path)}>
<div style={{ display: 'flex', }}>
{item.icon}
</div>
<div style={{
display: 'flex',
justifyContent: 'flex-start',
width: '100%',
overflow: 'hidden',
marginLeft: '1rem',
}}>
{item.label}
</div>
</Button>
))}
</div>
<div className={classes.content}>
<Outlet />
</div>
</div>
</div>
)
}
export default DashboardLayout