"use client"; import { useCallback, useEffect, useState } from "react"; import { useParams, useRouter } from "next/navigation"; import Link from "next/link"; import { toast } from "sonner"; import { quizzes, AdminError, type Quiz } from "@/lib/api"; import { Button } from "@/components/ui/button"; import { useConfirm } from "@/components/confirm"; import { Can, useStaff } from "@/components/staff-context"; import { cn } from "@/lib/utils"; import { QuizEditor } from "../quiz-editor"; import { KIND_LABEL } from "../labels"; import { Participants, Responses } from "./results"; import { Clamp } from "@/components/ui/clamp"; type Tab = "edit" | "participants" | "responses"; export default function QuizDetailPage() { const { id } = useParams<{ id: string }>(); const router = useRouter(); const confirm = useConfirm(); const { can } = useStaff(); const [quiz, setQuiz] = useState(null); const [tab, setTab] = useState("edit"); const [busy, setBusy] = useState(false); const load = useCallback(() => { quizzes .get(id) .then(setQuiz) .catch((err) => toast.error( err instanceof AdminError ? err.message : "Could not load the quiz", ), ); }, [id]); useEffect(() => { load(); }, [load]); if (!quiz) return

Loading…

; const togglePublish = async () => { const on = !quiz.published_at; if ( !on && !(await confirm({ title: "Unpublish this quiz?", message: "It disappears from the app. Results so far are kept, and you can publish it again.", confirmLabel: "Unpublish", })) ) { return; } setBusy(true); try { setQuiz(await quizzes.setPublished(quiz.id, on)); toast.success(on ? "Published" : "Unpublished"); } catch (err) { toast.error(err instanceof AdminError ? err.message : "That didn't work"); } finally { setBusy(false); } }; const remove = async () => { if ( !(await confirm({ title: `Delete “${quiz.title}”?`, message: "It disappears from the app. Participants' results are kept on record.", confirmLabel: "Delete", destructive: true, })) ) { return; } try { await quizzes.remove(quiz.id); toast.success("Quiz deleted"); router.replace("/quizzes"); } catch (err) { toast.error( err instanceof AdminError ? err.message : "Could not delete the quiz", ); } }; const tabs: { key: Tab; label: string; show: boolean }[] = [ { key: "edit", label: can("quizzes:write") ? "Edit" : "Questions", show: true, }, { key: "participants", label: `Participants (${quiz.attempt_count ?? 0})`, show: can("quizzes:results"), }, { key: "responses", label: "Responses", show: can("quizzes:results") }, ]; return (
← Quizzes

{quiz.title}

{KIND_LABEL[quiz.target_kind]} {quiz.target_title && ` · ${quiz.target_title}`} {quiz.target_path && ( ({quiz.target_path}) )}
{tabs .filter((t) => t.show) .map((t) => ( ))}
{tab === "edit" && ( )} {tab === "participants" && } {tab === "responses" && }
); }