import Link from "next/link"; import { redirect } from "next/navigation"; import { Badge } from "@/components/ui/badge"; 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 { getFilteredSubmissions, parseResultFilters, resultFiltersToSearchParams, RESULTS_PAGE_SIZE, } from "@/lib/admin-form-results"; import { DeleteAllSubmissionsButton, DeleteSubmissionButton } from "@/components/delete-buttons"; import { ResultsFilters } from "@/components/results-filters"; import { RealtimeRefresh } from "@/components/realtime-refresh"; import { getDiscordMemberProfile, type DiscordMemberProfile, } from "@/lib/discord"; export const dynamic = "force-dynamic"; function formatDate(date: Date) { return date.toLocaleString("en-GB", { timeZone: "Asia/Bangkok", hour12: false, }); } function RespondentName({ submission, profile, }: { submission: { userName: string | null; userDiscordId: string | null; }; profile: DiscordMemberProfile | null; }) { const displayName = profile?.globalName || profile?.username || submission.userName || submission.userDiscordId || "Anonymous"; const username = profile?.username || submission.userName; return ( {displayName} {username && username !== displayName && ({username})} ); } export default async function ResultsListPage({ params, searchParams, }: { params: Promise<{ id: string }>; searchParams: Promise>; }) { const [{ id }, rawFilters] = await Promise.all([params, searchParams]); const filters = parseResultFilters(rawFilters); const { rows, total } = await getFilteredSubmissions(id, filters); const pageCount = Math.max(1, Math.ceil(total / RESULTS_PAGE_SIZE)); if (total > 0 && filters.page > pageCount) { redirect(`?${resultFiltersToSearchParams(filters, { page: pageCount })}`); } const currentPage = Math.min(filters.page, pageCount); const listQuery = resultFiltersToSearchParams(filters); const discordIds = [ ...new Set( rows .map((submission) => submission.userDiscordId) .filter((discordId): discordId is string => Boolean(discordId)) ), ]; const respondentProfiles = new Map( await Promise.all( discordIds.map( async (discordId) => [discordId, await getDiscordMemberProfile(discordId)] as const ) ) ); return ( Responses {total} matching {total === 1 ? "response" : "responses"} {total > 0 && } {rows.length === 0 ? ( No responses found {total === 0 && !listQuery ? "Responses will appear here after people submit the form." : "Try changing or clearing the current filters."} ) : ( <> Respondent Submitted Status Admin note Actions {rows.map((submission) => { const detailHref = `/admin/form/${id}/result/${submission.id}${listQuery ? `?return=${encodeURIComponent(listQuery)}` : ""}`; const edited = Array.isArray(submission.editHistory) && submission.editHistory.length > 0; return ( {submission.userName && submission.userDiscordId && ( {submission.userDiscordId} )} {formatDate(submission.submittedAt)} {edited ? "Edited" : "Original"} {submission.adminNote ? ( {submission.adminNote} ) : ( No note )} ); })} {rows.map((submission) => { const detailHref = `/admin/form/${id}/result/${submission.id}${listQuery ? `?return=${encodeURIComponent(listQuery)}` : ""}`; return ( {formatDate(submission.submittedAt)} Admin note {submission.adminNote ? ( {submission.adminNote} ) : ( No note )} ); })} > )} {pageCount > 1 && ( {currentPage} / {pageCount} )} ); }
{total} matching {total === 1 ? "response" : "responses"}
{submission.userDiscordId}
{submission.adminNote}
Admin note
No note