add component CoinsDisplay and rework CustomTooltip

This commit is contained in:
2025-12-07 18:35:14 +05:00
parent 52336f8960
commit a456925a08
4 changed files with 402 additions and 171 deletions

View File

@ -0,0 +1,233 @@
// CoinsDisplay.tsx
import { Box, Typography } from '@mui/material';
import CustomTooltip from './CustomTooltip';
import { useEffect, useState } from 'react';
import { fetchCoins } from '../api';
interface CoinsDisplayProps {
// Основные пропсы
value?: number; // Передаем значение напрямую
username?: string; // Или получаем по username из API
// Опции отображения
size?: 'small' | 'medium' | 'large';
showTooltip?: boolean;
tooltipText?: string;
showIcon?: boolean;
iconColor?: string;
// Опции обновления
autoUpdate?: boolean; // Автоматическое обновление из API
updateInterval?: number; // Интервал обновления в миллисекундах
// Стилизация
backgroundColor?: string;
textColor?: string;
}
export default function CoinsDisplay({
// Основные пропсы
value: externalValue,
username,
// Опции отображения
size = 'medium',
showTooltip = true,
tooltipText = 'Попы — внутриигровая валюта, начисляемая за время игры на серверах.',
showIcon = true,
iconColor = '#2bff00ff',
// Опции обновления
autoUpdate = false,
updateInterval = 60000,
// Стилизация
backgroundColor = 'rgba(0, 0, 0, 0.2)',
textColor = 'white',
}: CoinsDisplayProps) {
const [coins, setCoins] = useState<number>(externalValue || 0);
const [isLoading, setIsLoading] = useState<boolean>(false);
// Определяем размеры в зависимости от параметра size
const getSizes = () => {
switch (size) {
case 'small':
return {
containerPadding: '4px 8px',
iconSize: '16px',
fontSize: '12px',
borderRadius: '12px',
gap: '6px',
};
case 'large':
return {
containerPadding: '8px 16px',
iconSize: '28px',
fontSize: '18px',
borderRadius: '20px',
gap: '10px',
};
case 'medium':
default:
return {
containerPadding: '6px 12px',
iconSize: '24px',
fontSize: '16px',
borderRadius: '16px',
gap: '8px',
};
}
};
const sizes = getSizes();
// Функция для получения количества монет из API
const fetchCoinsData = async () => {
if (!username) return;
setIsLoading(true);
try {
const coinsData = await fetchCoins(username);
setCoins(coinsData.coins);
} catch (error) {
console.error('Ошибка при получении количества монет:', error);
} finally {
setIsLoading(false);
}
};
// Эффект для внешнего значения
useEffect(() => {
if (externalValue !== undefined) {
setCoins(externalValue);
}
}, [externalValue]);
// Эффект для API обновлений
useEffect(() => {
if (username && autoUpdate) {
fetchCoinsData();
// Создаем интервалы для периодического обновления данных
const coinsInterval = setInterval(fetchCoinsData, updateInterval);
return () => {
clearInterval(coinsInterval);
};
}
}, [username, autoUpdate, updateInterval]);
// Ручное обновление данных
const handleRefresh = () => {
if (username) {
fetchCoinsData();
}
};
// Форматирование числа с разделителями тысяч
const formatNumber = (num: number): string => {
return num.toLocaleString('ru-RU');
};
const coinsDisplay = (
<Box
sx={{
display: 'flex',
alignItems: 'center',
gap: sizes.gap,
backgroundColor,
borderRadius: sizes.borderRadius,
padding: sizes.containerPadding,
border: '1px solid rgba(255, 255, 255, 0.1)',
cursor: showTooltip ? 'help' : 'default',
opacity: isLoading ? 0.7 : 1,
transition: 'opacity 0.2s ease',
}}
onClick={username ? handleRefresh : undefined}
title={username ? 'Нажмите для обновления' : undefined}
>
{showIcon && (
<Box
sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: sizes.iconSize,
height: sizes.iconSize,
borderRadius: '50%',
backgroundColor: 'rgba(255, 255, 255, 0.1)',
}}
>
<Typography
sx={{
color: iconColor,
fontWeight: 'bold',
fontSize: `calc(${sizes.fontSize} * 0.8)`,
}}
>
P
</Typography>
</Box>
)}
<Typography
variant="body1"
sx={{
color: textColor,
fontWeight: 'bold',
fontSize: sizes.fontSize,
lineHeight: 1,
fontFamily: 'Benzin-Bold, sans-serif',
}}
>
{isLoading ? '...' : formatNumber(coins)}
</Typography>
</Box>
);
if (showTooltip) {
return (
<CustomTooltip
title={tooltipText}
arrow
placement="bottom"
TransitionProps={{ timeout: 300 }}
>
{coinsDisplay}
</CustomTooltip>
);
}
return coinsDisplay;
}
// Примеры использования в комментариях для разработчика:
/*
// Пример 1: Простое отображение числа
<CoinsDisplay value={1500} />
// Пример 2: Получение данных по username с автообновлением
<CoinsDisplay
username="player123"
autoUpdate={true}
updateInterval={30000} // обновлять каждые 30 секунд
/>
// Пример 3: Кастомная стилизация без иконки
<CoinsDisplay
value={9999}
size="small"
showIcon={false}
showTooltip={false}
backgroundColor="rgba(255, 100, 100, 0.2)"
textColor="#ffcc00"
/>
// Пример 4: Большой отображение для профиля
<CoinsDisplay
username="player123"
size="large"
tooltipText="Ваш текущий баланс"
iconColor="#00ffaa"
/>
*/