import { useParams, useNavigate } from 'react-router'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import { adminBroadcastsApi, type BroadcastChannel } from '../api/adminBroadcasts'; import { AdminBackButton } from '../components/admin'; import { StatCard } from '@/components/stats'; import { BanIcon, DocumentIcon, EmailIcon, PhotoIcon, RefreshIcon, SendIcon, StopIcon, TelegramIcon, UsersIcon, VideoIcon, XCircleIcon, } from '@/components/icons'; // Channel badge component function ChannelBadge({ channel }: { channel?: BroadcastChannel }) { if (!channel || channel === 'telegram') { return ( Telegram ); } if (channel === 'email') { return ( Email ); } return ( + ); } // Status badge component const statusConfig: Record = { queued: { bg: 'bg-warning-500/20', text: 'text-warning-400', labelKey: 'admin.broadcasts.status.queued', }, in_progress: { bg: 'bg-accent-500/20', text: 'text-accent-400', labelKey: 'admin.broadcasts.status.inProgress', }, completed: { bg: 'bg-success-500/20', text: 'text-success-400', labelKey: 'admin.broadcasts.status.completed', }, partial: { bg: 'bg-warning-500/20', text: 'text-warning-400', labelKey: 'admin.broadcasts.status.partial', }, failed: { bg: 'bg-error-500/20', text: 'text-error-400', labelKey: 'admin.broadcasts.status.failed', }, cancelled: { bg: 'bg-dark-500/20', text: 'text-dark-400', labelKey: 'admin.broadcasts.status.cancelled', }, cancelling: { bg: 'bg-warning-500/20', text: 'text-warning-400', labelKey: 'admin.broadcasts.status.cancelling', }, }; function StatusBadge({ status }: { status: string }) { const { t } = useTranslation(); const config = statusConfig[status] || statusConfig.queued; return ( {t(config.labelKey)} ); } export default function AdminBroadcastDetail() { const { t } = useTranslation(); const navigate = useNavigate(); const queryClient = useQueryClient(); const { id } = useParams<{ id: string }>(); const broadcastId = id ? parseInt(id, 10) : null; // Fetch broadcast details const { data: broadcast, isLoading, refetch, } = useQuery({ queryKey: ['admin', 'broadcasts', 'detail', broadcastId], queryFn: async () => { if (!broadcastId) throw new Error('Invalid broadcast ID'); return adminBroadcastsApi.get(broadcastId); }, enabled: !!broadcastId && !isNaN(broadcastId), refetchInterval: (query) => { const data = query.state.data; if (data && ['queued', 'in_progress', 'cancelling'].includes(data.status)) { return 3000; } return false; }, }); // Stop mutation const stopMutation = useMutation({ mutationFn: adminBroadcastsApi.stop, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['admin', 'broadcasts'] }); refetch(); }, }); const isRunning = broadcast && ['queued', 'in_progress', 'cancelling'].includes(broadcast.status); if (!broadcastId || isNaN(broadcastId)) { navigate('/admin/broadcasts'); return null; } if (isLoading) { return ( ); } if (!broadcast) { return ( {t('admin.broadcasts.notFound')} navigate('/admin/broadcasts')} className="rounded-lg bg-accent-500 px-4 py-2 text-white transition-colors hover:bg-accent-600" > {t('common.back')} ); } return ( {/* Header */} {t('admin.broadcasts.detail')} #{broadcast.id} {new Date(broadcast.created_at).toLocaleString()} refetch()} className="rounded-lg p-2 transition-colors hover:bg-dark-700" > {/* Progress */} {isRunning && ( {t('admin.broadcasts.progress')} {broadcast.progress_percent.toFixed(1)}% )} {/* Stats */} } tone="neutral" /> } tone="success" /> } tone="warning" /> } tone="error" /> {/* Target */} {t('admin.broadcasts.filter')} {broadcast.target_type} {/* Telegram Message */} {broadcast.message_text && ( {t('admin.broadcasts.message')} {broadcast.message_text} )} {/* Email Subject */} {broadcast.email_subject && ( {t('admin.broadcasts.emailSubject')} {broadcast.email_subject} )} {/* Email Content */} {broadcast.email_html_content && ( {t('admin.broadcasts.emailContent')} {broadcast.email_html_content} )} {/* Media */} {broadcast.has_media && ( {t('admin.broadcasts.media')} {broadcast.media_type === 'photo' && } {broadcast.media_type === 'video' && } {broadcast.media_type === 'document' && } {broadcast.media_type} )} {/* Admin info */} {t('admin.broadcasts.createdBy')}:{' '} {broadcast.admin_name || t('admin.broadcasts.unknownAdmin')} {new Date(broadcast.created_at).toLocaleString()} {/* Stop button */} {isRunning && broadcast.status !== 'cancelling' && ( stopMutation.mutate(broadcast.id)} disabled={stopMutation.isPending} className="flex w-full items-center justify-center gap-2 rounded-lg border border-error-500/30 bg-error-500/20 px-4 py-2 text-sm text-error-400 transition-colors hover:bg-error-500/30 disabled:opacity-50" > {stopMutation.isPending ? t('admin.broadcasts.stopping') : t('admin.broadcasts.stop')} )} ); }
{t('admin.broadcasts.notFound')}
{new Date(broadcast.created_at).toLocaleString()}
{t('admin.broadcasts.filter')}
{broadcast.target_type}
{t('admin.broadcasts.message')}
{t('admin.broadcasts.emailSubject')}
{t('admin.broadcasts.emailContent')}
{t('admin.broadcasts.media')}