feat(frontend): lessons page with filter (replaces Admin.tsx)
This commit is contained in:
61
packages/frontend/src/pages/Lessons.tsx
Normal file
61
packages/frontend/src/pages/Lessons.tsx
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { lessonsApi } from '../api/lessons.js';
|
||||||
|
import { useLessons } from '../stores/lessonsStore.js';
|
||||||
|
import { LessonTree } from '../components/LessonTree.js';
|
||||||
|
|
||||||
|
export function LessonsPage() {
|
||||||
|
const { tree, refresh, loading } = useLessons();
|
||||||
|
const [newRoot, setNewRoot] = useState('');
|
||||||
|
const [filter, setFilter] = useState('');
|
||||||
|
|
||||||
|
useEffect(() => { refresh(); }, [refresh]);
|
||||||
|
|
||||||
|
async function addRoot() {
|
||||||
|
if (!newRoot.trim()) return;
|
||||||
|
await lessonsApi.create({ name: newRoot.trim(), parentId: null });
|
||||||
|
setNewRoot('');
|
||||||
|
await refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="mx-auto max-w-3xl space-y-6">
|
||||||
|
<header>
|
||||||
|
<h1 className="font-display text-3xl font-bold">Lessen</h1>
|
||||||
|
<p className="mt-1 text-sm text-slate-600 dark:text-slate-400">
|
||||||
|
Maak een hiërarchie van lessen en sublessen. Sleep aan ⋮⋮ om te herordenen. Klik op een les voor details.
|
||||||
|
</p>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div className="surface flex flex-col gap-2 p-4 sm:flex-row">
|
||||||
|
<input
|
||||||
|
className="input-field"
|
||||||
|
placeholder="Nieuwe wortel-les…"
|
||||||
|
value={newRoot}
|
||||||
|
onChange={(e) => setNewRoot(e.target.value)}
|
||||||
|
onKeyDown={(e) => e.key === 'Enter' && addRoot()}
|
||||||
|
/>
|
||||||
|
<button className="btn-primary shrink-0" onClick={addRoot} disabled={!newRoot.trim()}>
|
||||||
|
+ Toevoegen
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="surface space-y-3 p-4">
|
||||||
|
<input
|
||||||
|
className="input-field"
|
||||||
|
placeholder="Filter lessen op naam…"
|
||||||
|
value={filter}
|
||||||
|
onChange={(e) => setFilter(e.target.value)}
|
||||||
|
/>
|
||||||
|
{loading ? (
|
||||||
|
<p className="text-sm text-slate-500">Laden…</p>
|
||||||
|
) : tree.length === 0 ? (
|
||||||
|
<div className="py-8 text-center text-sm text-slate-500">
|
||||||
|
Nog geen lessen. Voeg er hierboven een toe.
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<LessonTree nodes={tree} filter={filter} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user