Roostermaker: rol begeleider zichtbaar (LK/PO/KO) en sneltoetsen (N/pijltjes/T/Esc)
This commit is contained in:
parent
e1ada6d702
commit
5adddb03c1
3 changed files with 32 additions and 7 deletions
|
|
@ -15,10 +15,10 @@ volgt.
|
||||||
- [x] Vanuit de Roostermaker (tab **Indeling**) direct **subgroepen aanmaken**
|
- [x] Vanuit de Roostermaker (tab **Indeling**) direct **subgroepen aanmaken**
|
||||||
onder een hoofdgroep, met verantwoordelijke(n) — kolomsgewijs overzicht
|
onder een hoofdgroep, met verantwoordelijke(n) — kolomsgewijs overzicht
|
||||||
van subgroepen, vakken en wie verantwoordelijk is.
|
van subgroepen, vakken en wie verantwoordelijk is.
|
||||||
- [ ] **Sneltoetsen** voor veelgebruikte acties (bv. nieuw blok, kopiëren,
|
- [x] **Sneltoetsen** in de Roostermaker: N (nieuw blok), ←/→ (week terug/vooruit),
|
||||||
verwijderen, week vooruit/terug, opslaan).
|
T (deze week), Esc (paneel/sluiten); met hint.
|
||||||
- [ ] **Rol van een begeleider beter zichtbaar** in de roostermaker (bv. functie/
|
- [x] **Rol van een begeleider zichtbaar** in de Roostermaker: afkorting (LK/PO/KO)
|
||||||
rol tonen bij de begeleider in een blok en bij het toewijzen).
|
bij de begeleider in een blok en de volledige rol bij het toewijzen.
|
||||||
- [ ] **Vereenvoudigd vak/blok toevoegen** — bijvoorbeeld een **stap-voor-stap
|
- [ ] **Vereenvoudigd vak/blok toevoegen** — bijvoorbeeld een **stap-voor-stap
|
||||||
wizard** die meeschuift (activiteit → doelgroep → personeel → tijd), in
|
wizard** die meeschuift (activiteit → doelgroep → personeel → tijd), in
|
||||||
plaats van één groot formulier.
|
plaats van één groot formulier.
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,9 @@ const ROLLEN = [
|
||||||
{ value: "klassenondersteuner", label: "Klassenondersteuner" },
|
{ value: "klassenondersteuner", label: "Klassenondersteuner" },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Korte aanduiding van een medewerkersrol (compact in de roostervakjes).
|
||||||
|
const ROL_AFK = { leerkracht: "LK", praktijkondersteuner: "PO", klassenondersteuner: "KO" };
|
||||||
|
|
||||||
const WEEKDAGEN = [
|
const WEEKDAGEN = [
|
||||||
{ value: 0, label: "Maandag" },
|
{ value: 0, label: "Maandag" },
|
||||||
{ value: 1, label: "Dinsdag" },
|
{ value: 1, label: "Dinsdag" },
|
||||||
|
|
@ -1315,7 +1318,7 @@ function BlokBewerker({ blok, ctx, onSluit, onKlaar }) {
|
||||||
<div className="leden-keuze">
|
<div className="leden-keuze">
|
||||||
<div className="muted small">Begeleiders:</div>
|
<div className="muted small">Begeleiders:</div>
|
||||||
<div className="chips">
|
<div className="chips">
|
||||||
{medewerkers.map((m) => <button type="button" key={m.id} className={f.begeleiders.includes(m.id) ? "chip on" : "chip"} onClick={() => toggleBeg(m.id)}>{m.volledige_naam}</button>)}
|
{medewerkers.map((m) => <button type="button" key={m.id} className={f.begeleiders.includes(m.id) ? "chip on" : "chip"} onClick={() => toggleBeg(m.id)}>{m.volledige_naam}{m.rol_label ? ` · ${m.rol_label}` : ""}</button>)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="form-row"><input placeholder="Opmerking" value={f.opmerkingen} onChange={(e) => setF({ ...f, opmerkingen: e.target.value })} /></div>
|
<div className="form-row"><input placeholder="Opmerking" value={f.opmerkingen} onChange={(e) => setF({ ...f, opmerkingen: e.target.value })} /></div>
|
||||||
|
|
@ -1540,6 +1543,23 @@ export function RoosterScherm({ mode }) {
|
||||||
return () => { window.removeEventListener("pointermove", move); window.removeEventListener("pointerup", up); };
|
return () => { window.removeEventListener("pointermove", move); window.removeEventListener("pointerup", up); };
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// Sneltoetsen (alleen in de Roostermaker).
|
||||||
|
useEffect(() => {
|
||||||
|
if (!edit) return;
|
||||||
|
function onKey(e) {
|
||||||
|
const t = e.target;
|
||||||
|
const typing = t && (t.tagName === "INPUT" || t.tagName === "SELECT" || t.tagName === "TEXTAREA" || t.isContentEditable);
|
||||||
|
if (e.key === "Escape") { setBewerkBlok(null); setToonForm(false); return; }
|
||||||
|
if (typing) return;
|
||||||
|
if (e.key === "n" || e.key === "N") { setTab("week"); setToonForm((v) => !v); }
|
||||||
|
else if (e.key === "ArrowLeft") { setMaandag((m) => plusDagen(m, -7)); }
|
||||||
|
else if (e.key === "ArrowRight") { setMaandag((m) => plusDagen(m, 7)); }
|
||||||
|
else if (e.key === "t" || e.key === "T") { setMaandag(maandagVan(new Date())); }
|
||||||
|
}
|
||||||
|
window.addEventListener("keydown", onKey);
|
||||||
|
return () => window.removeEventListener("keydown", onKey);
|
||||||
|
}, [edit]);
|
||||||
|
|
||||||
function startDrag(e, blok) {
|
function startDrag(e, blok) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
dragRef.current = blok;
|
dragRef.current = blok;
|
||||||
|
|
@ -1581,6 +1601,7 @@ export function RoosterScherm({ mode }) {
|
||||||
const uitzOp = (blokId, iso) => uitzonderingen.find((u) => u.roosterblok === blokId && u.datum === iso);
|
const uitzOp = (blokId, iso) => uitzonderingen.find((u) => u.roosterblok === blokId && u.datum === iso);
|
||||||
// Op id vergelijken, niet op naam: twee personen kunnen dezelfde naam hebben.
|
// Op id vergelijken, niet op naam: twee personen kunnen dezelfde naam hebben.
|
||||||
const persoonAfwezig = (id, iso) => afwezig.some((a) => a.persoon === id && a.start_datum <= iso && a.eind_datum >= iso);
|
const persoonAfwezig = (id, iso) => afwezig.some((a) => a.persoon === id && a.start_datum <= iso && a.eind_datum >= iso);
|
||||||
|
const rolAfk = (id) => { const m = medewerkers.find((x) => x.id === id); return m ? (ROL_AFK[m.rol] || "") : ""; };
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="rooster-scherm">
|
<section className="rooster-scherm">
|
||||||
|
|
@ -1642,6 +1663,9 @@ export function RoosterScherm({ mode }) {
|
||||||
<button className={tab === "instellingen" ? "tab on" : "tab"} onClick={() => setTab("instellingen")}>Instellingen</button>
|
<button className={tab === "instellingen" ? "tab on" : "tab"} onClick={() => setTab("instellingen")}>Instellingen</button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{edit && tab === "week" && (
|
||||||
|
<p className="muted small no-print sneltoets-hint">Sneltoetsen: <b>N</b> nieuw blok · <b>←</b>/<b>→</b> week · <b>T</b> deze week · <b>Esc</b> sluiten</p>
|
||||||
|
)}
|
||||||
|
|
||||||
{edit && schooljaar && tab === "week" && toonForm && (
|
{edit && schooljaar && tab === "week" && toonForm && (
|
||||||
<form className="form-card no-print" onSubmit={opslaan}>
|
<form className="form-card no-print" onSubmit={opslaan}>
|
||||||
|
|
@ -1673,7 +1697,7 @@ export function RoosterScherm({ mode }) {
|
||||||
<div className="leden-keuze">
|
<div className="leden-keuze">
|
||||||
<div className="muted small">Begeleiders:</div>
|
<div className="muted small">Begeleiders:</div>
|
||||||
<div className="chips">
|
<div className="chips">
|
||||||
{medewerkers.map((m) => <button type="button" key={m.id} className={form.begeleiders.includes(m.id) ? "chip on" : "chip"} onClick={() => toggleBegeleider(m.id)}>{m.volledige_naam}</button>)}
|
{medewerkers.map((m) => <button type="button" key={m.id} className={form.begeleiders.includes(m.id) ? "chip on" : "chip"} onClick={() => toggleBegeleider(m.id)}>{m.volledige_naam}{m.rol_label ? ` · ${m.rol_label}` : ""}</button>)}
|
||||||
{medewerkers.length === 0 && <span className="muted small">Nog geen medewerkers.</span>}
|
{medewerkers.length === 0 && <span className="muted small">Nog geen medewerkers.</span>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -1731,7 +1755,7 @@ export function RoosterScherm({ mode }) {
|
||||||
{b.locatie_naam && <div className="small">📍 {b.locatie_naam}</div>}
|
{b.locatie_naam && <div className="small">📍 {b.locatie_naam}</div>}
|
||||||
{b.begeleiders_namen.length > 0 && (
|
{b.begeleiders_namen.length > 0 && (
|
||||||
<div className="small muted">👤 {b.begeleiders_namen.map((x, idx) => (
|
<div className="small muted">👤 {b.begeleiders_namen.map((x, idx) => (
|
||||||
<span key={x.id} className={persoonAfwezig(x.id, iso) ? "afwezig" : ""}>{idx > 0 ? ", " : ""}{x.naam}</span>
|
<span key={x.id} className={persoonAfwezig(x.id, iso) ? "afwezig" : ""}>{idx > 0 ? ", " : ""}{x.naam}{rolAfk(x.id) ? ` (${rolAfk(x.id)})` : ""}</span>
|
||||||
))}</div>
|
))}</div>
|
||||||
)}
|
)}
|
||||||
{kal && <div className="small rb-status">Vervalt — {kal.type_label}</div>}
|
{kal && <div className="small rb-status">Vervalt — {kal.type_label}</div>}
|
||||||
|
|
|
||||||
|
|
@ -148,6 +148,7 @@ input[type="color"] { padding: 2px; width: 44px; min-width: 44px; height: 38px;
|
||||||
.drag-ghost { position: fixed; z-index: 1000; pointer-events: none; background: var(--brand); color: #fff; padding: 6px 12px; border-radius: 8px; font-size: 13px; font-weight: 600; box-shadow: 0 6px 18px rgba(0,0,0,.25); }
|
.drag-ghost { position: fixed; z-index: 1000; pointer-events: none; background: var(--brand); color: #fff; padding: 6px 12px; border-radius: 8px; font-size: 13px; font-weight: 600; box-shadow: 0 6px 18px rgba(0,0,0,.25); }
|
||||||
|
|
||||||
.dag-actie { display: block; margin-top: 4px; font-size: 11px; }
|
.dag-actie { display: block; margin-top: 4px; font-size: 11px; }
|
||||||
|
.sneltoets-hint { margin: -4px 0 12px; }
|
||||||
|
|
||||||
/* --- Groepsindeling --- */
|
/* --- Groepsindeling --- */
|
||||||
.indeling { margin-top: 12px; }
|
.indeling { margin-top: 12px; }
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue