import { useCallback, useEffect, useRef, useState } from "react"; import { useSearchParams } from "react-router"; import { FilePlus2, PenTool, RefreshCw, Trash2 } from "lucide-react"; import { useClient } from "hooks/useClient"; /** * The list of designs — the one concept upstream does not have. * * Standalone M3E Canvas holds exactly one document, in one browser, in `localStorage`. Everything here * exists because Officer gives it several, belonging to a person rather than to a browser. * * Selection is `?doc=` in the URL rather than a channel, so a design is addressable and survives a * reload — `docs/navigation-audit.md`. The canvas panel reads the same parameter rather than being * handed the id. */ type Row = { id: number; title: string; updatedAt: string }; export const DesignsPanel = () => { const client = useClient(); const clientRef = useRef(client); clientRef.current = client; const [rows, setRows] = useState(null); const [error, setError] = useState(null); const [params, setParams] = useSearchParams(); const selected = params.get("doc"); const load = useCallback(async () => { try { setRows(await clientRef.current.get("/m3e-canvas/documents")); setError(null); } catch { setError("Could not load designs."); setRows(null); } }, []); useEffect(() => { void load(); }, [load]); // The canvas creates a row on its first save, so this only has to clear the selection — a design // with nothing drawn in it should not exist, and creating one here would leave empties behind // every time somebody clicked New and changed their mind. const startNew = () => setParams((p) => { p.delete("doc"); return p; }, { replace: true }); const remove = async (id: number, title: string) => { if (!confirm(`Delete "${title}"? This cannot be undone.`)) return; try { await clientRef.current.delete(`/m3e-canvas/documents/${id}`); if (selected === String(id)) startNew(); await load(); } catch { setError("Could not delete that design."); } }; return (
{error ?

{error}

: null} {rows === null ? ( Loading… ) : rows.length === 0 ? ( No designs yet. Draw something and it saves itself. ) : (
    {rows.map((row) => (
  • ))}
)}
); }; const Centred = ({ children }: { children: React.ReactNode }) => (
{children}
);