Step 2 (code quality): dedup + stop FE recomputing a server rule

- H1: tasksFromProfile takes the server's eligibleForHerregistratie decision
  instead of recomputing isHerregistratieEligible — the FE renders the rule,
  doesn't own it (ADR-0001). Policy reference impl kept for tests.
- M1: one shared runSubmit(fn, fallback) wrapper; the 4 submit-* commands keep
  only their payload mapping. +spec.
- M2: whenTag() kernel helper removes 10 repeated `as Extract<U,{tag}>` casts
  across the wizard/form components.

M4 (shared JA_NEE) folded into the upcoming i18n pass (clean dedup needs
$localize labels to sit in shared without breaking the English-shared-UI rule).
L1 already resolved by the restyle commit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
eho
2026-06-27 13:48:35 +02:00
co-authored by Claude Opus 4.8
parent 94ffcf3d41
commit 1c65025fef
14 changed files with 118 additions and 68 deletions
+8 -3
View File
@@ -1,4 +1,4 @@
import { Component, inject } from '@angular/core';
import { Component, computed, inject } from '@angular/core';
import { PageShellComponent } from '@shared/layout/page-shell/page-shell.component';
import { HeadingComponent } from '@shared/ui/heading/heading.component';
import { LinkComponent } from '@shared/ui/link/link.component';
@@ -103,10 +103,15 @@ import { tasksFromProfile } from '@registratie/domain/tasks';
})
export class DashboardPage {
protected store = inject(BigProfileStore);
private readonly today = new Date();
/** Server-computed eligibility (rendered, not recomputed). */
private readonly eligible = computed(() => {
const d = this.store.decisions();
return d.tag === 'Success' && d.value.eligibleForHerregistratie;
});
protected tasksFor(reg: Registration) {
return tasksFromProfile(reg, this.today);
return tasksFromProfile(reg, this.eligible());
}
/** Portal sections (navigation, not actions). */