refactor: move the portal home into its own overzicht context (RD-03)

The dashboard page lived inside registratie, a context with no permitted
outbound edges. Two of its sections do cross-context navigation: action
links to herregistratie/intake/brief/concepts, and an admin links section
that imported ADMIN_LINKS directly from the app shell.

Move the page and these two navigation sections into a new overzicht
context. Declare overzicht: ['registratie'] as the one sanctioned edge, so
the four data sections that stay in registratie/ui/dashboard/ remain
reachable. The route stays at /dashboard: it is a user-visible URL and four
e2e specs assert it, so only the import path and class name change.

beheer-links.section.ts now injects HEADER_ADMIN_LINKS, the same token the
site header uses, instead of importing the app shell's nav config directly.

Used npm run gen:context and corrected its three known-wrong outputs: the
overzicht: [] edge, the scaffolded overzicht.page.ts (the real page is the
moved dashboard.page.ts), and the scaffolded path: 'overzicht' route.

Verified the boundary is enforced, not decorative: a temporary import of a
herregistratie file into overzicht.page.ts makes dep:check fail, as
expected, then reverted.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
eho
2026-09-04 16:26:11 +02:00
co-authored by Claude Sonnet 5
parent b9d572cfdc
commit b9fd411283
8 changed files with 187 additions and 13 deletions
@@ -0,0 +1,36 @@
import { Component, computed, inject } from '@angular/core';
import { HeadingComponent } from '@shared/ui/heading/heading.component';
import { ApplicationListComponent } from '@shared/ui/application-list/application-list.component';
import { ApplicationLinkComponent } from '@shared/ui/application-link/application-link.component';
import { AccessStore } from '@shared/application/access.store';
import { HEADER_ADMIN_LINKS } from '@shared/layout/site-header/nav-config';
/** Section: "Beheer" — the admin pages the current principal may reach, capability-
gated (never role-derived), the same source + filter the site header uses.
Empty for a non-admin → the section renders nothing (see the page). */
@Component({
selector: 'app-beheer-links-section',
imports: [HeadingComponent, ApplicationListComponent, ApplicationLinkComponent],
template: `
@if (adminLinks().length) {
<section>
<app-heading [level]="2" i18n="@@dashboard.beheer">Beheer</app-heading>
<app-application-list class="app-section">
@for (link of adminLinks(); track link.to) {
<li
app-application-link
[heading]="link.label"
[subtitle]="link.description"
[to]="link.to"
></li>
}
</app-application-list>
</section>
}
`,
})
export class BeheerLinksSection {
private access = inject(AccessStore);
private rawAdminLinks = inject(HEADER_ADMIN_LINKS);
protected adminLinks = computed(() => this.rawAdminLinks.filter((l) => this.access.can(l.cap)));
}