"use client"; /** * The "All" tab of /quizzes, as a drill-down: * * All → Books → a book → its quizzes * → Lectures & Conversations → a year → its quizzes * → Other quizzes (stand-alone) * * Where you are lives in the URL (?in=books&book=bg, ?in=lectures&year=1972) * so a refresh, Back, or a shared link lands in the same place. Every level * only offers categories that actually hold quizzes; a stale or hand-typed * URL pointing at an empty one falls back to its parent. */ import Link from "next/link"; import { BookOpen, CalendarDays, ChevronRight, ClipboardCheck, Mic, } from "lucide-react"; import type { QuizCard } from "@/lib/quiz"; import { groupQuizzes, type QuizGroup } from "@/lib/quiz-groups"; import { QuizCategoryCard } from "./quiz-category-card"; import { QuizGrid } from "./quiz-grid"; export type QuizBrowsePath = { in?: string | null; book?: string | null; year?: string | null; }; const BOOKS = "books"; const LECTURES = "lectures"; const OTHER = "other"; /** /quizzes URL for a browse position (the All tab is the default). */ export function quizzesHref(p: QuizBrowsePath): string { const qs = new URLSearchParams(); if (p.in) qs.set("in", p.in); if (p.book) qs.set("book", p.book); if (p.year) qs.set("year", p.year); const s = qs.toString(); return s ? `/quizzes?${s}` : "/quizzes"; } export function QuizBrowser({ quizzes, path, }: { quizzes: QuizCard[]; path: QuizBrowsePath; }) { const { books, lectures, other } = groupQuizzes(quizzes); const all = (gs: QuizGroup[]) => gs.flatMap((g) => g.quizzes); const book = path.in === BOOKS ? books.find((g) => g.key === path.book) : undefined; const year = path.in === LECTURES ? lectures.find((g) => g.key === path.year) : undefined; // Books → a book: its quizzes. if (book) { return ( ); } // Lectures → a year: its quizzes. if (year) { return ( ); } // Books: a card per book. if (path.in === BOOKS && books.length > 0) { return ( {books.map((g) => ( } /> ))} ); } // Lectures: a card per year. if (path.in === LECTURES && lectures.length > 0) { return ( {lectures.map((g) => ( } /> ))} ); } // Stand-alone quizzes. if (path.in === OTHER && other.length > 0) { return ( ); } // Top level: one card per category that has quizzes. return ( {books.length > 0 && ( } /> )} {lectures.length > 0 && ( } /> )} {other.length > 0 && ( } /> )} ); } function CardGrid({ children }: { children: React.ReactNode }) { return (
{children}
); } /** A level below the top: a breadcrumb back up, then its content. */ function Level({ crumbs, children, }: { /** [label, href?] — the last (current) one has no link. */ crumbs: [string, string?][]; children: React.ReactNode; }) { return (
{children}
); }