diff --git a/src/components/PaymentMethodIcon.tsx b/src/components/PaymentMethodIcon.tsx new file mode 100644 index 0000000..3f4aa1b --- /dev/null +++ b/src/components/PaymentMethodIcon.tsx @@ -0,0 +1,170 @@ +interface PaymentMethodIconProps { + method: string; + className?: string; +} + +export default function PaymentMethodIcon({ + method, + className = 'h-8 w-8', +}: PaymentMethodIconProps) { + switch (method) { + case 'telegram_stars': + return ( + + + + + ); + + case 'cryptobot': + return ( + + + + + ); + + case 'yookassa': + return ( + + + + + + + + ); + + case 'heleket': + return ( + + + + + ); + + case 'mulenpay': + return ( + + + + + ); + + case 'pal24': + return ( + + + + + P24 + + + + ); + + case 'platega': + return ( + + + + + ); + + case 'wata': + return ( + + + + + + ); + + case 'freekassa': + return ( + + + + + FK + + + + ); + + case 'cloudpayments': + return ( + + + + + ); + + case 'tribute': + return ( + + + + + ); + + case 'kassa_ai': + return ( + + + + + + + + + + + AI + + + + ); + + default: + return ( + + + + + ); + } +} diff --git a/src/pages/AdminPaymentMethodEdit.tsx b/src/pages/AdminPaymentMethodEdit.tsx index b1e3622..29a9fdd 100644 --- a/src/pages/AdminPaymentMethodEdit.tsx +++ b/src/pages/AdminPaymentMethodEdit.tsx @@ -6,6 +6,7 @@ import { adminPaymentMethodsApi } from '../api/adminPaymentMethods'; import type { PromoGroupSimple } from '../types'; import { usePlatform } from '../platform/hooks/usePlatform'; import { createNumberInputHandler, toNumber } from '../utils/inputHelpers'; +import PaymentMethodIcon from '@/components/PaymentMethodIcon'; const BackIcon = () => ( ( ); -const METHOD_ICONS: Record = { - telegram_stars: '⭐', - tribute: '🎁', - cryptobot: '🪙', - heleket: '⚡', - yookassa: '🏦', - mulenpay: '💳', - pal24: '💸', - platega: '💰', - wata: '💧', - freekassa: '💵', - cloudpayments: '☁️', - kassa_ai: '🏦', -}; - const METHOD_LABELS: Record = { telegram_stars: 'Telegram Stars', tribute: 'Tribute', @@ -195,7 +181,6 @@ export default function AdminPaymentMethodEdit() { } const displayName = config.display_name || config.default_display_name; - const icon = METHOD_ICONS[config.method_id] || '💳'; return (
@@ -210,8 +195,8 @@ export default function AdminPaymentMethodEdit() { )} -
- {icon} +
+

{displayName}

diff --git a/src/pages/AdminPaymentMethods.tsx b/src/pages/AdminPaymentMethods.tsx index 0994386..1b129fb 100644 --- a/src/pages/AdminPaymentMethods.tsx +++ b/src/pages/AdminPaymentMethods.tsx @@ -23,6 +23,7 @@ import { import { CSS } from '@dnd-kit/utilities'; import { adminPaymentMethodsApi } from '../api/adminPaymentMethods'; import type { PaymentMethodConfig } from '../types'; +import PaymentMethodIcon from '@/components/PaymentMethodIcon'; // ============ Icons ============ @@ -64,23 +65,6 @@ const SaveIcon = () => ( ); -// ============ Method icon by type ============ - -const METHOD_ICONS: Record = { - telegram_stars: '\u2B50', - tribute: '\uD83C\uDF81', - cryptobot: '\uD83E\uDE99', - heleket: '\u26A1', - yookassa: '\uD83C\uDFE6', - mulenpay: '\uD83D\uDCB3', - pal24: '\uD83D\uDCB8', - platega: '\uD83D\uDCB0', - wata: '\uD83D\uDCA7', - freekassa: '\uD83D\uDCB5', - cloudpayments: '\u2601\uFE0F', - kassa_ai: '\uD83C\uDFE6', -}; - // ============ Sortable Card ============ interface SortableCardProps { @@ -102,7 +86,6 @@ function SortablePaymentCard({ config, onClick }: SortableCardProps) { }; const displayName = config.display_name || config.default_display_name; - const icon = METHOD_ICONS[config.method_id] || '\uD83D\uDCB3'; // Build condition summary chips const chips: string[] = []; @@ -153,8 +136,8 @@ function SortablePaymentCard({ config, onClick }: SortableCardProps) { {/* Method icon */} -
- {icon} +
+
{/* Content */} @@ -337,8 +320,8 @@ export default function AdminPaymentMethods() { ) : (
-
- {'\uD83D\uDCB3'} +
+
{t('admin.paymentMethods.noMethods')}
diff --git a/src/pages/TopUpMethodSelect.tsx b/src/pages/TopUpMethodSelect.tsx index 1801e6a..b5fa841 100644 --- a/src/pages/TopUpMethodSelect.tsx +++ b/src/pages/TopUpMethodSelect.tsx @@ -7,6 +7,7 @@ import { balanceApi } from '../api/balance'; import { useCurrency } from '../hooks/useCurrency'; import { Card } from '@/components/data-display/Card'; import { staggerContainer, staggerItem } from '@/components/motion/transitions'; +import PaymentMethodIcon from '@/components/PaymentMethodIcon'; export default function TopUpMethodSelect() { const { t } = useTranslation(); @@ -70,8 +71,11 @@ export default function TopUpMethodSelect() { className={!method.is_available ? 'cursor-not-allowed opacity-50' : ''} onClick={() => method.is_available && handleMethodClick(method.id)} > -
- {translatedName || method.name} +
+ +
+ {translatedName || method.name} +
{(translatedDesc || method.description) && (
diff --git a/src/pages/Wheel.tsx b/src/pages/Wheel.tsx index 6a2cca0..1bb03f1 100644 --- a/src/pages/Wheel.tsx +++ b/src/pages/Wheel.tsx @@ -4,7 +4,6 @@ import { useTranslation } from 'react-i18next'; import { wheelApi, type SpinResult, type SpinHistoryItem } from '../api/wheel'; import FortuneWheel from '../components/wheel/FortuneWheel'; import WheelLegend from '../components/wheel/WheelLegend'; -import InsufficientBalancePrompt from '../components/InsufficientBalancePrompt'; import { usePlatform, useHaptic } from '@/platform'; import { useNotify } from '@/platform/hooks/useNotify'; import { Card } from '@/components/data-display/Card/Card'; @@ -461,11 +460,13 @@ export default function Wheel() { const daysEnabled = config.spin_cost_days_enabled && config.spin_cost_days; const bothMethodsAvailable = !!(starsEnabled && daysEnabled); + // Stars via Telegram invoice don't require ruble balance, so only check daily limit + const dailyLimitReached = config.daily_limit > 0 && config.user_spins_today >= config.daily_limit; const spinDisabled = - !config.can_spin || isSpinning || isPayingStars || - (config.daily_limit > 0 && config.user_spins_today >= config.daily_limit); + dailyLimitReached || + (paymentType === 'telegram_stars' ? !starsEnabled : !config.can_spin); return (
@@ -570,25 +571,21 @@ export default function Wheel() { )} - {/* Cannot spin hint */} - {!config.can_spin && !isSpinning && ( - <> - {config.can_spin_reason === 'daily_limit_reached' ? ( -
-

{t('wheel.errors.dailyLimitReached')}

-
- ) : config.can_spin_reason === 'insufficient_balance' ? ( - - ) : ( -
-

{t('wheel.errors.cannotSpin')}

-
- )} - + {/* Cannot spin hint — only show for days payment (Stars via invoice always works) */} + {!isSpinning && paymentType !== 'telegram_stars' && !config.can_spin && ( +
+

+ {config.can_spin_reason === 'daily_limit_reached' + ? t('wheel.errors.dailyLimitReached') + : t('wheel.errors.cannotSpin')} +

+
+ )} + {/* Daily limit hint for Stars payment (not covered by can_spin check) */} + {!isSpinning && paymentType === 'telegram_stars' && dailyLimitReached && ( +
+

{t('wheel.errors.dailyLimitReached')}

+
)} {/* Inline Result Card */}