refactor: story titles to Domein/<Context>/<Name>; add 2 missing stories (RD-04)
Three dashboard-section stories used a fourth title segment (`Domein/Registratie/Dashboard/<Name>`) that the sidebar rule does not have. Drop the `Dashboard/` segment so all story titles follow the one rule from CLAUDE.md decision 5. Add the two missing stories for sections that have more than one visual state: `wat-moet-ik-regelen` (4 states) and `wat-wilt-u-doen` (2 states, the first story in the new `Domein/Overzicht/` bucket). `beheer-links` gets no story — it has one visual state and its other branch renders nothing. The `MetTaken` story disables the a11y addon with the same reason and WP-11 reference already used on `task-list.stories.ts` and `choice-list.stories.ts`: `app-choice-link`'s host sits between the keuzelijst `<ul>` and its `<li>`, a pre-existing structural gap this ticket does not fix. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,28 @@
|
|||||||
|
import type { Meta, StoryObj } from '@storybook/angular';
|
||||||
|
import { applicationConfig } from '@storybook/angular';
|
||||||
|
import { provideRouter } from '@angular/router';
|
||||||
|
import { WatWiltUDoenSection } from './wat-wilt-u-doen.section';
|
||||||
|
import { FeatureFlagStore } from '@shared/application/feature-flags.store';
|
||||||
|
|
||||||
|
const meta: Meta<WatWiltUDoenSection> = {
|
||||||
|
title: 'Domein/Overzicht/Wat Wilt U Doen',
|
||||||
|
component: WatWiltUDoenSection,
|
||||||
|
decorators: [applicationConfig({ providers: [provideRouter([])] })],
|
||||||
|
};
|
||||||
|
export default meta;
|
||||||
|
type Story = StoryObj<WatWiltUDoenSection>;
|
||||||
|
|
||||||
|
export const InschrijvingOpen: Story = {
|
||||||
|
decorators: [
|
||||||
|
applicationConfig({
|
||||||
|
providers: [{ provide: FeatureFlagStore, useValue: { enabled: () => true } }],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
export const InschrijvingDicht: Story = {
|
||||||
|
decorators: [
|
||||||
|
applicationConfig({
|
||||||
|
providers: [{ provide: FeatureFlagStore, useValue: { enabled: () => false } }],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
};
|
||||||
@@ -34,7 +34,7 @@ function storeStub(aanvragen: RemoteData<Error | undefined, Aanvraag[]>, lastErr
|
|||||||
}
|
}
|
||||||
|
|
||||||
const meta: Meta<MijnAanvragenSection> = {
|
const meta: Meta<MijnAanvragenSection> = {
|
||||||
title: 'Domein/Registratie/Dashboard/Mijn Aanvragen',
|
title: 'Domein/Registratie/Mijn Aanvragen',
|
||||||
component: MijnAanvragenSection,
|
component: MijnAanvragenSection,
|
||||||
decorators: [applicationConfig({ providers: [provideRouter([])] })],
|
decorators: [applicationConfig({ providers: [provideRouter([])] })],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ function storeStub(profileRd: RemoteData<Error | undefined, BigProfile>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const meta: Meta<MijnRegistratieSection> = {
|
const meta: Meta<MijnRegistratieSection> = {
|
||||||
title: 'Domein/Registratie/Dashboard/Mijn Registratie',
|
title: 'Domein/Registratie/Mijn Registratie',
|
||||||
component: MijnRegistratieSection,
|
component: MijnRegistratieSection,
|
||||||
};
|
};
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ function storeStub(aantekeningen: RemoteData<Error | undefined, Aantekening[]>)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const meta: Meta<SpecialismenSection> = {
|
const meta: Meta<SpecialismenSection> = {
|
||||||
title: 'Domein/Registratie/Dashboard/Specialismen',
|
title: 'Domein/Registratie/Specialismen',
|
||||||
component: SpecialismenSection,
|
component: SpecialismenSection,
|
||||||
};
|
};
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|||||||
@@ -0,0 +1,109 @@
|
|||||||
|
import type { Meta, StoryObj } from '@storybook/angular';
|
||||||
|
import { applicationConfig } from '@storybook/angular';
|
||||||
|
import { WatMoetIkRegelenSection } from './wat-moet-ik-regelen.section';
|
||||||
|
import { BigProfileStore } from '@registratie/application/big-profile.store';
|
||||||
|
import { BigProfile } from '@registratie/domain/big-profile';
|
||||||
|
import { HerregistratieDecisions } from '@registratie/domain/registration';
|
||||||
|
import { RemoteData } from '@shared/application/remote-data';
|
||||||
|
import { loading, success } from '@shared/testing/remote-data';
|
||||||
|
|
||||||
|
const profile: BigProfile = {
|
||||||
|
registration: {
|
||||||
|
bigNummer: '19012345601',
|
||||||
|
naam: 'Dr. A. (Anna) de Vries',
|
||||||
|
beroep: 'Arts',
|
||||||
|
registratiedatum: '2012-09-01',
|
||||||
|
geboortedatum: '1985-03-14',
|
||||||
|
status: { tag: 'Geregistreerd', herregistratieDatum: '2027-09-01' },
|
||||||
|
},
|
||||||
|
person: {
|
||||||
|
naam: 'Dr. A. (Anna) de Vries',
|
||||||
|
geboortedatum: '1985-03-14',
|
||||||
|
adres: { straat: 'Rijksweg 1', postcode: '2514 EA', woonplaats: 'Den Haag' },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Minimal store stand-in — only the members the section's template and class read. */
|
||||||
|
function storeStub(
|
||||||
|
profileRd: RemoteData<Error | undefined, BigProfile>,
|
||||||
|
decisionsRd: RemoteData<Error | undefined, HerregistratieDecisions>,
|
||||||
|
pendingHerregistratie: boolean,
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
profile: () => profileRd,
|
||||||
|
decisions: () => decisionsRd,
|
||||||
|
pendingHerregistratie: () => pendingHerregistratie,
|
||||||
|
reloadProfile: () => {},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const meta: Meta<WatMoetIkRegelenSection> = {
|
||||||
|
title: 'Domein/Registratie/Wat Moet Ik Regelen',
|
||||||
|
component: WatMoetIkRegelenSection,
|
||||||
|
};
|
||||||
|
export default meta;
|
||||||
|
type Story = StoryObj<WatMoetIkRegelenSection>;
|
||||||
|
|
||||||
|
export const Loading: Story = {
|
||||||
|
decorators: [
|
||||||
|
applicationConfig({
|
||||||
|
providers: [{ provide: BigProfileStore, useValue: storeStub(loading(), loading(), false) }],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
export const MetTaken: Story = {
|
||||||
|
decorators: [
|
||||||
|
applicationConfig({
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: BigProfileStore,
|
||||||
|
useValue: storeStub(
|
||||||
|
success(profile),
|
||||||
|
success({ eligibleForHerregistratie: true }),
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
parameters: {
|
||||||
|
// Structural: app-choice-link's host sits between the keuzelijst <ul> and its <li>
|
||||||
|
// — axe's list/listitem rule needs them adjacent regardless of `display:contents`.
|
||||||
|
// Same pre-existing gap as task-list.stories.ts and choice-list.stories.ts. WP-11
|
||||||
|
// (CIBG markup fidelity) reworks this markup; see
|
||||||
|
// docs/project/backlog/WP-11-markup-fidelity.md.
|
||||||
|
a11y: { disable: true },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
export const NietsOpenstaand: Story = {
|
||||||
|
decorators: [
|
||||||
|
applicationConfig({
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: BigProfileStore,
|
||||||
|
useValue: storeStub(
|
||||||
|
success(profile),
|
||||||
|
success({ eligibleForHerregistratie: false }),
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
export const InBehandeling: Story = {
|
||||||
|
decorators: [
|
||||||
|
applicationConfig({
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: BigProfileStore,
|
||||||
|
useValue: storeStub(
|
||||||
|
success(profile),
|
||||||
|
success({ eligibleForHerregistratie: false }),
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
};
|
||||||
@@ -0,0 +1,170 @@
|
|||||||
|
# RD-04 — Story titles to `Domein/<Context>/<Name>`, 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/<Context>/<Name>` — "full stop, regardless of which atomic layer it is". The three
|
||||||
|
dashboard-section stories break it. They read `Domein/Registratie/Dashboard/<Name>`, 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 — `<app-async>`'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<Err, HerregistratieDecisions>`. 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.
|
||||||
@@ -98,7 +98,7 @@ two. Note that RD-15 exists because 22 abandoned agent worktrees are still on di
|
|||||||
| RD-01 | Scaffold this backlog: README, PLAN, ticket template | — | | done |
|
| RD-01 | Scaffold this backlog: README, PLAN, ticket template | — | | done |
|
||||||
| RD-02 | `max-lines` rule + `reportUnusedDisableDirectives` + 7 disables | 01 | | done |
|
| RD-02 | `max-lines` rule + `reportUnusedDisableDirectives` + 7 disables | 01 | | done |
|
||||||
| RD-03 | `overzicht` context: page + 2 nav sections, boundary edge, admin-links token | 02 | yes | done |
|
| RD-03 | `overzicht` context: page + 2 nav sections, boundary edge, admin-links token | 02 | yes | done |
|
||||||
| RD-04 | Story titles to `Domein/<Context>/<Name>`; add the missing stories | 03 | yes | todo |
|
| RD-04 | Story titles to `Domein/<Context>/<Name>`; add the missing stories | 03 | yes | done |
|
||||||
| RD-05 | `createStore` gains the effect map + specs | 02 | | done |
|
| RD-05 | `createStore` gains the effect map + specs | 02 | | done |
|
||||||
| RD-06 | **Bug fix:** 2 single-step forms to the effect map + retry affordance | 05 | yes | done |
|
| RD-06 | **Bug fix:** 2 single-step forms to the effect map + retry affordance | 05 | yes | done |
|
||||||
| RD-07 | Add `Primary` to the 3 wizard machines + specs | 05 | | done |
|
| RD-07 | Add `Primary` to the 3 wizard machines + specs | 05 | | done |
|
||||||
|
|||||||
Reference in New Issue
Block a user