From 1b559dd2c6c7fed70ed478b1e80d1f22191b3f8f Mon Sep 17 00:00:00 2001 From: bes-r <27369668+bes-r@users.noreply.github.com> Date: Fri, 19 Jun 2026 23:45:06 +0200 Subject: [PATCH] printopties-dialog: bereik, indeling, kleur, details, papierformaat & orientatie --- ROADMAP.md | 6 +++ frontend/src/pages.jsx | 98 ++++++++++++++++++++++++++++++++++++++--- frontend/src/styles.css | 23 +++++++++- 3 files changed, 119 insertions(+), 8 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index 45e9f81..6aa9ca6 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -40,6 +40,12 @@ volgt. ## Fase 6 — Weergave & beheer +- [x] **Printopties-dialog** (🖨 in Rooster/Roostermaker): kies wát (huidige + selectie / alle klassen) en hóé je afdrukt — indeling (kolommen / dagen + onder elkaar), vakken in kleur, begeleiding/lokaal tonen, optionele + koptekst — plus **papierformaat** (A4/A3/A5/Letter) en oriëntatie + (liggend/staand). Toegepast via body-classes + dynamische `@page`. + - [x] **Vakkleur als vlak** (toggle 🎨, onthouden per browser): vak volledig in de activiteitskleur i.p.v. een streepje, met automatisch leesbare tekstkleur (zwart/wit op basis van helderheid). Werkt in Rooster/Roostermaker en diff --git a/frontend/src/pages.jsx b/frontend/src/pages.jsx index 019db4a..b57d748 100644 --- a/frontend/src/pages.jsx +++ b/frontend/src/pages.jsx @@ -2072,6 +2072,12 @@ export function RoosterScherm({ mode }) { const setWeergave = (v) => { setWeergaveState(v); try { localStorage.setItem("rw_weergave", v); } catch { /* niet beschikbaar */ } }; const [vakkleurVlak, setVakkleurState] = useState(() => { try { return localStorage.getItem("rw_vakkleur") === "vlak"; } catch { return false; } }); const setVakkleur = (v) => { setVakkleurState(v); try { localStorage.setItem("rw_vakkleur", v ? "vlak" : "streep"); } catch { /* niet beschikbaar */ } }; + // Printopties + const [printOpen, setPrintOpen] = useState(false); + const [printPending, setPrintPending] = useState(false); + const [printAllesActief, setPrintAllesActief] = useState(false); + const [printKop, setPrintKop] = useState(""); + const [printOpts, setPrintOpts] = useState({ bereik: "huidig", indeling: "kolom", kleur: false, begeleiding: true, lokaal: true, papier: "A4", orientatie: "landscape" }); useEffect(() => { listResource("schooljaren").then((j) => { setSchooljaren(j); if (j.length) setSchooljaar((s) => s || String(j[0].id)); }).catch((e) => setError(e.message)); @@ -2096,7 +2102,9 @@ export function RoosterScherm({ mode }) { // Scope-context + gefilterde blokken (voor weergave/afdrukken). const scopeCtx = { leerlingen, subgroepen, leerpleinen }; const scope = { type: scopeType, id: scopeId ? Number(scopeId) : "" }; - const zichtbareBlokken = blokken.filter((b) => blokInScope(b, scope, scopeCtx)); + // Bij printen "alle klassen" tijdelijk de scope negeren. + const effScope = printAllesActief ? { type: "alles", id: "" } : scope; + const zichtbareBlokken = blokken.filter((b) => blokInScope(b, effScope, scopeCtx)); // Conflicten over álle blokken (niet alleen de zichtbare scope), zodat de // melding compleet is en de betrokken blokken in het rooster omlijnd worden. const conflictInfo = berekenRoosterConflicten(blokken, scopeCtx, tijdsloten); @@ -2194,6 +2202,34 @@ export function RoosterScherm({ mode }) { setBewerkBlok(null); setToonForm(true); } + // Print: pas de gekozen opties toe via body-classes + @page, dan afdrukken. + function zetPaginaStijl(papier, orientatie) { + let el = document.getElementById("rw-print-page"); + if (!el) { el = document.createElement("style"); el.id = "rw-print-page"; document.head.appendChild(el); } + el.textContent = `@page { size: ${papier} ${orientatie}; margin: 10mm; }`; + } + function startPrint() { + const b = document.body.classList; + b.toggle("print-lijst", printOpts.indeling === "lijst"); + b.toggle("print-kolom", printOpts.indeling === "kolom"); + b.toggle("print-kleur", !!printOpts.kleur); + b.toggle("print-geen-begeleiding", !printOpts.begeleiding); + b.toggle("print-geen-lokaal", !printOpts.lokaal); + zetPaginaStijl(printOpts.papier, printOpts.orientatie); + setPrintKop(printOpts.kop || ""); + if (printOpts.bereik === "alles") setPrintAllesActief(true); + setPrintOpen(false); + setPrintPending(true); + } + useEffect(() => { + if (!printPending) return; + const id = setTimeout(() => { + window.print(); + setPrintPending(false); + setPrintAllesActief(false); + }, 120); + return () => clearTimeout(id); + }, [printPending]); // Direct vanuit een tijdvak in het rooster een vak toevoegen: tijdslot vast, // en het doel alvast op de actieve scope (klas/leerling) zetten. function openNieuwBlokVoorSlot(tijdslotId) { @@ -2338,7 +2374,7 @@ export function RoosterScherm({ mode }) {
{edit @@ -2501,7 +2538,7 @@ export function RoosterScherm({ mode }) {