restyle Shop components

This commit is contained in:
2025-12-07 20:27:56 +05:00
parent 14905fcee7
commit 23308c8598
4 changed files with 263 additions and 309 deletions

View File

@ -1,3 +1,4 @@
// src/renderer/components/BonusShopItem.tsx
import React from 'react';
import {
Card,
@ -80,53 +81,45 @@ export const BonusShopItem: React.FC<BonusShopItemProps> = ({
sx={{
position: 'relative',
width: '100%',
maxWidth: 280,
height: 420,
maxWidth: 300,
height: 440,
display: 'flex',
flexDirection: 'column',
bgcolor: 'rgba(5, 5, 15, 0.96)',
borderRadius: '20px',
border: '1px solid rgba(255, 255, 255, 0.08)',
boxShadow: '0 18px 45px rgba(0, 0, 0, 0.8)',
background: 'rgba(20,20,20,0.9)',
borderRadius: '2.5vw',
border: '1px solid rgba(255,255,255,0.08)',
boxShadow: '0 10px 40px rgba(0,0,0,0.8)',
overflow: 'hidden',
transition:
'transform 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease',
transition: 'transform 0.35s ease, box-shadow 0.35s ease',
'&:hover': {
transform: 'translateY(-6px)',
boxShadow: '0 26px 60px rgba(0, 0, 0, 0.95)',
borderColor: 'rgba(255, 255, 255, 0.18)',
transform: 'scale(1.05)',
boxShadow: '0 20px 60px rgba(242,113,33,0.45)',
},
}}
>
{/* верхний свет */}
{/* Градиентный свет сверху — как в ShopItem */}
<Box
sx={{
position: 'absolute',
inset: 0,
pointerEvents: 'none',
background:
'radial-gradient(circle at top, rgba(255,255,255,0.13), transparent 55%)',
'radial-gradient(circle at top, rgba(242,113,33,0.25), transparent 60%)',
}}
/>
{imageUrl && (
<Box
sx={{
position: 'relative',
p: '0.9vw',
pb: 0,
overflow: 'hidden',
}}
>
<Box sx={{ position: 'relative', p: 1.5, pb: 0 }}>
<Box
sx={{
borderRadius: '16px',
borderRadius: '1.8vw',
overflow: 'hidden',
border: '1px solid rgba(255, 255, 255, 0.12)',
border: '1px solid rgba(255,255,255,0.12)',
background:
'linear-gradient(135deg, rgba(40,40,80,0.9), rgba(15,15,35,0.9))',
'linear-gradient(135deg, rgba(40,40,40,0.9), rgba(15,15,15,0.9))',
}}
>
<CardMedia
@ -135,10 +128,8 @@ export const BonusShopItem: React.FC<BonusShopItemProps> = ({
alt={name}
sx={{
width: '100%',
height: '11vw',
minHeight: '140px',
height: 160,
objectFit: 'cover',
filter: 'saturate(1.1)',
}}
/>
</Box>
@ -147,91 +138,95 @@ export const BonusShopItem: React.FC<BonusShopItemProps> = ({
<CardContent
sx={{
position: 'relative',
zIndex: 1,
pt: imageUrl ? '0.9vw' : '1.4vw',
pb: '1.3vw',
flexGrow: 1,
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-between',
pt: 2,
pb: 2,
}}
>
<Box>
{/* Имя бонуса — градиентом как у ShopItem */}
<Typography
variant="h6"
color="white"
sx={{
fontFamily: 'Benzin-Bold',
fontSize: '1.05rem',
mb: 0.5,
backgroundImage:
'linear-gradient(136deg, rgb(242,113,33), rgb(233,64,87), rgb(138,35,135))',
WebkitBackgroundClip: 'text',
WebkitTextFillColor: 'transparent',
}}
>
{name}
</Typography>
<Typography
variant="body2"
color="white"
sx={{
opacity: 0.7,
color: 'rgba(255,255,255,0.7)',
fontSize: '0.8rem',
mb: 1,
mb: 0.8,
}}
>
Уровень: {level}
{isPermanent && ' • Постоянный'}
</Typography>
{description && (
<Typography
variant="body2"
color="white"
sx={{
opacity: 0.75,
color: 'rgba(255,255,255,0.75)',
fontSize: '0.85rem',
mb: 1.4,
mb: 1.2,
minHeight: 40,
maxHeight: 40,
overflow: 'hidden',
textOverflow: 'ellipsis',
}}
>
{description}
</Typography>
)}
<Box sx={{ mb: 1.2 }}>
<Box sx={{ mb: 1 }}>
<Typography
variant="body2"
color="white"
sx={{ opacity: 0.8, fontSize: '0.8rem' }}
sx={{ color: 'rgba(255,255,255,0.8)', fontSize: '0.8rem' }}
>
Текущий эффект: <b>{effectValue.toLocaleString('ru-RU')}</b>
Текущий эффект:{' '}
<Box component="b" sx={{ fontWeight: 600 }}>
{effectValue.toLocaleString('ru-RU')}
</Box>
</Typography>
{typeof nextEffectValue === 'number' &&
!isBuyMode &&
canUpgrade && (
<Typography
variant="body2"
color="white"
sx={{ opacity: 0.8, fontSize: '0.8rem', mt: 0.4 }}
sx={{
color: 'rgba(255,255,255,0.8)',
fontSize: '0.8rem',
mt: 0.4,
}}
>
Следующий уровень:{' '}
<b>{nextEffectValue.toLocaleString('ru-RU')}</b>
<Box component="b" sx={{ fontWeight: 600 }}>
{nextEffectValue.toLocaleString('ru-RU')}
</Box>
</Typography>
)}
</Box>
<Box sx={{ mb: 1 }}>
<Typography
variant="body2"
color={isActive ? 'success.main' : 'warning.main'}
sx={{ fontSize: '0.78rem' }}
>
{isActive ? 'Бонус активен' : 'Бонус не активен'}
</Typography>
</Box>
<Typography
sx={{
fontSize: '0.78rem',
mb: 1,
color: isActive
? 'rgba(0, 200, 140, 0.9)'
: 'rgba(255, 180, 80, 0.9)',
}}
>
{isActive ? 'Бонус активен' : 'Бонус не активен'}
</Typography>
<Box
sx={{
@ -242,9 +237,7 @@ export const BonusShopItem: React.FC<BonusShopItemProps> = ({
}}
>
<Typography
variant="body2"
color="white"
sx={{ opacity: 0.8, fontSize: '0.85rem' }}
sx={{ color: 'rgba(255,255,255,0.8)', fontSize: '0.85rem' }}
>
{isBuyMode ? 'Цена покупки' : 'Цена улучшения'}
</Typography>
@ -262,43 +255,48 @@ export const BonusShopItem: React.FC<BonusShopItemProps> = ({
<Button
variant="outlined"
size="small"
sx={{
mb: 1,
borderRadius: '999px',
textTransform: 'none',
fontSize: '0.75rem',
}}
onClick={onToggleActive}
disabled={disabled}
sx={{
mt: 0.5,
borderRadius: '2.5vw',
textTransform: 'none',
fontSize: '0.75rem',
px: 2,
borderColor: 'rgba(255,255,255,0.4)',
color: 'rgba(255,255,255,0.9)',
'&:hover': {
borderColor: 'rgba(255,255,255,0.8)',
background: 'rgba(255,255,255,0.05)',
},
}}
>
{isActive ? 'Выключить' : 'Включить'}
</Button>
)}
</Box>
{/* Кнопка в стиле Registration / ShopItem */}
<Button
variant="contained"
fullWidth
sx={{
mt: 0.5,
borderRadius: '999px',
py: '0.45vw',
color: 'white',
background: !buttonDisabled
? 'linear-gradient(135deg, rgb(0, 160, 90), rgb(0, 200, 140))'
: 'linear-gradient(135deg, rgba(120,120,120,0.9), rgba(80,80,80,0.9))',
'&:hover': {
background: !buttonDisabled
? 'linear-gradient(135deg, rgba(0, 160, 90, 0.85), rgba(0, 200, 140, 0.9))'
: 'linear-gradient(135deg, rgba(120,120,120,0.9), rgba(80,80,80,0.9))',
},
fontFamily: 'Benzin-Bold',
fontSize: '0.9rem',
textTransform: 'uppercase',
letterSpacing: 0.8,
}}
disabled={buttonDisabled}
onClick={handlePrimaryClick}
sx={{
mt: 2,
transition: 'transform 0.3s ease, opacity 0.2s ease',
background: buttonDisabled
? 'linear-gradient(71deg, #555 0%, #666 70%, #444 100%)'
: 'linear-gradient(71deg, #F27121 0%, #E940CD 70%, #8A2387 100%)',
fontFamily: 'Benzin-Bold',
borderRadius: '2.5vw',
fontSize: '0.85rem',
color: '#fff',
opacity: buttonDisabled ? 0.6 : 1,
'&:hover': {
transform: buttonDisabled ? 'none' : 'scale(1.1)',
},
}}
>
{buttonText}
</Button>

View File

@ -81,17 +81,14 @@ export default function CaseRoulette({
useEffect(() => {
if (!open || !reward || !items || items.length === 0) return;
// Очистка предыдущих таймеров
if (animationTimeoutRef.current) clearTimeout(animationTimeoutRef.current);
if (finishTimeoutRef.current) clearTimeout(finishTimeoutRef.current);
// Сброс состояний
setAnimating(false);
setAnimationFinished(false);
setOffset(0);
itemRefs.current = [];
// 1. Генерируем последовательность
const totalItems = VISIBLE_ITEMS * 3;
const seq: CaseItem[] = [];
@ -108,7 +105,7 @@ export default function CaseRoulette({
setSequence(seq);
}, [open, reward, items]);
// Эффект для запуска анимации после рендера элементов
// Эффект запуска анимации
useEffect(() => {
if (sequence.length === 0 || !open) return;
@ -116,12 +113,10 @@ export default function CaseRoulette({
const widths = measureItemWidths();
const winPosition = Math.floor(sequence.length / 2);
// Сколько "оборотов" хотим сделать до остановки
const EXTRA_SPINS = 3;
const averageItemWidth = ITEM_WIDTH + ITEM_GAP;
const extraDistance = EXTRA_SPINS * VISIBLE_ITEMS * averageItemWidth;
// fallback, если не смогли корректно измерить ширины
if (widths.length === 0 || widths.length !== sequence.length) {
const centerItemCenter =
winPosition * (ITEM_WIDTH + ITEM_GAP) + ITEM_WIDTH / 2;
@ -143,7 +138,6 @@ export default function CaseRoulette({
return;
}
// вариант с реальными ширинами
let cumulativeOffset = 0;
for (let i = 0; i < winPosition; i++) {
cumulativeOffset += widths[i] + ITEM_GAP;
@ -196,51 +190,64 @@ export default function CaseRoulette({
fullWidth
PaperProps={{
sx: {
bgcolor: 'rgba(5, 5, 10, 0.96)',
borderRadius: '24px',
border: '1px solid rgba(255,255,255,0.12)',
boxShadow: '0 25px 80px rgba(0,0,0,0.8)',
bgcolor: 'transparent',
borderRadius: '2.5vw',
overflow: 'hidden',
boxShadow: '0 30px 80px rgba(0,0,0,0.9)',
},
}}
>
<DialogContent
sx={{
position: 'relative',
px: 3,
py: 3.5,
background:
'radial-gradient(circle at top, rgba(255,255,255,0.06), transparent 60%)',
overflow: 'clip',
'radial-gradient(circle at top, #101018 0%, #050509 40%, #000 100%)',
}}
>
{/* лёгкий "бордер" по контуру */}
<Box
sx={{
position: 'absolute',
inset: 0,
pointerEvents: 'none',
borderRadius: '2.5vw',
border: '1px solid rgba(255,255,255,0.08)',
}}
/>
{/* заголовок с градиентом как в Registration */}
<Typography
variant="h6"
color="white"
sx={{
textAlign: 'center',
mb: 2.5,
fontFamily: 'Benzin-Bold',
letterSpacing: 0.5,
letterSpacing: 0.6,
backgroundImage:
'linear-gradient(136deg, rgb(242,113,33) 0%, rgb(233,64,87) 50%, rgb(138,35,135) 100%)',
WebkitBackgroundClip: 'text',
WebkitTextFillColor: 'transparent',
}}
>
Открытие кейса {caseName}
</Typography>
{/* контейнер рулетки */}
<Box
sx={{
position: 'relative',
overflow: 'hidden',
borderRadius: '18px',
border: '1px solid rgba(255, 255, 255, 0.15)',
borderRadius: '2vw',
px: 2,
py: 3,
width: `${CONTAINER_WIDTH}px`,
maxWidth: '100%',
mx: 'auto',
background:
'linear-gradient(135deg, rgba(10,10,20,0.9), rgba(25,25,45,0.9))',
backdropFilter: 'blur(18px)',
boxShadow: '0 0 40px rgba(0,0,0,0.7)',
'linear-gradient(135deg, rgba(15,15,20,0.96), rgba(30,20,35,0.96))',
boxShadow: '0 0 40px rgba(0,0,0,0.8)',
}}
>
{/* затемнённые края */}
@ -250,12 +257,12 @@ export default function CaseRoulette({
inset: 0,
pointerEvents: 'none',
background:
'linear-gradient(90deg, rgba(0,0,0,0.7) 0%, transparent 20%, transparent 80%, rgba(0,0,0,0.7) 100%)',
'linear-gradient(90deg, rgba(0,0,0,0.85) 0%, transparent 20%, transparent 80%, rgba(0,0,0,0.85) 100%)',
zIndex: 1,
}}
/>
{/* Линия центра */}
{/* центральная линия (прицел) */}
<Box
sx={{
position: 'absolute',
@ -264,13 +271,14 @@ export default function CaseRoulette({
left: `${LINE_X}px`,
transform: 'translateX(-1px)',
width: '2px',
bgcolor: 'rgba(255, 77, 77, 0.9)',
boxShadow: '0 0 18px rgba(255,77,77,0.9)',
background:
'linear-gradient(180deg, rgb(242,113,33), rgb(233,64,87))',
boxShadow: '0 0 16px rgba(233,64,87,0.9)',
zIndex: 2,
}}
/>
{/* Лента с предметами */}
{/* Лента предметов */}
<Box
sx={{
display: 'flex',
@ -305,10 +313,9 @@ export default function CaseRoulette({
ref={(el) => (itemRefs.current[index] = el)}
sx={{
minWidth: `${ITEM_WIDTH}px`,
width: 'auto',
height: '130px',
borderRadius: '14px',
bgcolor: 'rgba(255, 255, 255, 0.03)',
height: 130,
borderRadius: '1.4vw',
background: 'rgba(255,255,255,0.03)',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
@ -317,10 +324,10 @@ export default function CaseRoulette({
? `2px solid ${color}`
: `1px solid ${color}`,
boxShadow: isWinningItem
? `0 0 22px ${color}`
: '0 0 8px rgba(0,0,0,0.6)',
? `0 0 24px ${color}`
: '0 0 10px rgba(0,0,0,0.6)',
transition: 'all 0.3s ease',
padding: '0 10px',
px: 1,
transform: isWinningItem ? 'scale(1.08)' : 'scale(1)',
}}
>
@ -329,8 +336,8 @@ export default function CaseRoulette({
src={`https://cdn.minecraft.popa-popa.ru/textures/${item.material.toLowerCase()}.png`}
alt={item.material}
sx={{
width: '52px',
height: '52px',
width: 52,
height: 52,
objectFit: 'contain',
imageRendering: 'pixelated',
mb: 1,
@ -342,7 +349,7 @@ export default function CaseRoulette({
color: 'white',
textAlign: 'center',
fontSize: '0.72rem',
maxWidth: '100px',
maxWidth: 100,
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
@ -359,46 +366,50 @@ export default function CaseRoulette({
{animationFinished && winningName && (
<Typography
variant="body1"
color="white"
sx={{
textAlign: 'center',
mt: 2.5,
animation: 'fadeIn 0.5s ease',
color: 'rgba(255,255,255,0.9)',
}}
>
Вам выпало:{' '}
<b style={{ color: getRarityColor(reward?.weight) }}>
<Box
component="span"
sx={{
fontFamily: 'Benzin-Bold',
backgroundImage:
'linear-gradient(136deg, rgb(242,113,33) 0%, rgb(233,64,87) 50%, rgb(138,35,135) 100%)',
WebkitBackgroundClip: 'text',
WebkitTextFillColor: 'transparent',
}}
>
{winningName}
</b>
</Box>
</Typography>
)}
<Box
sx={{
display: 'flex',
justifyContent: 'center',
mt: 3,
}}
>
{/* кнопка как в Registration */}
<Box sx={{ display: 'flex', justifyContent: 'center', mt: 3 }}>
<Button
variant="contained"
onClick={onClose}
sx={{
borderRadius: '999px',
px: '2.8vw',
py: '0.6vw',
color: 'white',
transition: 'transform 0.3s ease',
borderRadius: '2.5vw',
px: '3vw',
py: '0.7vw',
background:
'linear-gradient(135deg, rgb(255, 77, 77), rgb(255, 120, 100))',
'&:hover': {
background:
'linear-gradient(135deg, rgba(255, 77, 77, 0.8), rgba(255, 120, 100, 0.8))',
},
'linear-gradient(71deg, #F27121 0%, #E940CD 70%, #8A2387 100%)',
fontFamily: 'Benzin-Bold',
opacity: animationFinished ? 1 : 0.5,
pointerEvents: animationFinished ? 'auto' : 'none',
fontSize: '0.9rem',
textTransform: 'uppercase',
letterSpacing: 1,
color: '#fff',
opacity: animationFinished ? 1 : 0.4,
pointerEvents: animationFinished ? 'auto' : 'none',
'&:hover': {
transform: 'scale(1.1)',
},
}}
>
Закрыть

View File

@ -18,21 +18,14 @@ export type ShopItemType = 'case' | 'cape';
export interface ShopItemProps {
type: ShopItemType;
id: string;
name: string;
description?: string;
imageUrl?: string;
price?: number;
// только для кейсов
itemsCount?: number;
isOpening?: boolean;
// для препросмотра плаща
playerSkinUrl?: string;
// для обоих
disabled?: boolean;
onClick: () => void;
}
@ -49,8 +42,6 @@ export default function ShopItem({
playerSkinUrl,
onClick,
}: ShopItemProps) {
const badgeLabel = type === 'case' ? 'Кейс' : 'Плащ';
const buttonText =
type === 'case' ? (isOpening ? 'Открываем...' : 'Открыть кейс') : 'Купить';
@ -61,55 +52,46 @@ export default function ShopItem({
sx={{
position: 'relative',
width: '100%',
maxWidth: 280,
height: 420, // ✅ ФИКСИРОВАННАЯ ВЫСОТА
maxWidth: 300,
height: 440,
display: 'flex',
flexDirection: 'column',
bgcolor: 'rgba(5, 5, 15, 0.96)',
borderRadius: '20px',
border: '1px solid rgba(255, 255, 255, 0.08)',
boxShadow: '0 18px 45px rgba(0, 0, 0, 0.8)',
background: 'rgba(20,20,20,0.9)',
borderRadius: '2.5vw',
border: '1px solid rgba(255,255,255,0.08)',
boxShadow: '0 10px 40px rgba(0,0,0,0.8)',
overflow: 'hidden',
transition:
'transform 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease',
transition: 'transform 0.35s ease, box-shadow 0.35s ease',
'&:hover': {
transform: 'translateY(-6px)',
boxShadow: '0 26px 60px rgba(0, 0, 0, 0.95)',
borderColor: 'rgba(255, 255, 255, 0.18)',
transform: 'scale(1.05)',
boxShadow: '0 20px 60px rgba(242,113,33,0.45)',
},
}}
>
{/* верхний свет */}
{/* Градиентный свет сверху */}
<Box
sx={{
position: 'absolute',
inset: 0,
pointerEvents: 'none',
background:
'radial-gradient(circle at top, rgba(255,255,255,0.13), transparent 55%)',
'radial-gradient(circle at top, rgba(242,113,33,0.25), transparent 60%)',
}}
/>
{imageUrl && (
<Box
sx={{
position: 'relative',
p: type === 'case' ? '0.9vw' : 0,
pb: 0,
overflow: 'hidden',
}}
>
<Box sx={{ position: 'relative', p: 1.5, pb: 0 }}>
{type === 'case' ? (
/* как было для кейсов */
<Box
sx={{
borderRadius: '16px',
borderRadius: '1.8vw',
overflow: 'hidden',
border: '1px solid rgba(255, 255, 255, 0.12)',
border: '1px solid rgba(255,255,255,0.12)',
background:
'linear-gradient(135deg, rgba(40,40,80,0.9), rgba(15,15,35,0.9))',
'linear-gradient(135deg, rgba(40,40,40,0.9), rgba(15,15,15,0.9))',
}}
>
<CardMedia
@ -118,166 +100,128 @@ export default function ShopItem({
alt={name}
sx={{
width: '100%',
height: '11vw',
minHeight: '140px',
height: 160,
objectFit: 'cover',
filter: 'saturate(1.1)',
}}
/>
</Box>
) : (
// ✅ здесь используем CapePreview
<CapePreview imageUrl={imageUrl} alt={name} />
)}
{/* кнопка предпросмотра плаща */}
{/* Кнопка предпросмотра плаща */}
{type === 'cape' && (
<Box
<IconButton
onClick={(e) => {
e.stopPropagation();
setPreviewOpen(true);
}}
sx={{
position: 'absolute',
top: type === 'case' ? '1.2vw' : 8,
right: type === 'case' ? '1.6vw' : 8,
px: 1.2,
py: 0.4,
borderRadius: '999px',
fontSize: '0.7rem',
textTransform: 'uppercase',
letterSpacing: 0.6,
bgcolor: 'rgba(0, 0, 0, 0.6)',
border: '1px solid rgba(255, 255, 255, 0.4)',
top: 10,
right: 10,
color: 'white',
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
gap: 1,
background:
'linear-gradient(71deg, #F27121 0%, #E940CD 70%, #8A2387 100%)',
'&:hover': {
transform: 'scale(1.1)',
},
}}
>
<IconButton
size="small"
onClick={(e) => {
e.stopPropagation();
setPreviewOpen(true);
}}
sx={{
p: 0.3,
color: 'white',
bgcolor: 'rgba(0,0,0,0.4)',
'&:hover': {
bgcolor: 'rgba(0,0,0,0.7)',
},
}}
>
<VisibilityIcon fontSize="small" />
</IconButton>
</Box>
<VisibilityIcon fontSize="small" />
</IconButton>
)}
</Box>
)}
<CardContent
sx={{
position: 'relative',
zIndex: 1,
pt: imageUrl ? '0.9vw' : '1.4vw',
pb: '1.3vw',
flexGrow: 1, // ✅ растягивает середину
flexGrow: 1,
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-between', // ✅ кнопка уезжает вниз
justifyContent: 'space-between',
pt: 2,
pb: 2,
}}
>
<Typography
variant="h6"
color="white"
sx={{
fontFamily: 'Benzin-Bold',
fontSize: '1.05rem',
mb: 0.8,
}}
>
{name}
</Typography>
{description && (
<Box>
<Typography
variant="body2"
color="white"
sx={{
opacity: 0.75,
fontSize: '0.85rem',
mb: 1.5,
minHeight: 40,
maxHeight: 40, // ✅ фикс высоты
overflow: 'hidden',
textOverflow: 'ellipsis',
}}
>
{description}
</Typography>
)}
{typeof price === 'number' && (
<Box
sx={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
fontFamily: 'Benzin-Bold',
fontSize: '1.05rem',
mb: 1,
backgroundImage:
'linear-gradient(136deg, rgb(242,113,33), rgb(233,64,87), rgb(138,35,135))',
WebkitBackgroundClip: 'text',
WebkitTextFillColor: 'transparent',
}}
>
<Typography
variant="body2"
color="white"
sx={{ opacity: 0.8, fontSize: '0.85rem' }}
>
Цена
</Typography>
<CoinsDisplay
value={price}
size="small"
autoUpdate={false}
showTooltip={true}
/>
</Box>
)}
{type === 'case' && typeof itemsCount === 'number' && (
<Typography
variant="body2"
color="white"
sx={{ opacity: 0.6, fontSize: '0.8rem', mb: 1.4 }}
>
Предметов в кейсе: {itemsCount}
{name}
</Typography>
)}
{description && (
<Typography
sx={{
color: 'rgba(255,255,255,0.75)',
fontSize: '0.85rem',
minHeight: 42,
maxHeight: 42,
overflow: 'hidden',
}}
>
{description}
</Typography>
)}
{typeof price === 'number' && (
<Box
sx={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
mt: 1.2,
}}
>
<Typography
sx={{ color: 'rgba(255,255,255,0.7)', fontSize: '0.8rem' }}
>
Цена
</Typography>
<CoinsDisplay value={price} size="small" />
</Box>
)}
{type === 'case' && typeof itemsCount === 'number' && (
<Typography
sx={{
color: 'rgba(255,255,255,0.6)',
fontSize: '0.75rem',
mt: 1,
}}
>
Предметов в кейсе: {itemsCount}
</Typography>
)}
</Box>
{/* Кнопка как в Registration */}
<Button
variant="contained"
fullWidth
sx={{
mt: 0.5,
borderRadius: '999px',
py: '0.45vw',
color: 'white',
background:
type === 'case'
? 'linear-gradient(135deg, rgb(255, 77, 77), rgb(255, 120, 100))'
: 'linear-gradient(135deg, rgb(0, 160, 90), rgb(0, 200, 140))',
'&:hover': {
background:
type === 'case'
? 'linear-gradient(135deg, rgba(255, 77, 77, 0.85), rgba(255, 120, 100, 0.9))'
: 'linear-gradient(135deg, rgba(0, 160, 90, 0.85), rgba(0, 200, 140, 0.9))',
},
fontFamily: 'Benzin-Bold',
fontSize: '0.9rem',
textTransform: 'uppercase',
letterSpacing: 0.8,
}}
disabled={disabled}
onClick={onClick}
sx={{
mt: 2,
transition: 'transform 0.3s ease',
background:
'linear-gradient(71deg, #F27121 0%, #E940CD 70%, #8A2387 100%)',
fontFamily: 'Benzin-Bold',
borderRadius: '2.5vw',
fontSize: '0.85rem',
'&:hover': {
transform: 'scale(1.1)',
},
}}
>
{buttonText}
</Button>

View File

@ -422,7 +422,7 @@ export default function Shop() {
height: '80%',
gap: '2vw',
overflow: 'auto',
paddingBottom: '7vh',
paddingBottom: '10vh',
paddingLeft: '5vw',
paddingRight: '5vw',
}}
@ -560,6 +560,10 @@ export default function Shop() {
transform: 'scale(1.1)',
},
}}
onClick={() => {
checkPlayerStatus(); // обновляем онлайн-статус
loadCases(); // обновляем ТОЛЬКО кейсы
}}
>
Обновить
</Button>
@ -658,12 +662,9 @@ export default function Shop() {
onClose={handleCloseNotification}
>
<Alert
sx={{
background:
'linear-gradient(71deg, #F27121 0%, #E940CD 70%, #8A2387 100%)',
color: 'white',
fontFamily: 'Benzin-Bold',
}}
onClose={handleCloseNotification}
severity={notification.type}
sx={{ width: '100%' }}
>
{notification.message}
</Alert>