"use client"; import React, { useCallback, useState } from "react"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Textarea } from "@/components/ui/textarea"; import { Field, FieldDescription, FieldGroup, FieldLabel, } from "@/components/ui/field"; import { ContextMenu, ContextMenuTrigger, ContextMenuContent, ContextMenuLabel, ContextMenuSeparator, ContextMenuItem, ContextMenuGroup } from "@/components/ui/context-menu"; import { AlertCircle, Calendar, Check, Clock, Copy, Loader2, Users, } from "lucide-react"; import { ScrollArea } from "@/components/ui/scroll-area"; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog"; import Image from 'next/image'; import { stripHtml } from "@/lib/utils"; import { HtmlDisplay } from "@/components/html-display"; import { formatStoredAnswer } from "@/lib/form-answer-values"; import { normalizeStoredAnswerSnapshot } from "@/lib/submission-intake"; import { updateSubmissionAdminNote } from "@/app/admin/form/actions"; import { useDebouncedAutoSave, type AutoSaveStatus, } from "@/hooks/use-debounced-autosave"; import { DiscordProfileDropdown, type DiscordMemberProfile, } from "@/components/dropdown-menu-avatar"; interface Question { id: string; label: string; type: string; imageUrl: string | null; } interface SubmissionDetailClientProps { submission: { id: string; formId: string; userName: string | null; userDiscordId: string | null; userProfile: DiscordMemberProfile | null; submittedAt: Date; adminNote: string | null; editHistory?: { editedAt: string; oldAnswers: Record }[] | null; }; questions: Question[]; answers: Record; } export default function SubmissionDetailClient({ submission, questions, answers, }: SubmissionDetailClientProps) { const [copiedId, setCopiedId] = useState(null); const [adminNote, setAdminNote] = useState(submission.adminNote ?? ""); const handleCopy = (text: string, id: string) => { if (!text) return; navigator.clipboard.writeText(text); setCopiedId(id); setTimeout(() => setCopiedId(null), 2000); }; const userLabel = submission.userName ? `${submission.userName} (${submission.userDiscordId || "N/A"})` : submission.userDiscordId || "Anonymous"; const editHistory = Array.isArray(submission.editHistory) ? submission.editHistory : []; const saveAdminNote = useCallback( () => updateSubmissionAdminNote( submission.formId, submission.id, adminNote ).then(() => undefined), [adminNote, submission.formId, submission.id] ); const noteAutoSave = useDebouncedAutoSave({ save: saveAdminNote, delay: 1000, }); return (
{/* Submission Metadata Card */} Submission Info Details about this respondent.
Respondent: {userLabel} {submission.userProfile?.globalName && ( )}
Initial Submission: {new Date(submission.submittedAt).toLocaleString("en-GB", { timeZone: "Asia/Bangkok", hour12: false })}
{editHistory.length > 0 && (
Edit History:
    {editHistory.map((edit, idx) => (
  • Edited at {new Date(edit.editedAt).toLocaleString("en-GB", { timeZone: "Asia/Bangkok", hour12: false })}
  • ))}
)}
Admin note Private context for administrators. Respondents cannot see this note. Note