Page Review · Multi-agent

Rapportage-flow (admin)

Geconsolideerde review van de drie samenhangende admin-rapportageschermen van het klant-dashboard: overzicht, editor en uren-werkblad. 24 agents, vier rollen, drie views.

8 juni 2026 3 views · 0 mislukt 24 agents Rollen: UX/a11y · Frontend/perf · Content · Functioneel Intern product (geen klant-context) ✓ Alle bevindingen opgelost · PR #48 gemerged
Status: opgelost. Alle bevindingen uit deze review zijn weggewerkt in PR #48 (gemerged 8 juni 2026, 328/328 tests groen). Onderstaand rapport blijft staan als verslag van de uitgangssituatie. Per fix:
  • Toegankelijke <Modal> (native dialog, focus-trap + Escape) → publiceer-modal + window.prompt vervangen
  • Data-bug hardgecodeerde datum 2026-05-15 → afgeleid uit de rapportagemaand
  • Responsive werkblad (sidebar stapelt onder breakpoint), uren-pattern verankerd, status-badge, breadcrumb met klantnaam, a11y-headings + aria-live, loading/error-boundaries, viewport-meta, robots noindex, CLS-reservering
  • Valse blocker "leeg op mobiel" geschrapt na verificatie met verse ingelogde screenshots

Scores per view

Hoe dieper de flow in, hoe lager (uitgangssituatie)

Rapportage-overzicht

6,0/10

Rapportage-editor

5,5/10

Uren-werkblad

5,0/10

Executive summary

Fundament staat, afwerking niet

De drie views vormen samen de admin-rapportageflow voor één klant (De Waal): de rapportagelijst, een specifieke maandrapportage, en het onderliggende uren-werkblad. De set is functioneel maar nog niet productierijp. Scores dalen consistent naarmate je dieper de flow ingaat (6,0 → 5,5 → 5,0), wat erop wijst dat de meer interactie-zware schermen (editor, werkblad) de meeste schuld dragen op toegankelijkheid en robuustheid.

De rode draad: het fundament (navigatie, semantiek, happy-path-rendering, schone DOM, geen console-errors) staat, maar de set faalt structureel op drie assen die WCAG-conformiteit en mobiel gebruik blokkeren: (1) toegankelijkheid van interactieve elementen (focus-traps, labels, screen-reader-feedback), (2) mobiele weergave, en (3) het gebruik van native browser-dialogen (window.prompt) voor destructieve acties.

Geen enkele view is "af". Bruikbaar voor een interne pilot, niet leverbaar als de klant of een toetsende partij meekijkt. De grootste hefboom zit in gedeelde componenten (dialoog-primitive, breadcrumb, formulier-laag), niet in losse patches.

Let op bij het lezen: de inhoudelijke bevindingen komen uit de code-review-agents, mét file:line-bewijs — die zijn betrouwbaar. De visuele screenshot-laag van de oorspronkelijke run was ongeldig (agent was niet ingelogd, legde het login-scherm vast tegen een e-commerce-checklist). De screenshots hieronder zijn achteraf opnieuw gemaakt met een ingelogde sessie en tonen de echte schermen. Eén oorspronkelijke "bevinding" bleek daardoor vals: zie hieronder.
Gecorrigeerd na verse screenshots: de oorspronkelijke run meldde "rapportage-overzicht rendert volledig leeg op mobiel" als blocker. Dat was een artefact van de login-screenshot — het overzicht rendert op 390px prima (hamburger-menu, formulier, lijst). Deze bevinding is geschrapt. De mobiele bevinding op het werkblad (vaste 256px-sidebar) blijft wél staan: die komt uit de CSS-code, niet uit een screenshot.

Prioriteiten

Wat eerst, set-breed

  1. Responsive werkblad fixenHet werkblad heeft een vaste 256px-sidebar zonder media-query, onbruikbaar onder ~700px. Een breakpoint die sidebar en main stapelt. (Het overzicht rendert op mobiel wél correct — de oorspronkelijke "leeg op mobiel"-blocker was een screenshot-artefact en is geschrapt.)
  2. Eén gedeelde dialoog-primitive met focus-trap + focus-teruggaveVervangt window.prompt() (editor + werkblad "Uitsluiten") én repareert de publiceer-modal en bevestigingsdialoog zonder focus-management (WCAG 2.4.3 / 2.1.2). Hoogste hefboom: één component, meerdere plekken beter.
  3. Formulier-toegankelijkheid set-breed<label> op alle inputs (Omschrijving/Reden), uren-pattern verankeren (^…$) met inline foutfeedback i.p.v. een server-roundtrip. Eén formulier-hygiene-pass over alle views.
  4. Hardgecodeerde datum fixen (data-bug)De handmatige werkblad-regel krijgt standaard 2026-05-15 mee — buiten de rapportageperiode. Afleiden uit reportLabel. Stille data-correctheidsbug.
  5. Breadcrumb consoliderenKlantnaam altijd in het pad (verdwijnt nu op de editor), maand-formattering consistent ("juni" vs "jun"). Eén gedeelde breadcrumb-component.
  6. A11y-afrondingaria-live voor pending-states, sectiekoppen als headings i.p.v. <p>, skip-link, loading.tsx/error.tsx boundaries, robots: noindex op admin, viewport-meta in root layout.

Cross-view consistentie

Breadcrumb loopt uiteen

Wat overal identiek hoort te zijn (je zit binnen dezelfde klantcontext), is het niet:

ViewBreadcrumb nuProbleem
OverzichtKlanten / De Waal / RapportagesReferentie
EditorKlanten / Rapportages / juni 2026Klantnaam "De Waal" verdwenen uit het pad
WerkbladKlanten / De Waal / Rapportages / jun 2026Maand afgekort ("jun" i.p.v. "juni"), inconsistent met editor

View ① · webapp (admin)

Rapportage-overzicht

UX/a11y 6 · Frontend/perf 6

/admin/clients/[id]/rapportages — maand/jaar-formulier ("concept openen of aanmaken") + lijst bestaande rapportages.

Top correctness-issues

ErnstIssueAanbeveling
HoogGeen error.tsx boundary op de rapportages-route — bij een falende query crasht de pagina naar de generieke Next-foutpagina.Client error.tsx met statusText + "Probeer opnieuw". Ook voor [reportId].
Hoog?fout=maand redirect levert geen inline-fout (WCAG 3.3.1) — gebruiker wordt stil teruggestuurd.Searchparam uitlezen, foutbanner/Field-error tonen.
HoogGeen skip-link naar hoofdinhoud in de AppShell (WCAG 2.4.1).Visually-hidden skip-link als eerste element, focus naar #main-content.
MidAdmin-routes missen robots: noindex — bij publieke bereikbaarheid indexeerbaar.export const metadata = { robots: { index:false } } in (authed)/layout.tsx.
MidGeen loading.tsx-fallback; statuslabels zijn rauwe DB-waarden zonder badge.Skeleton-loading + status naar badge met statuskleur + aria-label.

Screenshots vers · ingelogd

Overzicht desktop 1440px
Desktop 1440px
Overzicht mobiel 390px
Mobiel 390px — rendert correct

View ② · webapp (admin)

Rapportage-editor

UX/a11y 5 · Frontend/perf 6

/admin/clients/[id]/rapportages/[reportId] — metrics, uren-velden, narrative, opslaan/publiceren.

Top correctness-issues

ErnstIssueAanbeveling
KritiekPubliceren-modal zonder focus-trap (WCAG 2.4.3 / 2.1.2) — toetsenbordgebruikers tabben achter de backdrop.Focus-trap bij mount, restore bij sluiten; inert op de rest.
Hoogwindow.prompt() voor destructieve "Uitsluiten" — niet toegankelijk, niet stylebaar (WCAG 3.3.4).Inline mini-modal met gelabeld veld + Bevestigen/Annuleren.
HoogInputs "Omschrijving"/"Reden" zonder <label>, alleen placeholder (WCAG 1.3.1).aria-label of bestaand <Field>-component hergebruiken.
HoogUren-pattern niet verankerd: \d+(\.\d{1,2})? accepteert 12abc in browser, faalt server-side.pattern="^\d+(\.\d{1,2})?$" + required op beide inputs.
HoogViewport-meta ontbreekt in root layout — geen correcte mobiele schaling.export const viewport = { width:'device-width', initialScale:1 }.

Screenshots vers · ingelogd

Editor desktop 1440px
Desktop 1440px
Editor mobiel 390px
Mobiel 390px

View ③ · webapp (admin)

Uren-werkblad

UX/a11y 5 · Frontend/perf 5

/admin/clients/[id]/rapportages/[reportId]/werkblad — freeze, regels, type-toggles, handmatige regels, budget, publiceer-modal. Het rijkste scherm van de set.

Top correctness-issues

ErnstIssueAanbeveling
KritiekGeen responsive layout: vaste 256px-sidebar zonder media-query, onbruikbaar onder ~700px.@media (max-width:720px) → sidebar/main stapelen, width:100%.
Kritiekwindow.prompt() voor uitsluitingsreden — niet toegankelijk, blokkeert event loop, faalt in WebView.Inline-form of bestaande ConfirmProvider/confirm-dialog.
HoogHardgecodeerde datum 2026-05-15 in ManualForm — handmatige regel buiten de rapportageperiode. Data-bug.Afleiden uit reportLabel: ${y}-${m}-01.
HoogPubliceer-dialoog mist focus-trap, Escape sluit niet, focus keert niet terug (WCAG 2.1.2).Bestaand confirm-dialog.tsx-systeem hergebruiken.
HoogSidebar-sectiekoppen zijn <p>; geen aria-live voor pending-states.Koppen naar <h2>/<h3> + aria-live="polite"-regio.

Screenshots vers · ingelogd

Werkblad desktop 1440px
Desktop 1440px
Werkblad mobiel 390px
Mobiel 390px — vaste sidebar breekt hier

Proces-notitie

Wat de volgende run beter moet doen

De code-review-laag was sterk (echte issues met file:line-bewijs), maar twee dingen liepen mis en horen in de workflow gefixt te worden voordat dit een herhaalbaar instrument is: