mnoga che sdelal
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
import { Box, Button, Tab, Tabs, Typography } from '@mui/material';
|
||||
import { Box, Button, Tab, Tabs, Typography, Menu, MenuItem, Divider } from '@mui/material';
|
||||
import CloseRoundedIcon from '@mui/icons-material/CloseRounded';
|
||||
import { useLocation, useNavigate } from 'react-router-dom';
|
||||
import ArrowBackRoundedIcon from '@mui/icons-material/ArrowBackRounded';
|
||||
@ -7,6 +7,11 @@ import { Tooltip } from '@mui/material';
|
||||
import { fetchCoins } from '../api';
|
||||
import CustomTooltip from './Notifications/CustomTooltip';
|
||||
import CoinsDisplay from './CoinsDisplay';
|
||||
import { HeadAvatar } from './HeadAvatar';
|
||||
import { fetchPlayer } from './../api'
|
||||
import CalendarMonthIcon from '@mui/icons-material/CalendarMonth';
|
||||
import EmojiEventsIcon from '@mui/icons-material/EmojiEvents';
|
||||
import PersonIcon from '@mui/icons-material/Person';
|
||||
declare global {
|
||||
interface Window {
|
||||
electron: {
|
||||
@ -29,14 +34,38 @@ export default function TopBar({ onRegister, username }: TopBarProps) {
|
||||
// Получаем текущий путь
|
||||
const location = useLocation();
|
||||
const isLoginPage = location.pathname === '/login';
|
||||
const [isAuthed, setIsAuthed] = useState(false);
|
||||
const isLaunchPage = location.pathname.startsWith('/launch');
|
||||
const isVersionsExplorerPage = location.pathname.startsWith('/');
|
||||
const isRegistrationPage = location.pathname === '/registration';
|
||||
const navigate = useNavigate();
|
||||
const [coins, setCoins] = useState<number>(0);
|
||||
const [value, setValue] = useState(1);
|
||||
const [activePage, setActivePage] = useState('versions');
|
||||
const tabsWrapperRef = useRef<HTMLDivElement | null>(null);
|
||||
const [skinUrl, setSkinUrl] = useState<string>('');
|
||||
const [avatarAnchorEl, setAvatarAnchorEl] =
|
||||
useState<null | HTMLElement>(null);
|
||||
const [menuOpen, setMenuOpen] = useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
const saved = localStorage.getItem('launcher_config');
|
||||
try {
|
||||
const cfg = saved ? JSON.parse(saved) : null;
|
||||
setIsAuthed(Boolean(cfg?.accessToken)); // или cfg?.uuid/username — как у тебя принято
|
||||
} catch {
|
||||
setIsAuthed(false);
|
||||
}
|
||||
}, [location.pathname]); // можно и без dependency, но так надёжнее при logout/login
|
||||
|
||||
const avatarMenuOpen = Boolean(avatarAnchorEl);
|
||||
|
||||
const handleAvatarClick = (event: React.MouseEvent<HTMLElement>) => {
|
||||
setAvatarAnchorEl(event.currentTarget);
|
||||
};
|
||||
|
||||
const handleAvatarMenuClose = () => {
|
||||
setAvatarAnchorEl(null);
|
||||
};
|
||||
|
||||
const handleChange = (event: React.SyntheticEvent, newValue: number) => {
|
||||
setValue(newValue);
|
||||
@ -147,6 +176,19 @@ export default function TopBar({ onRegister, username }: TopBarProps) {
|
||||
navigate('/login');
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const savedConfig = localStorage.getItem('launcher_config');
|
||||
if (!savedConfig) return;
|
||||
|
||||
const config = JSON.parse(savedConfig);
|
||||
const uuid = config.uuid;
|
||||
if (!uuid) return;
|
||||
|
||||
fetchPlayer(uuid)
|
||||
.then((player) => setSkinUrl(player.skin_url))
|
||||
.catch((e) => console.error('Не удалось получить скин:', e));
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
@ -197,7 +239,7 @@ export default function TopBar({ onRegister, username }: TopBarProps) {
|
||||
<ArrowBackRoundedIcon />
|
||||
</Button>
|
||||
)}
|
||||
{!isLaunchPage && !isRegistrationPage && !isLoginPage && (
|
||||
{isAuthed && !isLaunchPage && (
|
||||
<Box
|
||||
ref={tabsWrapperRef}
|
||||
onWheel={handleTabsWheel}
|
||||
@ -264,25 +306,6 @@ export default function TopBar({ onRegister, username }: TopBarProps) {
|
||||
transition: 'all 0.3s ease',
|
||||
}}
|
||||
/>
|
||||
<Tab
|
||||
label="Профиль"
|
||||
disableRipple={true}
|
||||
onClick={() => {
|
||||
setActivePage('profile');
|
||||
}}
|
||||
sx={{
|
||||
color: 'white',
|
||||
fontFamily: 'Benzin-Bold',
|
||||
fontSize: '0.7em',
|
||||
'&.Mui-selected': {
|
||||
color: 'rgba(255, 77, 77, 1)',
|
||||
},
|
||||
'&:hover': {
|
||||
color: 'rgb(177, 52, 52)',
|
||||
},
|
||||
transition: 'all 0.3s ease',
|
||||
}}
|
||||
/>
|
||||
<Tab
|
||||
label="Магазин"
|
||||
disableRipple={true}
|
||||
@ -357,32 +380,17 @@ export default function TopBar({ onRegister, username }: TopBarProps) {
|
||||
}}
|
||||
>
|
||||
{!isLoginPage && !isRegistrationPage && username && (
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
onClick={() => logout()}
|
||||
sx={{
|
||||
width: '8em',
|
||||
height: '3em',
|
||||
borderRadius: '2.5vw',
|
||||
fontFamily: 'Benzin-Bold',
|
||||
fontSize: '0.9em',
|
||||
background:
|
||||
'linear-gradient(71deg, #F27121 0%, #E940CD 70%, #8A2387 100%)',
|
||||
color: 'white',
|
||||
border: 'none',
|
||||
transition: 'transform 0.3s ease',
|
||||
'&:hover': {
|
||||
background:
|
||||
'linear-gradient(71deg, #F27121 0%, #E940CD 70%, #8A2387 100%)',
|
||||
transform: 'scale(1.01)',
|
||||
boxShadow: '0 4px 15px rgba(242, 113, 33, 0.4)',
|
||||
},
|
||||
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.3)',
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: '1vw' }}>
|
||||
<HeadAvatar
|
||||
skinUrl={skinUrl}
|
||||
size={44}
|
||||
style={{
|
||||
borderRadius: '3vw',
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
>
|
||||
Выйти
|
||||
</Button>
|
||||
onClick={handleAvatarClick}
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
{/* Кнопка регистрации, если на странице логина */}
|
||||
{!isLoginPage && !isRegistrationPage && username && (
|
||||
@ -393,37 +401,6 @@ export default function TopBar({ onRegister, username }: TopBarProps) {
|
||||
showTooltip={true}
|
||||
/>
|
||||
)}
|
||||
{isLoginPage && (
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={() => navigate('/registration')}
|
||||
sx={{
|
||||
width: '13em',
|
||||
height: '3em',
|
||||
borderRadius: '2.5vw',
|
||||
fontFamily: 'Benzin-Bold',
|
||||
fontSize: '0.9em',
|
||||
background:
|
||||
'linear-gradient(71deg, #F27121 0%, #E940CD 70%, #8A2387 100%)',
|
||||
color: 'white',
|
||||
border: 'none',
|
||||
transition: 'all 0.3s ease',
|
||||
'&:hover': {
|
||||
background:
|
||||
'linear-gradient(71deg, #F27121 0%, #E940CD 70%, #8A2387 100%)',
|
||||
transform: 'scale(1.01)',
|
||||
boxShadow: '0 4px 15px rgba(242, 113, 33, 0.4)',
|
||||
},
|
||||
'&:active': {
|
||||
color: 'transparent',
|
||||
},
|
||||
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.3)',
|
||||
userSelect: 'none',
|
||||
}}
|
||||
>
|
||||
<Typography sx={{ fontSize: '1em', color: 'white' }}>Регистрация</Typography>
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{/* Кнопки управления окном */}
|
||||
<Button
|
||||
@ -465,6 +442,165 @@ export default function TopBar({ onRegister, username }: TopBarProps) {
|
||||
<CloseRoundedIcon sx={{ color: 'white' }} />
|
||||
</Button>
|
||||
</Box>
|
||||
<Menu
|
||||
anchorEl={avatarAnchorEl}
|
||||
open={avatarMenuOpen}
|
||||
onClose={handleAvatarMenuClose}
|
||||
anchorOrigin={{
|
||||
vertical: 'bottom',
|
||||
horizontal: 'right',
|
||||
}}
|
||||
transformOrigin={{
|
||||
vertical: 'top',
|
||||
horizontal: 'right',
|
||||
}}
|
||||
PaperProps={{
|
||||
sx: {
|
||||
mt: '0.5vw',
|
||||
borderRadius: '1vw',
|
||||
minWidth: '16vw',
|
||||
bgcolor: 'rgba(0,0,0,0.92)',
|
||||
color: 'white',
|
||||
boxShadow: '0 0 20px rgba(0,0,0,0.6)',
|
||||
border: '1px solid rgba(255,77,77,0.35)',
|
||||
},
|
||||
}}
|
||||
>
|
||||
{/* ===== 1 строка: аватар + ник + валюта ===== */}
|
||||
<Box
|
||||
sx={{
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'auto 1fr',
|
||||
gap: '1.5vw',
|
||||
alignItems: 'center',
|
||||
px: '2vw',
|
||||
py: '0.8vw',
|
||||
}}
|
||||
>
|
||||
<HeadAvatar
|
||||
skinUrl={skinUrl}
|
||||
size={40}
|
||||
style={{ borderRadius: '3vw' }}
|
||||
/>
|
||||
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column' }}>
|
||||
<Typography
|
||||
sx={{
|
||||
fontFamily: 'Benzin-Bold',
|
||||
fontSize: '2vw',
|
||||
}}
|
||||
>
|
||||
{username || 'Игрок'}
|
||||
</Typography>
|
||||
|
||||
<CoinsDisplay
|
||||
username={username}
|
||||
size="medium"
|
||||
autoUpdate={true}
|
||||
showTooltip={true}
|
||||
sx={{
|
||||
border: 'none',
|
||||
padding: '0vw',
|
||||
}}
|
||||
backgroundColor={'rgba(0, 0, 0, 0)'}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<Divider sx={{ my: '0.4vw', borderColor: 'rgba(255,255,255,0.08)' }} />
|
||||
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
handleAvatarMenuClose();
|
||||
navigate('/profile');
|
||||
}}
|
||||
sx={{
|
||||
fontFamily: 'Benzin-Bold',
|
||||
fontSize: '1.5vw',
|
||||
gap: '0.5vw',
|
||||
py: '0.7vw',
|
||||
'&:hover': {
|
||||
bgcolor: 'rgba(255,77,77,0.15)',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<PersonIcon sx={{ fontSize: '2vw' }}/> Профиль
|
||||
</MenuItem>
|
||||
|
||||
{/* ===== 2 строка: ежедневные задания ===== */}
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
handleAvatarMenuClose();
|
||||
navigate('/dailyquests');
|
||||
}}
|
||||
sx={{
|
||||
fontFamily: 'Benzin-Bold',
|
||||
fontSize: '1.5vw',
|
||||
gap: '0.5vw',
|
||||
py: '0.7vw',
|
||||
'&:hover': {
|
||||
bgcolor: 'rgba(255,77,77,0.15)',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<CalendarMonthIcon sx={{ fontSize: '2vw' }} /> Ежедневные задания
|
||||
</MenuItem>
|
||||
|
||||
{/* ===== 3 строка: ежедневная награда ===== */}
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
handleAvatarMenuClose();
|
||||
navigate('/daily');
|
||||
}}
|
||||
sx={{
|
||||
fontFamily: 'Benzin-Bold',
|
||||
fontSize: '1.5vw',
|
||||
gap: '0.5vw',
|
||||
py: '0.7vw',
|
||||
'&:hover': {
|
||||
bgcolor: 'rgba(255,77,77,0.15)',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<EmojiEventsIcon sx={{ fontSize: '2vw' }} /> Ежедневная награда
|
||||
</MenuItem>
|
||||
|
||||
<Divider sx={{ my: '0.4vw', borderColor: 'rgba(255,255,255,0.08)' }} />
|
||||
{!isLoginPage && !isRegistrationPage && username && (
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
onClick={() => {
|
||||
logout();
|
||||
setMenuOpen(false);
|
||||
}}
|
||||
sx={{
|
||||
width: '8vw',
|
||||
height: '3vw',
|
||||
borderRadius: '2.5vw',
|
||||
fontFamily: 'Benzin-Bold',
|
||||
fontSize: '1.2vw',
|
||||
background:
|
||||
'linear-gradient(71deg, #F27121 0%, #E940CD 70%, #8A2387 100%)',
|
||||
color: 'white',
|
||||
border: 'none',
|
||||
transition: 'transform 0.3s ease',
|
||||
'&:hover': {
|
||||
background:
|
||||
'linear-gradient(71deg, #F27121 0%, #E940CD 70%, #8A2387 100%)',
|
||||
transform: 'scale(1.01)',
|
||||
boxShadow: '0 4px 15px rgba(242, 113, 33, 0.4)',
|
||||
},
|
||||
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.3)',
|
||||
m: '0 0 0 18vw'
|
||||
}}
|
||||
>
|
||||
Выйти
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{/* ↓↓↓ дальше ты сам добавишь пункты ↓↓↓ */}
|
||||
</Menu>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user