Quiz list: drill down by Books → book and Lectures → year
The All tab is now a click-through of category cards — Books, Lectures & Conversations, Other quizzes — each opening its books or years, then the quizzes themselves. Only categories with quizzes get a card. The position and tab live in the URL (?in=books&book=bg, ?tab=todo), so refresh, Back and shared links keep your place. Book quizzes list in chapter order. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
3af4e1bcd3
commit
0a23ab59f7
@@ -6,23 +6,37 @@
|
||||
* Reached from the Quizzes card on the search page. Quizzes are deliberately
|
||||
* not in search results: they're something to do, not something to look up.
|
||||
* Signed in only: visitors get the sign-in modal, and home if they dismiss it.
|
||||
*
|
||||
* The tab (?tab=todo) and, under All, the category you've drilled into
|
||||
* (?in=books&book=bg) both live in the URL, so a refresh keeps your place.
|
||||
*/
|
||||
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { usePathname, useRouter, useSearchParams } from "next/navigation";
|
||||
import { useSignedInPage } from "@/components/auth/use-signed-in-page";
|
||||
import { quiz, type QuizCard } from "@/lib/quiz";
|
||||
import { groupQuizzes } from "@/lib/quiz-groups";
|
||||
import { QuizGrid } from "@/components/quiz/quiz-grid";
|
||||
import { GroupedQuizzes } from "@/components/quiz/grouped-quizzes";
|
||||
import { QuizBrowser } from "@/components/quiz/quiz-browser";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
type Filter = "all" | "todo" | "done";
|
||||
const FILTERS: readonly Filter[] = ["all", "todo", "done"];
|
||||
|
||||
export function QuizzesList() {
|
||||
const { user } = useSignedInPage();
|
||||
const userId = user?.id;
|
||||
const [list, setList] = useState<QuizCard[] | null>(null);
|
||||
const [filter, setFilter] = useState<Filter>("all");
|
||||
const params = useSearchParams();
|
||||
const router = useRouter();
|
||||
const pathname = usePathname();
|
||||
const tabParam = params.get("tab") as Filter | null;
|
||||
const filter: Filter =
|
||||
tabParam && FILTERS.includes(tabParam) ? tabParam : "all";
|
||||
// Switching tab starts that tab at its top; All is the bare URL.
|
||||
const setFilter = (f: Filter) =>
|
||||
router.replace(f === "all" ? pathname : `${pathname}?tab=${f}`, {
|
||||
scroll: false,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!userId) return;
|
||||
@@ -99,7 +113,14 @@ export function QuizzesList() {
|
||||
) : filter !== "all" ? (
|
||||
<QuizGrid quizzes={shown} />
|
||||
) : (
|
||||
<GroupedQuizzes sections={groupQuizzes(shown)} />
|
||||
<QuizBrowser
|
||||
quizzes={shown}
|
||||
path={{
|
||||
in: params.get("in"),
|
||||
book: params.get("book"),
|
||||
year: params.get("year"),
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</main>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user