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>
48 lines
1.5 KiB
TypeScript
48 lines
1.5 KiB
TypeScript
/**
|
|
* A clickable category in the quiz browser — Books, a book, Lectures, a
|
|
* year. Shows how many quizzes it holds and how many are still to take.
|
|
*/
|
|
|
|
import Link from "next/link";
|
|
import { ChevronRight } from "lucide-react";
|
|
import type { QuizCard } from "@/lib/quiz";
|
|
|
|
export function QuizCategoryCard({
|
|
href,
|
|
label,
|
|
quizzes,
|
|
icon,
|
|
}: {
|
|
href: string;
|
|
label: string;
|
|
quizzes: QuizCard[];
|
|
icon: React.ReactNode;
|
|
}) {
|
|
const todo = quizzes.filter((q) => q.my.state !== "completed").length;
|
|
const n = quizzes.length;
|
|
return (
|
|
<Link
|
|
href={href}
|
|
className="group flex h-full min-w-0 items-center gap-3.5 rounded-2xl border border-border bg-card p-4 transition-colors hover:border-primary/40 hover:bg-muted/30"
|
|
>
|
|
<span className="inline-flex size-11 shrink-0 items-center justify-center rounded-xl bg-primary/10 text-primary">
|
|
{icon}
|
|
</span>
|
|
<span className="min-w-0 flex-1">
|
|
<span
|
|
title={label}
|
|
className="line-clamp-2 font-semibold leading-snug text-foreground [overflow-wrap:anywhere]"
|
|
>
|
|
{label}
|
|
</span>
|
|
<span className="mt-0.5 block text-xs text-muted-foreground">
|
|
{n} {n === 1 ? "quiz" : "quizzes"}
|
|
{todo > 0 && todo < n ? ` · ${todo} to do` : ""}
|
|
{todo === 0 ? " · all finished" : ""}
|
|
</span>
|
|
</span>
|
|
<ChevronRight className="size-5 shrink-0 text-muted-foreground transition-transform group-hover:translate-x-0.5 group-hover:text-foreground" />
|
|
</Link>
|
|
);
|
|
}
|