"use client"; import Link from "next/link"; import { useMemo, useState } from "react"; import { Kbd } from "@/components/ui/kbd"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; import { Pagination, PaginationContent, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious } from "@/components/ui/pagination"; import { DeleteAllSubmissionsButton, DeleteSubmissionButton } from "@/components/delete-buttons"; import { ResultsFilters } from "@/components/results-filters"; import type { DiscordMemberProfile } from "@/lib/discord/discord"; const RESULTS_PAGE_SIZE = 25; type ResultFilters = { q: string; page: number; sort: "submittedAt" | "respondent"; direction: "asc" | "desc"; edited: "all" | "edited" | "unedited"; dateFrom: string; dateTo: string; }; function resultFiltersToSearchParams(filters: ResultFilters) { const params = new URLSearchParams(); if (filters.q) params.set("q", filters.q); if (filters.page > 1) params.set("page", String(filters.page)); if (filters.sort !== "submittedAt") params.set("sort", filters.sort); if (filters.direction !== "desc") params.set("direction", filters.direction); if (filters.edited !== "all") params.set("edited", filters.edited); if (filters.dateFrom) params.set("dateFrom", filters.dateFrom); if (filters.dateTo) params.set("dateTo", filters.dateTo); return params.toString(); } type ResultRow = { id: string; userName: string | null; userDiscordId: string | null; submittedAt: string; adminNote: string | null; editHistory: unknown[]; }; function formatDate(value: string) { return new Date(value).toLocaleString("en-GB", { timeZone: "Asia/Bangkok", hour12: false, }); } function bangkokDate(value: string) { const parts = new Intl.DateTimeFormat("en-CA", { timeZone: "Asia/Bangkok", year: "numeric", month: "2-digit", day: "2-digit", }).formatToParts(new Date(value)); const values = Object.fromEntries(parts.map((part) => [part.type, part.value])); return `${values.year}-${values.month}-${values.day}`; } function RespondentName({ row, profile, }: { row: ResultRow; profile: DiscordMemberProfile | null; }) { const displayName = profile?.globalName || profile?.username || row.userName || row.userDiscordId || "Anonymous"; const username = profile?.username || row.userName; return ( {displayName} {username && username !== displayName && ({username})} ); } export default function ResultsClient({ formId, initialFilters, rows, profiles, }: { formId: string; initialFilters: ResultFilters; rows: ResultRow[]; profiles: Record; }) { const [filters, setFilters] = useState(initialFilters); const [page, setPage] = useState(initialFilters.page); const filteredRows = useMemo(() => { const query = filters.q.toLocaleLowerCase(); return rows .filter((row) => { const matchesQuery = !query || `${row.userName ?? ""} ${row.userDiscordId ?? ""}`.toLocaleLowerCase().includes(query); const edited = row.editHistory.length > 0; const matchesEdited = filters.edited === "all" || (filters.edited === "edited" ? edited : !edited); const date = bangkokDate(row.submittedAt); return matchesQuery && matchesEdited && (!filters.dateFrom || date >= filters.dateFrom) && (!filters.dateTo || date <= filters.dateTo); }) .sort((a, b) => { if (filters.sort === "respondent") { const result = (a.userName || a.userDiscordId || "").localeCompare(b.userName || b.userDiscordId || ""); return filters.direction === "asc" ? result : -result; } const result = new Date(a.submittedAt).getTime() - new Date(b.submittedAt).getTime(); return filters.direction === "asc" ? result : -result; }); }, [filters, rows]); const pageCount = Math.max(1, Math.ceil(filteredRows.length / RESULTS_PAGE_SIZE)); const currentPage = Math.min(page, pageCount); const visibleRows = filteredRows.slice((currentPage - 1) * RESULTS_PAGE_SIZE, currentPage * RESULTS_PAGE_SIZE); const updateFilters = (next: ResultFilters) => { const normalized = { ...next, page: 1 }; setFilters(normalized); setPage(1); const query = resultFiltersToSearchParams(normalized); window.history.replaceState(null, "", `/admin/form/${formId}/result${query ? `?${query}` : ""}`); }; return (

Responses

{filteredRows.length} matching {filteredRows.length === 1 ? "response" : "responses"}

{rows.length > 0 && }
{visibleRows.length === 0 ? ( No responses foundTry changing or clearing the current filters. ) : ( <> RespondentSubmittedNoteActions {visibleRows.map((row) => {row.userName && row.userDiscordId &&

{row.userDiscordId}

}
{formatDate(row.submittedAt)}{row.adminNote ?

{row.adminNote}

: No note}
)}
{visibleRows.map((row) => {formatDate(row.submittedAt)}

Note

{row.adminNote ?

{row.adminNote}

:

No note

}
)}
)} {pageCount > 1 && { event.preventDefault(); setPage(Math.max(1, currentPage - 1)); }} aria-disabled={currentPage === 1} /> event.preventDefault()}>{currentPage} / {pageCount} { event.preventDefault(); setPage(Math.min(pageCount, currentPage + 1)); }} aria-disabled={currentPage === pageCount} />}
); }