Files
spsays-training/lib/quiz-groups.ts
T
2026-10-18 13:02:30 +05:30

88 lines
2.6 KiB
TypeScript

/**
* 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<string, QuizCard[]>();
const years = new Map<number | null, QuizCard[]>();
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(),
quizzes,
})),
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,
};
}