# RD-04 — Story titles to `Domein//`, and the two missing stories Status: done Source: PLAN.md Phase 0 ("Also settle the two deviations the refactor left behind") ## Why CLAUDE.md decision 5 sets one title rule for a component in an app context's `ui/`: `Domein//` — "full stop, regardless of which atomic layer it is". The three dashboard-section stories break it. They read `Domein/Registratie/Dashboard/`, a fourth segment that invents a sidebar folder the rule does not have. All 66 other story files comply. RD-03 split the dashboard into two contexts but did not touch the stories. Three of the six sections still have no story at all. ## Read first - `apps/ssp/src/app/registratie/ui/dashboard/mijn-registratie.section.stories.ts` — the shape to copy: a `storeStub` returning only the members the template reads, one `applicationConfig` decorator per story, and `loading`/`success`/`failure` from `@shared/testing/remote-data`. - `apps/ssp/src/app/registratie/ui/dashboard/wat-moet-ik-regelen.section.ts` — needs a story. - `apps/ssp/src/app/overzicht/ui/wat-wilt-u-doen.section.ts` — needs a story. - `apps/ssp/src/app/registratie/domain/tasks.ts` — `tasksFromProfile`, which decides whether the task list renders full or empty. - CLAUDE.md decision 5, the paragraph starting "Story titles mirror the sidebar's". ## Decisions (pre-made, don't relitigate) 1. **Retitle the three existing stories. Drop the `Dashboard/` segment only.** | File | From | To | | ----------------------------------------------- | ----------------------------------------------- | ------------------------------------- | | `dashboard/mijn-aanvragen.section.stories.ts` | `Domein/Registratie/Dashboard/Mijn Aanvragen` | `Domein/Registratie/Mijn Aanvragen` | | `dashboard/mijn-registratie.section.stories.ts` | `Domein/Registratie/Dashboard/Mijn Registratie` | `Domein/Registratie/Mijn Registratie` | | `dashboard/specialismen.section.stories.ts` | `Domein/Registratie/Dashboard/Specialismen` | `Domein/Registratie/Specialismen` | The files stay where they are. RD-03 decision 3 keeps the four data sections in `registratie/ui/dashboard/`; the folder is not the title. 2. **Add exactly two story files, not three.** PLAN's rule is "add one only where the section has more than one visual state". - `wat-moet-ik-regelen.section.stories.ts`, titled `Domein/Registratie/Wat Moet Ik Regelen` — four states. - `wat-wilt-u-doen.section.stories.ts`, titled `Domein/Overzicht/Wat Wilt U Doen` — two states. This creates the `Domein/Overzicht/` sidebar bucket; it is the first story in that context. 3. **`beheer-links.section.ts` gets no story.** It has one visual state. Its other branch renders nothing at all — `@if (adminLinks().length)` wraps the whole template — and a story whose canvas is blank documents nothing and gives the a11y addon nothing to check. The capability filter it applies (`AccessStore.can`) is already covered where it can actually be asserted, in the application layer. Do not add the file. 4. **`wat-moet-ik-regelen` gets four stories**, from a stub with the four members its template and class read — `profile()`, `decisions()`, `pendingHerregistratie()`, `reloadProfile()`: | Story | `profile()` | `decisions()` | `pendingHerregistratie()` | Renders | | ----------------- | ------------ | ----------------------------------------------- | ------------------------- | ------------------------------ | | `Loading` | `loading()` | `loading()` | `false` | two skeleton bars | | `MetTaken` | `success(p)` | `success({ eligibleForHerregistratie: true })` | `false` | the task list, one task | | `NietsOpenstaand` | `success(p)` | `success({ eligibleForHerregistratie: false })` | `false` | the "niets openstaan" text | | `InBehandeling` | `success(p)` | `success({ eligibleForHerregistratie: false })` | `true` | the info alert above the above | `Failed` is deliberately absent — ``'s failure template is already exercised by `Mijn Registratie`'s `Failed` story, and this section adds nothing to it. 5. **The task count follows from `tasksFromProfile`, so pick the profile deliberately.** With `status.tag === 'Geregistreerd'`, the list is empty unless `eligibleForHerregistratie` is true. That is what separates `MetTaken` from `NietsOpenstaand` — the eligibility flag, not the profile. Reuse the `profile` fixture from `mijn-registratie.section.stories.ts` verbatim (copy it; do not export it from the other story file and import it — story files in this repo are self-contained). 6. **`wat-wilt-u-doen` gets two stories**, from a `FeatureFlagStore` stub whose only member is `enabled`: | Story | stub | Renders | | ------------------- | -------------------------- | -------------------------------- | | `InschrijvingOpen` | `{ enabled: () => true }` | six actions, "Inschrijven" first | | `InschrijvingDicht` | `{ enabled: () => false }` | five actions, no "Inschrijven" | 7. **`libs/beheer`'s title stays wrong here.** `Domein/Beheer/Stamdata Table Editor` is a different deviation with a different verdict (the doc changes, not the code). RD-28 owns it. Do not touch it. ## Files - `apps/ssp/src/app/registratie/ui/dashboard/mijn-aanvragen.section.stories.ts` (title only) - `apps/ssp/src/app/registratie/ui/dashboard/mijn-registratie.section.stories.ts` (title only) - `apps/ssp/src/app/registratie/ui/dashboard/specialismen.section.stories.ts` (title only) - `apps/ssp/src/app/registratie/ui/dashboard/wat-moet-ik-regelen.section.stories.ts` (new) - `apps/ssp/src/app/overzicht/ui/wat-wilt-u-doen.section.stories.ts` (new) ## Steps 1. Retitle the three files per decision 1. Nothing else in those files changes. 2. Write `wat-moet-ik-regelen.section.stories.ts` per decisions 4 and 5. 3. Write `wat-wilt-u-doen.section.stories.ts` per decision 6. 4. `git add` all five files, then run the acceptance commands. 5. Update this ticket's `Status:` to `done` and the README's RD-04 row to `done`. 6. Commit all of it together. ## Acceptance criteria Dry-run against the tree before handover; the "is" numbers are measured, not estimated. **Run these after `git add`.** `git grep` and `git ls-files` read tracked files, so a new story file that is not yet staged does not exist as far as they are concerned. ```bash git grep -l "Domein/Registratie/Dashboard" -- apps | wc -l # is 3 -> MUST be 0 git grep -h "title: 'Domein" -- '*.stories.ts' | grep -c "Domein/[^/]*/[^/]*/" # is 3 -> MUST be 0 git ls-files '*.stories.ts' | wc -l # is 69 -> MUST be 71 ``` The second command counts title lines with a fourth path segment. It is the general form of the rule, so it also catches a retitle that invents a different extra segment. The two new stories exist, with the exact titles from decisions 2, 4 and 6: ```bash git grep -c "title: 'Domein/Registratie/Wat Moet Ik Regelen'" -- apps/ssp/src/app/registratie/ui/dashboard/wat-moet-ik-regelen.section.stories.ts # MUST be 1 git grep -c "title: 'Domein/Overzicht/Wat Wilt U Doen'" -- apps/ssp/src/app/overzicht/ui/wat-wilt-u-doen.section.stories.ts # MUST be 1 ``` `beheer-links` still has no story (decision 3): ```bash git ls-files 'apps/ssp/src/app/overzicht/ui/beheer-links.section.stories.ts' | wc -l # MUST be 0 ``` ```bash npm run ci --full # exits 0 ``` ## Verification **`--full` is required.** This ticket adds two story files, and `npm run ci` does not build Storybook. A story that fails to compile, or a decorator with a missing provider, is invisible until the storybook-a11y job runs. Run `npm run ci --full`, not `npm run ci`. Verified for you: `layers.mdx` deep-links exactly two story ids — `design-system-molecules-application-link--navigatie` and `domein-registratie-aanvraag-block--concept`. Neither is a dashboard section, so the three retitles break no link. Do not add a new deep link. ## Out of scope - Moving any story file. The four data sections stay in `registratie/ui/dashboard/` (RD-03 decision 3). - A story for `beheer-links.section.ts` (decision 3). - `libs/beheer`'s `Domein/Beheer/…` title (decision 7, RD-28 owns it). - The dashboard's 8 imports. PLAN settled this: accept, do not fix. - Renaming the `dashboard/` folder. The name is stale now that the page lives in `overzicht`, but no rule requires the folder to match a title, and the rename would touch every import. ## Risks - **A story title is a URL.** Storybook derives the story id from the title, so a retitle changes the id. Verified above that nothing links to these three; do not extend the retitle to a story outside the table without re-checking. - **`success(...)` needs the decisions shape, not a boolean.** `store.decisions()` is a `RemoteData`. The stub returns `success({ eligibleForHerregistratie: true })`, not `success(true)`. - **The stub must cover every member the class reads, not only the template.** `WatMoetIkRegelenSection` reads `decisions()` in a `computed`, which the template never names. A stub missing it throws at render time, and only `--full` catches that. - **Do not import a fixture across story files** (decision 5). Copy it.