'use client'; import AdminShell from '@/components/AdminShell'; import { api } from '@/lib/api'; import { formatDateTime } from '@/lib/utils'; import { useEffect, useState } from 'react'; import { Users, RefreshCw, CheckCircle, XCircle, Trash2, ChevronLeft, ChevronRight, Filter } from 'lucide-react'; const STATUS_COLORS: Record = { pending: 'bg-yellow-100 text-yellow-700', approved: 'bg-green-100 text-green-700', rejected: 'bg-red-100 text-red-700', invited: 'bg-blue-100 text-blue-700', }; export default function WaitlistPage() { const [entries, setEntries] = useState([]); const [total, setTotal] = useState(0); const [loading, setLoading] = useState(true); const [statusFilter, setStatusFilter] = useState(''); const [page, setPage] = useState(0); const [actionLoading, setActionLoading] = useState(null); const [notesModal, setNotesModal] = useState<{ id: string; notes: string } | null>(null); const limit = 50; const fetchList = (p = page, status = statusFilter) => { setLoading(true); api.listWaitlist({ status: status || undefined, limit, offset: p * limit }) .then((data) => { setEntries(data.entries || []); setTotal(data.total || 0); }) .catch(() => {}) .finally(() => setLoading(false)); }; useEffect(() => { fetchList(page, statusFilter); }, [page, statusFilter]); const handleStatusChange = async (id: string, status: string) => { setActionLoading(id + status); try { await api.updateWaitlist(id, { status }); fetchList(); } catch (e: any) { alert(`Failed: ${e.message}`); } setActionLoading(null); }; const handleDelete = async (id: string, email: string) => { if (!confirm(`Delete waitlist entry for ${email}?`)) return; setActionLoading(id + 'del'); try { await api.deleteWaitlist(id); fetchList(); } catch (e: any) { alert(`Failed: ${e.message}`); } setActionLoading(null); }; const handleSaveNotes = async () => { if (!notesModal) return; setActionLoading('notes'); try { await api.updateWaitlist(notesModal.id, { notes: notesModal.notes }); setNotesModal(null); fetchList(); } catch (e: any) { alert(`Failed: ${e.message}`); } setActionLoading(null); }; const totalPages = Math.max(1, Math.ceil(total / limit)); const counts: Record = {}; entries.forEach((e) => { counts[e.status || 'pending'] = (counts[e.status || 'pending'] || 0) + 1; }); return (

Waitlist

{total} total {statusFilter ? `(filtered: ${statusFilter})` : ''}

{/* Filter tabs */}
{['', 'pending', 'approved', 'rejected', 'invited'].map((s) => ( ))}
{loading ? (
{Array.from({ length: 8 }).map((_, i) => (
))}
) : entries.length === 0 ? (
No waitlist entries{statusFilter ? ` with status "${statusFilter}"` : ''}.
) : (
{entries.map((e) => ( ))}
Email Name Referral Status Joined Notes Actions
{e.email} {e.name || '—'} {e.referral_code ? {e.referral_code} : '—'} {e.invited_by && via {e.invited_by}} {e.status || 'pending'} {e.created_at ? formatDateTime(e.created_at) : '—'}
{e.status !== 'approved' && ( )} {e.status !== 'rejected' && ( )}
)} {/* Pagination */} {totalPages > 1 && (

Page {page + 1} of {totalPages}

)}
{/* Notes Modal */} {notesModal && (
setNotesModal(null)}>
e.stopPropagation()}>

Admin Notes