rework circulars loaders
This commit is contained in:
@ -18,6 +18,7 @@ import Profile from './pages/Profile';
|
||||
import Shop from './pages/Shop';
|
||||
import Marketplace from './pages/Marketplace';
|
||||
import { Registration } from './pages/Registration';
|
||||
import { FullScreenLoader } from './components/FullScreenLoader';
|
||||
|
||||
const AuthCheck = ({ children }: { children: ReactNode }) => {
|
||||
const [isAuthenticated, setIsAuthenticated] = useState<boolean | null>(null);
|
||||
@ -86,7 +87,7 @@ const AuthCheck = ({ children }: { children: ReactNode }) => {
|
||||
};
|
||||
|
||||
if (isAuthenticated === null) {
|
||||
return <div>Loading...</div>;
|
||||
return <FullScreenLoader message="Загрузка..." />;
|
||||
}
|
||||
|
||||
return isAuthenticated ? children : <Navigate to="/login" replace />;
|
||||
@ -127,7 +128,10 @@ const App = () => {
|
||||
<TopBar onRegister={handleRegister} username={username || ''} />
|
||||
<Notifier />
|
||||
<Routes>
|
||||
<Route path="/login" element={<Login />} />
|
||||
<Route
|
||||
path="/login"
|
||||
element={<Login onLoginSuccess={setUsername} />}
|
||||
/>
|
||||
<Route path="/registration" element={<Registration />} />
|
||||
<Route
|
||||
path="/"
|
||||
|
||||
@ -8,12 +8,12 @@ import {
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
Collapse,
|
||||
CircularProgress,
|
||||
} from '@mui/material';
|
||||
import FolderIcon from '@mui/icons-material/Folder';
|
||||
import InsertDriveFileIcon from '@mui/icons-material/InsertDriveFile';
|
||||
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
||||
import ExpandLessIcon from '@mui/icons-material/ExpandLess';
|
||||
import { FullScreenLoader } from '../components/FullScreenLoader';
|
||||
|
||||
interface FileNode {
|
||||
name: string;
|
||||
@ -190,7 +190,7 @@ export default function FilesSelector({
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
return <CircularProgress />;
|
||||
return <FullScreenLoader fullScreen={false} />;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
|
||||
@ -1,59 +1,72 @@
|
||||
import Box from '@mui/material/Box';
|
||||
import Typography from '@mui/material/Typography';
|
||||
|
||||
export const FullScreenLoader = ({ message }: { message?: string }) => (
|
||||
<Box
|
||||
sx={{
|
||||
position: 'fixed',
|
||||
top: '50%',
|
||||
left: '50%',
|
||||
transform: 'translate(-50%, -50%)',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
gap: 3,
|
||||
zIndex: 9999,
|
||||
pointerEvents: 'none', // чтобы не блокировал клики, если нужно
|
||||
}}
|
||||
>
|
||||
{/* Градиентное вращающееся кольцо */}
|
||||
<Box
|
||||
sx={{
|
||||
width: 80,
|
||||
height: 80,
|
||||
borderRadius: '50%',
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
interface FullScreenLoaderProps {
|
||||
message?: string;
|
||||
fullScreen?: boolean; // <-- новый проп
|
||||
}
|
||||
|
||||
// сам градиент, который будет крутиться
|
||||
background: 'conic-gradient(#F27121, #E940CD, #8A2387, #F27121)',
|
||||
export const FullScreenLoader = ({
|
||||
message,
|
||||
fullScreen = true,
|
||||
}: FullScreenLoaderProps) => {
|
||||
const containerSx = fullScreen
|
||||
? {
|
||||
position: 'fixed' as const,
|
||||
inset: 0,
|
||||
display: 'flex',
|
||||
flexDirection: 'column' as const,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
gap: 3,
|
||||
zIndex: 9999,
|
||||
pointerEvents: 'none' as const,
|
||||
}
|
||||
: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column' as const,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
gap: 3,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
};
|
||||
|
||||
animation: 'spin 1s linear infinite',
|
||||
|
||||
// создаём отверстие внутри маской
|
||||
WebkitMask: 'radial-gradient(circle, transparent 55%, black 56%)',
|
||||
mask: 'radial-gradient(circle, transparent 55%, black 56%)',
|
||||
|
||||
'@keyframes spin': {
|
||||
'0%': { transform: 'rotate(0deg)' },
|
||||
'100%': { transform: 'rotate(360deg)' },
|
||||
},
|
||||
}}
|
||||
/>
|
||||
|
||||
{message && (
|
||||
<Typography
|
||||
variant="h6"
|
||||
return (
|
||||
<Box sx={containerSx}>
|
||||
{/* Градиентное вращающееся кольцо */}
|
||||
<Box
|
||||
sx={{
|
||||
fontFamily: 'Benzin-Bold',
|
||||
background:
|
||||
'linear-gradient(71deg, #F27121 0%, #E940CD 70%, #8A2387 100%)',
|
||||
WebkitBackgroundClip: 'text',
|
||||
WebkitTextFillColor: 'transparent',
|
||||
width: 80,
|
||||
height: 80,
|
||||
borderRadius: '50%',
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
background: 'conic-gradient(#F27121, #E940CD, #8A2387, #F27121)',
|
||||
animation: 'spin 1s linear infinite',
|
||||
WebkitMask: 'radial-gradient(circle, transparent 55%, black 56%)',
|
||||
mask: 'radial-gradient(circle, transparent 55%, black 56%)',
|
||||
'@keyframes spin': {
|
||||
'0%': { transform: 'rotate(0deg)' },
|
||||
'100%': { transform: 'rotate(360deg)' },
|
||||
},
|
||||
}}
|
||||
>
|
||||
{message}
|
||||
</Typography>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
/>
|
||||
|
||||
{message && (
|
||||
<Typography
|
||||
variant="h6"
|
||||
sx={{
|
||||
fontFamily: 'Benzin-Bold',
|
||||
background:
|
||||
'linear-gradient(71deg, #F27121 0%, #E940CD 70%, #8A2387 100%)',
|
||||
WebkitBackgroundClip: 'text',
|
||||
WebkitTextFillColor: 'transparent',
|
||||
}}
|
||||
>
|
||||
{message}
|
||||
</Typography>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
@ -8,7 +8,6 @@ import {
|
||||
CardMedia,
|
||||
CardContent,
|
||||
Button,
|
||||
CircularProgress,
|
||||
Dialog,
|
||||
DialogTitle,
|
||||
DialogContent,
|
||||
@ -22,6 +21,7 @@ import {
|
||||
sellItem,
|
||||
PlayerInventoryItem,
|
||||
} from '../api';
|
||||
import { FullScreenLoader } from './FullScreenLoader';
|
||||
|
||||
interface PlayerInventoryProps {
|
||||
username: string;
|
||||
@ -223,9 +223,7 @@ export default function PlayerInventory({
|
||||
)}
|
||||
|
||||
{loading ? (
|
||||
<Box sx={{ display: 'flex', justifyContent: 'center', my: 4 }}>
|
||||
<CircularProgress />
|
||||
</Box>
|
||||
<FullScreenLoader fullScreen={false} />
|
||||
) : (
|
||||
<>
|
||||
{inventoryItems.length === 0 ? (
|
||||
@ -266,7 +264,13 @@ export default function PlayerInventory({
|
||||
alt={item.material}
|
||||
/>
|
||||
<CardContent sx={{ p: 1 }}>
|
||||
<Box sx={{ display: 'flex', gap: '1vw', justifyContent: 'space-between' }}>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
gap: '1vw',
|
||||
justifyContent: 'space-between',
|
||||
}}
|
||||
>
|
||||
<Typography variant="body2" color="white" noWrap>
|
||||
{getItemDisplayName(item.material)}
|
||||
</Typography>
|
||||
@ -363,7 +367,7 @@ export default function PlayerInventory({
|
||||
color="primary"
|
||||
disabled={sellLoading}
|
||||
>
|
||||
{sellLoading ? <CircularProgress size={24} /> : 'Продать'}
|
||||
{sellLoading ? <FullScreenLoader fullScreen={false} /> : 'Продать'}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Box, Typography, CircularProgress, Avatar } from '@mui/material';
|
||||
import { Box, Typography, Avatar } from '@mui/material';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
interface ServerStatusProps {
|
||||
|
||||
@ -8,7 +8,11 @@ import useConfig from '../hooks/useConfig';
|
||||
import { useState } from 'react';
|
||||
import { FullScreenLoader } from '../components/FullScreenLoader';
|
||||
|
||||
const Login = () => {
|
||||
interface LoginProps {
|
||||
onLoginSuccess?: (username: string) => void;
|
||||
}
|
||||
|
||||
const Login = ({ onLoginSuccess }: LoginProps) => {
|
||||
const navigate = useNavigate();
|
||||
const { config, setConfig, saveConfig, handleInputChange } = useConfig();
|
||||
const { status, validateSession, refreshSession, authenticateWithElyBy } =
|
||||
@ -88,6 +92,11 @@ const Login = () => {
|
||||
}
|
||||
|
||||
console.log('Авторизация успешно завершена');
|
||||
|
||||
if (onLoginSuccess) {
|
||||
onLoginSuccess(config.username);
|
||||
}
|
||||
|
||||
navigate('/');
|
||||
} catch (error: any) {
|
||||
console.log(`ОШИБКА при авторизации: ${error.message}`);
|
||||
|
||||
@ -3,7 +3,6 @@ import { useEffect, useState } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Typography,
|
||||
CircularProgress,
|
||||
Button,
|
||||
Grid,
|
||||
Card,
|
||||
@ -18,6 +17,7 @@ import {
|
||||
import { isPlayerOnline, getPlayerServer } from '../utils/playerOnlineCheck';
|
||||
import { buyItem, fetchMarketplace, MarketplaceResponse, Server } from '../api';
|
||||
import PlayerInventory from '../components/PlayerInventory';
|
||||
import { FullScreenLoader } from '../components/FullScreenLoader';
|
||||
|
||||
interface TabPanelProps {
|
||||
children?: React.ReactNode;
|
||||
@ -195,14 +195,14 @@ export default function Marketplace() {
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
height: '100%',
|
||||
height: '20vh',
|
||||
gap: 2,
|
||||
}}
|
||||
>
|
||||
<CircularProgress size={60} />
|
||||
<Typography variant="h6" color="white">
|
||||
Проверяем, находитесь ли вы на сервере...
|
||||
</Typography>
|
||||
<FullScreenLoader
|
||||
fullScreen={true}
|
||||
message="Проверяем, находитесь ли вы на сервере..."
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
@ -339,7 +339,7 @@ export default function Marketplace() {
|
||||
<TabPanel value={tabValue} index={0}>
|
||||
{marketLoading ? (
|
||||
<Box sx={{ display: 'flex', justifyContent: 'center', mt: '50vw' }}>
|
||||
<CircularProgress />
|
||||
<FullScreenLoader fullScreen={false} />
|
||||
</Box>
|
||||
) : !marketItems || marketItems.items.length === 0 ? (
|
||||
<Box sx={{ mt: 4, textAlign: 'center' }}>
|
||||
|
||||
@ -19,10 +19,10 @@ import {
|
||||
Select,
|
||||
MenuItem,
|
||||
Alert,
|
||||
CircularProgress,
|
||||
} from '@mui/material';
|
||||
|
||||
import CapeCard from '../components/CapeCard';
|
||||
import { FullScreenLoader } from '../components/FullScreenLoader';
|
||||
|
||||
export default function Profile() {
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
@ -195,7 +195,7 @@ export default function Profile() {
|
||||
}}
|
||||
>
|
||||
{loading ? (
|
||||
<CircularProgress />
|
||||
<FullScreenLoader message="Загрузка вашего профиля" />
|
||||
) : (
|
||||
<>
|
||||
<Paper
|
||||
@ -406,12 +406,12 @@ export default function Profile() {
|
||||
disabled={uploadStatus === 'loading' || !skinFile}
|
||||
startIcon={
|
||||
uploadStatus === 'loading' ? (
|
||||
<CircularProgress size={20} color="inherit" />
|
||||
<FullScreenLoader fullScreen={false} />
|
||||
) : null
|
||||
}
|
||||
>
|
||||
{uploadStatus === 'loading' ? (
|
||||
<Typography sx={{ color: 'white' }}>Загрузка...</Typography>
|
||||
<FullScreenLoader message="Загрузка..." />
|
||||
) : (
|
||||
<Typography sx={{ color: 'white' }}>
|
||||
Установить скин
|
||||
|
||||
@ -12,7 +12,6 @@ import {
|
||||
TextField,
|
||||
Button,
|
||||
Snackbar,
|
||||
CircularProgress,
|
||||
} from '@mui/material';
|
||||
import LoginRoundedIcon from '@mui/icons-material/LoginRounded';
|
||||
import VerifiedRoundedIcon from '@mui/icons-material/VerifiedRounded';
|
||||
@ -25,6 +24,7 @@ import {
|
||||
import QRCodeStyling from 'qr-code-styling';
|
||||
import popalogo from '../../../assets/icons/popa-popa.svg';
|
||||
import GradientTextField from '../components/GradientTextField';
|
||||
import { FullScreenLoader } from '../components/FullScreenLoader';
|
||||
|
||||
const ColorlibConnector = styled(StepConnector)(({ theme }) => ({
|
||||
[`&.${stepConnectorClasses.alternativeLabel}`]: {
|
||||
@ -34,7 +34,7 @@ const ColorlibConnector = styled(StepConnector)(({ theme }) => ({
|
||||
[`& .${stepConnectorClasses.line}`]: {
|
||||
backgroundImage:
|
||||
//'linear-gradient( 95deg,rgb(242,113,33) 0%,rgb(233,64,87) 50%,rgb(138,35,135) 100%)',
|
||||
'linear-gradient( 95deg,rgb(150,150,150) 0%, rgb(242,113,33) 80%,rgb(233,64,87) 110%,rgb(138,35,135) 150%)'
|
||||
'linear-gradient( 95deg,rgb(150,150,150) 0%, rgb(242,113,33) 80%,rgb(233,64,87) 110%,rgb(138,35,135) 150%)',
|
||||
},
|
||||
},
|
||||
[`&.${stepConnectorClasses.completed}`]: {
|
||||
@ -46,7 +46,8 @@ const ColorlibConnector = styled(StepConnector)(({ theme }) => ({
|
||||
[`& .${stepConnectorClasses.line}`]: {
|
||||
height: 3,
|
||||
border: 0,
|
||||
backgroundImage: 'linear-gradient( 275deg,rgb(150,150,150) 0%, rgb(242,113,33) 80%,rgb(233,64,87) 110%,rgb(138,35,135) 150%)',
|
||||
backgroundImage:
|
||||
'linear-gradient( 275deg,rgb(150,150,150) 0%, rgb(242,113,33) 80%,rgb(233,64,87) 110%,rgb(138,35,135) 150%)',
|
||||
borderRadius: 1,
|
||||
transition: 'background-image 1s ease, background-color 1s ease',
|
||||
...theme.applyStyles('dark', {
|
||||
@ -84,8 +85,7 @@ const ColorlibStepIconRoot = styled('div')<{
|
||||
{
|
||||
props: ({ ownerState }) => ownerState.completed,
|
||||
style: {
|
||||
backgroundImage:
|
||||
'#adadad',
|
||||
backgroundImage: '#adadad',
|
||||
},
|
||||
},
|
||||
],
|
||||
@ -282,7 +282,7 @@ export const Registration = () => {
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: '10%',
|
||||
}} // чтобы отделить степпер от формы
|
||||
}} // чтобы отделить степпер от формы
|
||||
>
|
||||
{steps.map((label) => (
|
||||
<Step key={label}>
|
||||
@ -311,7 +311,15 @@ export const Registration = () => {
|
||||
))}
|
||||
</Stepper>
|
||||
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2, width: '50vw', mt: activeStep === 1 ? '20%' : '0%' }}>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: '1vh',
|
||||
width: '50vw',
|
||||
mt: activeStep === 1 ? '20%' : '0%',
|
||||
}}
|
||||
>
|
||||
{activeStep === 0 && (
|
||||
<Box
|
||||
sx={{
|
||||
@ -357,13 +365,13 @@ export const Registration = () => {
|
||||
transition: 'transform 0.3s ease',
|
||||
width: '60%',
|
||||
mt: 2,
|
||||
background: 'linear-gradient(71deg, #F27121 0%, #E940CD 70%, #8A2387 100%)',
|
||||
background:
|
||||
'linear-gradient(71deg, #F27121 0%, #E940CD 70%, #8A2387 100%)',
|
||||
fontFamily: 'Benzin-Bold',
|
||||
borderRadius: '2.5vw',
|
||||
fontSize: '2vw',
|
||||
'&:hover': {
|
||||
transform: 'scale(1.1)',
|
||||
|
||||
},
|
||||
}}
|
||||
onClick={handleCreateAccount}
|
||||
@ -389,13 +397,13 @@ export const Registration = () => {
|
||||
transition: 'transform 0.3s ease',
|
||||
width: '60%',
|
||||
mt: 2,
|
||||
background: 'linear-gradient(71deg, #F27121 0%, #E940CD 70%, #8A2387 100%)',
|
||||
background:
|
||||
'linear-gradient(71deg, #F27121 0%, #E940CD 70%, #8A2387 100%)',
|
||||
fontFamily: 'Benzin-Bold',
|
||||
borderRadius: '2.5vw',
|
||||
fontSize: '2vw',
|
||||
'&:hover': {
|
||||
transform: 'scale(1.1)',
|
||||
|
||||
},
|
||||
}}
|
||||
onClick={handleOpenBot}
|
||||
@ -425,10 +433,10 @@ export const Registration = () => {
|
||||
{verificationCode}
|
||||
</Typography>
|
||||
<Typography variant="body1">Ждем ответа от бота</Typography>
|
||||
<CircularProgress />
|
||||
<FullScreenLoader fullScreen={false} />
|
||||
</>
|
||||
) : (
|
||||
<CircularProgress />
|
||||
<FullScreenLoader fullScreen={false} />
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
|
||||
@ -9,6 +9,7 @@ import {
|
||||
StoreCape,
|
||||
} from '../api';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { FullScreenLoader } from '../components/FullScreenLoader';
|
||||
|
||||
export default function Shop() {
|
||||
const [storeCapes, setStoreCapes] = useState<StoreCape[]>([]);
|
||||
@ -88,7 +89,7 @@ export default function Shop() {
|
||||
}}
|
||||
>
|
||||
{loading ? (
|
||||
<Typography>Загрузка...</Typography>
|
||||
<FullScreenLoader message="Загрузка..." />
|
||||
) : (
|
||||
<Box
|
||||
sx={{
|
||||
|
||||
@ -8,7 +8,6 @@ import {
|
||||
CardContent,
|
||||
CardActions,
|
||||
Button,
|
||||
CircularProgress,
|
||||
Modal,
|
||||
List,
|
||||
ListItem,
|
||||
@ -18,6 +17,7 @@ import {
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import AddIcon from '@mui/icons-material/Add';
|
||||
import DownloadIcon from '@mui/icons-material/Download';
|
||||
import { FullScreenLoader } from '../components/FullScreenLoader';
|
||||
|
||||
interface VersionCardProps {
|
||||
id: string;
|
||||
@ -308,9 +308,7 @@ export const VersionsExplorer = () => {
|
||||
/>
|
||||
|
||||
{loading ? (
|
||||
<Box display="flex" justifyContent="center" my={5}>
|
||||
<CircularProgress />
|
||||
</Box>
|
||||
<FullScreenLoader message="Загрузка ваших версий..." />
|
||||
) : (
|
||||
<Grid
|
||||
container
|
||||
|
||||
Reference in New Issue
Block a user