add component CoinsDisplay and rework CustomTooltip
This commit is contained in:
233
src/renderer/components/CoinsDisplay.tsx
Normal file
233
src/renderer/components/CoinsDisplay.tsx
Normal 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"
|
||||
/>
|
||||
*/
|
||||
Reference in New Issue
Block a user