"use client"; // app/library/page.jsx — everything you've made, saved locally in data/db.json. import { useEffect, useState } from "react"; import Link from "next/link"; import { useRouter } from "next/navigation"; const TYPE_LABELS = { quiz: "Quiz", test: "Test", worksheet: "Worksheet", discussion: "Discussion", case_study: "Case study", }; function SkeletonCard() { return (
); } export default function LibraryPage() { const router = useRouter(); const [items, setItems] = useState(null); const [query, setQuery] = useState(""); const [error, setError] = useState(""); const [busy, setBusy] = useState(""); function load() { fetch("/api/assignments") .then((r) => r.json()) .then((d) => setItems(d.assignments || [])) .catch(() => setError("Could not load your library.")); } useEffect(load, []); async function duplicate(id) { setBusy(id); setError(""); try { const res = await fetch("/api/assignments/" + id); const full = await res.json(); if (!res.ok) throw new Error(full.error || "Could not load that assignment."); const { id: _id, createdAt, updatedAt, ...copy } = full; copy.title = (copy.title || "Untitled") + " (copy)"; const res2 = await fetch("/api/assignments", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(copy), }); const created = await res2.json(); if (!res2.ok) throw new Error(created.error || "Could not duplicate."); load(); } catch (e) { setError(String(e.message || e)); } finally { setBusy(""); } } async function remove(id, title) { if (!confirm(`Delete "${title}"? This can't be undone.`)) return; setBusy(id); try { await fetch("/api/assignments/" + id, { method: "DELETE" }); load(); } finally { setBusy(""); } } const filtered = (items || []).filter((a) => { const q = query.trim().toLowerCase(); if (!q) return true; return [a.title, a.subject, a.gradeLevel, TYPE_LABELS[a.assignmentType]] .filter(Boolean) .join(" ") .toLowerCase() .includes(q); }); return (Everything you’ve created, stored locally on this computer.
Create your first assignment and it will be saved here automatically.
Create an assignmentNo matches for “{query}”.
}
{[a.gradeLevel, a.subject].filter(Boolean).join(" · ")}
{a.questionCount} question{a.questionCount === 1 ? "" : "s"} · {a.totalPoints} pts · updated {formatDate(a.updatedAt)}