refactor: ui/dashboard becomes ui/overzicht-secties (RD-36)

RD-03 moved the dashboard page to overzicht/ui/overzicht.page.ts and left four
sections in registratie/ui/dashboard/. The folder was named after a page that
lives in another context. A reader who opened it found four sections that are
not the dashboard.

The folder is now overzicht-secties/ — registratie's sections for the overzicht
page. The alias does not change, because the sections stay in the registratie
context. The story titles do not change, because they name the context.

Five documents cited registratie/ui/dashboard.page.ts, a file that RD-03
renamed. They now name overzicht.page.ts, or the section that owns the
behaviour they describe.

The /dashboard route keeps its path. It is a user-visible URL.

npm run ci --full passes: 67 and 45 storybook suites, 306 axe tests.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
eho
2026-09-09 16:21:15 +02:00
co-authored by Claude Opus 5
parent d9aef9541f
commit 44dcc69811
15 changed files with 127 additions and 13 deletions
+1 -1
View File
@@ -62,7 +62,7 @@ Work through that checklist, keeping the GREEN gate below passing at every step.
re-target it at an arbitrary new context, so it's deleted alongside `registratie`, along
with its three wiring lines in `shell.component.ts` (import, `imports:` entry, template tag).
- The `dashboard` route is **not** deleted even though it currently imports
`@registratie/ui/dashboard.page` — too much else hardcodes `/dashboard` (login's post-auth
`@overzicht/ui/overzicht.page` — too much else hardcodes `/dashboard` (login's post-auth
redirect, `authGuard`'s fallback, header nav/logo, breadcrumb trail, several stories/specs).
The script rewrites its `loadComponent` to point at the freshly scaffolded `--context` page
instead (a `TODO(create-frontend)` stopgap landing page, not a real overview).
@@ -1,15 +1,15 @@
import { Component } from '@angular/core';
import { PageShellComponent } from '@shared/layout/page-shell/page-shell.component';
import { MijnAanvragenSection } from '@registratie/ui/dashboard/mijn-aanvragen.section';
import { WatMoetIkRegelenSection } from '@registratie/ui/dashboard/wat-moet-ik-regelen.section';
import { MijnRegistratieSection } from '@registratie/ui/dashboard/mijn-registratie.section';
import { SpecialismenSection } from '@registratie/ui/dashboard/specialismen.section';
import { MijnAanvragenSection } from '@registratie/ui/overzicht-secties/mijn-aanvragen.section';
import { WatMoetIkRegelenSection } from '@registratie/ui/overzicht-secties/wat-moet-ik-regelen.section';
import { MijnRegistratieSection } from '@registratie/ui/overzicht-secties/mijn-registratie.section';
import { SpecialismenSection } from '@registratie/ui/overzicht-secties/specialismen.section';
import { WatWiltUDoenSection } from './wat-wilt-u-doen.section';
import { BeheerLinksSection } from './beheer-links.section';
/** Page: "Mijn overzicht" — the portal home, following the NL Design System "Mijn
omgeving" pattern. Composition only: each section below answers its own data
question (own store, own async state) — four sections stay in `registratie/ui/dashboard/`
question (own store, own async state) — four sections stay in `registratie/ui/overzicht-secties/`
(they render registratie data), two live here (cross-context navigation). */
@Component({
selector: 'app-overzicht-page',
@@ -0,0 +1,114 @@
# RD-36 — `ui/dashboard/` becomes `ui/overzicht-secties/`
Status: done
Phase: 5 — fix the docs that describe this flow
## Why
RD-03 moved the dashboard page to `overzicht/ui/overzicht.page.ts` and left four data sections
in `registratie/ui/dashboard/`. The folder is now named after a page that lives somewhere else.
A reader who opens `registratie/ui/dashboard/` finds four sections that are not the dashboard,
and the page it is named for is in another context.
RD-04 recorded the name as stale and left it. This ticket fixes it.
## Read first
- `docs/project/readable-codebase/PLAN.md:267-282` — the decision and its measured cost.
- `apps/ssp/src/app/overzicht/ui/overzicht.page.ts` — the only importer.
## Decisions (pre-made, do not relitigate)
1. **The new name is `overzicht-secties/`.** It says what the four files are: registratie's
sections for the overzicht page. It keeps the Dutch that CLAUDE.md requires of a domain
context.
2. **Flattening into `registratie/ui/` is rejected.** That directory holds one folder per
component. Eight loose files would break its shape.
3. **The alias does not change.** The four sections stay in the `registratie` context, so the
imports stay `@registratie/ui/…`. Only the folder segment changes.
4. **Story titles do not change.** They are `Domein/Registratie/<Name>`, which is a context
name, not a folder name. Both Storybook globs are recursive, so no config changes.
5. **Fold in the two stale `dashboard.page` paths named in PLAN.** `docs/reference/feature-flags.md:55`
and `.claude/skills/new-ssp/SKILL.md:65` both cite `registratie/ui/dashboard.page`, a file
that no longer exists. The flag logic they describe lives in
`apps/ssp/src/app/overzicht/ui/wat-wilt-u-doen.section.ts` now.
6. **Fix the other live citations of the deleted file too.** Same defect, same commit:
`docs/reference/architecture/ARCHITECTURE.md:55` (the pages node in the Mermaid diagram) and
`:79` (the `ui/` row of the layer table), and `libs/shared/docs/remote-data.mdx:64`. Each
names `dashboard.page.ts` as a live example. The current name is `overzicht.page.ts`.
7. **Leave `docs/project/archive/` and the shipped RD ticket records alone.** They describe the
tree as it was when they ran. A historical record that cites a path from its own time is
correct, not stale.
## Files
The move — 8 files, `git mv` the directory:
`apps/ssp/src/app/registratie/ui/dashboard/``apps/ssp/src/app/registratie/ui/overzicht-secties/`
```
mijn-aanvragen.section.ts mijn-aanvragen.section.stories.ts
mijn-registratie.section.ts mijn-registratie.section.stories.ts
specialismen.section.ts specialismen.section.stories.ts
wat-moet-ik-regelen.section.ts wat-moet-ik-regelen.section.stories.ts
```
The importer — one file, four import lines plus one comment:
- `apps/ssp/src/app/overzicht/ui/overzicht.page.ts:3-6`, and the comment at line 12 that says
"four sections stay in `registratie/ui/dashboard/`".
**RD-31 added two more.** Its rewrite of `ARCHITECTURE.md` §6a links the read walkthrough to
`registratie/ui/dashboard/mijn-registratie.section.ts` and
`registratie/ui/dashboard/wat-moet-ik-regelen.section.ts` by full path. Both move here. Fix
them, or §6a's links break the day this ticket lands.
The five doc citations: `docs/reference/feature-flags.md:55`,
`.claude/skills/new-ssp/SKILL.md:65`, `docs/reference/architecture/ARCHITECTURE.md:55` and `:79`,
`libs/shared/docs/remote-data.mdx:64`.
## Steps
1. `git mv` the directory.
2. Fix the four imports and the comment in `overzicht.page.ts`.
3. Fix the five doc citations per decisions 5 and 6.
4. `npm run ci --full`.
## Acceptance criteria
- [x] `apps/ssp/src/app/registratie/ui/dashboard/` no longer exists.
- [x] `grep -rn "ui/dashboard" apps libs docs/reference libs/shared/docs .claude` returns
nothing outside the `.xlf` extraction metadata named in Out of scope.
- [x] No live document cites `dashboard.page`. Historical records under
`docs/project/archive/` and the shipped `RD-*.md` files are exempt.
- [x] `git diff --stat -M` shows renames plus small edits, no rewritten files.
- [x] `npm run ci --full` is green.
## Verification
1. `npm run ci --full`. The four story files move, and only `build-storybook` proves that both
Storybook globs still pick them up.
2. `npm run storybook` — the four `Domein/Registratie/…` stories are still in the sidebar under
the same titles.
3. `npm start`, open `http://localhost:4200/dashboard`. All six sections render.
## Out of scope
- The `<context context-type="sourcefile">` metadata in `apps/*/src/locale/messages*.xlf`.
It still names `src/app/registratie/ui/dashboard.page.ts`, which RD-03 renamed. That
metadata comes from `ng extract-i18n` and no build reads it, so it is stale extraction
output from before RD-03, not a citation this ticket created. Regenerating it is its own
job.
- Renaming the `/dashboard` **route** to `/overzicht`. `PLAN.md` puts it under "Deliberately
out of scope": it needs a redirect and it is user-visible.
- Moving the four sections into the `overzicht` context. They read `BigProfileStore` and belong
to `registratie`; `overzicht` composes them. That is RD-03's decision and it stands.
## Risks
1. **A missed specifier fails the typecheck, not the build.** Run `npm run ci --full`, which
typechecks all four tsconfigs.
2. **`git mv` of a directory, then edits, can look like deletes and adds.** Commit the rename
and the edits together and check `git diff --stat -M` before you push.
3. **The route stays `/dashboard`.** Do not "tidy" it while renaming the folder. The folder name
and the URL are separate decisions, and only one of them is in this ticket.
+1 -1
View File
@@ -130,7 +130,7 @@ two. Note that RD-15 exists because 22 abandoned agent worktrees are still on di
| RD-33 | CLAUDE.md + `atomic-design.mdx` + the `ui-component` skill | 03, 27, 29 | yes | done |
| RD-34 | _(optional)_ `NO_SUBORGS`/`NO_TABLES` become `RemoteData.Empty` | 11 | | todo |
| RD-35 | _(optional, last, alone)_ upload `type:` discriminant to `tag:` | 27 | | todo |
| RD-36 | `ui/dashboard/``ui/overzicht-secties/` + 2 stale `dashboard.page` paths | 04 | yes | todo |
| RD-36 | `ui/dashboard/``ui/overzicht-secties/` + 2 stale `dashboard.page` paths | 04 | yes | done |
| RD-37 | **a11y:** 5 suppressions name a closed ticket — decide the `li[…]` host | 01 | yes | done |
| RD-38 | One member order for the 3 wizard containers + 2 pure extractions | 22, 23 | | done |
| RD-39 | **Bug:** the wizards' `seed` input never arrived (21 stories) | 38 | yes | done |
+4 -4
View File
@@ -52,7 +52,7 @@ ever uses the level(s) below it — so anything you build is reusable by everyth
```mermaid
graph TD
P["Pages<br>dashboard.page · login.page · intake.page"]
P["Pages<br>overzicht.page · login.page · intake.page"]
T["Templates<br>page-shell · shell"]
O["Organisms<br>login-form · registration-table · intake-wizard"]
M["Molecules<br>form-field · data-row · async"]
@@ -76,7 +76,7 @@ questions:
| `application/` | How do we coordinate a task / state? | Yes (signals) | `big-profile.store.ts` |
| `infrastructure/` | Where does data come from? | Yes (HTTP) | `big-register.adapter.ts`, `brp.adapter.ts` |
| `contracts/` | What's the FE⇄BE wire shape? | **No** (pure DTOs) | `dashboard-view.dto.ts` |
| `ui/` | How does it look? | Yes (components) | `dashboard.page.ts` |
| `ui/` | How does it look? | Yes (components) | `overzicht.page.ts` |
**The one rule that keeps it sane: dependencies only point _inward_.** UI may use
application, application may use domain, everyone (in either app) may use `libs/shared`
@@ -590,7 +590,7 @@ no longer hand-written DTOs — it's an **NSwag-generated typed client**
toggle) and `role.interceptor.ts` (`X-Role` on role-aware endpoints).
**A read (dashboard):** `<app-async [data]="store.profile()">` in
[`mijn-registratie.section.ts`](../../../apps/ssp/src/app/registratie/ui/dashboard/mijn-registratie.section.ts)
[`mijn-registratie.section.ts`](../../../apps/ssp/src/app/registratie/ui/overzicht-secties/mijn-registratie.section.ts)
(`MijnRegistratieSection`) →
[`BigProfileStore`](../../../apps/ssp/src/app/registratie/application/big-profile.store.ts) →
`DashboardViewAdapter.dashboardViewResource()` = `resource({ loader: () =>
@@ -598,7 +598,7 @@ client.dashboardView() })`
([`dashboard-view.adapter.ts`](../../../apps/ssp/src/app/registratie/infrastructure/dashboard-view.adapter.ts))
→ GET `/api/v1/dashboard-view``httpClientFetch` → proxy → backend → back through the
`parseDashboardView(json): Result` trust boundary → `RemoteData<DashboardView>` → rendered.
[`wat-moet-ik-regelen.section.ts`](../../../apps/ssp/src/app/registratie/ui/dashboard/wat-moet-ik-regelen.section.ts)
[`wat-moet-ik-regelen.section.ts`](../../../apps/ssp/src/app/registratie/ui/overzicht-secties/wat-moet-ik-regelen.section.ts)
reads the same store.
**A write (change address):** the `Submitting` effect (§2d) → `createSubmitChangeRequest`
+1 -1
View File
@@ -52,7 +52,7 @@ Each UI consumer injects `FeatureFlagStore`, imports the flag-key constant, and
its own gating predicate inline:
- `shared/layout/site-header/site-header.component.ts` — filters the "Inschrijven" nav item.
- `registratie/ui/dashboard.page.ts` — hides the "Inschrijven" dashboard action.
- `overzicht/ui/wat-wilt-u-doen.section.ts` — hides the "Inschrijven" dashboard action.
So a second flag with a second consumer **repeats the pattern by hand** — there's no shared
"gate this thing by flag" abstraction. That's fine at one flag / two consumers (a helper for
+1 -1
View File
@@ -61,7 +61,7 @@ even though they're nested in the same template. Angular types it `unknown`, and
`AsyncComponent`/`AsyncLoadedDirective` pair is properly generic internally, but that
genericity stops at the component's own boundary.
The idiom this repo uses instead — see `brief.page.ts`, `dashboard.page.ts`,
The idiom this repo uses instead — see `brief.page.ts`, `overzicht.page.ts`,
`registration-detail.page.ts` — is a small **typed `computed()`** that unwraps the
`Success` value, narrowed locally in the template with `@if (x(); as p)`: