'use client'; import { useEffect, useState } from 'react'; import { useParams, useRouter } from 'next/navigation'; import { createClient } from '@/lib/supabase/client'; import { Broadcast, BroadcastRecipient } from '@/types'; import { Button } from '@/components/ui/button'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table'; import { ArrowLeft, Loader2, Users, Send, CheckCheck, Eye, AlertCircle, } from 'lucide-react'; const statusConfig: Record = { draft: { label: 'Draft', classes: 'bg-slate-500/10 text-slate-400 border-slate-500/20' }, scheduled: { label: 'Scheduled', classes: 'bg-blue-500/10 text-blue-400 border-blue-500/20' }, sending: { label: 'Sending', classes: 'bg-yellow-500/10 text-yellow-400 border-yellow-500/20' }, sent: { label: 'Sent', classes: 'bg-emerald-500/10 text-emerald-400 border-emerald-500/20' }, failed: { label: 'Failed', classes: 'bg-red-500/10 text-red-400 border-red-500/20' }, }; const recipientStatusConfig: Record = { pending: { label: 'Pending', classes: 'bg-slate-500/10 text-slate-400 border-slate-500/20' }, sent: { label: 'Sent', classes: 'bg-blue-500/10 text-blue-400 border-blue-500/20' }, delivered: { label: 'Delivered', classes: 'bg-emerald-500/10 text-emerald-400 border-emerald-500/20' }, read: { label: 'Read', classes: 'bg-emerald-500/10 text-emerald-300 border-emerald-500/20' }, replied: { label: 'Replied', classes: 'bg-purple-500/10 text-purple-400 border-purple-500/20' }, failed: { label: 'Failed', classes: 'bg-red-500/10 text-red-400 border-red-500/20' }, }; interface StatCardProps { label: string; value: number; total: number; icon: React.ReactNode; color: string; } function StatCard({ label, value, total, icon, color }: StatCardProps) { const pct = total > 0 ? Math.round((value / total) * 100) : 0; return (
{icon}
{pct}%

{value.toLocaleString()}

{label}

); } export default function BroadcastDetailPage() { const params = useParams(); const router = useRouter(); const broadcastId = params.id as string; const [broadcast, setBroadcast] = useState(null); const [recipients, setRecipients] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { async function fetchData() { try { const supabase = createClient(); const { data: bc, error: bcError } = await supabase .from('broadcasts') .select('*') .eq('id', broadcastId) .single(); if (bcError) throw bcError; setBroadcast(bc); const { data: recs, error: recsError } = await supabase .from('broadcast_recipients') .select('*, contact:contacts(*)') .eq('broadcast_id', broadcastId) .order('created_at', { ascending: false }); if (recsError) throw recsError; setRecipients(recs ?? []); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to load broadcast'); } finally { setLoading(false); } } fetchData(); }, [broadcastId]); if (loading) { return (
); } if (error || !broadcast) { return (

{error ?? 'Broadcast not found'}

); } const status = statusConfig[broadcast.status] ?? statusConfig.draft; return (
{/* Header */}

{broadcast.name}

{status.label}
Template: {broadcast.template_name} - Created {new Date(broadcast.created_at).toLocaleDateString()}
{/* Stats */}
} color="bg-slate-800 text-slate-300" /> } color="bg-blue-500/10 text-blue-400" /> } color="bg-emerald-500/10 text-emerald-400" /> } color="bg-emerald-500/10 text-emerald-300" /> } color="bg-red-500/10 text-red-400" />
{/* Recipients Table */}

Recipients ({recipients.length})

{recipients.length === 0 ? (

No recipients found.

) : ( Contact Phone Status Sent At Error {recipients.map((recipient) => { const rStatus = recipientStatusConfig[recipient.status] ?? recipientStatusConfig.pending; return ( {recipient.contact?.name ?? 'Unknown'} {recipient.contact?.phone ?? '-'} {rStatus.label} {recipient.sent_at ? new Date(recipient.sent_at).toLocaleString() : '-'} {recipient.error_message ?? '-'} ); })}
)}
); }