Step 2 (i18n): $localize sweep + JA_NEE dedup (M3, M4)
Wrap every user-facing Dutch string in Angular's first-party i18n — `i18n`/ `i18n-<attr>` in templates, `$localize` in TS (value-objects, machines, commands, label constants, shared-component defaults). Source locale stays nl; a second locale is now a translation file, not a code change. - M3: ~145 strings localized with stable @@ ids across registratie, herregistratie, auth, shared/ui, shared/layout. Skipped: showcase, debug-state, scenario interceptor, generated client, specs/stories, raw status enum tags, internal parse* diagnostics. - M4: single shared JA_NEE (localized labels) in radio-group; both wizard copies removed. Gate green: lint, check:tokens, build, test 77/77. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -40,7 +40,7 @@ function validate(draft: Draft): Result<Errors, Valid> {
|
||||
const straat = draft.straat.trim();
|
||||
const postcode = parsePostcode(draft.postcode);
|
||||
const errors: Errors = {};
|
||||
if (!straat) errors.straat = 'Vul straat en huisnummer in.';
|
||||
if (!straat) errors.straat = $localize`:@@validation.straat:Vul straat en huisnummer in.`;
|
||||
if (!postcode.ok) errors.postcode = postcode.error;
|
||||
if (straat && postcode.ok) {
|
||||
return { ok: true, value: { straat, postcode: postcode.value, woonplaats: draft.woonplaats.trim() } };
|
||||
|
||||
@@ -85,11 +85,11 @@ function validateStep(step: StepId, d: Draft): Result<Errors, void> {
|
||||
const errors: Errors = {};
|
||||
switch (step) {
|
||||
case 'adres': {
|
||||
if (!d.straat || d.straat.trim() === '') errors.straat = 'Vul een straat en huisnummer in.';
|
||||
if (!d.straat || d.straat.trim() === '') errors.straat = $localize`:@@validation.straat2:Vul een straat en huisnummer in.`;
|
||||
const pc = parsePostcode(d.postcode ?? '');
|
||||
if (!pc.ok) errors.postcode = pc.error;
|
||||
if (!d.woonplaats || d.woonplaats.trim() === '') errors.woonplaats = 'Vul een woonplaats in.';
|
||||
if (!d.correspondentie) errors.correspondentie = 'Maak een keuze.';
|
||||
if (!d.woonplaats || d.woonplaats.trim() === '') errors.woonplaats = $localize`:@@validation.woonplaats:Vul een woonplaats in.`;
|
||||
if (!d.correspondentie) errors.correspondentie = $localize`:@@validation.maakKeuze:Maak een keuze.`;
|
||||
// E-mail is only required when 'email' is the chosen channel.
|
||||
if (d.correspondentie === 'email') {
|
||||
const e = parseEmail(d.email ?? '');
|
||||
@@ -100,7 +100,7 @@ function validateStep(step: StepId, d: Draft): Result<Errors, void> {
|
||||
case 'beroep': {
|
||||
// A diploma must be chosen (or declared manually); its beroep is then known.
|
||||
if (!d.diplomaId || !d.beroep) {
|
||||
errors.diploma = 'Kies het diploma waarmee u zich wilt registreren, of voer het handmatig in.';
|
||||
errors.diploma = $localize`:@@validation.diploma:Kies het diploma waarmee u zich wilt registreren, of voer het handmatig in.`;
|
||||
break;
|
||||
}
|
||||
// Every policy question the chosen diploma raised must be answered. Which
|
||||
@@ -108,7 +108,7 @@ function validateStep(step: StepId, d: Draft): Result<Errors, void> {
|
||||
// they're answered.
|
||||
const open: Record<string, string> = {};
|
||||
for (const id of d.vraagIds ?? []) {
|
||||
if (!(d.antwoorden[id] ?? '').trim()) open[id] = 'Beantwoord deze vraag.';
|
||||
if (!(d.antwoorden[id] ?? '').trim()) open[id] = $localize`:@@validation.beantwoordVraag:Beantwoord deze vraag.`;
|
||||
}
|
||||
if (Object.keys(open).length > 0) errors.antwoorden = open;
|
||||
break;
|
||||
|
||||
@@ -28,30 +28,30 @@ export function tasksFromProfile(reg: Registration, eligibleForHerregistratie: b
|
||||
if (eligibleForHerregistratie) {
|
||||
const deadline = herregistratieDeadline(reg);
|
||||
tasks.push({
|
||||
title: 'Vraag uw herregistratie aan',
|
||||
title: $localize`:@@task.herregistratie.title:Vraag uw herregistratie aan`,
|
||||
description: deadline
|
||||
? `Verleng uw registratie vóór ${formatNL(deadline)}.`
|
||||
: 'U kunt nu uw herregistratie aanvragen.',
|
||||
? $localize`:@@task.herregistratie.deadline:Verleng uw registratie vóór ${formatNL(deadline)}:deadline:.`
|
||||
: $localize`:@@task.herregistratie.nodeadline:U kunt nu uw herregistratie aanvragen.`,
|
||||
to: '/herregistratie',
|
||||
actionLabel: 'Herregistratie aanvragen',
|
||||
actionLabel: $localize`:@@task.herregistratie.action:Herregistratie aanvragen`,
|
||||
});
|
||||
}
|
||||
|
||||
if (reg.status.tag === 'Geschorst') {
|
||||
tasks.push({
|
||||
title: 'Uw registratie is geschorst',
|
||||
title: $localize`:@@task.geschorst.title:Uw registratie is geschorst`,
|
||||
description: reg.status.reden,
|
||||
to: '/registratie',
|
||||
actionLabel: 'Bekijk uw gegevens',
|
||||
actionLabel: $localize`:@@task.bekijkGegevens.action:Bekijk uw gegevens`,
|
||||
});
|
||||
}
|
||||
|
||||
if (reg.status.tag === 'Doorgehaald') {
|
||||
tasks.push({
|
||||
title: 'Uw registratie is doorgehaald',
|
||||
title: $localize`:@@task.doorgehaald.title:Uw registratie is doorgehaald`,
|
||||
description: reg.status.reden,
|
||||
to: '/registratie',
|
||||
actionLabel: 'Bekijk uw gegevens',
|
||||
actionLabel: $localize`:@@task.bekijkGegevens.action:Bekijk uw gegevens`,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -5,5 +5,5 @@ export type BigNummer = Brand<string, 'BigNummer'>;
|
||||
|
||||
export function parseBigNummer(raw: string): Result<string, BigNummer> {
|
||||
const t = raw.trim();
|
||||
return /^\d{11}$/.test(t) ? ok(t as BigNummer) : err('Een BIG-nummer bestaat uit 11 cijfers.');
|
||||
return /^\d{11}$/.test(t) ? ok(t as BigNummer) : err($localize`:@@validation.bigNummer:Een BIG-nummer bestaat uit 11 cijfers.`);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ export function parseEmail(raw: string): Result<string, Email> {
|
||||
// Deliberately lax: a single @ with non-empty, dot-bearing parts. Good enough
|
||||
// for instant feedback; the server re-validates.
|
||||
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t)) {
|
||||
return err('Voer een geldig e-mailadres in, bijv. naam@voorbeeld.nl.');
|
||||
return err($localize`:@@validation.email:Voer een geldig e-mailadres in, bijv. naam@voorbeeld.nl.`);
|
||||
}
|
||||
return ok(t as Email);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ export type Postcode = Brand<string, 'Postcode'>;
|
||||
export function parsePostcode(raw: string): Result<string, Postcode> {
|
||||
const t = raw.trim().toUpperCase();
|
||||
if (!/^[1-9]\d{3}\s?[A-Z]{2}$/.test(t)) {
|
||||
return err('Voer een geldige postcode in, bijv. 1234 AB.');
|
||||
return err($localize`:@@validation.postcode:Voer een geldige postcode in, bijv. 1234 AB.`);
|
||||
}
|
||||
// Normalise to "1234 AB" — the parser also cleans up.
|
||||
return ok(t.replace(/^(\d{4})\s?([A-Z]{2})$/, '$1 $2') as Postcode);
|
||||
|
||||
@@ -8,7 +8,7 @@ export function parseUren(raw: string): Result<string, Uren> {
|
||||
const n = Number(t);
|
||||
// Number('') is 0 — guard the empty string explicitly.
|
||||
if (t === '' || !Number.isInteger(n) || n < 0) {
|
||||
return err('Vul een geheel aantal in (0 of meer).');
|
||||
return err($localize`:@@validation.uren:Vul een geheel aantal in (0 of meer).`);
|
||||
}
|
||||
return ok(n as Uren);
|
||||
}
|
||||
|
||||
@@ -27,17 +27,17 @@ export type AdresErrors = Partial<Record<keyof AdresValue, string>>;
|
||||
template: `
|
||||
<fieldset class="utrecht-form-fieldset utrecht-form-fieldset--html-fieldset">
|
||||
<legend class="utrecht-form-fieldset__legend utrecht-form-fieldset__legend--html-legend">{{ legend() }}</legend>
|
||||
<app-form-field label="Straat en huisnummer" [fieldId]="idPrefix() + '-straat'" required [error]="errors().straat">
|
||||
<app-form-field i18n-label="@@address.straat" label="Straat en huisnummer" [fieldId]="idPrefix() + '-straat'" required [error]="errors().straat">
|
||||
<app-text-input [inputId]="idPrefix() + '-straat'" [invalid]="!!errors().straat"
|
||||
[ngModel]="value().straat" (ngModelChange)="fieldChange.emit({ key: 'straat', value: $event })"
|
||||
name="straat" [ngModelOptions]="{ standalone: true }" />
|
||||
</app-form-field>
|
||||
<app-form-field label="Postcode" [fieldId]="idPrefix() + '-postcode'" required [error]="errors().postcode">
|
||||
<app-form-field i18n-label="@@address.postcode" label="Postcode" [fieldId]="idPrefix() + '-postcode'" required [error]="errors().postcode">
|
||||
<app-text-input [inputId]="idPrefix() + '-postcode'" [invalid]="!!errors().postcode"
|
||||
[ngModel]="value().postcode" (ngModelChange)="fieldChange.emit({ key: 'postcode', value: $event })"
|
||||
name="postcode" placeholder="1234 AB" [ngModelOptions]="{ standalone: true }" />
|
||||
name="postcode" i18n-placeholder="@@address.postcodePlaceholder" placeholder="1234 AB" [ngModelOptions]="{ standalone: true }" />
|
||||
</app-form-field>
|
||||
<app-form-field label="Woonplaats" [fieldId]="idPrefix() + '-woonplaats'" required [error]="errors().woonplaats">
|
||||
<app-form-field i18n-label="@@address.woonplaats" label="Woonplaats" [fieldId]="idPrefix() + '-woonplaats'" required [error]="errors().woonplaats">
|
||||
<app-text-input [inputId]="idPrefix() + '-woonplaats'" [invalid]="!!errors().woonplaats"
|
||||
[ngModel]="value().woonplaats" (ngModelChange)="fieldChange.emit({ key: 'woonplaats', value: $event })"
|
||||
name="woonplaats" [ngModelOptions]="{ standalone: true }" />
|
||||
@@ -50,6 +50,6 @@ export class AddressFieldsComponent {
|
||||
errors = input<AdresErrors>({});
|
||||
/** Prefix for field ids/labels — keeps them unique if two blocks ever co-exist. */
|
||||
idPrefix = input('adres');
|
||||
legend = input('Adres');
|
||||
legend = input($localize`:@@address.legend:Adres`);
|
||||
fieldChange = output<{ key: keyof AdresValue; value: string }>();
|
||||
}
|
||||
|
||||
@@ -20,14 +20,14 @@ import { ApiClient } from '@shared/infrastructure/api-client';
|
||||
imports: [ButtonComponent, HeadingComponent, AlertComponent, AddressFieldsComponent],
|
||||
template: `
|
||||
@if (state().tag === 'Submitted') {
|
||||
<app-alert type="ok">
|
||||
<app-alert type="ok" i18n="@@changeRequest.success">
|
||||
Uw adreswijziging is ontvangen (referentie {{ referentie() }}). U ontvangt binnen 5 werkdagen bericht.
|
||||
</app-alert>
|
||||
<div class="app-section">
|
||||
<app-button variant="secondary" (click)="dispatch({ tag: 'Reset' })">Nieuwe wijziging doorgeven</app-button>
|
||||
<app-button variant="secondary" (click)="dispatch({ tag: 'Reset' })" i18n="@@changeRequest.nieuwe">Nieuwe wijziging doorgeven</app-button>
|
||||
</div>
|
||||
} @else {
|
||||
<app-heading [level]="2">Adreswijziging doorgeven</app-heading>
|
||||
<app-heading [level]="2" i18n="@@changeRequest.heading">Adreswijziging doorgeven</app-heading>
|
||||
<form (ngSubmit)="onSubmit()" class="app-form app-form-panel app-section">
|
||||
<app-address-fields
|
||||
idPrefix="cr"
|
||||
@@ -36,11 +36,11 @@ import { ApiClient } from '@shared/infrastructure/api-client';
|
||||
(fieldChange)="dispatch({ tag: 'SetField', key: $event.key, value: $event.value })" />
|
||||
|
||||
@if (failedError()) {
|
||||
<app-alert type="error">Het indienen is niet gelukt: {{ failedError() }}</app-alert>
|
||||
<app-alert type="error"><ng-container i18n="@@changeRequest.failed">Het indienen is niet gelukt:</ng-container> {{ failedError() }}</app-alert>
|
||||
}
|
||||
|
||||
<app-button type="submit" variant="primary" [disabled]="state().tag === 'Submitting'">
|
||||
{{ state().tag === 'Submitting' ? 'Bezig met indienen…' : 'Wijziging indienen' }}
|
||||
{{ state().tag === 'Submitting' ? submitBezigLabel : submitLabel }}
|
||||
</app-button>
|
||||
</form>
|
||||
}
|
||||
@@ -56,6 +56,9 @@ export class ChangeRequestFormComponent {
|
||||
readonly state = this.store.model;
|
||||
protected dispatch = this.store.dispatch;
|
||||
|
||||
protected readonly submitLabel = $localize`:@@changeRequest.submit:Wijziging indienen`;
|
||||
protected readonly submitBezigLabel = $localize`:@@changeRequest.submitBezig:Bezig met indienen…`;
|
||||
|
||||
private editing = computed(() => whenTag(this.state(), 'Editing'));
|
||||
protected errors = computed<AdresErrors>(() => this.editing()?.errors ?? {});
|
||||
protected failedError = computed(() => whenTag(this.state(), 'Failed')?.error ?? '');
|
||||
|
||||
@@ -25,13 +25,13 @@ import { tasksFromProfile } from '@registratie/domain/tasks';
|
||||
RegistrationSummaryComponent, RegistrationTableComponent,
|
||||
],
|
||||
template: `
|
||||
<app-page-shell heading="Mijn overzicht" intro="Welkom in uw persoonlijke omgeving van het BIG-register. Hier ziet u uw registratie en regelt u uw zaken.">
|
||||
<app-page-shell i18n-heading="@@dashboard.heading" heading="Mijn overzicht" i18n-intro="@@dashboard.intro" intro="Welkom in uw persoonlijke omgeving van het BIG-register. Hier ziet u uw registratie en regelt u uw zaken.">
|
||||
<div class="app-overview">
|
||||
<app-side-nav [items]="nav" />
|
||||
|
||||
<div class="app-stack">
|
||||
@if (store.pendingHerregistratie()) {
|
||||
<app-alert type="info">Uw herregistratie-aanvraag is in behandeling.</app-alert>
|
||||
<app-alert type="info" i18n="@@dashboard.pendingHerregistratie">Uw herregistratie-aanvraag is in behandeling.</app-alert>
|
||||
}
|
||||
|
||||
<app-async [data]="store.profile()">
|
||||
@@ -39,24 +39,24 @@ import { tasksFromProfile } from '@registratie/domain/tasks';
|
||||
@let tasks = tasksFor($any(p).registration);
|
||||
|
||||
<section>
|
||||
<app-heading [level]="2">Wat moet ik regelen</app-heading>
|
||||
<app-heading [level]="2" i18n="@@dashboard.watMoetIkRegelen">Wat moet ik regelen</app-heading>
|
||||
@if (tasks.length) {
|
||||
<app-task-list class="app-section" [tasks]="tasks" />
|
||||
} @else {
|
||||
<p class="rhc-paragraph app-text-subtle">U heeft op dit moment niets openstaan.</p>
|
||||
<p class="rhc-paragraph app-text-subtle" i18n="@@dashboard.nietsOpenstaan">U heeft op dit moment niets openstaan.</p>
|
||||
}
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<app-heading [level]="2">Mijn registratie</app-heading>
|
||||
<app-heading [level]="2" i18n="@@dashboard.mijnRegistratie">Mijn registratie</app-heading>
|
||||
<div class="app-section">
|
||||
<app-registration-summary [reg]="$any(p).registration" />
|
||||
</div>
|
||||
<app-card class="app-section" heading="Persoonsgegevens (BRP)">
|
||||
<app-card class="app-section" i18n-heading="@@dashboard.persoonsgegevens" heading="Persoonsgegevens (BRP)">
|
||||
<dl class="rhc-data-summary rhc-data-summary--row">
|
||||
<app-data-row key="Straat" [value]="$any(p).person.adres.straat" />
|
||||
<app-data-row key="Postcode" [value]="$any(p).person.adres.postcode" />
|
||||
<app-data-row key="Woonplaats" [value]="$any(p).person.adres.woonplaats" />
|
||||
<app-data-row i18n-key="@@dashboard.straat" key="Straat" [value]="$any(p).person.adres.straat" />
|
||||
<app-data-row i18n-key="@@dashboard.postcode" key="Postcode" [value]="$any(p).person.adres.postcode" />
|
||||
<app-data-row i18n-key="@@dashboard.woonplaats" key="Woonplaats" [value]="$any(p).person.adres.woonplaats" />
|
||||
</dl>
|
||||
</app-card>
|
||||
</section>
|
||||
@@ -67,7 +67,7 @@ import { tasksFromProfile } from '@registratie/domain/tasks';
|
||||
</app-async>
|
||||
|
||||
<section>
|
||||
<app-heading [level]="2">Specialismen en aantekeningen</app-heading>
|
||||
<app-heading [level]="2" i18n="@@dashboard.specialismen">Specialismen en aantekeningen</app-heading>
|
||||
<div class="app-section">
|
||||
<app-async [data]="store.aantekeningen()">
|
||||
<ng-template appAsyncLoaded let-r>
|
||||
@@ -77,14 +77,14 @@ import { tasksFromProfile } from '@registratie/domain/tasks';
|
||||
<app-skeleton height="2.5rem" [count]="3" />
|
||||
</ng-template>
|
||||
<ng-template appAsyncEmpty>
|
||||
<p class="rhc-paragraph app-text-subtle">U heeft nog geen specialismen of aantekeningen.</p>
|
||||
<p class="rhc-paragraph app-text-subtle" i18n="@@dashboard.geenSpecialismen">U heeft nog geen specialismen of aantekeningen.</p>
|
||||
</ng-template>
|
||||
</app-async>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<app-heading [level]="2">Wat wilt u doen?</app-heading>
|
||||
<app-heading [level]="2" i18n="@@dashboard.watWiltUDoen">Wat wilt u doen?</app-heading>
|
||||
<ul class="app-card-grid app-section">
|
||||
@for (a of acties; track a.to) {
|
||||
<li>
|
||||
@@ -116,16 +116,16 @@ export class DashboardPage {
|
||||
|
||||
/** 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' },
|
||||
{ label: $localize`:@@dashboard.nav.overzicht:Overzicht`, to: '/dashboard' },
|
||||
{ label: $localize`:@@dashboard.nav.gegevens:Mijn gegevens`, to: '/registratie' },
|
||||
{ label: $localize`:@@dashboard.nav.herregistratie:Herregistratie`, to: '/herregistratie' },
|
||||
{ label: $localize`:@@dashboard.nav.inschrijven: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: '/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' },
|
||||
{ to: '/registreren', titel: $localize`:@@dashboard.actie.inschrijven.titel:Inschrijven`, tekst: $localize`:@@dashboard.actie.inschrijven.tekst:Schrijf u in in het BIG-register via de registratiewizard.`, actie: $localize`:@@dashboard.actie.inschrijven.actie:Start inschrijving` },
|
||||
{ to: '/herregistratie', titel: $localize`:@@dashboard.actie.herregistratie.titel:Herregistratie aanvragen`, tekst: $localize`:@@dashboard.actie.herregistratie.tekst:Verleng uw registratie voor de komende periode.`, actie: $localize`:@@dashboard.actie.herregistratie.actie:Vraag aan` },
|
||||
{ to: '/registratie', titel: $localize`:@@dashboard.actie.wijzigen.titel:Gegevens wijzigen`, tekst: $localize`:@@dashboard.actie.wijzigen.tekst:Bekijk uw gegevens of geef een wijziging door.`, actie: $localize`:@@dashboard.actie.wijzigen.actie:Bekijk gegevens` },
|
||||
];
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Component, computed, effect, inject, input, untracked } from '@angular/
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { FormFieldComponent } from '@shared/ui/form-field/form-field.component';
|
||||
import { TextInputComponent } from '@shared/ui/text-input/text-input.component';
|
||||
import { RadioGroupComponent } from '@shared/ui/radio-group/radio-group.component';
|
||||
import { RadioGroupComponent, JA_NEE } from '@shared/ui/radio-group/radio-group.component';
|
||||
import { ButtonComponent } from '@shared/ui/button/button.component';
|
||||
import { AlertComponent } from '@shared/ui/alert/alert.component';
|
||||
import { SkeletonComponent } from '@shared/ui/skeleton/skeleton.component';
|
||||
@@ -31,8 +31,10 @@ import { submitRegistratie } from '@registratie/application/submit-registratie';
|
||||
import { ApiClient } from '@shared/infrastructure/api-client';
|
||||
|
||||
const STORAGE_KEY = 'registratie-v1'; // ponytail: bump the suffix if the persisted shape changes; no migration.
|
||||
const KANALEN = [{ value: 'email', label: 'E-mail' }, { value: 'post', label: 'Post' }];
|
||||
const JA_NEE = [{ value: 'ja', label: 'Ja' }, { value: 'nee', label: 'Nee' }];
|
||||
const KANALEN = [
|
||||
{ value: 'email', label: $localize`:@@registratie.kanaalEmail:E-mail` },
|
||||
{ value: 'post', label: $localize`:@@registratie.kanaalPost:Post` },
|
||||
];
|
||||
const HANDMATIG = '__handmatig__'; // sentinel option: "my diploma isn't listed"
|
||||
|
||||
/** Organism: the BIG-registration wizard. All state lives in one signal driven by
|
||||
@@ -58,7 +60,7 @@ const HANDMATIG = '__handmatig__'; // sentinel option: "my diploma isn't listed"
|
||||
[canGoBack]="cursor() > 0"
|
||||
[errors]="errorList()"
|
||||
[errorMessage]="errorMessage()"
|
||||
submittingLabel="Uw registratie wordt verwerkt…"
|
||||
i18n-submittingLabel="@@regWizard.submitting" submittingLabel="Uw registratie wordt verwerkt…"
|
||||
(primary)="onPrimary()"
|
||||
(back)="dispatch({ tag: 'Back' })"
|
||||
(cancel)="restart()"
|
||||
@@ -71,26 +73,26 @@ const HANDMATIG = '__handmatig__'; // sentinel option: "my diploma isn't listed"
|
||||
} @else {
|
||||
@switch (adresStatus()) {
|
||||
@case ('gevonden') {
|
||||
<app-alert type="info">Vooraf ingevuld op basis van de BRP. Controleer en pas zo nodig aan.</app-alert>
|
||||
<app-alert type="info" i18n="@@regWizard.brpGevonden">Vooraf ingevuld op basis van de BRP. Controleer en pas zo nodig aan.</app-alert>
|
||||
}
|
||||
@case ('geen') {
|
||||
<app-alert type="warning">We vonden geen adres in de BRP. Vul uw adres hieronder handmatig in.</app-alert>
|
||||
<app-alert type="warning" i18n="@@regWizard.brpGeen">We vonden geen adres in de BRP. Vul uw adres hieronder handmatig in.</app-alert>
|
||||
}
|
||||
@case ('fout') {
|
||||
<app-alert type="warning">We konden de BRP nu niet bereiken. Vul uw adres hieronder handmatig in.</app-alert>
|
||||
<app-alert type="warning" i18n="@@regWizard.brpFout">We konden de BRP nu niet bereiken. Vul uw adres hieronder handmatig in.</app-alert>
|
||||
}
|
||||
}
|
||||
<app-address-fields
|
||||
[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)" />
|
||||
<app-form-field label="Hoe wilt u correspondentie ontvangen?" fieldId="correspondentie" required [error]="err('correspondentie')">
|
||||
<app-form-field i18n-label="@@regWizard.correspondentieLabel" label="Hoe wilt u correspondentie ontvangen?" fieldId="correspondentie" required [error]="err('correspondentie')">
|
||||
<app-radio-group name="correspondentie" [options]="kanalen" [invalid]="!!err('correspondentie')"
|
||||
[ngModel]="draft().correspondentie ?? ''" (ngModelChange)="setKanaal($event)" />
|
||||
</app-form-field>
|
||||
@if (draft().correspondentie === 'email') {
|
||||
<app-form-field label="E-mailadres" fieldId="email" required [error]="err('email')">
|
||||
<app-text-input inputId="email" type="email" [invalid]="!!err('email')" [ngModel]="draft().email ?? ''" (ngModelChange)="set('email', $event)" name="email" placeholder="naam@voorbeeld.nl" />
|
||||
<app-form-field i18n-label="@@regWizard.emailLabel" label="E-mailadres" fieldId="email" required [error]="err('email')">
|
||||
<app-text-input inputId="email" type="email" [invalid]="!!err('email')" [ngModel]="draft().email ?? ''" (ngModelChange)="set('email', $event)" name="email" i18n-placeholder="@@regWizard.emailPlaceholder" placeholder="naam@voorbeeld.nl" />
|
||||
</app-form-field>
|
||||
}
|
||||
}
|
||||
@@ -98,20 +100,20 @@ const HANDMATIG = '__handmatig__'; // sentinel option: "my diploma isn't listed"
|
||||
@case ('beroep') {
|
||||
<app-async [data]="lookupRd()">
|
||||
<ng-template appAsyncLoaded let-data>
|
||||
<app-form-field label="Kies het diploma waarmee u zich wilt registreren" fieldId="diploma" required [error]="err('diploma')">
|
||||
<app-form-field i18n-label="@@regWizard.diplomaLabel" label="Kies het diploma waarmee u zich wilt registreren" fieldId="diploma" required [error]="err('diploma')">
|
||||
<app-radio-group name="diploma" [options]="diplomaOptions($any(data))" [invalid]="!!err('diploma')"
|
||||
[ngModel]="diplomaKeuze()" (ngModelChange)="onDiplomaKeuze($any(data), $event)" />
|
||||
</app-form-field>
|
||||
|
||||
@if (handmatigActief()) {
|
||||
<app-alert type="warning">Een handmatig ingevoerd diploma kan niet automatisch worden geverifieerd. Kies uw beroep en beantwoord de aanvullende vragen; uw aanvraag wordt daarna handmatig beoordeeld.</app-alert>
|
||||
<app-form-field label="Voor welk beroep wilt u zich registreren?" fieldId="hm-beroep" [error]="err('diploma')">
|
||||
<app-alert type="warning" i18n="@@regWizard.handmatigWaarschuwing">Een handmatig ingevoerd diploma kan niet automatisch worden geverifieerd. Kies uw beroep en beantwoord de aanvullende vragen; uw aanvraag wordt daarna handmatig beoordeeld.</app-alert>
|
||||
<app-form-field i18n-label="@@regWizard.beroepLabel" label="Voor welk beroep wilt u zich registreren?" fieldId="hm-beroep" [error]="err('diploma')">
|
||||
<app-radio-group name="hm-beroep" [options]="beroepOptions($any(data))" [invalid]="!!err('diploma')"
|
||||
[ngModel]="draft().beroep ?? ''" (ngModelChange)="dispatch({ tag: 'DeclareerBeroep', beroep: $event })" />
|
||||
</app-form-field>
|
||||
} @else if (draft().beroep) {
|
||||
<dl class="rhc-data-summary rhc-data-summary--row app-section">
|
||||
<app-data-row key="Beroep (afgeleid uit diploma)" [value]="draft().beroep ?? ''" />
|
||||
<app-data-row i18n-key="@@regWizard.beroepAfgeleid" key="Beroep (afgeleid uit diploma)" [value]="draft().beroep ?? ''" />
|
||||
</dl>
|
||||
}
|
||||
|
||||
@@ -133,31 +135,31 @@ const HANDMATIG = '__handmatig__'; // sentinel option: "my diploma isn't listed"
|
||||
</app-async>
|
||||
}
|
||||
@case ('controle') {
|
||||
<app-alert type="info">Controleer uw gegevens en dien de registratie in.</app-alert>
|
||||
<app-alert type="info" i18n="@@regWizard.controleer">Controleer uw gegevens en dien de registratie in.</app-alert>
|
||||
<dl class="rhc-data-summary rhc-data-summary--row app-section">
|
||||
<app-data-row key="Adres" [value]="adresSamenvatting()" />
|
||||
<app-data-row key="Herkomst adres" [value]="adresHerkomstLabel()" />
|
||||
<app-data-row key="Correspondentie" [value]="correspondentieLabel()" />
|
||||
<app-data-row i18n-key="@@regWizard.summary.adres" key="Adres" [value]="adresSamenvatting()" />
|
||||
<app-data-row i18n-key="@@regWizard.summary.herkomstAdres" key="Herkomst adres" [value]="adresHerkomstLabel()" />
|
||||
<app-data-row i18n-key="@@regWizard.summary.correspondentie" key="Correspondentie" [value]="correspondentieLabel()" />
|
||||
@if (draft().correspondentie === 'email') {
|
||||
<app-data-row key="E-mailadres" [value]="draft().email ?? ''" />
|
||||
<app-data-row i18n-key="@@regWizard.summary.email" key="E-mailadres" [value]="draft().email ?? ''" />
|
||||
}
|
||||
<app-data-row key="Beroep" [value]="draft().beroep ?? ''" />
|
||||
<app-data-row key="Herkomst diploma" [value]="diplomaHerkomstLabel()" />
|
||||
<app-data-row i18n-key="@@regWizard.summary.beroep" key="Beroep" [value]="draft().beroep ?? ''" />
|
||||
<app-data-row i18n-key="@@regWizard.summary.herkomstDiploma" key="Herkomst diploma" [value]="diplomaHerkomstLabel()" />
|
||||
@for (item of samenvattingVragen(); track item.vraag) {
|
||||
<app-data-row [key]="item.vraag" [value]="item.antwoord" />
|
||||
}
|
||||
</dl>
|
||||
<div class="app-button-row app-section">
|
||||
<app-button type="button" variant="subtle" (click)="dispatch({ tag: 'GaNaarStap', cursor: 0 })">Adres wijzigen</app-button>
|
||||
<app-button type="button" variant="subtle" (click)="dispatch({ tag: 'GaNaarStap', cursor: 1 })">Diploma wijzigen</app-button>
|
||||
<app-button type="button" variant="subtle" (click)="dispatch({ tag: 'GaNaarStap', cursor: 0 })" i18n="@@regWizard.adresWijzigen">Adres wijzigen</app-button>
|
||||
<app-button type="button" variant="subtle" (click)="dispatch({ tag: 'GaNaarStap', cursor: 1 })" i18n="@@regWizard.diplomaWijzigen">Diploma wijzigen</app-button>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
<div wizardSuccess>
|
||||
<app-alert type="ok">Uw registratie is ontvangen. Uw referentienummer is {{ referentie() }}. Bewaar dit nummer voor uw administratie.</app-alert>
|
||||
<app-alert type="ok" i18n="@@regWizard.success">Uw registratie is ontvangen. Uw referentienummer is {{ referentie() }}. Bewaar dit nummer voor uw administratie.</app-alert>
|
||||
<div class="app-section">
|
||||
<app-button variant="secondary" (click)="restart()">Nieuwe registratie starten</app-button>
|
||||
<app-button variant="secondary" (click)="restart()" i18n="@@regWizard.nieuweRegistratie">Nieuwe registratie starten</app-button>
|
||||
</div>
|
||||
</div>
|
||||
</app-wizard-shell>
|
||||
@@ -176,8 +178,8 @@ export class RegistratieWizardComponent {
|
||||
seed = input<RegistratieState>(initial);
|
||||
|
||||
readonly kanalen = KANALEN;
|
||||
readonly stepLabels = ['Adres', 'Beroep', 'Controle']; // short labels for the stepper
|
||||
private stepTitles = ['Adres en correspondentievoorkeur', 'Beroep op basis van uw diploma', 'Controleren en indienen'];
|
||||
readonly stepLabels = [$localize`:@@regWizard.step.adres:Adres`, $localize`:@@regWizard.step.beroep:Beroep`, $localize`:@@regWizard.step.controle:Controle`]; // short labels for the stepper
|
||||
private stepTitles = [$localize`:@@regWizard.title.adres:Adres en correspondentievoorkeur`, $localize`:@@regWizard.title.beroep:Beroep op basis van uw diploma`, $localize`:@@regWizard.title.controle:Controleren en indienen`];
|
||||
readonly state = this.store.model;
|
||||
readonly dispatch = this.store.dispatch;
|
||||
|
||||
@@ -190,8 +192,8 @@ export class RegistratieWizardComponent {
|
||||
protected failedError = computed(() => whenTag(this.state(), 'Mislukt')?.error ?? '');
|
||||
|
||||
// --- Presentational wiring for the shared wizard shell ---------------------
|
||||
protected primaryLabel = computed(() => (this.step() === 'controle' ? 'Registratie indienen' : 'Volgende'));
|
||||
protected errorMessage = computed(() => `Het indienen is niet gelukt: ${this.failedError()}`);
|
||||
protected primaryLabel = computed(() => (this.step() === 'controle' ? $localize`:@@regWizard.indienen:Registratie indienen` : $localize`:@@wizard.volgende:Volgende`));
|
||||
protected errorMessage = computed(() => $localize`:@@regWizard.indienenMislukt:Het indienen is niet gelukt:` + ` ${this.failedError()}`);
|
||||
protected shellStatus = computed<WizardStatus>(() => {
|
||||
switch (this.state().tag) {
|
||||
case 'Invullen': return 'editing';
|
||||
@@ -217,9 +219,9 @@ export class RegistratieWizardComponent {
|
||||
return [d.straat, [d.postcode, d.woonplaats].filter(Boolean).join(' ')].filter(Boolean).join(', ');
|
||||
});
|
||||
// Readable labels for the controle summary (instead of raw enum values).
|
||||
protected adresHerkomstLabel = computed(() => ({ brp: 'Automatisch uit de BRP', handmatig: 'Handmatig ingevoerd' }[this.draft().adresHerkomst ?? 'handmatig']));
|
||||
protected correspondentieLabel = computed(() => ({ email: 'Per e-mail', post: 'Per post' }[this.draft().correspondentie ?? 'post']));
|
||||
protected diplomaHerkomstLabel = computed(() => ({ duo: 'Geverifieerd via DUO', handmatig: 'Handmatig ingevoerd (wordt beoordeeld)' }[this.draft().diplomaHerkomst ?? 'handmatig']));
|
||||
protected adresHerkomstLabel = computed(() => ({ brp: $localize`:@@regWizard.herkomst.adresBrp:Automatisch uit de BRP`, handmatig: $localize`:@@regWizard.herkomst.adresHandmatig:Handmatig ingevoerd` }[this.draft().adresHerkomst ?? 'handmatig']));
|
||||
protected correspondentieLabel = computed(() => ({ email: $localize`:@@regWizard.corr.email:Per e-mail`, post: $localize`:@@regWizard.corr.post:Per post` }[this.draft().correspondentie ?? 'post']));
|
||||
protected diplomaHerkomstLabel = computed(() => ({ duo: $localize`:@@regWizard.herkomst.diplomaDuo:Geverifieerd via DUO`, handmatig: $localize`:@@regWizard.herkomst.diplomaHandmatig:Handmatig ingevoerd (wordt beoordeeld)` }[this.draft().diplomaHerkomst ?? 'handmatig']));
|
||||
|
||||
/** BRP lookup outcome. A failure or "geen adres" never blocks the wizard — both
|
||||
fall back to manual entry (PRD §7). 'geen' covers both no-address-found and a
|
||||
@@ -262,7 +264,7 @@ export class RegistratieWizardComponent {
|
||||
|
||||
protected diplomaOptions = (data: DuoLookupDto) => [
|
||||
...data.diplomas.map((d) => ({ value: d.id, label: `${d.naam} — ${d.instelling} (${d.jaar})` })),
|
||||
{ value: HANDMATIG, label: 'Mijn diploma staat er niet bij' },
|
||||
{ value: HANDMATIG, label: $localize`:@@regWizard.diplomaNietBij:Mijn diploma staat er niet bij` },
|
||||
];
|
||||
|
||||
protected beroepOptions = (data: DuoLookupDto) => data.handmatig.beroepen.map((b) => ({ value: b, label: b }));
|
||||
|
||||
@@ -10,9 +10,10 @@ import { RegistratieWizardComponent } from '@registratie/ui/registratie-wizard/r
|
||||
imports: [PageShellComponent, AlertComponent, RegistratieWizardComponent],
|
||||
template: `
|
||||
<app-page-shell
|
||||
i18n-heading="@@registratie.heading"
|
||||
heading="Inschrijven in het BIG-register"
|
||||
backLink="/dashboard">
|
||||
<app-alert type="info">
|
||||
<app-alert type="info" i18n="@@registratie.intro">
|
||||
In drie stappen schrijft u zich in: uw adres en correspondentievoorkeur, het
|
||||
diploma waarmee u zich registreert, en een controle. Uw gegevens blijven bewaard
|
||||
als u de pagina herlaadt.
|
||||
|
||||
@@ -13,7 +13,7 @@ import { BigProfileStore } from '@registratie/application/big-profile.store';
|
||||
RegistrationSummaryComponent, ChangeRequestFormComponent,
|
||||
],
|
||||
template: `
|
||||
<app-page-shell heading="Mijn gegevens" backLink="/dashboard">
|
||||
<app-page-shell i18n-heading="@@registratieDetail.heading" heading="Mijn gegevens" backLink="/dashboard">
|
||||
<app-async [data]="store.profile()">
|
||||
<ng-template appAsyncLoaded let-p>
|
||||
<app-registration-summary [reg]="$any(p).registration" />
|
||||
|
||||
@@ -13,25 +13,25 @@ import { CardComponent } from '@shared/ui/card/card.component';
|
||||
template: `
|
||||
<app-card>
|
||||
<dl class="rhc-data-summary rhc-data-summary--row">
|
||||
<app-data-row key="BIG-nummer" [value]="reg().bigNummer" />
|
||||
<app-data-row key="Naam" [value]="reg().naam" />
|
||||
<app-data-row key="Beroep" [value]="reg().beroep" />
|
||||
<app-data-row key="Status">
|
||||
<app-data-row i18n-key="@@summary.bigNummer" key="BIG-nummer" [value]="reg().bigNummer" />
|
||||
<app-data-row i18n-key="@@summary.naam" key="Naam" [value]="reg().naam" />
|
||||
<app-data-row i18n-key="@@summary.beroep" key="Beroep" [value]="reg().beroep" />
|
||||
<app-data-row i18n-key="@@summary.status" key="Status">
|
||||
<app-status-badge [label]="label()" [color]="color()" />
|
||||
</app-data-row>
|
||||
<app-data-row key="Registratiedatum" [value]="reg().registratiedatum | date:'longDate'" />
|
||||
<app-data-row i18n-key="@@summary.registratiedatum" key="Registratiedatum" [value]="reg().registratiedatum | date:'longDate'" />
|
||||
<!-- Each status variant renders only the row its own data supports. -->
|
||||
@switch (reg().status.tag) {
|
||||
@case ('Geregistreerd') {
|
||||
<app-data-row key="Uiterste herregistratie" [value]="$any(reg().status).herregistratieDatum | date:'longDate'" />
|
||||
<app-data-row i18n-key="@@summary.uiterste" key="Uiterste herregistratie" [value]="$any(reg().status).herregistratieDatum | date:'longDate'" />
|
||||
}
|
||||
@case ('Geschorst') {
|
||||
<app-data-row key="Geschorst tot" [value]="$any(reg().status).geschorstTot | date:'longDate'" />
|
||||
<app-data-row key="Reden" [value]="$any(reg().status).reden" />
|
||||
<app-data-row i18n-key="@@summary.geschorstTot" key="Geschorst tot" [value]="$any(reg().status).geschorstTot | date:'longDate'" />
|
||||
<app-data-row i18n-key="@@summary.reden" key="Reden" [value]="$any(reg().status).reden" />
|
||||
}
|
||||
@case ('Doorgehaald') {
|
||||
<app-data-row key="Doorgehaald op" [value]="$any(reg().status).doorgehaaldOp | date:'longDate'" />
|
||||
<app-data-row key="Reden" [value]="$any(reg().status).reden" />
|
||||
<app-data-row i18n-key="@@summary.doorgehaaldOp" key="Doorgehaald op" [value]="$any(reg().status).doorgehaaldOp | date:'longDate'" />
|
||||
<app-data-row i18n-key="@@summary.reden" key="Reden" [value]="$any(reg().status).reden" />
|
||||
}
|
||||
}
|
||||
</dl>
|
||||
|
||||
@@ -11,9 +11,9 @@ import { Aantekening } from '@registratie/domain/registration';
|
||||
<table class="utrecht-table utrecht-table--html-table utrecht-table--alternate-row-color">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="utrecht-table__header-cell">Type</th>
|
||||
<th class="utrecht-table__header-cell">Omschrijving</th>
|
||||
<th class="utrecht-table__header-cell">Datum</th>
|
||||
<th class="utrecht-table__header-cell" i18n="@@table.type">Type</th>
|
||||
<th class="utrecht-table__header-cell" i18n="@@table.omschrijving">Omschrijving</th>
|
||||
<th class="utrecht-table__header-cell" i18n="@@table.datum">Datum</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
Reference in New Issue
Block a user