'use client'; import { useMemo, useState, useTransition } from 'react'; import { Table, TableBody, TableHead, TableHeader, TableRow, TableCell } from '@workspace/ui/components/table'; import { Input } from '@workspace/ui/components/input'; import { Button } from '@workspace/ui/components/button'; import { Select, SelectTrigger, SelectContent, SelectItem, SelectValue, } from '@workspace/ui/components/select'; import StatusSelect from './StatusSelect'; type Applicant = { applicationId: number; status: string; firstName: string | null; lastName: string | null; email: string | null; studentId: number | null; }; const STATUS_OPTIONS = [ 'in review', 'Online Assessment', 'Interview round', 'offer given', 'accepted', 'rejected', ]; export default function ApplicationsTable({ applicants }: { applicants: Applicant[] }) { const [query, setQuery] = useState(''); const [selected, setSelected] = useState([]); const [bulkStatus, setBulkStatus] = useState(''); const [rows, setRows] = useState(applicants); const [sendEmail, setSendEmail] = useState(false); const [isPending, startTransition] = useTransition(); const filtered = useMemo(() => { if (!query.trim()) return rows; const q = query.toLowerCase(); return rows.filter((a) => { const name = `${a.firstName ?? ''} ${a.lastName ?? ''}`.toLowerCase(); const email = (a.email ?? '').toLowerCase(); return name.includes(q) || email.includes(q); }); }, [rows, query]); const toggleAll = (checked: boolean) => { setSelected(checked ? filtered.map((a) => a.applicationId) : []); }; const toggleOne = (id: number, checked: boolean) => { setSelected((prev) => (checked ? [...new Set([...prev, id])] : prev.filter((x) => x !== id))); }; const onBulkUpdate = () => { if (!bulkStatus || selected.length === 0) return; const targets = new Set(selected); startTransition(async () => { const updates = rows.filter((r) => targets.has(r.applicationId)); let notifiedCount = 0; let errorCount = 0; for (const r of updates) { try { const res = await fetch(`/api/applications/${r.applicationId}/status`, { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ status: bulkStatus, studentId: r.studentId ?? 0, notify: sendEmail }), }); const data = await res.json(); if (!res.ok) { errorCount += 1; } else if (sendEmail) { if (data?.notified) notifiedCount += 1; if (data?.emailError) errorCount += 1; } } catch (_e) { errorCount += 1; } } setRows((prev) => prev.map((r) => (targets.has(r.applicationId) ? { ...r, status: bulkStatus } : r)), ); setSelected([]); if (sendEmail) { if (errorCount === 0) { alert(`Updated ${updates.length} and emailed ${notifiedCount} student(s).`); } else { alert(`Updated ${updates.length}. Emails sent: ${notifiedCount}. Errors: ${errorCount}.`); } } else { alert(`Updated ${updates.length}.`); } }); }; const allSelected = filtered.length > 0 && selected.length === filtered.length; const someSelected = selected.length > 0 && selected.length < filtered.length; return (
setQuery(e.target.value)} className="w-72" /> {filtered.length} results
{selected.length > 0 && ( )}
{ if (el) el.indeterminate = someSelected; }} onChange={(e) => toggleAll(e.target.checked)} /> Name Email Status {filtered.map((applicant) => ( toggleOne(applicant.applicationId, e.target.checked)} /> {`${applicant.firstName ?? ''} ${applicant.lastName ?? ''}`.trim() || 'Unknown'} {applicant.email} ))}
); }