add secret page
This commit is contained in:
BIN
assets/images/fake-payment.png
Normal file
BIN
assets/images/fake-payment.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
@ -26,6 +26,7 @@ import DailyReward from './pages/DailyReward';
|
||||
import DailyQuests from './pages/DailyQuests';
|
||||
import Settings from './pages/Settings';
|
||||
import Inventory from './pages/Inventory';
|
||||
import FakePaymentPage from './pages/FakePaymentPage';
|
||||
import { TrayBridge } from './utils/TrayBridge';
|
||||
import { API_BASE_URL } from './api';
|
||||
|
||||
@ -398,6 +399,14 @@ const AppLayout = () => {
|
||||
</AuthCheck>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/fakepaymentpage"
|
||||
element={
|
||||
<AuthCheck>
|
||||
<FakePaymentPage />
|
||||
</AuthCheck>
|
||||
}
|
||||
/>
|
||||
</Routes>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
@ -21,6 +21,9 @@ interface CoinsDisplayProps {
|
||||
backgroundColor?: string;
|
||||
textColor?: string;
|
||||
|
||||
onClick?: () => void;
|
||||
disableRefreshOnClick?: boolean;
|
||||
|
||||
sx?: SxProps<Theme>;
|
||||
}
|
||||
|
||||
@ -40,6 +43,9 @@ export default function CoinsDisplay({
|
||||
backgroundColor = 'rgba(0, 0, 0, 0.2)',
|
||||
textColor = 'white',
|
||||
|
||||
onClick,
|
||||
disableRefreshOnClick = false,
|
||||
|
||||
sx,
|
||||
}: CoinsDisplayProps) {
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
@ -61,6 +67,14 @@ export default function CoinsDisplay({
|
||||
}
|
||||
};
|
||||
|
||||
const handleClick = () => {
|
||||
// 1) если передали внешний обработчик — выполняем его
|
||||
if (onClick) onClick();
|
||||
|
||||
// 2) опционально оставляем обновление баланса по клику
|
||||
if (!disableRefreshOnClick && username) fetchCoinsData();
|
||||
};
|
||||
|
||||
const [coins, setCoins] = useState<number>(() => {
|
||||
// 1) если пришло значение извне — оно приоритетнее
|
||||
if (externalValue !== undefined) return externalValue;
|
||||
@ -76,7 +90,8 @@ export default function CoinsDisplay({
|
||||
useEffect(() => {
|
||||
const handler = () => setSettingsVersion((v) => v + 1);
|
||||
window.addEventListener('settings-updated', handler as EventListener);
|
||||
return () => window.removeEventListener('settings-updated', handler as EventListener);
|
||||
return () =>
|
||||
window.removeEventListener('settings-updated', handler as EventListener);
|
||||
}, []);
|
||||
|
||||
const isTooltipDisabledBySettings = useMemo(() => {
|
||||
@ -191,7 +206,7 @@ export default function CoinsDisplay({
|
||||
borderRadius: sizes.borderRadius,
|
||||
padding: sizes.containerPadding,
|
||||
border: '1px solid rgba(255, 255, 255, 0.1)',
|
||||
cursor: tooltipEnabled ? 'help' : 'default',
|
||||
cursor: onClick ? 'pointer' : tooltipEnabled ? 'help' : 'default',
|
||||
|
||||
// можно оставить лёгкий намёк на загрузку, но без "пульса" текста
|
||||
opacity: isLoading ? 0.85 : 1,
|
||||
@ -199,7 +214,7 @@ export default function CoinsDisplay({
|
||||
|
||||
...sx,
|
||||
}}
|
||||
onClick={username ? handleRefresh : undefined}
|
||||
onClick={handleClick}
|
||||
title={username ? 'Нажмите для обновления' : undefined}
|
||||
>
|
||||
{showIcon && (
|
||||
|
||||
@ -34,6 +34,7 @@ export default function PageHeader() {
|
||||
path === '/marketplace' ||
|
||||
path === '/profile' ||
|
||||
path === '/inventory' ||
|
||||
path === '/fakepaymentpage' ||
|
||||
path.startsWith('/launch')
|
||||
) {
|
||||
return { title: '', subtitle: '', hidden: true };
|
||||
@ -43,7 +44,7 @@ export default function PageHeader() {
|
||||
return {
|
||||
title: 'Настройки',
|
||||
subtitle: 'Персонализация интерфейса и поведения лаунчера',
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (path === '/news') {
|
||||
@ -63,7 +64,8 @@ export default function PageHeader() {
|
||||
if (path.startsWith('/daily')) {
|
||||
return {
|
||||
title: 'Ежедневные награды',
|
||||
subtitle: 'Ежедневный вход на сервер приносит бонусы и полезные награды!',
|
||||
subtitle:
|
||||
'Ежедневный вход на сервер приносит бонусы и полезные награды!',
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -262,12 +262,13 @@ export default function TopBar({ onRegister, username }: TopBarProps) {
|
||||
};
|
||||
|
||||
window.addEventListener('settings-updated', handler as EventListener);
|
||||
return () => window.removeEventListener('settings-updated', handler as EventListener);
|
||||
return () =>
|
||||
window.removeEventListener('settings-updated', handler as EventListener);
|
||||
}, [updateGradientVars]);
|
||||
|
||||
return (
|
||||
<Box
|
||||
className={isAuthPage ? undefined : 'glass-ui'}
|
||||
className={isAuthPage ? undefined : 'glass-ui'}
|
||||
sx={[
|
||||
{
|
||||
display: 'flex',
|
||||
@ -454,6 +455,8 @@ export default function TopBar({ onRegister, username }: TopBarProps) {
|
||||
size="medium"
|
||||
autoUpdate={true}
|
||||
showTooltip={true}
|
||||
onClick={() => navigate('/fakepaymentpage')}
|
||||
disableRefreshOnClick={true} // чтобы клик не дёргал fetchCoins
|
||||
/>
|
||||
)}
|
||||
|
||||
|
||||
518
src/renderer/pages/FakePaymentPage.tsx
Normal file
518
src/renderer/pages/FakePaymentPage.tsx
Normal file
@ -0,0 +1,518 @@
|
||||
// pages/TopUpPage.tsx
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Paper,
|
||||
Stack,
|
||||
TextField,
|
||||
Typography,
|
||||
ToggleButton,
|
||||
ToggleButtonGroup,
|
||||
CircularProgress,
|
||||
LinearProgress,
|
||||
} from '@mui/material';
|
||||
import { styled } from '@mui/material/styles';
|
||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import fakePaymentImg from '../../../assets/images/fake-payment.png';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
type PayMethod = 'sbp' | 'card' | 'crypto' | 'other';
|
||||
type Stage = 'form' | 'processing' | 'done';
|
||||
|
||||
const STEPS: string[] = [
|
||||
'Создаём счёт…',
|
||||
'Проверяем данные…',
|
||||
'Подключаем платёжный шлюз…',
|
||||
'Ожидаем подтверждение…',
|
||||
'Подписываем запрос…',
|
||||
'Проверяем лимиты…',
|
||||
'Синхронизируем баланс…',
|
||||
'Завершаем операцию…',
|
||||
'Почти готово…',
|
||||
];
|
||||
|
||||
// ===== Styles “как Registration” =====
|
||||
const GRADIENT =
|
||||
'linear-gradient(71deg, #F27121 0%, #E940CD 70%, #8A2387 100%)';
|
||||
|
||||
const GlassPaper = styled(Paper)(() => ({
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
borderRadius: 28,
|
||||
background: 'rgba(0,0,0,0.35)',
|
||||
border: '1px solid rgba(255,255,255,0.10)',
|
||||
backdropFilter: 'blur(14px)',
|
||||
boxShadow: '0 20px 60px rgba(0,0,0,0.45)',
|
||||
}));
|
||||
|
||||
const Glow = styled('div')(() => ({
|
||||
position: 'absolute',
|
||||
inset: -2,
|
||||
background:
|
||||
'radial-gradient(800px 300px at 20% 10%, rgba(242,113,33,0.22), transparent 60%),' +
|
||||
'radial-gradient(800px 300px at 80% 0%, rgba(233,64,205,0.18), transparent 55%),' +
|
||||
'radial-gradient(900px 420px at 50% 110%, rgba(138,35,135,0.20), transparent 60%)',
|
||||
pointerEvents: 'none',
|
||||
}));
|
||||
|
||||
const GradientTitle = styled(Typography)(() => ({
|
||||
fontWeight: 900,
|
||||
backgroundImage:
|
||||
'linear-gradient(136deg, rgb(242,113,33) 0%, rgb(233,64,87) 50%, rgb(138,35,135) 100%)',
|
||||
WebkitBackgroundClip: 'text',
|
||||
WebkitTextFillColor: 'transparent',
|
||||
fontFamily: 'Benzin-Bold, sans-serif',
|
||||
}));
|
||||
|
||||
const GradientButton = styled(Button)(() => ({
|
||||
background: GRADIENT,
|
||||
fontFamily: 'Benzin-Bold, sans-serif',
|
||||
borderRadius: 999,
|
||||
textTransform: 'none',
|
||||
transition: 'transform 0.25s ease, filter 0.25s ease, box-shadow 0.25s ease',
|
||||
boxShadow: '0 12px 30px rgba(0,0,0,0.35)',
|
||||
'&:hover': {
|
||||
transform: 'scale(1.04)',
|
||||
filter: 'brightness(1.06)',
|
||||
boxShadow: '0 16px 42px rgba(0,0,0,0.48)',
|
||||
background: GRADIENT,
|
||||
},
|
||||
'&:disabled': {
|
||||
background: 'rgba(255,255,255,0.08)',
|
||||
color: 'rgba(255,255,255,0.35)',
|
||||
boxShadow: 'none',
|
||||
},
|
||||
}));
|
||||
|
||||
const StyledToggleButtonGroup = styled(ToggleButtonGroup)(() => ({
|
||||
borderRadius: 999,
|
||||
overflow: 'hidden',
|
||||
border: '1px solid rgba(255,255,255,0.10)',
|
||||
background: 'rgba(255,255,255,0.06)',
|
||||
'& .MuiToggleButton-root': {
|
||||
border: 'none',
|
||||
color: 'rgba(255,255,255,0.75)',
|
||||
fontFamily: 'Benzin-Bold, sans-serif',
|
||||
letterSpacing: '0.02em',
|
||||
paddingTop: 10,
|
||||
paddingBottom: 10,
|
||||
transition: 'transform 0.2s ease, background 0.2s ease, color 0.2s ease',
|
||||
},
|
||||
'& .MuiToggleButton-root:hover': {
|
||||
background: 'rgba(255,255,255,0.08)',
|
||||
transform: 'scale(1.02)',
|
||||
},
|
||||
'& .MuiToggleButton-root.Mui-selected': {
|
||||
color: '#fff',
|
||||
background: GRADIENT,
|
||||
},
|
||||
'& .MuiToggleButton-root.Mui-selected:hover': {
|
||||
background: GRADIENT,
|
||||
},
|
||||
}));
|
||||
|
||||
const StyledTextField = styled(TextField)(() => ({
|
||||
'& .MuiInputLabel-root': {
|
||||
color: 'rgba(255,255,255,0.65)',
|
||||
},
|
||||
'& .MuiInputLabel-root.Mui-focused': {
|
||||
color: 'rgba(255,255,255,0.9)',
|
||||
},
|
||||
'& .MuiOutlinedInput-root': {
|
||||
borderRadius: 20,
|
||||
background: 'rgba(255,255,255,0.06)',
|
||||
color: '#fff',
|
||||
fontFamily: 'Benzin-Bold, sans-serif',
|
||||
},
|
||||
'& .MuiOutlinedInput-notchedOutline': {
|
||||
borderColor: 'rgba(255,255,255,0.10)',
|
||||
},
|
||||
'& .MuiOutlinedInput-root:hover .MuiOutlinedInput-notchedOutline': {
|
||||
borderColor: 'rgba(255,255,255,0.18)',
|
||||
},
|
||||
'& .MuiOutlinedInput-root.Mui-focused .MuiOutlinedInput-notchedOutline': {
|
||||
borderColor: 'rgba(233,64,205,0.55)',
|
||||
boxShadow: '0 0 0 6px rgba(233,64,205,0.12)',
|
||||
},
|
||||
'& input': {
|
||||
color: '#fff',
|
||||
},
|
||||
}));
|
||||
|
||||
export default function TopUpPage() {
|
||||
const [coins, setCoins] = useState<number>(100);
|
||||
const [method, setMethod] = useState<PayMethod>('sbp');
|
||||
const [stage, setStage] = useState<Stage>('form');
|
||||
|
||||
const [stepText, setStepText] = useState<string>('Обработка платежа…');
|
||||
const [progress, setProgress] = useState<number>(0);
|
||||
|
||||
const doneTimerRef = useRef<number | null>(null);
|
||||
const stepIntervalRef = useRef<number | null>(null);
|
||||
const navigate = useNavigate();
|
||||
|
||||
const rubles = useMemo(() => {
|
||||
const safe = Number.isFinite(coins) ? coins : 0;
|
||||
return Math.max(0, Math.floor(safe));
|
||||
}, [coins]);
|
||||
|
||||
const methodLabel = useMemo(() => {
|
||||
switch (method) {
|
||||
case 'sbp':
|
||||
return 'СБП';
|
||||
case 'card':
|
||||
return 'Карта';
|
||||
case 'crypto':
|
||||
return 'Crypto';
|
||||
default:
|
||||
return 'Другое';
|
||||
}
|
||||
}, [method]);
|
||||
|
||||
const clearTimers = () => {
|
||||
if (doneTimerRef.current !== null) {
|
||||
window.clearTimeout(doneTimerRef.current);
|
||||
doneTimerRef.current = null;
|
||||
}
|
||||
if (stepIntervalRef.current !== null) {
|
||||
window.clearInterval(stepIntervalRef.current);
|
||||
stepIntervalRef.current = null;
|
||||
}
|
||||
};
|
||||
|
||||
const startProcessing = () => {
|
||||
clearTimers();
|
||||
setStage('processing');
|
||||
setProgress(0);
|
||||
|
||||
const used = new Set<number>();
|
||||
const pickStep = () => {
|
||||
if (used.size >= STEPS.length) used.clear();
|
||||
let idx = Math.floor(Math.random() * STEPS.length);
|
||||
while (used.has(idx)) idx = Math.floor(Math.random() * STEPS.length);
|
||||
used.add(idx);
|
||||
return STEPS[idx];
|
||||
};
|
||||
|
||||
setStepText(pickStep());
|
||||
|
||||
const totalMs = 1600 + Math.floor(Math.random() * 1600); // 1.6–3.2
|
||||
const stepsCount = 3 + Math.floor(Math.random() * 4); // 3–6
|
||||
|
||||
let ticks = 0;
|
||||
stepIntervalRef.current = window.setInterval(
|
||||
() => {
|
||||
ticks += 1;
|
||||
|
||||
setStepText(pickStep());
|
||||
setProgress((p) => {
|
||||
const bump = 8 + Math.floor(Math.random() * 18); // 8..25
|
||||
return Math.min(95, p + bump);
|
||||
});
|
||||
|
||||
if (ticks >= stepsCount && stepIntervalRef.current !== null) {
|
||||
window.clearInterval(stepIntervalRef.current);
|
||||
stepIntervalRef.current = null;
|
||||
}
|
||||
},
|
||||
400 + Math.floor(Math.random() * 500),
|
||||
); // 400..900
|
||||
|
||||
doneTimerRef.current = window.setTimeout(() => {
|
||||
setProgress(100);
|
||||
setStepText('Готово!');
|
||||
window.setTimeout(() => setStage('done'), 250);
|
||||
doneTimerRef.current = null;
|
||||
}, totalMs);
|
||||
};
|
||||
|
||||
const handlePay = () => {
|
||||
if (rubles <= 0) return;
|
||||
startProcessing();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
return () => clearTimers();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
// ===== Layout wrapper =====
|
||||
const PageCenter = ({ children }: { children: React.ReactNode }) => (
|
||||
<Box
|
||||
sx={{
|
||||
height: 'calc(100vh - 8vh)',
|
||||
pt: '8vh',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
px: 2,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
);
|
||||
|
||||
// ===== DONE =====
|
||||
if (stage === 'done') {
|
||||
return (
|
||||
<PageCenter>
|
||||
<GlassPaper sx={{ width: 'min(680px, 92vw)', p: 3 }}>
|
||||
<Glow />
|
||||
<Stack
|
||||
spacing={2.2}
|
||||
alignItems="center"
|
||||
sx={{ position: 'relative' }}
|
||||
>
|
||||
<Box
|
||||
component="img"
|
||||
src={fakePaymentImg}
|
||||
alt="payment"
|
||||
sx={{
|
||||
width: 'min(440px, 82vw)',
|
||||
height: 'auto',
|
||||
borderRadius: '24px',
|
||||
boxShadow: '0 20px 60px rgba(0,0,0,0.55)',
|
||||
}}
|
||||
/>
|
||||
|
||||
<GradientTitle variant="h5" sx={{ textAlign: 'center' }}>
|
||||
Че реально думал донат добавили?
|
||||
</GradientTitle>
|
||||
|
||||
<Typography sx={{ opacity: 0.8, textAlign: 'center' }}>
|
||||
Хуй тебе а не донат
|
||||
</Typography>
|
||||
|
||||
<Button
|
||||
variant="outlined"
|
||||
onClick={() => {
|
||||
navigate('/');
|
||||
}}
|
||||
sx={{
|
||||
borderRadius: 999,
|
||||
px: 3,
|
||||
borderColor: 'rgba(255,255,255,0.18)',
|
||||
color: 'rgba(255,255,255,0.85)',
|
||||
textTransform: 'none',
|
||||
'&:hover': {
|
||||
borderColor: 'rgba(255,255,255,0.30)',
|
||||
background: 'rgba(255,255,255,0.06)',
|
||||
},
|
||||
}}
|
||||
>
|
||||
Вернуться назад
|
||||
</Button>
|
||||
</Stack>
|
||||
</GlassPaper>
|
||||
</PageCenter>
|
||||
);
|
||||
}
|
||||
|
||||
// ===== PROCESSING =====
|
||||
if (stage === 'processing') {
|
||||
return (
|
||||
<PageCenter>
|
||||
<GlassPaper sx={{ width: 'min(680px, 92vw)', p: 3 }}>
|
||||
<Glow />
|
||||
<Stack
|
||||
spacing={2.2}
|
||||
alignItems="center"
|
||||
sx={{ position: 'relative' }}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
width: 72,
|
||||
height: 72,
|
||||
borderRadius: '50%',
|
||||
display: 'grid',
|
||||
placeItems: 'center',
|
||||
background: 'rgba(255,255,255,0.06)',
|
||||
border: '1px solid rgba(255,255,255,0.10)',
|
||||
}}
|
||||
>
|
||||
<CircularProgress />
|
||||
</Box>
|
||||
|
||||
<GradientTitle variant="h6" sx={{ textAlign: 'center' }}>
|
||||
{stepText}
|
||||
</GradientTitle>
|
||||
|
||||
<Box sx={{ width: '100%' }}>
|
||||
<LinearProgress
|
||||
variant="determinate"
|
||||
value={progress}
|
||||
sx={{
|
||||
height: 10,
|
||||
borderRadius: 999,
|
||||
backgroundColor: 'rgba(255,255,255,0.08)',
|
||||
'& .MuiLinearProgress-bar': {
|
||||
borderRadius: 999,
|
||||
backgroundImage: GRADIENT,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
<Typography sx={{ fontSize: 12, opacity: 0.75, mt: 1 }}>
|
||||
{Math.round(progress)}%
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
gap: 1,
|
||||
flexWrap: 'wrap',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
px: 1.5,
|
||||
py: 0.8,
|
||||
borderRadius: 999,
|
||||
background: 'rgba(255,255,255,0.06)',
|
||||
border: '1px solid rgba(255,255,255,0.10)',
|
||||
}}
|
||||
>
|
||||
<Typography sx={{ opacity: 0.85, fontSize: 13 }}>
|
||||
{rubles.toLocaleString('ru-RU')} ₽
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
px: 1.5,
|
||||
py: 0.8,
|
||||
borderRadius: 999,
|
||||
background: 'rgba(255,255,255,0.06)',
|
||||
border: '1px solid rgba(255,255,255,0.10)',
|
||||
}}
|
||||
>
|
||||
<Typography sx={{ opacity: 0.85, fontSize: 13 }}>
|
||||
{rubles.toLocaleString('ru-RU')} монет
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
px: 1.5,
|
||||
py: 0.8,
|
||||
borderRadius: 999,
|
||||
background: 'rgba(255,255,255,0.06)',
|
||||
border: '1px solid rgba(255,255,255,0.10)',
|
||||
}}
|
||||
>
|
||||
<Typography sx={{ opacity: 0.85, fontSize: 13 }}>
|
||||
{methodLabel}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<Typography
|
||||
sx={{ fontSize: 12, opacity: 0.55, textAlign: 'center' }}
|
||||
>
|
||||
Пожалуйста, не закрывайте окно
|
||||
</Typography>
|
||||
</Stack>
|
||||
</GlassPaper>
|
||||
</PageCenter>
|
||||
);
|
||||
}
|
||||
|
||||
// ===== FORM =====
|
||||
return (
|
||||
<PageCenter>
|
||||
<GlassPaper sx={{ width: 'min(680px, 92vw)', p: 3 }}>
|
||||
<Glow />
|
||||
<Stack spacing={2.2} sx={{ position: 'relative' }}>
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 0.5 }}>
|
||||
<GradientTitle variant="h5">Пополнение баланса</GradientTitle>
|
||||
<Typography sx={{ opacity: 0.75 }}>1 ₽ = 1 монета</Typography>
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
display: 'grid',
|
||||
gridTemplateColumns: { xs: '1fr', md: '1.3fr 1fr' },
|
||||
gap: 2,
|
||||
alignItems: 'start',
|
||||
}}
|
||||
>
|
||||
<StyledTextField
|
||||
label="Сколько монет нужно?"
|
||||
type="number"
|
||||
value={coins}
|
||||
onChange={(e) => setCoins(Number(e.target.value))}
|
||||
inputProps={{ min: 0, step: 1 }}
|
||||
fullWidth
|
||||
/>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
borderRadius: 20,
|
||||
background: 'rgba(255,255,255,0.06)',
|
||||
border: '1px solid rgba(255,255,255,0.10)',
|
||||
p: 2,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<Typography sx={{ opacity: 0.75, fontSize: 12 }}>
|
||||
Итого к оплате
|
||||
</Typography>
|
||||
<Typography
|
||||
sx={{
|
||||
mt: 0.5,
|
||||
fontSize: 26,
|
||||
fontWeight: 900,
|
||||
fontFamily: 'Benzin-Bold, sans-serif',
|
||||
}}
|
||||
>
|
||||
{rubles.toLocaleString('ru-RU')} ₽
|
||||
</Typography>
|
||||
<Typography sx={{ opacity: 0.65, fontSize: 12, mt: 0.5 }}>
|
||||
Начислим: {rubles.toLocaleString('ru-RU')} монет
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
<Typography sx={{ mb: 1, fontWeight: 700, opacity: 0.9 }}>
|
||||
Способ оплаты
|
||||
</Typography>
|
||||
|
||||
<StyledToggleButtonGroup
|
||||
value={method}
|
||||
exclusive
|
||||
onChange={(_, v) => v && setMethod(v)}
|
||||
fullWidth
|
||||
>
|
||||
<ToggleButton value="sbp">СБП</ToggleButton>
|
||||
<ToggleButton value="card">Карта</ToggleButton>
|
||||
<ToggleButton value="crypto">Crypto</ToggleButton>
|
||||
<ToggleButton value="other">Другое</ToggleButton>
|
||||
</StyledToggleButtonGroup>
|
||||
|
||||
<Typography sx={{ mt: 1, fontSize: 12, opacity: 0.55 }}>
|
||||
Выбрано: {methodLabel}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<GradientButton
|
||||
variant="contained"
|
||||
size="large"
|
||||
onClick={handlePay}
|
||||
disabled={rubles <= 0}
|
||||
sx={{
|
||||
height: 52,
|
||||
fontSize: 16,
|
||||
}}
|
||||
>
|
||||
Оплатить
|
||||
</GradientButton>
|
||||
</Stack>
|
||||
</GlassPaper>
|
||||
</PageCenter>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user