/** * Groups the quiz list for the "All" tab: * * Books → one group per book, in the library's order * Lectures & Conversations → one group per year, oldest first, undated last * Other quizzes → stand-alone quizzes * * Only groups with quizzes in them are returned, so an empty category or * sub-category never renders. */ import { BOOK_NAMES } from "@/lib/constants"; import type { QuizCard } from "@/lib/quiz"; export type QuizGroup = { key: string; label: string; quizzes: QuizCard[] }; export type QuizSections = { books: QuizGroup[]; lectures: QuizGroup[]; other: QuizCard[]; }; const BOOK_ORDER = Object.keys(BOOK_NAMES); /** "bg" from /books/bg/2 — the book a chapter quiz belongs to. */ function bookCode(path?: string | null): string | null { const m = path?.match(/^\/books\/([^/]+)/); return m ? m[1] : null; } /** * The recording's year. Saved on the quiz since target_year existed; for * older quizzes, read from the slug's yymmdd prefix (720720sb-london → 1972) * when it falls in Śrīla Prabhupāda's recorded years. */ function lectureYear(q: QuizCard): number | null { if (q.target_year) return q.target_year; const m = q.target_path?.match(/^\/transcriptions\/(\d{2})\d{4}/); if (!m) return null; const y = 1900 + Number(m[1]); return y >= 1966 && y <= 1977 ? y : null; } export function groupQuizzes(cards: QuizCard[]): QuizSections { const books = new Map(); const years = new Map(); const other: QuizCard[] = []; for (const q of cards) { if (q.target_kind === "chapter") { const code = bookCode(q.target_path) ?? "other"; books.set(code, [...(books.get(code) ?? []), q]); } else if ( q.target_kind === "lecture" || q.target_kind === "conversation" ) { const y = lectureYear(q); years.set(y, [...(years.get(y) ?? []), q]); } else { other.push(q); } } const rank = (code: string) => { const i = BOOK_ORDER.indexOf(code); return i < 0 ? BOOK_ORDER.length : i; }; return { books: [...books.entries()] .sort(([a], [b]) => rank(a) - rank(b) || a.localeCompare(b)) .map(([code, quizzes]) => ({ key: code, label: BOOK_NAMES[code] ?? code.toUpperCase(), // Chapter order (/books/bg/2 before /books/bg/10), not newest first. quizzes: [...quizzes].sort((a, b) => (a.target_path ?? "").localeCompare(b.target_path ?? "", undefined, { numeric: true, }), ), })), lectures: [...years.entries()] // Oldest first; undated (null) last. .sort(([a], [b]) => (a ?? 9999) - (b ?? 9999)) .map(([year, quizzes]) => ({ key: String(year ?? "undated"), label: year ? String(year) : "Undated", quizzes, })), other, }; }