315 lines
8.8 KiB
TypeScript
315 lines
8.8 KiB
TypeScript
import { Box, Button, Tab, Tabs, Typography } from '@mui/material';
|
||
import CloseRoundedIcon from '@mui/icons-material/CloseRounded';
|
||
import { useLocation, useNavigate } from 'react-router-dom';
|
||
import ArrowBackRoundedIcon from '@mui/icons-material/ArrowBackRounded';
|
||
import { useEffect, useState } from 'react';
|
||
import { Tooltip } from '@mui/material';
|
||
import { fetchCoins } from '../api';
|
||
|
||
declare global {
|
||
interface Window {
|
||
electron: {
|
||
ipcRenderer: {
|
||
invoke(channel: string, ...args: unknown[]): Promise<any>;
|
||
on(channel: string, func: (...args: unknown[]) => void): void;
|
||
removeAllListeners(channel: string): void;
|
||
};
|
||
};
|
||
}
|
||
}
|
||
|
||
// Определяем пропсы
|
||
interface TopBarProps {
|
||
onRegister?: () => void; // Опционально, если нужен обработчик регистрации
|
||
username?: string;
|
||
}
|
||
|
||
export default function TopBar({ onRegister, username }: TopBarProps) {
|
||
// Получаем текущий путь
|
||
const location = useLocation();
|
||
const isLoginPage = location.pathname === '/login';
|
||
const isLaunchPage = location.pathname.startsWith('/launch');
|
||
const isVersionsExplorerPage = location.pathname.startsWith('/');
|
||
const navigate = useNavigate();
|
||
const [coins, setCoins] = useState<number>(0);
|
||
const [value, setValue] = useState(0);
|
||
|
||
const handleChange = (event: React.SyntheticEvent, newValue: number) => {
|
||
setValue(newValue);
|
||
if (newValue === 0) {
|
||
navigate('/');
|
||
} else if (newValue === 1) {
|
||
navigate('/profile');
|
||
} else if (newValue === 2) {
|
||
navigate('/shop');
|
||
} else if (newValue === 3) {
|
||
navigate('/marketplace');
|
||
}
|
||
};
|
||
|
||
const handleLaunchPage = () => {
|
||
navigate('/');
|
||
};
|
||
|
||
const getPageTitle = () => {
|
||
if (isLoginPage) {
|
||
return 'Вход';
|
||
}
|
||
if (isLaunchPage) {
|
||
return 'Запуск';
|
||
}
|
||
if (isVersionsExplorerPage) {
|
||
return 'Версии';
|
||
}
|
||
return 'Неизвестная страница';
|
||
};
|
||
|
||
// Функция для получения количества монет
|
||
const fetchCoinsData = async () => {
|
||
if (!username) return;
|
||
|
||
try {
|
||
const coinsData = await fetchCoins(username);
|
||
setCoins(coinsData.coins);
|
||
} catch (error) {
|
||
console.error('Ошибка при получении количества монет:', error);
|
||
}
|
||
};
|
||
|
||
useEffect(() => {
|
||
if (username) {
|
||
fetchCoinsData();
|
||
|
||
// Создаем интервалы для периодического обновления данных
|
||
const coinsInterval = setInterval(fetchCoinsData, 60000);
|
||
|
||
return () => {
|
||
clearInterval(coinsInterval);
|
||
};
|
||
}
|
||
}, [username]);
|
||
|
||
return (
|
||
<Box
|
||
sx={{
|
||
display: 'flex',
|
||
position: 'absolute',
|
||
top: 0,
|
||
left: 0,
|
||
right: 0,
|
||
height: '7vh',
|
||
zIndex: 1000,
|
||
width: '100%',
|
||
WebkitAppRegion: 'drag',
|
||
overflow: 'hidden',
|
||
justifyContent: 'space-between',
|
||
alignItems: 'center',
|
||
// marginLeft: '1em',
|
||
// marginRight: '1em',
|
||
}}
|
||
>
|
||
{/* Левая часть */}
|
||
<Box
|
||
sx={{
|
||
display: 'flex',
|
||
WebkitAppRegion: 'no-drag',
|
||
gap: '2vw',
|
||
alignItems: 'center',
|
||
marginLeft: '1vw',
|
||
}}
|
||
>
|
||
{isLaunchPage && (
|
||
<Button
|
||
variant="outlined"
|
||
color="primary"
|
||
onClick={() => handleLaunchPage()}
|
||
sx={{
|
||
width: '3em',
|
||
height: '3em',
|
||
borderRadius: '50%',
|
||
border: 'unset',
|
||
color: 'white',
|
||
minWidth: 'unset',
|
||
minHeight: 'unset',
|
||
}}
|
||
>
|
||
<ArrowBackRoundedIcon />
|
||
</Button>
|
||
)}
|
||
{!isLaunchPage && (
|
||
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
|
||
<Tabs
|
||
value={value}
|
||
onChange={handleChange}
|
||
aria-label="basic tabs example"
|
||
>
|
||
<Tab
|
||
label="Версии"
|
||
sx={{
|
||
color: 'white',
|
||
fontFamily: 'Benzin-Bold',
|
||
fontSize: '0.7em',
|
||
}}
|
||
/>
|
||
<Tab
|
||
label="Профиль"
|
||
sx={{
|
||
color: 'white',
|
||
fontFamily: 'Benzin-Bold',
|
||
fontSize: '0.7em',
|
||
}}
|
||
/>
|
||
<Tab
|
||
label="Магазин"
|
||
sx={{
|
||
color: 'white',
|
||
fontFamily: 'Benzin-Bold',
|
||
fontSize: '0.7em',
|
||
}}
|
||
/>
|
||
<Tab
|
||
label="Рынок"
|
||
sx={{
|
||
color: 'white',
|
||
fontFamily: 'Benzin-Bold',
|
||
fontSize: '0.7em',
|
||
}}
|
||
/>
|
||
</Tabs>
|
||
</Box>
|
||
)}
|
||
</Box>
|
||
{/* Центр */}
|
||
<Box
|
||
sx={{
|
||
position: 'absolute',
|
||
left: '50%',
|
||
transform: 'translateX(-50%)',
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
justifyContent: 'center',
|
||
flexGrow: 1,
|
||
WebkitAppRegion: 'drag',
|
||
}}
|
||
>
|
||
<Typography variant="h6" sx={{ color: 'white' }}>
|
||
{getPageTitle()}
|
||
</Typography>
|
||
</Box>
|
||
{/* Правая часть со всеми кнопками */}
|
||
<Box
|
||
sx={{
|
||
display: 'flex',
|
||
WebkitAppRegion: 'no-drag',
|
||
gap: '1vw',
|
||
alignItems: 'center',
|
||
marginRight: '1vw',
|
||
}}
|
||
>
|
||
{/* Кнопка регистрации, если на странице логина */}
|
||
{username && (
|
||
<Tooltip
|
||
title="Попы — внутриигровая валюта, начисляемая за время игры на серверах."
|
||
arrow
|
||
>
|
||
<Box
|
||
sx={{
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: '8px',
|
||
backgroundColor: 'rgba(0, 0, 0, 0.2)',
|
||
borderRadius: '16px',
|
||
padding: '6px 12px',
|
||
border: '1px solid rgba(255, 255, 255, 0.1)',
|
||
}}
|
||
>
|
||
<Box
|
||
sx={{
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
width: '24px',
|
||
height: '24px',
|
||
}}
|
||
>
|
||
<Typography sx={{ color: '#2bff00ff' }}>P</Typography>
|
||
</Box>
|
||
<Typography
|
||
variant="body1"
|
||
sx={{
|
||
color: 'white',
|
||
fontWeight: 'bold',
|
||
fontSize: '16px',
|
||
lineHeight: 1,
|
||
}}
|
||
>
|
||
{coins}
|
||
</Typography>
|
||
</Box>
|
||
</Tooltip>
|
||
)}
|
||
{isLoginPage && (
|
||
<Button
|
||
variant="outlined"
|
||
color="primary"
|
||
onClick={() => onRegister && onRegister()}
|
||
sx={{
|
||
width: '10em',
|
||
height: '3em',
|
||
borderRadius: '1.5vw',
|
||
color: 'white',
|
||
backgroundImage: 'linear-gradient(to right, #7BB8FF, #FFB7ED)',
|
||
border: 'unset',
|
||
'&:hover': {
|
||
backgroundImage: 'linear-gradient(to right, #6AA8EE, #EEA7DD)',
|
||
},
|
||
boxShadow: '0.5em 0.5em 0.5em 0px #00000040 inset',
|
||
}}
|
||
>
|
||
Регистрация
|
||
</Button>
|
||
)}
|
||
|
||
{/* Кнопки управления окном */}
|
||
<Button
|
||
onClick={() => {
|
||
window.electron.ipcRenderer.invoke('minimize-app');
|
||
}}
|
||
sx={{
|
||
minWidth: 'unset',
|
||
minHeight: 'unset',
|
||
width: '3em',
|
||
height: '3em',
|
||
borderRadius: '50%',
|
||
}}
|
||
>
|
||
<svg
|
||
className="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium"
|
||
focusable="false"
|
||
aria-hidden="true"
|
||
viewBox="0 0 24 24"
|
||
>
|
||
<path
|
||
d="M 7 19 h 10 c 0.55 0 1 0.45 1 1 s -0.45 1 -1 1 H 7 c -0.55 0 -1 -0.45 -1 -1 s 0.45 -1 1 -1"
|
||
fill="white"
|
||
></path>
|
||
</svg>
|
||
</Button>
|
||
<Button
|
||
onClick={() => {
|
||
window.electron.ipcRenderer.invoke('close-app');
|
||
}}
|
||
sx={{
|
||
minWidth: 'unset',
|
||
minHeight: 'unset',
|
||
width: '3em',
|
||
height: '3em',
|
||
borderRadius: '50%',
|
||
}}
|
||
>
|
||
<CloseRoundedIcon sx={{ color: 'white' }} />
|
||
</Button>
|
||
</Box>
|
||
</Box>
|
||
);
|
||
}
|