import { useState } from 'react'; import { useNavigate } from 'react-router'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import i18n from '../i18n'; import { promocodesApi, PromoCode, PromoCodeType } from '../api/promocodes'; import { usePlatform } from '../platform/hooks/usePlatform'; import { copyToClipboard } from '../utils/clipboard'; import { BackIcon, PlusIcon, EditIcon, TrashIcon, CheckIcon, CopyIcon, ChartIcon, ChartBarIcon, CheckCircleIcon, TagIcon, TicketIcon, } from '@/components/icons'; import { StatCard } from '../components/stats'; // Helper functions const getTypeLabel = (type: PromoCodeType): string => { const labels: Record = { balance: i18n.t('admin.promocodes.type.balance'), subscription_days: i18n.t('admin.promocodes.type.subscriptionDays'), trial_subscription: i18n.t('admin.promocodes.type.trialSubscription'), promo_group: i18n.t('admin.promocodes.type.promoGroup'), discount: i18n.t('admin.promocodes.type.discount'), }; return labels[type] || type; }; const getTypeColor = (type: PromoCodeType): string => { const colors: Record = { balance: 'bg-success-500/20 text-success-400', subscription_days: 'bg-accent-500/20 text-accent-400', trial_subscription: 'bg-accent-500/20 text-accent-400', promo_group: 'bg-warning-500/20 text-warning-400', discount: 'bg-pink-500/20 text-pink-400', }; return colors[type] || 'bg-dark-600 text-dark-300'; }; const formatDate = (date: string | null): string => { if (!date) return '-'; const localeMap: Record = { ru: 'ru-RU', en: 'en-US', zh: 'zh-CN', fa: 'fa-IR' }; const locale = localeMap[i18n.language] || 'ru-RU'; return new Date(date).toLocaleDateString(locale, { day: '2-digit', month: '2-digit', year: 'numeric', }); }; export default function AdminPromocodes() { const { t } = useTranslation(); const navigate = useNavigate(); const queryClient = useQueryClient(); const { capabilities } = usePlatform(); const [deleteConfirm, setDeleteConfirm] = useState(null); const [copiedCode, setCopiedCode] = useState(null); // Query const { data: promocodesData, isLoading } = useQuery({ queryKey: ['admin-promocodes'], queryFn: () => promocodesApi.getPromocodes({ limit: 100 }), }); // Delete mutation const deleteMutation = useMutation({ mutationFn: promocodesApi.deletePromocode, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['admin-promocodes'] }); setDeleteConfirm(null); }, }); const handleCopyCode = (code: string) => { void copyToClipboard(code); setCopiedCode(code); setTimeout(() => setCopiedCode(null), 2000); }; const promocodes = promocodesData?.items || []; return (
{/* Header */}
{/* Show back button only on web, not in Telegram Mini App */} {!capabilities.hasBackButton && ( )}

{t('admin.promocodes.title')}

{t('admin.promocodes.subtitle')}

{/* Stats Overview */} {promocodes.length > 0 && (
} tone="neutral" /> p.is_active && p.is_valid).length} icon={} tone="success" /> sum + p.current_uses, 0)} icon={} tone="accent" /> p.uses_left === 0 && p.max_uses > 0).length} icon={} tone="warning" />
)} {/* Promocodes List */} {isLoading ? (
) : promocodes.length === 0 ? (

{t('admin.promocodes.noPromocodes')}

) : (
{promocodes.map((promo: PromoCode) => (
{/* Mobile: stacked layout, Desktop: row layout */}
{/* Code with copy button */}
{/* Badges - wrap on mobile */}
{getTypeLabel(promo.type)} {!promo.is_active && ( {t('admin.promocodes.stats.inactive')} )} {promo.first_purchase_only && ( {t('admin.promocodes.firstPurchase')} )}
{/* Info line */}
{promo.type === 'balance' && ( +{promo.balance_bonus_rubles} {t('admin.promocodes.form.rub')} )} {(promo.type === 'subscription_days' || promo.type === 'trial_subscription') && ( +{promo.subscription_days} {t('admin.promocodes.form.days')} )} {promo.type === 'discount' && ( {t('admin.promocodes.discountForHours', { percent: promo.balance_bonus_kopeks, hours: promo.subscription_days, })} )} {t('admin.promocodes.used')}: {promo.current_uses}/ {promo.max_uses === 0 ? '∞' : promo.max_uses} {promo.valid_until && ( {t('admin.promocodes.until')}: {formatDate(promo.valid_until)} )}
{/* Action buttons - full width on mobile */}
))}
)} {/* Delete Confirmation */} {deleteConfirm && (

{t('admin.promocodes.confirm.deletePromocode')}

{t('admin.promocodes.confirm.deletePromocodeText')}

)}
); }