base commit
This commit is contained in:
@@ -1,14 +1,65 @@
|
||||
import { type PropsWithChildren } from 'react'
|
||||
import { type PropsWithChildren, useState } from 'react'
|
||||
import AccountCircleOutlinedIcon from '@mui/icons-material/AccountCircleOutlined'
|
||||
import DarkModeOutlinedIcon from '@mui/icons-material/DarkModeOutlined'
|
||||
import LightModeOutlinedIcon from '@mui/icons-material/LightModeOutlined'
|
||||
import AppBar from '@mui/material/AppBar'
|
||||
import Badge from '@mui/material/Badge'
|
||||
import Box from '@mui/material/Box'
|
||||
import Button from '@mui/material/Button'
|
||||
import Container from '@mui/material/Container'
|
||||
import FormControl from '@mui/material/FormControl'
|
||||
import IconButton from '@mui/material/IconButton'
|
||||
import InputLabel from '@mui/material/InputLabel'
|
||||
import ListItemText from '@mui/material/ListItemText'
|
||||
import Menu from '@mui/material/Menu'
|
||||
import MenuItem from '@mui/material/MenuItem'
|
||||
import Select from '@mui/material/Select'
|
||||
import type { SelectChangeEvent } from '@mui/material/Select'
|
||||
import Toolbar from '@mui/material/Toolbar'
|
||||
import Typography from '@mui/material/Typography'
|
||||
import { Link as RouterLink } from 'react-router-dom'
|
||||
import { Link as RouterLink, useNavigate } from 'react-router-dom'
|
||||
import { useUnit } from 'effector-react'
|
||||
import type { ColorScheme } from '@/app/providers/theme-controller'
|
||||
import { useThemeController } from '@/app/providers/theme-controller'
|
||||
import { STORE_NAME } from '@/shared/config'
|
||||
import { $user, logout, tokenSet } from '@/shared/model/auth'
|
||||
|
||||
export function MainLayout({ children }: PropsWithChildren) {
|
||||
const { mode, resolvedMode, scheme, setMode, setScheme, cycleMode } = useThemeController()
|
||||
const user = useUnit($user)
|
||||
const navigate = useNavigate()
|
||||
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null)
|
||||
const menuOpen = Boolean(anchorEl)
|
||||
|
||||
const onSchemeChange = (e: SelectChangeEvent<string>) => {
|
||||
setScheme(e.target.value as ColorScheme)
|
||||
}
|
||||
|
||||
const onModeChange = (e: SelectChangeEvent<string>) => {
|
||||
const v = e.target.value
|
||||
if (v === 'system' || v === 'light' || v === 'dark') setMode(v)
|
||||
}
|
||||
|
||||
const openUserMenu = (e: React.MouseEvent<HTMLElement>) => setAnchorEl(e.currentTarget)
|
||||
const closeUserMenu = () => setAnchorEl(null)
|
||||
|
||||
const onLogout = () => {
|
||||
tokenSet(null)
|
||||
logout()
|
||||
closeUserMenu()
|
||||
navigate('/')
|
||||
}
|
||||
|
||||
const goToAuth = () => {
|
||||
closeUserMenu()
|
||||
navigate('/auth')
|
||||
}
|
||||
|
||||
const goToMe = () => {
|
||||
closeUserMenu()
|
||||
navigate('/me')
|
||||
}
|
||||
|
||||
return (
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', minHeight: '100vh' }}>
|
||||
<AppBar position="sticky" color="primary" elevation={0} sx={{ borderBottom: 1, borderColor: 'divider' }}>
|
||||
@@ -27,6 +78,107 @@ export function MainLayout({ children }: PropsWithChildren) {
|
||||
<Button component={RouterLink} to="/admin" color="inherit">
|
||||
Админка
|
||||
</Button>
|
||||
|
||||
<IconButton color="inherit" onClick={openUserMenu} sx={{ ml: 1 }} aria-label="Пользователь">
|
||||
<Badge
|
||||
variant="dot"
|
||||
color="success"
|
||||
overlap="circular"
|
||||
invisible={!user}
|
||||
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
|
||||
>
|
||||
<AccountCircleOutlinedIcon />
|
||||
</Badge>
|
||||
</IconButton>
|
||||
<Menu
|
||||
anchorEl={anchorEl}
|
||||
open={menuOpen}
|
||||
onClose={closeUserMenu}
|
||||
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
|
||||
transformOrigin={{ vertical: 'top', horizontal: 'right' }}
|
||||
>
|
||||
{user ? (
|
||||
<>
|
||||
<MenuItem onClick={goToMe}>
|
||||
<ListItemText primary={(user.name && user.name.trim()) || user.email} secondary="Профиль" />
|
||||
</MenuItem>
|
||||
<MenuItem onClick={onLogout}>Выход</MenuItem>
|
||||
</>
|
||||
) : (
|
||||
<MenuItem onClick={goToAuth}>Войти / регистрация</MenuItem>
|
||||
)}
|
||||
</Menu>
|
||||
|
||||
<FormControl
|
||||
size="small"
|
||||
sx={{
|
||||
ml: 2,
|
||||
minWidth: 160,
|
||||
'& .MuiInputLabel-root': { color: 'rgba(255,255,255,0.85)' },
|
||||
'& .MuiInputLabel-root.Mui-focused': { color: '#fff' },
|
||||
'& .MuiInputLabel-root.MuiInputLabel-shrink': { color: 'rgba(255,255,255,0.92)' },
|
||||
}}
|
||||
>
|
||||
<InputLabel id="scheme-label">Тема</InputLabel>
|
||||
<Select
|
||||
labelId="scheme-label"
|
||||
value={scheme}
|
||||
label="Тема"
|
||||
onChange={onSchemeChange}
|
||||
sx={{
|
||||
color: 'inherit',
|
||||
'.MuiOutlinedInput-notchedOutline': { borderColor: 'rgba(255,255,255,0.5)' },
|
||||
'&:hover .MuiOutlinedInput-notchedOutline': { borderColor: 'rgba(255,255,255,0.9)' },
|
||||
'&.Mui-focused .MuiOutlinedInput-notchedOutline': { borderColor: 'rgba(255,255,255,0.95)' },
|
||||
'.MuiSvgIcon-root': { color: 'inherit' },
|
||||
}}
|
||||
>
|
||||
<MenuItem value="craft">Крафт</MenuItem>
|
||||
<MenuItem value="forest">Лес</MenuItem>
|
||||
<MenuItem value="ocean">Океан</MenuItem>
|
||||
<MenuItem value="berry">Ягоды</MenuItem>
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
<FormControl
|
||||
size="small"
|
||||
sx={{
|
||||
ml: 2,
|
||||
minWidth: 150,
|
||||
'& .MuiInputLabel-root': { color: 'rgba(255,255,255,0.85)' },
|
||||
'& .MuiInputLabel-root.Mui-focused': { color: '#fff' },
|
||||
'& .MuiInputLabel-root.MuiInputLabel-shrink': { color: 'rgba(255,255,255,0.92)' },
|
||||
}}
|
||||
>
|
||||
<InputLabel id="mode-label">Режим</InputLabel>
|
||||
<Select
|
||||
labelId="mode-label"
|
||||
value={mode}
|
||||
label="Режим"
|
||||
onChange={onModeChange}
|
||||
sx={{
|
||||
color: 'inherit',
|
||||
'.MuiOutlinedInput-notchedOutline': { borderColor: 'rgba(255,255,255,0.5)' },
|
||||
'&:hover .MuiOutlinedInput-notchedOutline': { borderColor: 'rgba(255,255,255,0.9)' },
|
||||
'&.Mui-focused .MuiOutlinedInput-notchedOutline': { borderColor: 'rgba(255,255,255,0.95)' },
|
||||
'.MuiSvgIcon-root': { color: 'inherit' },
|
||||
}}
|
||||
>
|
||||
<MenuItem value="system">Авто (система)</MenuItem>
|
||||
<MenuItem value="light">Светлая</MenuItem>
|
||||
<MenuItem value="dark">Тёмная</MenuItem>
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
<IconButton
|
||||
color="inherit"
|
||||
onClick={cycleMode}
|
||||
sx={{ ml: 1 }}
|
||||
aria-label="Переключить режим темы (авто/светлая/тёмная)"
|
||||
title={`Сейчас: ${mode === 'system' ? `авто (${resolvedMode})` : mode}`}
|
||||
>
|
||||
{resolvedMode === 'dark' ? <LightModeOutlinedIcon /> : <DarkModeOutlinedIcon />}
|
||||
</IconButton>
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
<Box component="main" sx={{ flex: 1, py: 3 }}>
|
||||
|
||||
Reference in New Issue
Block a user