- @if (store.pendingHerregistratie()) {
-
Uw herregistratie-aanvraag is in behandeling.
- }
+
+
+
-
-
-
-
-
-
Persoonsgegevens (BRP)
-
-
-
-
-
-
-
-
-
-
-
+
+ @if (store.pendingHerregistratie()) {
+
Uw herregistratie-aanvraag is in behandeling.
+ }
-
- Specialismen en aantekeningen
-
-
-
+
+
+ @let tasks = tasksFor($any(p).registration);
+
+
+ Wat moet ik regelen
+ @if (tasks.length) {
+
+ } @else {
+ U heeft op dit moment niets openstaan.
+ }
+
+
+
+ Mijn registratie
+
+
+
+
+
+
+
+
+
-
-
-
- U heeft nog geen specialismen of aantekeningen.
+
-
-
- Wat wilt u doen?
-
- @for (a of acties; track a.to) {
- -
- {{ a.titel }}
-
{{ a.tekst }}
- {{ a.actie }} →
-
- }
-
-
+
+ Specialismen en aantekeningen
+
+
+
+
+
+
+
+
+
+ U heeft nog geen specialismen of aantekeningen.
+
+
+
+
+
+
+ Wat wilt u doen?
+
+ @for (a of acties; track a.to) {
+ -
+
+
{{ a.tekst }}
+ {{ a.actie }} →
+
+
+ }
+
+
+
`,
})
export class DashboardPage {
protected store = inject(BigProfileStore);
+ private readonly today = new Date();
- /** Primary actions, rendered as an accessible card grid. */
+ protected tasksFor(reg: Registration) {
+ return tasksFromProfile(reg, this.today);
+ }
+
+ /** Portal sections (navigation, not actions). */
+ protected readonly nav: NavItem[] = [
+ { label: 'Overzicht', to: '/dashboard' },
+ { label: 'Mijn gegevens', to: '/registratie' },
+ { label: 'Herregistratie', to: '/herregistratie' },
+ { label: 'Inschrijven', to: '/registreren' },
+ ];
+
+ /** Primary transactional actions, as a card grid. */
protected readonly acties = [
{ to: '/registreren', titel: 'Inschrijven', tekst: 'Schrijf u in in het BIG-register via de registratiewizard.', actie: 'Start inschrijving' },
- { to: '/registratie', titel: 'Mijn gegevens', tekst: 'Bekijk uw gegevens of geef een wijziging door.', actie: 'Bekijk gegevens' },
- { to: '/herregistratie', titel: 'Herregistratie', tekst: 'Vraag uw herregistratie aan.', actie: 'Vraag aan' },
- { to: '/intake', titel: 'Herregistratie-intake', tekst: 'Vragenlijst met vertakkingen.', actie: 'Start intake' },
- { to: '/concepts', titel: 'Functionele patronen', tekst: 'Onmogelijke toestanden onmogelijk maken.', actie: 'Bekijk patronen' },
+ { to: '/herregistratie', titel: 'Herregistratie aanvragen', tekst: 'Verleng uw registratie voor de komende periode.', actie: 'Vraag aan' },
+ { to: '/registratie', titel: 'Gegevens wijzigen', tekst: 'Bekijk uw gegevens of geef een wijziging door.', actie: 'Bekijk gegevens' },
];
}
diff --git a/src/app/registratie/ui/registratie-wizard/registratie-wizard.component.ts b/src/app/registratie/ui/registratie-wizard/registratie-wizard.component.ts
index 5f7aba9..00563eb 100644
--- a/src/app/registratie/ui/registratie-wizard/registratie-wizard.component.ts
+++ b/src/app/registratie/ui/registratie-wizard/registratie-wizard.component.ts
@@ -83,12 +83,12 @@ const HANDMATIG = '__handmatig__'; // sentinel option: "my diploma isn't listed"
[value]="{ straat: draft().straat ?? '', postcode: draft().postcode ?? '', woonplaats: draft().woonplaats ?? '' }"
[errors]="{ straat: err('straat'), postcode: err('postcode'), woonplaats: err('woonplaats') }"
(fieldChange)="set($event.key, $event.value)" />
-
+
@if (draft().correspondentie === 'email') {
-
+
}
@@ -97,7 +97,7 @@ const HANDMATIG = '__handmatig__'; // sentinel option: "my diploma isn't listed"
@case ('beroep') {
-
+
diff --git a/src/app/registratie/ui/registratie.page.ts b/src/app/registratie/ui/registratie.page.ts
index 3d3510a..d20fa43 100644
--- a/src/app/registratie/ui/registratie.page.ts
+++ b/src/app/registratie/ui/registratie.page.ts
@@ -11,8 +11,7 @@ import { RegistratieWizardComponent } from '@registratie/ui/registratie-wizard/r
template: `
+ backLink="/dashboard">
In drie stappen schrijft u zich in: uw adres en correspondentievoorkeur, het
diploma waarmee u zich registreert, en een controle. Uw gegevens blijven bewaard
diff --git a/src/app/registratie/ui/registration-detail.page.ts b/src/app/registratie/ui/registration-detail.page.ts
index 60aa606..222193c 100644
--- a/src/app/registratie/ui/registration-detail.page.ts
+++ b/src/app/registratie/ui/registration-detail.page.ts
@@ -23,7 +23,7 @@ import { BigProfileStore } from '@registratie/application/big-profile.store';
-
+
diff --git a/src/app/registratie/ui/registration-summary/registration-summary.component.ts b/src/app/registratie/ui/registration-summary/registration-summary.component.ts
index 4c7ee64..83b1ff9 100644
--- a/src/app/registratie/ui/registration-summary/registration-summary.component.ts
+++ b/src/app/registratie/ui/registration-summary/registration-summary.component.ts
@@ -4,13 +4,14 @@ import { Registration } from '@registratie/domain/registration';
import { statusColor, statusLabel } from '@registratie/domain/registration.policy';
import { DataRowComponent } from '@shared/ui/data-row/data-row.component';
import { StatusBadgeComponent } from '@shared/ui/status-badge/status-badge.component';
+import { CardComponent } from '@shared/ui/card/card.component';
/** Organism: registration summary card. Composes data-row molecules + status-badge atom. */
@Component({
selector: 'app-registration-summary',
- imports: [DatePipe, DataRowComponent, StatusBadgeComponent],
+ imports: [DatePipe, DataRowComponent, StatusBadgeComponent, CardComponent],
template: `
-
+
@@ -34,7 +35,7 @@ import { StatusBadgeComponent } from '@shared/ui/status-badge/status-badge.compo
}
}
-
+
`,
})
export class RegistrationSummaryComponent {
diff --git a/src/app/shared/application/session.port.ts b/src/app/shared/application/session.port.ts
new file mode 100644
index 0000000..da78cad
--- /dev/null
+++ b/src/app/shared/application/session.port.ts
@@ -0,0 +1,14 @@
+import { InjectionToken, Signal } from '@angular/core';
+
+/**
+ * A shared seam for the chrome to show "who is logged in" + log out, WITHOUT
+ * shared/ depending on the auth context (the import-direction rule forbids that).
+ * Auth provides this token at the app root (see app.config.ts); the shared header
+ * injects it. SessionStore satisfies this shape structurally.
+ */
+export interface SessionPort {
+ readonly session: Signal<{ naam: string } | null>;
+ logout(): void;
+}
+
+export const SESSION_PORT = new InjectionToken
('SESSION_PORT');
diff --git a/src/app/shared/layout/breadcrumb/breadcrumb-trail.ts b/src/app/shared/layout/breadcrumb/breadcrumb-trail.ts
new file mode 100644
index 0000000..6eb9838
--- /dev/null
+++ b/src/app/shared/layout/breadcrumb/breadcrumb-trail.ts
@@ -0,0 +1,32 @@
+import { BreadcrumbItem } from './breadcrumb.component';
+
+/** Route → breadcrumb label + parent. The app has a small fixed route set
+ (see app.routes.ts), so a static map is enough — no per-page wiring.
+ ponytail: static map, not a breadcrumb service; revisit if routes go dynamic. */
+interface Crumb { label: string; parent?: string }
+
+const ROUTES: Record = {
+ '/dashboard': { label: 'Mijn overzicht' },
+ '/registratie': { label: 'Mijn gegevens', parent: '/dashboard' },
+ '/registreren': { label: 'Inschrijven', parent: '/dashboard' },
+ '/herregistratie': { label: 'Herregistratie', parent: '/dashboard' },
+ '/intake': { label: 'Herregistratie-intake', parent: '/dashboard' },
+ '/concepts': { label: 'Functionele patronen', parent: '/dashboard' },
+};
+
+/** Build the breadcrumb trail for a router url (query/fragment stripped).
+ Returns [] for unknown routes (e.g. /login) so the bar can hide itself. */
+export function trailFor(url: string): BreadcrumbItem[] {
+ const path = url.split(/[?#]/)[0];
+ const trail: BreadcrumbItem[] = [];
+ let cursor: string | undefined = path;
+ while (cursor) {
+ const node: Crumb | undefined = ROUTES[cursor];
+ if (!node) break;
+ trail.unshift({ label: node.label, link: cursor });
+ cursor = node.parent;
+ }
+ // The current (last) page is not a link.
+ if (trail.length) delete trail[trail.length - 1].link;
+ return trail;
+}
diff --git a/src/app/shared/layout/breadcrumb/breadcrumb.component.ts b/src/app/shared/layout/breadcrumb/breadcrumb.component.ts
index 7c17e3d..286d4d3 100644
--- a/src/app/shared/layout/breadcrumb/breadcrumb.component.ts
+++ b/src/app/shared/layout/breadcrumb/breadcrumb.component.ts
@@ -14,19 +14,27 @@ export interface BreadcrumbItem {
imports: [RouterLink],
styles: [`
:host{display:block}
- .list{display:flex;flex-wrap:wrap;gap:var(--rhc-space-max-md);align-items:center;list-style:none;margin:0;padding:0}
+ .list{display:flex;flex-wrap:wrap;gap:var(--rhc-space-max-md);align-items:center;list-style:none;margin:0;padding:0;font-size:var(--rhc-text-font-size-sm)}
+ .crumb{display:inline-flex;align-items:center;gap:var(--rhc-space-max-md)}
+ a{color:var(--rhc-color-foreground-link);text-decoration:underline}
+ a:hover{color:var(--rhc-color-foreground-link-hover)}
+ .current{color:var(--rhc-color-foreground-subtle)}
.sep{color:var(--rhc-color-foreground-subtle)}
+ /* Inverse: on the blue header bar, everything is white. */
+ :host(.inverse) a,
+ :host(.inverse) .current,
+ :host(.inverse) .sep { color: var(--rhc-color-foreground-on-primary); }
`],
template: `