Two backlog trees are complete: `docs/project/backlog/` (75 files, every WP done) and `docs/project/refactor-backlog-setup/` (the arc before it). Move both under `docs/project/archive/` with `git mv`, so history stays intact through `git log --follow`. `SHOWCASE-ROADMAP.md` moves with them, because it points at the now-archived backlog README. Add `docs/project/archive/README.md`. It states that these trees are historical and names the two directories that are still live. Repoint every inbound reference named in RD-30's Files table: CLAUDE.md, the root README, both backend READMEs, `LetterHtml.cs`, `a11y.mdx`, the `document-feature` and `new-ssp` skills, and the readable-codebase PLAN, README, and RD-19 ticket. Fix two upward-relative links inside the moved WP files (WP-68, WP-69) that gained a directory level and would otherwise break. Repoint `.prettierignore`'s two agent-prompt exclusions to their new path, so prettier keeps leaving those files' exact wording alone. Mark RD-30 done and check off its acceptance criteria; flip its README row to done. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
86 lines
4.1 KiB
Markdown
86 lines
4.1 KiB
Markdown
# WP-09 — Pure-logic closure: dates + missing command specs
|
|
|
|
Status: done
|
|
Phase: 1 — FP/DDD core
|
|
|
|
## Why
|
|
|
|
Three hand-rolled copies of the same `nl-NL {day: numeric, month: long, year: numeric}`
|
|
formatter exist with divergent signatures, while other components use the Angular `date`
|
|
pipe — two mechanisms plus drift risk. And two application commands with real logic have
|
|
no spec despite "domain and pure logic must have a spec" (CLAUDE.md §5).
|
|
|
|
## Read first
|
|
|
|
- `src/app/registratie/domain/tasks.ts` (~line 15, `formatNL(d: Date)`)
|
|
- `src/app/registratie/ui/aanvraag-block/aanvraag-block.component.ts` (~line 96,
|
|
`formatNL(iso?: string)`)
|
|
- `src/app/brief/ui/letter-preview/letter-preview.component.ts` (~line 96, inline copy)
|
|
- `src/app/registratie/application/draft-sync.ts` (debounce logic)
|
|
- `src/app/registratie/application/submit-change-request.ts`
|
|
- `src/app/app.config.ts` (LOCALE_ID `nl` is already set)
|
|
|
|
## Decisions (pre-made, don't relitigate)
|
|
|
|
- **Templates use `DatePipe`; pure TS uses one `formatDatumNl`** in
|
|
`src/app/shared/kernel/datum.ts` (Intl.DateTimeFormat, accepts ISO string | Date,
|
|
empty-safe). Rule goes into CLAUDE.md conventions.
|
|
- Kernel naming is Dutch (`datum.ts`) — it formats for the Dutch UI; if that clashes with
|
|
the "shared = English" rule during implementation, `format-date-nl.ts` is the
|
|
alternative — pick one and note it here.
|
|
|
|
## Files
|
|
|
|
- New `src/app/shared/kernel/datum.ts` + `datum.spec.ts`
|
|
- The three formatter copies (delete, redirect to pipe or kernel fn)
|
|
- New `src/app/registratie/application/draft-sync.spec.ts`
|
|
- New `src/app/registratie/application/submit-change-request.spec.ts`
|
|
- `CLAUDE.md` conventions (one line: DatePipe in templates, `formatDatumNl` in pure TS)
|
|
|
|
## Steps
|
|
|
|
1. Write `formatDatumNl` + spec (pin exact expected strings, e.g. `2 juli 2026`;
|
|
undefined/empty → `''`).
|
|
2. Replace the three copies; templates that can use the pipe use the pipe.
|
|
3. `draft-sync.spec.ts` with vitest fake timers: coalescing (n rapid changes → 1 sync),
|
|
trailing call, flush-on-submit if applicable.
|
|
4. `submit-change-request.spec.ts`: ok path, error path (stubbed client), Result shape.
|
|
5. Also sweep the tiny dead exports flagged in the audit: remove unused `map3` from
|
|
`shared/kernel/fp.ts` (verify unused first) and the never-set `variant` input on
|
|
`confirmation.component.ts`.
|
|
|
|
## Acceptance criteria
|
|
|
|
- [x] Exactly one hand-written date formatter in the repo. `formatDatumNl` uses
|
|
`Intl.DateTimeFormat(...).format()` rather than `.toLocaleDateString()`, so
|
|
`grep -rn "toLocaleDateString" src/app` now hits **nothing** (stronger than the
|
|
literal criterion, same intent — no file anywhere hand-rolls date formatting).
|
|
- [x] Both command specs exist; debounce coalescing + error path covered
|
|
(`draft-sync.spec.ts`, `submit-change-request.spec.ts`).
|
|
- [x] `map3` removed (found in `shared/application/remote-data.ts`, not
|
|
`shared/kernel/fp.ts` as the WP text guessed — updated the three docs that
|
|
mentioned it: CLAUDE.md, `docs/reference/architecture/ARCHITECTURE.md`, `remote-data.mdx`). The
|
|
`variant` input on `confirmation.component.ts` no longer exists — already
|
|
cleaned up before this WP ran; nothing to do.
|
|
- [x] CLAUDE.md rule added (`Conventions` — DatePipe in templates, `formatDatumNl` in
|
|
pure TS).
|
|
|
|
## Verification
|
|
|
|
GREEN + `npm run test-storybook:ci` (208 unit tests, up from WP-08's 201 by the 7 new
|
|
specs; 137 Storybook/a11y unchanged). Manual smoke via a running `docker compose` stack +
|
|
Playwright: dashboard's herregistratie-deadline task text ("Verleng uw registratie vóór 1
|
|
maart 2027"), the Concept aanvraag-block's complete-before text ("Rond de aanvraag af
|
|
vóór 2 augustus 2026"), and `formatDatumNl` unit specs for the letter-preview's `today` —
|
|
all render the expected long-form Dutch date, no console errors.
|
|
|
|
## Out of scope
|
|
|
|
`Result` combinators (map/andThen/fold) — nice-to-have from the old roadmap, not in this
|
|
backlog.
|
|
|
|
## Risks
|
|
|
|
Node ICU vs browser locale output differences — the spec pins strings; if CI's Node lacks
|
|
full ICU (it shouldn't on Node 24), pin via `Intl.DateTimeFormat('nl-NL', …)` explicitly.
|