import { useState } from 'react'; import { useNavigate, useParams } from 'react-router'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import i18n from '../i18n'; import { couponsApi } from '../api/coupons'; import { usePlatform } from '../platform/hooks/usePlatform'; import { copyToClipboard } from '../utils/clipboard'; import { formatPrice, formatShortDate } from '../utils/format'; import { getApiErrorMessage } from '../utils/api-error'; import { useToast } from '../components/Toast'; import { PermissionGate } from '../components/auth/PermissionGate'; import { BackIcon, CheckIcon, CheckCircleIcon, ChartBarIcon, CopyIcon, DownloadIcon, TicketIcon, } from '@/components/icons'; import { StatCard } from '../components/stats'; export default function AdminCouponDetail() { const { t } = useTranslation(); const navigate = useNavigate(); const { id } = useParams<{ id: string }>(); const queryClient = useQueryClient(); const { capabilities } = usePlatform(); const { showToast } = useToast(); const batchId = Number(id); const [revokeConfirm, setRevokeConfirm] = useState(false); const [copied, setCopied] = useState(false); const { data: batch, isLoading } = useQuery({ queryKey: ['admin-coupon-batch', batchId], queryFn: () => couponsApi.getBatch(batchId), enabled: Number.isFinite(batchId), }); const hasActive = (batch?.active_count ?? 0) > 0; const { data: links } = useQuery({ queryKey: ['admin-coupon-batch-links', batchId], queryFn: () => couponsApi.getBatchLinks(batchId), enabled: Number.isFinite(batchId) && hasActive, }); const revokeMutation = useMutation({ mutationFn: () => couponsApi.revokeBatch(batchId), onSuccess: (result) => { queryClient.invalidateQueries({ queryKey: ['admin-coupon-batch', batchId] }); queryClient.invalidateQueries({ queryKey: ['admin-coupon-batch-links', batchId] }); queryClient.invalidateQueries({ queryKey: ['admin-coupon-batches'] }); setRevokeConfirm(false); showToast({ type: 'success', title: t('admin.coupons.revoke.success', { count: result.revoked_count }), message: result.batch.name, }); }, onError: (err) => { setRevokeConfirm(false); showToast({ type: 'error', title: t('admin.coupons.errors.revokeFailed'), message: getApiErrorMessage(err, ''), }); }, }); const handleCopyAll = () => { if (!links) return; void copyToClipboard(links.links.join('\n')); setCopied(true); setTimeout(() => setCopied(false), 2000); }; const handleDownload = () => { if (!links) return; const blob = new Blob([links.links.join('\n') + '\n'], { type: 'text/plain;charset=utf-8' }); const url = URL.createObjectURL(blob); const anchor = document.createElement('a'); anchor.href = url; anchor.download = `coupons_batch_${batchId}.txt`; anchor.click(); URL.revokeObjectURL(url); }; if (isLoading) { return (
{t('admin.coupons.errors.loadFailed')}
{batch.tariff_name || '—'} · {batch.period_days} {t('admin.coupons.days')} {batch.is_revoked && ( {t('admin.coupons.list.revoked')} )}
{t('admin.coupons.revoke.confirmText', { count: batch.active_count })}