feat(frontend): due-overview card with start-review CTA

This commit is contained in:
2026-05-21 07:05:35 +02:00
parent a10d02cbaf
commit 4c2d42779f

View File

@@ -0,0 +1,55 @@
import { useNavigate } from 'react-router-dom';
import { sessionsApi } from '../api/sessions.js';
import { useSession } from '../stores/sessionStore.js';
export interface DueOverview { overdue: number; today: number; tomorrow: number; thisWeek: number; }
export function DueOverviewCard({ data }: { data: DueOverview }) {
const navigate = useNavigate();
const total = data.overdue + data.today;
async function startReview() {
const r = await sessionsApi.startDue();
useSession.setState({
session: r.session,
current: r.queue[0] ?? null,
done: r.queue.length === 0,
showAnswer: false,
shownAt: Date.now(),
});
navigate(`/practice/${r.session.lessonId}`);
}
return (
<div className="surface space-y-4 p-5">
<div className="grid grid-cols-2 gap-3 sm:grid-cols-4">
<Badge tone="danger" label="Overdue" value={data.overdue} />
<Badge tone="brand" label="Vandaag" value={data.today} />
<Badge tone="success" label="Morgen" value={data.tomorrow} />
<Badge tone="muted" label="Deze week" value={data.thisWeek} />
</div>
<button
className="btn-primary w-full py-3"
onClick={startReview}
disabled={total === 0}
>
{total === 0
? 'Niets te reviewen — alles up-to-date 🎉'
: `Start review (${total} ${total === 1 ? 'kaart' : 'kaarten'})`}
</button>
</div>
);
}
function Badge({ tone, label, value }: { tone: 'danger'|'brand'|'success'|'muted'; label: string; value: number }) {
const cls =
tone === 'danger' ? 'bg-danger-50 text-danger-700 dark:bg-danger-400/15 dark:text-danger-400'
: tone === 'brand' ? 'bg-brand-100 text-brand-700 dark:bg-brand-900/30 dark:text-brand-200'
: tone === 'success' ? 'bg-success-50 text-success-700 dark:bg-success-700/15 dark:text-success-400'
: 'bg-slate-100 text-slate-700 dark:bg-slate-800 dark:text-slate-300';
return (
<div className={`rounded-2xl p-3 ${cls}`}>
<div className="text-[10px] font-semibold uppercase tracking-wider opacity-80">{label}</div>
<div className="mt-1 font-display text-2xl font-bold">{value}</div>
</div>
);
}