diff --git a/packages/frontend/src/components/LessonProgressList.tsx b/packages/frontend/src/components/LessonProgressList.tsx new file mode 100644 index 0000000..2eebb7f --- /dev/null +++ b/packages/frontend/src/components/LessonProgressList.tsx @@ -0,0 +1,79 @@ +import { useMemo, useState } from 'react'; +import { Link } from 'react-router-dom'; + +export interface LessonProgressRow { + lessonId: number; + name: string; + totalCards: number; + masteredCards: number; + scorePct: number; + lastSessionAt: number | null; +} + +type SortKey = 'name' | 'score' | 'last'; + +function relativeTime(unixSec: number | null): string { + if (!unixSec) return 'nooit'; + const diff = Math.floor(Date.now() / 1000) - unixSec; + if (diff < 60) return 'zojuist'; + if (diff < 3600) return `${Math.floor(diff / 60)}m geleden`; + if (diff < 86400) return `${Math.floor(diff / 3600)}u geleden`; + return `${Math.floor(diff / 86400)}d geleden`; +} + +export function LessonProgressList({ rows }: { rows: LessonProgressRow[] }) { + const [sortBy, setSortBy] = useState('score'); + + const sorted = useMemo(() => { + const copy = [...rows]; + copy.sort((a, b) => { + if (sortBy === 'name') return a.name.localeCompare(b.name); + if (sortBy === 'last') return (b.lastSessionAt ?? 0) - (a.lastSessionAt ?? 0); + return b.scorePct - a.scorePct; + }); + return copy; + }, [rows, sortBy]); + + if (rows.length === 0) { + return

Nog geen lessen.

; + } + + return ( +
+
+ Sorteer: + {(['score', 'name', 'last'] as SortKey[]).map((k) => ( + + ))} +
+ +
+ ); +}