{ "pipes": [], "interfaces": [ { "name": "Aantekening", "id": "interface-Aantekening-8e28c6bf4ec154e4db100e2ec1ee19fe9c2d50bc429733f8288f32277ce91963f67ec0363028632e71cfb7e05ce25001908c8dd8ee66d732632d67b993c0645b", "file": "src/app/registratie/domain/registration.ts", "deprecated": false, "deprecationMessage": "", "type": "interface", "sourceCode": "export type RegistrationStatus =\n | { tag: 'Geregistreerd'; herregistratieDatum: string } // ISO date\n | { tag: 'Geschorst'; geschorstTot: string; reden: string }\n | { tag: 'Doorgehaald'; doorgehaaldOp: string; reden: string };\n\n/** Just the discriminant — for atoms that only need the label/color. */\nexport type StatusTag = RegistrationStatus['tag'];\n\nexport interface Registration {\n bigNummer: string;\n naam: string;\n beroep: string; // arts, verpleegkundige, apotheker, ...\n registratiedatum: string; // ISO date\n geboortedatum: string;\n status: RegistrationStatus;\n}\n\n/** A note is either a recognised specialism or a plain annotation — a closed set,\n not an open string, so a typo can't slip through. */\nexport type AantekeningType = 'Specialisme' | 'Aantekening';\n\nexport interface Aantekening {\n type: AantekeningType;\n omschrijving: string;\n datum: string;\n}\n", "properties": [ { "name": "datum", "deprecated": false, "deprecationMessage": "", "type": "string", "indexKey": "", "optional": false, "description": "", "line": 32 }, { "name": "omschrijving", "deprecated": false, "deprecationMessage": "", "type": "string", "indexKey": "", "optional": false, "description": "", "line": 31 }, { "name": "type", "deprecated": false, "deprecationMessage": "", "type": "AantekeningType", "indexKey": "", "optional": false, "description": "", "line": 30 } ], "indexSignatures": [], "kind": 172, "methods": [], "extends": [] }, { "name": "Adres", "id": "interface-Adres-07cec46d80a41919e40d0bcb002981627d1a30edb363d64a0a140a8af2c38ad85be5603d88030d0704870800694c5bed9c709ae6891fe83e646e90c1a67cf548", "file": "src/app/registratie/domain/person.ts", "deprecated": false, "deprecationMessage": "", "type": "interface", "sourceCode": "export interface Adres {\n straat: string;\n postcode: string;\n woonplaats: string;\n}\n\nexport interface Person {\n naam: string;\n geboortedatum: string; // ISO date\n adres: Adres;\n}\n", "properties": [ { "name": "postcode", "deprecated": false, "deprecationMessage": "", "type": "string", "indexKey": "", "optional": false, "description": "", "line": 4 }, { "name": "straat", "deprecated": false, "deprecationMessage": "", "type": "string", "indexKey": "", "optional": false, "description": "", "line": 3 }, { "name": "woonplaats", "deprecated": false, "deprecationMessage": "", "type": "string", "indexKey": "", "optional": false, "description": "", "line": 5 } ], "indexSignatures": [], "kind": 172, "description": "
Person identity as supplied by the BRP (Basisregistratie Personen).
\n", "rawdescription": "\nPerson identity as supplied by the BRP (Basisregistratie Personen).", "methods": [], "extends": [] }, { "name": "Answers", "id": "interface-Answers-13704a2a04ab3cffa46cbc109ee84699b236928e1c2649f459e18e4daf323047e8b21cdd5a21440c5fd696a605a09feb673b4020394ba7954ae35162f1bd2732", "file": "src/app/herregistratie/domain/intake.machine.ts", "deprecated": false, "deprecationMessage": "", "type": "interface", "sourceCode": "import { Result, ok, err, assertNever } from '@shared/kernel/fp';\nimport { Uren, parseUren } from '@registratie/domain/value-objects/uren';\n\n/**\n * A FIXED 3-step wizard with progressive disclosure. The steps never change in\n * number (always `STEPS`); instead, follow-up questions appear *inline within a\n * step* depending on earlier answers — answer \"buiten Nederland gewerkt? → ja\"\n * and the country/hours questions reveal in the same step; report few hours and\n * the scholing-question reveals inside the 'werk' step. \"Is this field required\n * right now\" is a pure function (`validateStep`/`lageUren`), so it's trivial to\n * test and impossible to get out of sync with the data.\n */\n\nexport type JaNee = 'ja' | 'nee';\n\n/** The three fixed steps. Each step groups one or more questions. */\nexport type StepId = 'buitenland' | 'werk' | 'review';\n\n/** One record carried across every step (and persisted). All optional: the user\n fills it in gradually, and branches may never ask some fields. */\nexport interface Answers {\n buitenlandGewerkt?: JaNee; // Q1\n land?: string; // Q1a — only when buitenlandGewerkt === 'ja'\n buitenlandseUren?: string; // Q1b — only when buitenlandGewerkt === 'ja'\n uren?: string; // Q2 — uren in NL\n scholingGevolgd?: JaNee; // Q3 — only when total hours are below the threshold\n punten?: string; // Q4\n}\n\n/** What we have after the review step parses — guaranteed valid/typed. */\nexport interface ValidIntake {\n werktBuitenland: boolean;\n land?: string;\n buitenlandseUren?: Uren;\n uren: Uren;\n aanvullendeScholing?: boolean;\n punten?: Uren; // only collected when aanvullende scholing is gevolgd (scholingGevolgd === 'ja')\n}\n\n/** Demo fallback only — the real threshold is a SERVER-OWNED policy value fetched\n at runtime (see IntakePolicyDto / SetPolicy). ponytail: default is the offline\n fallback; the server value wins. */\nexport const SCHOLING_THRESHOLD_DEFAULT = 1000;\n\n/** True when NL-hours are low enough that the scholing question must be answered.\n The threshold is passed in (server-owned), not hardcoded. */\nexport function lageUren(a: Answers, scholingThreshold = SCHOLING_THRESHOLD_DEFAULT): boolean {\n const r = parseUren(a.uren ?? '');\n return r.ok && r.value < scholingThreshold;\n}\n\n/** The fixed step list. Number of steps never changes; questions reveal inline. */\nexport const STEPS: StepId[] = ['buitenland', 'werk', 'review'];\n\n/** Per-field error map: one message per question, since a step holds several. */\ntype Errors = PartialOne record carried across every step (and persisted). All optional: the user\nfills it in gradually, and branches may never ask some fields.
\n", "rawdescription": "\nOne record carried across every step (and persisted). All optional: the user\nfills it in gradually, and branches may never ask some fields.", "methods": [], "extends": [] }, { "name": "BigProfile", "id": "interface-BigProfile-c363e317899ff3cd424b0033c2f57ea14e9617f52401171543b5a82d67046a894a2806afc198812808d0080b3093471e081f7e79b12f2c8c37eef68785e47a43", "file": "src/app/registratie/domain/big-profile.ts", "deprecated": false, "deprecationMessage": "", "type": "interface", "sourceCode": "import { Registration } from './registration';\nimport { Person } from './person';\n\n/**\n * The view the dashboard/detail render: a registration (from the BIG-register)\n * enriched with person data (from the BRP). It only exists when BOTH sources\n * have loaded — see BigProfileStore, which builds it with map2.\n */\nexport interface BigProfile {\n registration: Registration;\n person: Person;\n}\n", "properties": [ { "name": "person", "deprecated": false, "deprecationMessage": "", "type": "Person", "indexKey": "", "optional": false, "description": "", "line": 11 }, { "name": "registration", "deprecated": false, "deprecationMessage": "", "type": "Registration", "indexKey": "", "optional": false, "description": "", "line": 10 } ], "indexSignatures": [], "kind": 172, "description": "The view the dashboard/detail render: a registration (from the BIG-register)\nenriched with person data (from the BRP). It only exists when BOTH sources\nhave loaded — see BigProfileStore, which builds it with map2.
\n", "rawdescription": "\n\nThe view the dashboard/detail render: a registration (from the BIG-register)\nenriched with person data (from the BRP). It only exists when BOTH sources\nhave loaded — see BigProfileStore, which builds it with map2.\n", "methods": [], "extends": [] }, { "name": "BreadcrumbItem", "id": "interface-BreadcrumbItem-4dedba5c509fabd51900b3062e33290365b01e1fdc64a11c5ce7fe12f20201b340d7fcfbe61254b0d0b7a386ab40a29795bd467542fb1a353f4d9bda46e65688", "file": "src/app/shared/layout/breadcrumb/breadcrumb.component.ts", "deprecated": false, "deprecationMessage": "", "type": "interface", "sourceCode": "import { Component, input } from '@angular/core';\nimport { RouterLink } from '@angular/router';\n\nexport interface BreadcrumbItem {\n label: string;\n link?: string; // omit on the current (last) page\n}\n\n/** Chrome: breadcrumb navigation. Renders the RHC/Utrecht breadcrumb pattern; the\n last item is the current page (no link, aria-current). Domain-free — the caller\n supplies the trail. */\n@Component({\n selector: 'app-breadcrumb',\n imports: [RouterLink],\n styles: [`\n :host{display:block}\n .list{display:flex;flex-wrap:wrap;gap:var(--rhc-space-max-md);align-items:center;list-style:none;margin:0;padding:0}\n .sep{color:var(--rhc-color-foreground-subtle)}\n `],\n template: `\n \n `,\n})\nexport class BreadcrumbComponent {\n items = input.requiredWIRE CONTRACT for the BRP address lookup ("BFF-lite" — one screen-shaped call).
\nIn production this is GENERATED from the OpenAPI/TypeSpec spec and served by our\nown backend, which talks to the BRP behind an adapter. The frontend never sees\nthe BRP's own wire format. See docs/architecture/0001-bff-lite-decision-dtos.md.
\n"Geen adres bekend" is a first-class outcome (gevonden: false), not an error —\nthe wizard falls back to manual entry (PRD §7). Slice 1 ships only the happy\npath (gevonden: true).
A submitted change request carries a parsed postcode (branded Postcode),\nnot a raw string — downstream code can't receive an unvalidated one.
\n", "rawdescription": "\nA submitted change request carries a *parsed* postcode (branded Postcode),\nnot a raw string — downstream code can't receive an unvalidated one.", "methods": [], "extends": [] }, { "name": "DashboardView", "id": "interface-DashboardView-b39e266ec8fabdaddad87f1e15a5b1b86e45d84ac2c95028b4e676c2eb425fd675c77383c3d4f8f88f4a072f3eb88a954eb0f8755597224ebef59da18d24fda0", "file": "src/app/registratie/contracts/dashboard-view.dto.ts", "deprecated": false, "deprecationMessage": "", "type": "interface", "sourceCode": "import { Registration } from '@registratie/domain/registration';\nimport { Person } from '@registratie/domain/person';\nimport { BigProfile } from '@registratie/domain/big-profile';\n\n/**\n * WIRE CONTRACT for the dashboard screen — the \"BFF-lite\" response.\n *\n * In production this type is GENERATED from the OpenAPI/TypeSpec spec (one source\n * of truth for both sides), and the `decisions` block is computed BY THE BACKEND\n * — never recomputed on the client. The frontend renders decisions; it does not\n * own the rules. See docs/architecture/0001-bff-lite-decision-dtos.md.\n *\n * One screen-shaped call replaces the previous three (BIG-register + BRP + …),\n * so the page always sees one consistent snapshot instead of three independently\n * loading/erroring resources.\n */\nexport interface DashboardViewDto {\n registration: Registration;\n person: Person;\n decisions: HerregistratieDecisions;\n}\n\n/** Server-computed decisions. The eligibility rule lives on the backend; the\n optional reason lets the UI explain itself without knowing the rule. */\nexport interface HerregistratieDecisions {\n eligibleForHerregistratie: boolean;\n herregistratieReason?: string;\n}\n\n/** The parsed, frontend-side view (DTO mapped onto our own domain model). Keeping\n this distinct from DashboardViewDto is the decoupling seam: the wire shape can\n change without the FE domain following, and vice-versa. */\nexport interface DashboardView {\n profile: BigProfile;\n decisions: HerregistratieDecisions;\n}\n", "properties": [ { "name": "decisions", "deprecated": false, "deprecationMessage": "", "type": "HerregistratieDecisions", "indexKey": "", "optional": false, "description": "", "line": 35 }, { "name": "profile", "deprecated": false, "deprecationMessage": "", "type": "BigProfile", "indexKey": "", "optional": false, "description": "", "line": 34 } ], "indexSignatures": [], "kind": 172, "description": "The parsed, frontend-side view (DTO mapped onto our own domain model). Keeping\nthis distinct from DashboardViewDto is the decoupling seam: the wire shape can\nchange without the FE domain following, and vice-versa.
\n", "rawdescription": "\nThe parsed, frontend-side view (DTO mapped onto our own domain model). Keeping\nthis distinct from DashboardViewDto is the decoupling seam: the wire shape can\nchange without the FE domain following, and vice-versa.", "methods": [], "extends": [] }, { "name": "DashboardViewDto", "id": "interface-DashboardViewDto-b39e266ec8fabdaddad87f1e15a5b1b86e45d84ac2c95028b4e676c2eb425fd675c77383c3d4f8f88f4a072f3eb88a954eb0f8755597224ebef59da18d24fda0", "file": "src/app/registratie/contracts/dashboard-view.dto.ts", "deprecated": false, "deprecationMessage": "", "type": "interface", "sourceCode": "import { Registration } from '@registratie/domain/registration';\nimport { Person } from '@registratie/domain/person';\nimport { BigProfile } from '@registratie/domain/big-profile';\n\n/**\n * WIRE CONTRACT for the dashboard screen — the \"BFF-lite\" response.\n *\n * In production this type is GENERATED from the OpenAPI/TypeSpec spec (one source\n * of truth for both sides), and the `decisions` block is computed BY THE BACKEND\n * — never recomputed on the client. The frontend renders decisions; it does not\n * own the rules. See docs/architecture/0001-bff-lite-decision-dtos.md.\n *\n * One screen-shaped call replaces the previous three (BIG-register + BRP + …),\n * so the page always sees one consistent snapshot instead of three independently\n * loading/erroring resources.\n */\nexport interface DashboardViewDto {\n registration: Registration;\n person: Person;\n decisions: HerregistratieDecisions;\n}\n\n/** Server-computed decisions. The eligibility rule lives on the backend; the\n optional reason lets the UI explain itself without knowing the rule. */\nexport interface HerregistratieDecisions {\n eligibleForHerregistratie: boolean;\n herregistratieReason?: string;\n}\n\n/** The parsed, frontend-side view (DTO mapped onto our own domain model). Keeping\n this distinct from DashboardViewDto is the decoupling seam: the wire shape can\n change without the FE domain following, and vice-versa. */\nexport interface DashboardView {\n profile: BigProfile;\n decisions: HerregistratieDecisions;\n}\n", "properties": [ { "name": "decisions", "deprecated": false, "deprecationMessage": "", "type": "HerregistratieDecisions", "indexKey": "", "optional": false, "description": "", "line": 20 }, { "name": "person", "deprecated": false, "deprecationMessage": "", "type": "Person", "indexKey": "", "optional": false, "description": "", "line": 19 }, { "name": "registration", "deprecated": false, "deprecationMessage": "", "type": "Registration", "indexKey": "", "optional": false, "description": "", "line": 18 } ], "indexSignatures": [], "kind": 172, "description": "WIRE CONTRACT for the dashboard screen — the "BFF-lite" response.
\nIn production this type is GENERATED from the OpenAPI/TypeSpec spec (one source\nof truth for both sides), and the decisions block is computed BY THE BACKEND\n— never recomputed on the client. The frontend renders decisions; it does not\nown the rules. See docs/architecture/0001-bff-lite-decision-dtos.md.
One screen-shaped call replaces the previous three (BIG-register + BRP + …),\nso the page always sees one consistent snapshot instead of three independently\nloading/erroring resources.
\n", "rawdescription": "\n\nWIRE CONTRACT for the dashboard screen — the \"BFF-lite\" response.\n\nIn production this type is GENERATED from the OpenAPI/TypeSpec spec (one source\nof truth for both sides), and the `decisions` block is computed BY THE BACKEND\n— never recomputed on the client. The frontend renders decisions; it does not\nown the rules. See docs/architecture/0001-bff-lite-decision-dtos.md.\n\nOne screen-shaped call replaces the previous three (BIG-register + BRP + …),\nso the page always sees one consistent snapshot instead of three independently\nloading/erroring resources.\n", "methods": [], "extends": [] }, { "name": "Draft", "id": "interface-Draft-097a742aa05bc7bbfee387dd3ea5b2ac382815db8ca18107e699d11e6da110cdeae2eb377bcea284f415cfd263937c3b0f6e7ed2ee9090d660d898dddefe3a4f", "file": "src/app/herregistratie/domain/herregistratie.machine.ts", "deprecated": false, "deprecationMessage": "", "type": "interface", "sourceCode": "import { Result, assertNever } from '@shared/kernel/fp';\nimport { Uren, parseUren } from '@registratie/domain/value-objects/uren';\n\n/** What the user is typing (raw, possibly invalid). */\nexport interface Draft {\n uren: string;\n jaren: string;\n punten: string;\n}\n\n/** What we have AFTER parsing — branded/typed, guaranteed valid. */\nexport interface Valid {\n uren: Uren;\n jaren: number;\n punten: number;\n}\n\n/**\n * The whole wizard as one tagged union. `step` and `errors` exist ONLY while\n * Editing; Submitting/Submitted/Failed carry a `Valid` payload and nothing else.\n * So \"submitting while a field is invalid\" or \"showing the success screen with\n * errors set\" are unrepresentable — the bug class is gone by construction.\n */\nexport type WizardState =\n | { tag: 'Editing'; step: 1 | 2; draft: Draft; errors: PartialWhat the user is typing (raw, possibly invalid).
\n", "rawdescription": "\nWhat the user is typing (raw, possibly invalid).", "methods": [], "extends": [] }, { "name": "Draft", "id": "interface-Draft-6ed41f6a28b6c00dc907f54219be9c1d7955aa11bc22f128620d2206b1ea12e6730533ac33f5f5df7b8d7c8d7f977584b3a0a3e98a6c2c3b91d1afe6411278e2-1", "file": "src/app/registratie/domain/registratie-wizard.machine.ts", "deprecated": false, "deprecationMessage": "", "type": "interface", "sourceCode": "import { Result, ok, err, assertNever } from '@shared/kernel/fp';\nimport { Postcode, parsePostcode } from '@registratie/domain/value-objects/postcode';\nimport { Email, parseEmail } from '@registratie/domain/value-objects/email';\n\n/**\n * A FIXED 3-step registration wizard. The steps never change in number (always\n * `STEPS`): (1) adres + correspondentievoorkeur, (2) beroep o.b.v. diploma,\n * (3) controle & indienen. Follow-up questions appear *inline within a step*\n * (e.g. choosing 'email' reveals the e-mail field). \"Is this field required\n * right now\" is a pure function (`validateStep`), so it is trivial to test and\n * impossible to get out of sync with the data. Invariants live here, not in the\n * UI: the wizard reaches `Indienen` only when a complete `ValidRegistratie` parses.\n */\n\nexport type StepId = 'adres' | 'beroep' | 'controle';\n\n/** The fixed step list. Number of steps never changes; questions reveal inline. */\nexport const STEPS: StepId[] = ['adres', 'beroep', 'controle'];\n\n/** Where a piece of data came from — recorded on the aggregate (PRD §5). */\nexport type AdresHerkomst = 'brp' | 'handmatig';\nexport type DiplomaHerkomst = 'duo' | 'handmatig';\nexport type Correspondentie = 'email' | 'post';\n\n/** One record carried across every step (and persisted). All optional: the user\n fills it in gradually. Adres fields are kept flat so one `SetField` message\n serves them all (mirrors the intake machine). */\nexport interface Draft {\n straat?: string;\n postcode?: string;\n woonplaats?: string;\n adresHerkomst?: AdresHerkomst;\n correspondentie?: Correspondentie;\n email?: string;\n diplomaId?: string;\n diplomaHerkomst?: DiplomaHerkomst;\n beroep?: string; // DERIVED from the chosen DUO diploma (or declared for a manual one)\n vraagIds?: string[]; // ids of the policy questions that apply to the chosen diploma\n antwoorden: RecordOne record carried across every step (and persisted). All optional: the user\nfills it in gradually. Adres fields are kept flat so one SetField message\nserves them all (mirrors the intake machine).
WIRE CONTRACT for the DUO diploma lookup ("BFF-lite" — one screen-shaped call\nreturning everything the beroep step needs).
\nEach diploma carries its server-computed beroep (the profession it maps to)\nand the policyQuestions (geldigheidsvragen) that apply to it. These are\nDECISIONS computed by the backend from the diploma's attributes — the frontend\nrenders them, it does not derive them (decision-DTO pattern, ADR-0001). E.g. an\nEnglish-language diploma carries the Dutch-proficiency question.
handmatig is the fallback when the diploma is not in the DUO list: the\nprofessions the user may declare and the MAXIMAL policy-question set that then\napplies (a manual diploma is unverified, so the strictest set is used).
Per-field error map. antwoorden holds per-policy-question errors, keyed by\nquestion id (a step can show several questions).
Server-computed decisions. The eligibility rule lives on the backend; the\noptional reason lets the UI explain itself without knowing the rule.
\n", "rawdescription": "\nServer-computed decisions. The eligibility rule lives on the backend; the\noptional reason lets the UI explain itself without knowing the rule.", "methods": [], "extends": [] }, { "name": "IntakePolicyDto", "id": "interface-IntakePolicyDto-1c35bbad790b2fa78117a69dd0537aa3737a0ede256f3d6834bedb78c85cb056d6f571ed0667abc30f5f6c9eff3e6561723917f21ba9f67b0712fd109594b27a", "file": "src/app/herregistratie/contracts/intake-policy.dto.ts", "deprecated": false, "deprecationMessage": "", "type": "interface", "sourceCode": "export interface IntakePolicyDto {\n /** Below this many NL-hours the scholing question is required. */\n scholingThreshold: number;\n}\n", "properties": [ { "name": "scholingThreshold", "deprecated": false, "deprecationMessage": "", "type": "number", "indexKey": "", "optional": false, "description": "Below this many NL-hours the scholing question is required.
\n", "line": 11, "rawdescription": "\nBelow this many NL-hours the scholing question is required." } ], "indexSignatures": [], "kind": 172, "description": "WIRE CONTRACT for intake policy values owned by the backend.
\nThis is the "config value" shape of moving policy off the client: instead of\nhardcoding the scholing threshold in the frontend, the backend ships the value\nand the UI applies it for instant feedback. The backend remains the AUTHORITY\n— it re-validates on submit. See docs/architecture/0001-bff-lite-decision-dtos.md.
\n", "rawdescription": "\n\nWIRE CONTRACT for intake policy values owned by the backend.\n\nThis is the \"config value\" shape of moving policy off the client: instead of\nhardcoding the scholing threshold in the frontend, the backend ships the value\nand the UI applies it for instant feedback. The backend remains the AUTHORITY\n— it re-validates on submit. See docs/architecture/0001-bff-lite-decision-dtos.md.\n", "methods": [], "extends": [] }, { "name": "ManualDiplomaPolicyDto", "id": "interface-ManualDiplomaPolicyDto-03b724eabc3fb95affe36abb0bef921275f0c9eeefd35fab64dd906d4d76e5a38fe849098232c0aaeaf7dd32fa6c0a7b7f2a1bfbbf4c03de4a440f860b3c46e1", "file": "src/app/registratie/contracts/duo-diplomas.dto.ts", "deprecated": false, "deprecationMessage": "", "type": "interface", "sourceCode": "export interface DuoLookupDto {\n diplomas: DuoDiplomaDto[];\n handmatig: ManualDiplomaPolicyDto;\n}\n\nexport interface DuoDiplomaDto {\n id: string;\n naam: string;\n instelling: string;\n jaar: number;\n beroep: string; // server-derived profession\n policyQuestions: PolicyQuestionDto[]; // server-decided geldigheidsvragen\n}\n\nexport interface ManualDiplomaPolicyDto {\n beroepen: string[]; // professions the user may declare for a manual diploma\n policyQuestions: PolicyQuestionDto[]; // maximal set applied to a manual diploma\n}\n\nexport interface PolicyQuestionDto {\n id: string;\n vraag: string;\n type: 'ja-nee' | 'tekst';\n}\n", "properties": [ { "name": "beroepen", "deprecated": false, "deprecationMessage": "", "type": "string[]", "indexKey": "", "optional": false, "description": "", "line": 30 }, { "name": "policyQuestions", "deprecated": false, "deprecationMessage": "", "type": "PolicyQuestionDto[]", "indexKey": "", "optional": false, "description": "", "line": 31 } ], "indexSignatures": [], "kind": 172, "methods": [], "extends": [] }, { "name": "Person", "id": "interface-Person-07cec46d80a41919e40d0bcb002981627d1a30edb363d64a0a140a8af2c38ad85be5603d88030d0704870800694c5bed9c709ae6891fe83e646e90c1a67cf548", "file": "src/app/registratie/domain/person.ts", "deprecated": false, "deprecationMessage": "", "type": "interface", "sourceCode": "export interface Adres {\n straat: string;\n postcode: string;\n woonplaats: string;\n}\n\nexport interface Person {\n naam: string;\n geboortedatum: string; // ISO date\n adres: Adres;\n}\n", "properties": [ { "name": "adres", "deprecated": false, "deprecationMessage": "", "type": "Adres", "indexKey": "", "optional": false, "description": "", "line": 11 }, { "name": "geboortedatum", "deprecated": false, "deprecationMessage": "", "type": "string", "indexKey": "", "optional": false, "description": "", "line": 10 }, { "name": "naam", "deprecated": false, "deprecationMessage": "", "type": "string", "indexKey": "", "optional": false, "description": "", "line": 9 } ], "indexSignatures": [], "kind": 172, "methods": [], "extends": [] }, { "name": "PolicyQuestionDto", "id": "interface-PolicyQuestionDto-03b724eabc3fb95affe36abb0bef921275f0c9eeefd35fab64dd906d4d76e5a38fe849098232c0aaeaf7dd32fa6c0a7b7f2a1bfbbf4c03de4a440f860b3c46e1", "file": "src/app/registratie/contracts/duo-diplomas.dto.ts", "deprecated": false, "deprecationMessage": "", "type": "interface", "sourceCode": "export interface DuoLookupDto {\n diplomas: DuoDiplomaDto[];\n handmatig: ManualDiplomaPolicyDto;\n}\n\nexport interface DuoDiplomaDto {\n id: string;\n naam: string;\n instelling: string;\n jaar: number;\n beroep: string; // server-derived profession\n policyQuestions: PolicyQuestionDto[]; // server-decided geldigheidsvragen\n}\n\nexport interface ManualDiplomaPolicyDto {\n beroepen: string[]; // professions the user may declare for a manual diploma\n policyQuestions: PolicyQuestionDto[]; // maximal set applied to a manual diploma\n}\n\nexport interface PolicyQuestionDto {\n id: string;\n vraag: string;\n type: 'ja-nee' | 'tekst';\n}\n", "properties": [ { "name": "id", "deprecated": false, "deprecationMessage": "", "type": "string", "indexKey": "", "optional": false, "description": "", "line": 35 }, { "name": "type", "deprecated": false, "deprecationMessage": "", "type": "\"ja-nee\" | \"tekst\"", "indexKey": "", "optional": false, "description": "", "line": 37 }, { "name": "vraag", "deprecated": false, "deprecationMessage": "", "type": "string", "indexKey": "", "optional": false, "description": "", "line": 36 } ], "indexSignatures": [], "kind": 172, "methods": [], "extends": [] }, { "name": "RadioOption", "id": "interface-RadioOption-a4c75390d3b62730cdd6f53a2ffcb3badde60f23c9104d57d8f8221d038f1dc96a229916ee28bbec4a54dd41e0e88c838ea46b35facfab0ddb5fea79fed37cc0", "file": "src/app/shared/ui/radio-group/radio-group.component.ts", "deprecated": false, "deprecationMessage": "", "type": "interface", "sourceCode": "import { Component, forwardRef, input } from '@angular/core';\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\n\nexport interface RadioOption {\n value: string;\n label: string;\n}\n\n/** Atom: a radio group. Thin wrapper over the Utrecht/RHC radio CSS, wired as a\n form control so it works with ngModel just like the text-input atom. */\n@Component({\n selector: 'app-radio-group',\n styles: [`\n .rhc-radio-option {\n display: flex;\n align-items: center;\n gap: var(--rhc-space-max-md);\n padding-block: var(--rhc-space-max-sm);\n }\n `],\n template: `\nWho is logged in. Framework-free domain type.
\n", "rawdescription": "\nWho is logged in. Framework-free domain type.", "methods": [], "extends": [] }, { "name": "Store", "id": "interface-Store-de6d0ec7e0704c5d9490e9a33e624477e924daff53384c527eb4aaa76178bd1716ada071d7e46af3e0a859a7cbec63cdc114f61db5d36b61e49effcd5ac744f9", "file": "src/app/shared/application/store.ts", "deprecated": false, "deprecationMessage": "", "type": "interface", "sourceCode": "import { Signal, signal } from '@angular/core';\n\n/**\n * A tiny \"Elm-style\" store. The whole idea: all state lives in ONE value\n * (the Model). The only way to change it is to send a message (Msg) to a PURE\n * function `update(model, msg)` that returns the next Model. Nothing else\n * mutates state, so to understand the app you only read the update function.\n *\n * Side effects (HTTP, timers) do NOT go in `update` — that stays pure and easy\n * to test. Instead, effectful \"command\" functions call the network and then\n * `dispatch` a message describing what happened (e.g. Loaded / Failed).\n */\nexport interface StoreThe current state, as a read-only Angular signal.
\n", "line": 15, "rawdescription": "\nThe current state, as a read-only Angular signal.", "modifierKind": [ 148 ] } ], "indexSignatures": [], "kind": 174, "description": "A tiny "Elm-style" store. The whole idea: all state lives in ONE value\n(the Model). The only way to change it is to send a message (Msg) to a PURE\nfunction update(model, msg) that returns the next Model. Nothing else\nmutates state, so to understand the app you only read the update function.
Side effects (HTTP, timers) do NOT go in update — that stays pure and easy\nto test. Instead, effectful "command" functions call the network and then\ndispatch a message describing what happened (e.g. Loaded / Failed).
Send a message; the model becomes update(model, msg).
\n", "jsdoctags": [ { "name": "msg", "type": "Msg", "optional": false, "dotDotDotToken": false, "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] } ], "extends": [] }, { "name": "Valid", "id": "interface-Valid-097a742aa05bc7bbfee387dd3ea5b2ac382815db8ca18107e699d11e6da110cdeae2eb377bcea284f415cfd263937c3b0f6e7ed2ee9090d660d898dddefe3a4f", "file": "src/app/herregistratie/domain/herregistratie.machine.ts", "deprecated": false, "deprecationMessage": "", "type": "interface", "sourceCode": "import { Result, assertNever } from '@shared/kernel/fp';\nimport { Uren, parseUren } from '@registratie/domain/value-objects/uren';\n\n/** What the user is typing (raw, possibly invalid). */\nexport interface Draft {\n uren: string;\n jaren: string;\n punten: string;\n}\n\n/** What we have AFTER parsing — branded/typed, guaranteed valid. */\nexport interface Valid {\n uren: Uren;\n jaren: number;\n punten: number;\n}\n\n/**\n * The whole wizard as one tagged union. `step` and `errors` exist ONLY while\n * Editing; Submitting/Submitted/Failed carry a `Valid` payload and nothing else.\n * So \"submitting while a field is invalid\" or \"showing the success screen with\n * errors set\" are unrepresentable — the bug class is gone by construction.\n */\nexport type WizardState =\n | { tag: 'Editing'; step: 1 | 2; draft: Draft; errors: PartialWhat we have AFTER parsing — branded/typed, guaranteed valid.
\n", "rawdescription": "\nWhat we have AFTER parsing — branded/typed, guaranteed valid.", "methods": [], "extends": [] }, { "name": "ValidIntake", "id": "interface-ValidIntake-13704a2a04ab3cffa46cbc109ee84699b236928e1c2649f459e18e4daf323047e8b21cdd5a21440c5fd696a605a09feb673b4020394ba7954ae35162f1bd2732", "file": "src/app/herregistratie/domain/intake.machine.ts", "deprecated": false, "deprecationMessage": "", "type": "interface", "sourceCode": "import { Result, ok, err, assertNever } from '@shared/kernel/fp';\nimport { Uren, parseUren } from '@registratie/domain/value-objects/uren';\n\n/**\n * A FIXED 3-step wizard with progressive disclosure. The steps never change in\n * number (always `STEPS`); instead, follow-up questions appear *inline within a\n * step* depending on earlier answers — answer \"buiten Nederland gewerkt? → ja\"\n * and the country/hours questions reveal in the same step; report few hours and\n * the scholing-question reveals inside the 'werk' step. \"Is this field required\n * right now\" is a pure function (`validateStep`/`lageUren`), so it's trivial to\n * test and impossible to get out of sync with the data.\n */\n\nexport type JaNee = 'ja' | 'nee';\n\n/** The three fixed steps. Each step groups one or more questions. */\nexport type StepId = 'buitenland' | 'werk' | 'review';\n\n/** One record carried across every step (and persisted). All optional: the user\n fills it in gradually, and branches may never ask some fields. */\nexport interface Answers {\n buitenlandGewerkt?: JaNee; // Q1\n land?: string; // Q1a — only when buitenlandGewerkt === 'ja'\n buitenlandseUren?: string; // Q1b — only when buitenlandGewerkt === 'ja'\n uren?: string; // Q2 — uren in NL\n scholingGevolgd?: JaNee; // Q3 — only when total hours are below the threshold\n punten?: string; // Q4\n}\n\n/** What we have after the review step parses — guaranteed valid/typed. */\nexport interface ValidIntake {\n werktBuitenland: boolean;\n land?: string;\n buitenlandseUren?: Uren;\n uren: Uren;\n aanvullendeScholing?: boolean;\n punten?: Uren; // only collected when aanvullende scholing is gevolgd (scholingGevolgd === 'ja')\n}\n\n/** Demo fallback only — the real threshold is a SERVER-OWNED policy value fetched\n at runtime (see IntakePolicyDto / SetPolicy). ponytail: default is the offline\n fallback; the server value wins. */\nexport const SCHOLING_THRESHOLD_DEFAULT = 1000;\n\n/** True when NL-hours are low enough that the scholing question must be answered.\n The threshold is passed in (server-owned), not hardcoded. */\nexport function lageUren(a: Answers, scholingThreshold = SCHOLING_THRESHOLD_DEFAULT): boolean {\n const r = parseUren(a.uren ?? '');\n return r.ok && r.value < scholingThreshold;\n}\n\n/** The fixed step list. Number of steps never changes; questions reveal inline. */\nexport const STEPS: StepId[] = ['buitenland', 'werk', 'review'];\n\n/** Per-field error map: one message per question, since a step holds several. */\ntype Errors = PartialWhat we have after the review step parses — guaranteed valid/typed.
\n", "rawdescription": "\nWhat we have after the review step parses — guaranteed valid/typed.", "methods": [], "extends": [] }, { "name": "ValidRegistratie", "id": "interface-ValidRegistratie-6ed41f6a28b6c00dc907f54219be9c1d7955aa11bc22f128620d2206b1ea12e6730533ac33f5f5df7b8d7c8d7f977584b3a0a3e98a6c2c3b91d1afe6411278e2", "file": "src/app/registratie/domain/registratie-wizard.machine.ts", "deprecated": false, "deprecationMessage": "", "type": "interface", "sourceCode": "import { Result, ok, err, assertNever } from '@shared/kernel/fp';\nimport { Postcode, parsePostcode } from '@registratie/domain/value-objects/postcode';\nimport { Email, parseEmail } from '@registratie/domain/value-objects/email';\n\n/**\n * A FIXED 3-step registration wizard. The steps never change in number (always\n * `STEPS`): (1) adres + correspondentievoorkeur, (2) beroep o.b.v. diploma,\n * (3) controle & indienen. Follow-up questions appear *inline within a step*\n * (e.g. choosing 'email' reveals the e-mail field). \"Is this field required\n * right now\" is a pure function (`validateStep`), so it is trivial to test and\n * impossible to get out of sync with the data. Invariants live here, not in the\n * UI: the wizard reaches `Indienen` only when a complete `ValidRegistratie` parses.\n */\n\nexport type StepId = 'adres' | 'beroep' | 'controle';\n\n/** The fixed step list. Number of steps never changes; questions reveal inline. */\nexport const STEPS: StepId[] = ['adres', 'beroep', 'controle'];\n\n/** Where a piece of data came from — recorded on the aggregate (PRD §5). */\nexport type AdresHerkomst = 'brp' | 'handmatig';\nexport type DiplomaHerkomst = 'duo' | 'handmatig';\nexport type Correspondentie = 'email' | 'post';\n\n/** One record carried across every step (and persisted). All optional: the user\n fills it in gradually. Adres fields are kept flat so one `SetField` message\n serves them all (mirrors the intake machine). */\nexport interface Draft {\n straat?: string;\n postcode?: string;\n woonplaats?: string;\n adresHerkomst?: AdresHerkomst;\n correspondentie?: Correspondentie;\n email?: string;\n diplomaId?: string;\n diplomaHerkomst?: DiplomaHerkomst;\n beroep?: string; // DERIVED from the chosen DUO diploma (or declared for a manual one)\n vraagIds?: string[]; // ids of the policy questions that apply to the chosen diploma\n antwoorden: RecordWhat we have after the controle step parses — guaranteed valid/typed.
\n", "rawdescription": "\nWhat we have after the controle step parses — guaranteed valid/typed.", "methods": [], "extends": [] } ], "injectables": [ { "name": "BigProfileStore", "id": "injectable-BigProfileStore-69aed5b05b57a19cafee014d2f45ac87468f795733cf7c00ad07d0283d30edd836e2d4b8a45cad42641fa5c84cad96f314aa4d287ca1c55d3fdd8feceefcd642", "file": "src/app/registratie/application/big-profile.store.ts", "properties": [ { "name": "aantekeningen", "defaultValue": "computedSpecialisms/notes stay a separate stream (they have their own empty state).
\n", "line": 45, "rawdescription": "\nSpecialisms/notes stay a separate stream (they have their own empty state).", "modifierKind": [ 148 ] }, { "name": "aantekeningenRes", "defaultValue": "this.big.aantekeningenResource()", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 28, "modifierKind": [ 123 ] }, { "name": "big", "defaultValue": "inject(BigRegisterAdapter)", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 24, "modifierKind": [ 123 ] }, { "name": "decisions", "defaultValue": "computedServer-computed decisions (e.g. herregistratie eligibility) — rendered, not recomputed.
\n", "line": 42, "rawdescription": "\nServer-computed decisions (e.g. herregistratie eligibility) — rendered, not recomputed.", "modifierKind": [ 148 ] }, { "name": "pending", "defaultValue": "signal(false)", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 50, "modifierKind": [ 123 ] }, { "name": "pendingHerregistratie", "defaultValue": "this.pending.asReadonly()", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "True while a herregistratie submission is in flight or just submitted.
\n", "line": 52, "rawdescription": "\nTrue while a herregistratie submission is in flight or just submitted.", "modifierKind": [ 148 ] }, { "name": "profile", "defaultValue": "computedRegistration + person, from the single aggregated call.
\n", "line": 39, "rawdescription": "\nRegistration + person, from the single aggregated call.", "modifierKind": [ 148 ] }, { "name": "view", "defaultValue": "computedThe aggregated view, validated at the trust boundary (DTO → domain).
\n", "line": 31, "rawdescription": "\nThe aggregated view, validated at the trust boundary (DTO → domain).", "modifierKind": [ 123 ] }, { "name": "viewAdapter", "defaultValue": "inject(DashboardViewAdapter)", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 25, "modifierKind": [ 123 ] }, { "name": "viewRes", "defaultValue": "this.viewAdapter.dashboardViewResource()", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 27, "modifierKind": [ 123 ] } ], "methods": [ { "name": "beginHerregistratie", "args": [], "optional": false, "returnType": "void", "typeParameters": [], "line": 54, "deprecated": false, "deprecationMessage": "" }, { "name": "confirmHerregistratie", "args": [], "optional": false, "returnType": "void", "typeParameters": [], "line": 57, "deprecated": false, "deprecationMessage": "" }, { "name": "rollbackHerregistratie", "args": [], "optional": false, "returnType": "void", "typeParameters": [], "line": 61, "deprecated": false, "deprecationMessage": "" } ], "deprecated": false, "deprecationMessage": "", "description": "The single source of truth for the logged-in professional's profile, shared\nacross pages (providedIn:'root' = one instance). It owns the httpResources\n(created here, in the required injection context) and exposes them as\nRemoteData signals.
\nThe dashboard data now comes from ONE screen-shaped ("BFF-lite") call that\nreturns registration + person + server-computed decisions. One request → one\nconsistent snapshot, instead of stitching three independently loading/erroring\nresources together client-side. See docs/architecture/0001-bff-lite-decision-dtos.md.
Infrastructure adapter for the BIG-register source. Exposes signal-based\nresources (Angular's httpResource); each returns a Resource with\nstatus()/value()/error()/reload(). Call from an injection context\n(a field initializer in the store).
\nNote: registration + person are now served via the aggregated dashboard-view\nendpoint (see DashboardViewAdapter). Only the notes stream remains separate.
\n", "rawdescription": "\n\nInfrastructure adapter for the BIG-register source. Exposes signal-based\nresources (Angular's httpResource); each returns a Resource with\nstatus()/value()/error()/reload(). Call from an injection context\n(a field initializer in the store).\n\nNote: registration + person are now served via the aggregated dashboard-view\nendpoint (see DashboardViewAdapter). Only the notes stream remains separate.\n", "sourceCode": "import { Injectable } from '@angular/core';\nimport { httpResource } from '@angular/common/http';\nimport { Aantekening } from '../domain/registration';\n\n/**\n * Infrastructure adapter for the BIG-register source. Exposes signal-based\n * resources (Angular's httpResource); each returns a Resource with\n * status()/value()/error()/reload(). Call from an injection context\n * (a field initializer in the store).\n *\n * Note: registration + person are now served via the aggregated dashboard-view\n * endpoint (see DashboardViewAdapter). Only the notes stream remains separate.\n */\n@Injectable({ providedIn: 'root' })\nexport class BigRegisterAdapter {\n aantekeningenResource() {\n return httpResourceInfrastructure adapter for the BRP address lookup, reached only through our own\n("BFF-lite") endpoint — the anti-corruption boundary. In this POC the endpoint\nis a static mock; pointing at a real backend touches only this file + the DTO.
\n", "rawdescription": "\n\nInfrastructure adapter for the BRP address lookup, reached only through our own\n(\"BFF-lite\") endpoint — the anti-corruption boundary. In this POC the endpoint\nis a static mock; pointing at a real backend touches only this file + the DTO.\n", "sourceCode": "import { Injectable } from '@angular/core';\nimport { httpResource } from '@angular/common/http';\nimport { Result, ok, err } from '@shared/kernel/fp';\nimport { BrpAddressDto } from '@registratie/contracts/brp-address.dto';\n\n/**\n * Infrastructure adapter for the BRP address lookup, reached only through our own\n * (\"BFF-lite\") endpoint — the anti-corruption boundary. In this POC the endpoint\n * is a static mock; pointing at a real backend touches only this file + the DTO.\n */\n@Injectable({ providedIn: 'root' })\nexport class BrpAdapter {\n // Typed as the DTO for ergonomics, but the value is untrusted JSON until\n // parseBrpAddress validates it.\n adresResource() {\n return httpResourceInfrastructure adapter for the screen-shaped ("BFF-lite") dashboard endpoint.\nONE call returns registration + person + server-computed decisions.\n(In this POC the endpoint is a static mock; the decisions are precomputed to\nstand in for what the backend would compute.)
\n", "rawdescription": "\n\nInfrastructure adapter for the screen-shaped (\"BFF-lite\") dashboard endpoint.\nONE call returns registration + person + server-computed decisions.\n(In this POC the endpoint is a static mock; the decisions are precomputed to\nstand in for what the backend would compute.)\n", "sourceCode": "import { Injectable } from '@angular/core';\nimport { httpResource } from '@angular/common/http';\nimport { Result, ok, err } from '@shared/kernel/fp';\nimport { DashboardViewDto, DashboardView } from '@registratie/contracts/dashboard-view.dto';\n\n/**\n * Infrastructure adapter for the screen-shaped (\"BFF-lite\") dashboard endpoint.\n * ONE call returns registration + person + server-computed decisions.\n * (In this POC the endpoint is a static mock; the decisions are precomputed to\n * stand in for what the backend would compute.)\n */\n@Injectable({ providedIn: 'root' })\nexport class DashboardViewAdapter {\n // Typed as the DTO for ergonomics, but the value is still untrusted JSON —\n // parseDashboardView validates it at the boundary before the app uses it.\n dashboardViewResource() {\n return httpResourceInfrastructure: talks to the (mock) DigiD identity provider.
\n", "rawdescription": "\nInfrastructure: talks to the (mock) DigiD identity provider.", "sourceCode": "import { Injectable } from '@angular/core';\nimport { Result, ok, err } from '@shared/kernel/fp';\nimport { Session } from '../domain/session';\n\n/** Infrastructure: talks to the (mock) DigiD identity provider. */\n@Injectable({ providedIn: 'root' })\nexport class DigidAdapter {\n // ponytail: fake DigiD — any 9-digit BSN authenticates to a fixed identity.\n // Swap for a real OIDC redirect flow when there's a backend.\n async authenticate(bsn: string): PromiseInfrastructure adapter for the DUO diploma lookup, reached only through our own\n("BFF-lite") endpoint — the anti-corruption boundary. The response carries the\nuser's diplomas (each with its server-computed beroep + policy questions) and\nthe manual-entry fallback policy. The frontend renders; it does not derive. In\nthis POC the endpoint is a static mock.
\n", "rawdescription": "\n\nInfrastructure adapter for the DUO diploma lookup, reached only through our own\n(\"BFF-lite\") endpoint — the anti-corruption boundary. The response carries the\nuser's diplomas (each with its server-computed beroep + policy questions) and\nthe manual-entry fallback policy. The frontend renders; it does not derive. In\nthis POC the endpoint is a static mock.\n", "sourceCode": "import { Injectable } from '@angular/core';\nimport { httpResource } from '@angular/common/http';\nimport { Result, ok, err } from '@shared/kernel/fp';\nimport { DuoLookupDto, DuoDiplomaDto, PolicyQuestionDto, ManualDiplomaPolicyDto } from '@registratie/contracts/duo-diplomas.dto';\n\nconst EMPTY: DuoLookupDto = { diplomas: [], handmatig: { beroepen: [], policyQuestions: [] } };\n\n/**\n * Infrastructure adapter for the DUO diploma lookup, reached only through our own\n * (\"BFF-lite\") endpoint — the anti-corruption boundary. The response carries the\n * user's diplomas (each with its server-computed beroep + policy questions) and\n * the manual-entry fallback policy. The frontend renders; it does not derive. In\n * this POC the endpoint is a static mock.\n */\n@Injectable({ providedIn: 'root' })\nexport class DuoAdapter {\n diplomasResource() {\n return httpResourceEffectful command: authenticate, then store the session on success.
\n", "modifierKind": [ 134 ], "jsdoctags": [ { "name": "bsn", "type": "string", "optional": false, "dotDotDotToken": false, "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "logout", "args": [], "optional": false, "returnType": "void", "typeParameters": [], "line": 50, "deprecated": false, "deprecationMessage": "" } ], "deprecated": false, "deprecationMessage": "", "description": "Holds the current session for the whole app. Because it is providedIn:'root'\nthere is exactly one instance — every component that injects it sees the same\nsession signal, so logging in is instantly visible everywhere (the guard, the\nheader, etc.). The session is mirrored to sessionStorage so a refresh or a\ndeep-link to a protected route keeps you logged in; it clears when the tab\ncloses. ponytail: sessionStorage, not localStorage — no cross-tab sync, which\nmatches a single-session portal.
\n", "rawdescription": "\n\nHolds the current session for the whole app. Because it is providedIn:'root'\nthere is exactly one instance — every component that injects it sees the same\nsession signal, so logging in is instantly visible everywhere (the guard, the\nheader, etc.). The session is mirrored to sessionStorage so a refresh or a\ndeep-link to a protected route keeps you logged in; it clears when the tab\ncloses. ponytail: sessionStorage, not localStorage — no cross-tab sync, which\nmatches a single-session portal.\n", "sourceCode": "import { Injectable, computed, effect, inject, signal } from '@angular/core';\nimport { Result } from '@shared/kernel/fp';\nimport { Session } from '../domain/session';\nimport { DigidAdapter } from '../infrastructure/digid.adapter';\n\nconst STORAGE_KEY = 'session-v1';\n\n/** Restore a persisted session (best-effort; corrupt entry → logged out). */\nfunction restore(): Session | null {\n try {\n const raw = sessionStorage.getItem(STORAGE_KEY);\n return raw ? (JSON.parse(raw) as Session) : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Holds the current session for the whole app. Because it is providedIn:'root'\n * there is exactly one instance — every component that injects it sees the same\n * session signal, so logging in is instantly visible everywhere (the guard, the\n * header, etc.). The session is mirrored to sessionStorage so a refresh or a\n * deep-link to a protected route keeps you logged in; it clears when the tab\n * closes. ponytail: sessionStorage, not localStorage — no cross-tab sync, which\n * matches a single-session portal.\n */\n@Injectable({ providedIn: 'root' })\nexport class SessionStore {\n private digid = inject(DigidAdapter);\n private _session = signalGeen gegevens gevonden.
}\n }\n @case ('Success') {\nGeen gegevens gevonden.
}\n }\n @case ('Success') {\nGeen gegevens gevonden.
}\n }\n @case ('Success') {\nGeen gegevens gevonden.
}\n }\n @case ('Success') {\nAtom: alert/message banner.
\n", "rawdescription": "\nAtom: alert/message banner.", "type": "component", "sourceCode": "import { Component, input } from '@angular/core';\n\ntype AlertType = 'info' | 'ok' | 'warning' | 'error';\n\n/** Atom: alert/message banner. */\n@Component({\n selector: 'app-alert',\n template: `\nGeen gegevens gevonden.
}\n }\n @case ('Success') {\nRenders exactly ONE of loading / empty / error / loaded for a signal-based\nresource (e.g. httpResource). Built on a RemoteData tagged union (see\ncore/remote-data.ts), so the states are mutually exclusive by construction —\nthe UI can never show two at once ("impossible states"). Unprovided slots\nfall back to sensible defaults.
\n", "rawdescription": "\n\nRenders exactly ONE of loading / empty / error / loaded for a signal-based\nresource (e.g. httpResource). Built on a RemoteData tagged union (see\ncore/remote-data.ts), so the states are mutually exclusive by construction —\nthe UI can never show two at once (\"impossible states\"). Unprovided slots\nfall back to sensible defaults.\n", "type": "component", "sourceCode": "import { Component, Directive, TemplateRef, computed, contentChild, input } from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport type { Resource } from '@angular/core';\nimport { SpinnerComponent } from '@shared/ui/spinner/spinner.component';\nimport { AlertComponent } from '@shared/ui/alert/alert.component';\nimport { ButtonComponent } from '@shared/ui/button/button.component';\nimport { RemoteData, fromResource, foldRemote } from '@shared/application/remote-data';\n\n/* Slot markers. Put onGeen gegevens gevonden.
}\n }\n @case ('Success') {\nChrome: breadcrumb navigation. Renders the RHC/Utrecht breadcrumb pattern; the\nlast item is the current page (no link, aria-current). Domain-free — the caller\nsupplies the trail.
\n", "rawdescription": "\nChrome: breadcrumb navigation. Renders the RHC/Utrecht breadcrumb pattern; the\nlast item is the current page (no link, aria-current). Domain-free — the caller\nsupplies the trail.", "type": "component", "sourceCode": "import { Component, input } from '@angular/core';\nimport { RouterLink } from '@angular/router';\n\nexport interface BreadcrumbItem {\n label: string;\n link?: string; // omit on the current (last) page\n}\n\n/** Chrome: breadcrumb navigation. Renders the RHC/Utrecht breadcrumb pattern; the\n last item is the current page (no link, aria-current). Domain-free — the caller\n supplies the trail. */\n@Component({\n selector: 'app-breadcrumb',\n imports: [RouterLink],\n styles: [`\n :host{display:block}\n .list{display:flex;flex-wrap:wrap;gap:var(--rhc-space-max-md);align-items:center;list-style:none;margin:0;padding:0}\n .sep{color:var(--rhc-color-foreground-subtle)}\n `],\n template: `\n \n `,\n})\nexport class BreadcrumbComponent {\n items = input.requiredAtom: button. Thin wrapper over the Utrecht/RHC button CSS.
\n", "rawdescription": "\nAtom: button. Thin wrapper over the Utrecht/RHC button CSS.", "type": "component", "sourceCode": "import { Component, input } from '@angular/core';\n\ntype Variant = 'primary' | 'secondary' | 'subtle' | 'danger';\n\n/** Atom: button. Thin wrapper over the Utrecht/RHC button CSS. */\n@Component({\n selector: 'app-button',\n template: `\n \n `,\n})\nexport class ButtonComponent {\n variant = inputOrganism: change-request (adreswijziging) form. Reuses the same form-field\nmolecule + text-input/button atoms as the login form. Field errors come\nstraight from the parser's Result — no parallel "is it valid" flag to drift.
\n", "rawdescription": "\nOrganism: change-request (adreswijziging) form. Reuses the same form-field\nmolecule + text-input/button atoms as the login form. Field errors come\nstraight from the parser's Result — no parallel \"is it valid\" flag to drift.", "type": "component", "sourceCode": "import { Component, output, signal } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FormFieldComponent } from '@shared/ui/form-field/form-field.component';\nimport { TextInputComponent } from '@shared/ui/text-input/text-input.component';\nimport { ButtonComponent } from '@shared/ui/button/button.component';\nimport { HeadingComponent } from '@shared/ui/heading/heading.component';\nimport { Postcode, parsePostcode } from '@registratie/domain/value-objects/postcode';\n\n/** A submitted change request carries a *parsed* postcode (branded Postcode),\n not a raw string — downstream code can't receive an unvalidated one. */\nexport interface ChangeRequest {\n street: string;\n zip: Postcode;\n city: string;\n}\n\n/** Organism: change-request (adreswijziging) form. Reuses the same form-field\n molecule + text-input/button atoms as the login form. Field errors come\n straight from the parser's Result — no parallel \"is it valid\" flag to drift. */\n@Component({\n selector: 'app-change-request-form',\n imports: [FormsModule, FormFieldComponent, TextInputComponent, ButtonComponent, HeadingComponent],\n template: `\n\n Vijf functionele patronen die atomic design makkelijker maakt om te tonen — telkens\n \"fout\" (de oude vorm liet het toe) naast \"goed\" (het type maakt het onmogelijk).\n
\n\n \nLaat elke variant precies de gegevens dragen die kloppen — niets meer.
\nFout — vlakke interface
\n \nEen doorgehaalde registratie houdt tóch een herregistratiedatum: onmogelijke toestand.
\nGoed — sum type
\nDe variant Doorgehaald kent geen herregistratiedatum, dus de rij bestaat simpelweg niet.
Eén waarde met vier elkaar uitsluitende toestanden in plaats van drie losse booleans.
\nVier toestanden, één molecuul
\nLoading
\nEmpty
\nFailure
\nSuccess
\nDe exhaustieve fold
\n \nEen nieuwe variant toevoegen breekt de compile via assertNever tot je hem afhandelt.
Na het parsen onthoudt het type dat de waarde geldig is.
\nSmart constructor → Result
\nok
\nPostcode = \"{{ $any(parsed()).value }}\"\n Een gevalideerde Postcode is een ander type dan een ruwe string.
err
\n{{ $any(parsed()).error }}\n }\n Eén tagged union stuurt de UI. Speel met de wizard — de gemarkeerde toestand is de huidige.
\nFout — losse booleans
\n \nNiets verhindert \"submitting\" mét validatiefouten of een successcherm met errors.
\nGoed — één tagged union
\n\n Het aantal stappen ligt vast (STEPS); vervolgvragen verschijnen binnen een stap\n op basis van eerdere antwoorden. Antwoord \"ja\" op buitenland of vul weinig uren in, en er komt een\n extra vraag bij in dezelfde stap — de voortgang \"van N\" blijft gelijk.\n
Vaste stappen
\nDe stappen zijn altijd dezelfde; alleen de vragen binnen een stap verschijnen of verdwijnen.
\nDe wizard
\nTeaching showcase: each section pairs the impossible-state-permitting "before"\nwith the "after" where the type system rules it out. Composition-only.
\n", "rawdescription": "\nTeaching showcase: each section pairs the impossible-state-permitting \"before\"\nwith the \"after\" where the type system rules it out. Composition-only.", "type": "component", "sourceCode": "import { Component, computed, signal } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport type { Resource } from '@angular/core';\nimport { PageShellComponent } from '@shared/layout/page-shell/page-shell.component';\nimport { HeadingComponent } from '@shared/ui/heading/heading.component';\nimport { TextInputComponent } from '@shared/ui/text-input/text-input.component';\nimport { ASYNC } from '@shared/ui/async/async.component';\nimport { SkeletonComponent } from '@shared/ui/skeleton/skeleton.component';\nimport { RegistrationSummaryComponent } from '@registratie/ui/registration-summary/registration-summary.component';\nimport { HerregistratieWizardComponent } from '@herregistratie/ui/herregistratie-wizard/herregistratie-wizard.component';\nimport { IntakeWizardComponent } from '@herregistratie/ui/intake-wizard/intake-wizard.component';\nimport { Registration } from '@registratie/domain/registration';\nimport { parsePostcode } from '@registratie/domain/value-objects/postcode';\n\n/** Minimal fake Resource so\n Vijf functionele patronen die atomic design makkelijker maakt om te tonen — telkens\n \"fout\" (de oude vorm liet het toe) naast \"goed\" (het type maakt het onmogelijk).\n
\n\n \nLaat elke variant precies de gegevens dragen die kloppen — niets meer.
\nFout — vlakke interface
\n \nEen doorgehaalde registratie houdt tóch een herregistratiedatum: onmogelijke toestand.
\nGoed — sum type
\nDe variant Doorgehaald kent geen herregistratiedatum, dus de rij bestaat simpelweg niet.
Eén waarde met vier elkaar uitsluitende toestanden in plaats van drie losse booleans.
\nVier toestanden, één molecuul
\nLoading
\nEmpty
\nFailure
\nSuccess
\nDe exhaustieve fold
\n \nEen nieuwe variant toevoegen breekt de compile via assertNever tot je hem afhandelt.
Na het parsen onthoudt het type dat de waarde geldig is.
\nSmart constructor → Result
\nok
\nPostcode = \"{{ $any(parsed()).value }}\"\n Een gevalideerde Postcode is een ander type dan een ruwe string.
err
\n{{ $any(parsed()).error }}\n }\n Eén tagged union stuurt de UI. Speel met de wizard — de gemarkeerde toestand is de huidige.
\nFout — losse booleans
\n \nNiets verhindert \"submitting\" mét validatiefouten of een successcherm met errors.
\nGoed — één tagged union
\n\n Het aantal stappen ligt vast (STEPS); vervolgvragen verschijnen binnen een stap\n op basis van eerdere antwoorden. Antwoord \"ja\" op buitenland of vul weinig uren in, en er komt een\n extra vraag bij in dezelfde stap — de voortgang \"van N\" blijft gelijk.\n
Vaste stappen
\nDe stappen zijn altijd dezelfde; alleen de vragen binnen een stap verschijnen of verdwijnen.
\nDe wizard
\nU heeft nog geen specialismen of aantekeningen.
\n\n
\n
\n
\n
\n
U heeft nog geen specialismen of aantekeningen.
\n\n
\n
\n
\n
\n
Molecule: one key/value row inside an RHC data-summary.\nWrap several of these in .rhc-data-summary (see registration-summary).
\n", "rawdescription": "\nMolecule: one key/value row inside an RHC data-summary.\nWrap several of these in .rhc-data-summary (see registration-summary).", "type": "component", "sourceCode": "import { Component, input } from '@angular/core';\n\n/** Molecule: one key/value row inside an RHC data-summary.\n Wrap several of these in .rhc-data-summary (see registration-summary). */\n@Component({\n selector: 'app-data-row',\n // The RHC item draws a divider below every row; drop it on the last one so the\n // list ends cleanly instead of looking like a trailing empty row.\n styles: [`:host:last-child .rhc-data-summary__item { border-block-end-style: none; }`],\n template: `\nMolecule: form field = label + projected control + optional error/description.\nReused by both the login form and the change-request form.
\n", "rawdescription": "\nMolecule: form field = label + projected control + optional error/description.\nReused by both the login form and the change-request form.", "type": "component", "sourceCode": "import { Component, input } from '@angular/core';\n\n/** Molecule: form field = label + projected control + optional error/description.\n Reused by both the login form and the change-request form. */\n@Component({\n selector: 'app-form-field',\n template: `\nAtom: heading. Renders the right h1..h5 with RHC heading styling.\nSingle
A whole new page built from existing building blocks. Eligibility is a\nSERVER-computed decision read from the aggregated view — the frontend renders\nit, it does not recompute the rule.
\n", "rawdescription": "\nA whole new page built from existing building blocks. Eligibility is a\nSERVER-computed decision read from the aggregated view — the frontend renders\nit, it does not recompute the rule.", "type": "component", "sourceCode": "import { Component, computed, inject } from '@angular/core';\nimport { PageShellComponent } from '@shared/layout/page-shell/page-shell.component';\nimport { AlertComponent } from '@shared/ui/alert/alert.component';\nimport { ASYNC } from '@shared/ui/async/async.component';\nimport { map } from '@shared/application/remote-data';\nimport { BigProfileStore } from '@registratie/application/big-profile.store';\nimport { HerregistratieWizardComponent } from '@herregistratie/ui/herregistratie-wizard/herregistratie-wizard.component';\n\n/** A whole new page built from existing building blocks. Eligibility is a\n SERVER-computed decision read from the aggregated view — the frontend renders\n it, it does not recompute the rule. */\n@Component({\n selector: 'app-herregistratie-page',\n imports: [PageShellComponent, AlertComponent, ...ASYNC, HerregistratieWizardComponent],\n template: `\nStap {{ step() }} van 2
\n \n }\n @case ('Submitting') {\nOptional seed so Storybook / the showcase can mount any state directly.
\n", "line": 73, "rawdescription": "\nOptional seed so Storybook / the showcase can mount any state directly.", "required": false } ], "outputsClass": [], "propertiesClass": [ { "name": "dispatch", "defaultValue": "this.store.dispatch", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 76, "modifierKind": [ 124 ] }, { "name": "draft", "defaultValue": "computedReset the wizard to a fresh, empty start.
\n" }, { "name": "runIfSubmitting", "args": [], "optional": false, "returnType": "any", "typeParameters": [], "line": 109, "deprecated": false, "deprecationMessage": "", "rawdescription": "\nThe effect: when we entered Submitting, call the backend command, flip the\noptimistic cross-page flag, then dispatch the result (and commit/rollback).", "description": "The effect: when we entered Submitting, call the backend command, flip the\noptimistic cross-page flag, then dispatch the result (and commit/rollback).
\n", "modifierKind": [ 123, 134 ] } ], "deprecated": false, "deprecationMessage": "", "hostBindings": [], "hostListeners": [], "standalone": false, "imports": [ { "name": "FormsModule", "type": "module" }, { "name": "FormFieldComponent", "type": "component" }, { "name": "TextInputComponent", "type": "component" }, { "name": "ButtonComponent", "type": "component" }, { "name": "AlertComponent", "type": "component" }, { "name": "SpinnerComponent", "type": "component" } ], "description": "Organism: multi-step herregistratie wizard. ALL state lives in one signal\ndriven by the pure reduce function (see herregistratie.machine.ts) via an\nElm-style store. The UI just sends messages and folds over the state's tag —\nno booleans like submitting/submitted that could contradict each other.\nSubmitting also flips an optimistic flag on the shared BigProfileStore, so\nthe dashboard shows "in behandeling" immediately.
Stap {{ step() }} van 2
\n \n }\n @case ('Submitting') {\nPage: the branching intake questionnaire. Built entirely from existing\nbuilding blocks (page shell + alert + the intake-wizard organism).
\n", "rawdescription": "\nPage: the branching intake questionnaire. Built entirely from existing\nbuilding blocks (page shell + alert + the intake-wizard organism).", "type": "component", "sourceCode": "import { Component } from '@angular/core';\nimport { PageShellComponent } from '@shared/layout/page-shell/page-shell.component';\nimport { AlertComponent } from '@shared/ui/alert/alert.component';\nimport { IntakeWizardComponent } from '@herregistratie/ui/intake-wizard/intake-wizard.component';\n\n/** Page: the branching intake questionnaire. Built entirely from existing\n building blocks (page shell + alert + the intake-wizard organism). */\n@Component({\n selector: 'app-intake-page',\n imports: [PageShellComponent, AlertComponent, IntakeWizardComponent],\n template: `\nStap {{ cursor() + 1 }} van {{ steps.length }}
\n \n }\n @case ('Submitting') {\nOptional seed so Storybook / the showcase can mount any state directly.
\n", "line": 129, "rawdescription": "\nOptional seed so Storybook / the showcase can mount any state directly.", "required": false } ], "outputsClass": [], "propertiesClass": [ { "name": "answering", "defaultValue": "computed(() => (this.state().tag === 'Answering' ? (this.state() as ExtractServer-owned threshold from the policy endpoint (mirrored into machine state).
\n", "line": 142, "rawdescription": "\nServer-owned threshold from the policy endpoint (mirrored into machine state).", "modifierKind": [ 124 ] }, { "name": "scholingZichtbaar", "defaultValue": "computed(() => lageUren(this.answers(), this.scholingThreshold()))", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "Whether the inline scholing question is shown (and required) in the 'werk' step.
\n", "line": 144, "rawdescription": "\nWhether the inline scholing question is shown (and required) in the 'werk' step.", "modifierKind": [ 124 ] }, { "name": "set", "defaultValue": "() => {...}", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 148, "modifierKind": [ 124 ] }, { "name": "state", "defaultValue": "this.store.model", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 132, "modifierKind": [ 148 ] }, { "name": "step", "defaultValue": "computedPublic so the showcase can render the (fixed) step list next to the wizard.
\n", "line": 137, "rawdescription": "\nPublic so the showcase can render the (fixed) step list next to the wizard.", "modifierKind": [ 148 ] }, { "name": "store", "defaultValue": "createStoreThe effect: when we enter Submitting, call the backend, flip the optimistic\ncross-page flag, then dispatch the outcome (and commit/rollback).
\n", "modifierKind": [ 123, 134 ] } ], "deprecated": false, "deprecationMessage": "", "hostBindings": [], "hostListeners": [], "standalone": false, "imports": [ { "name": "FormsModule", "type": "module" }, { "name": "FormFieldComponent", "type": "component" }, { "name": "TextInputComponent", "type": "component" }, { "name": "RadioGroupComponent", "type": "component" }, { "name": "ButtonComponent", "type": "component" }, { "name": "AlertComponent", "type": "component" }, { "name": "SpinnerComponent", "type": "component" } ], "description": "Organism: a BRANCHING intake questionnaire. All state lives in one signal\ndriven by the pure reduce (intake.machine.ts). Which step renders is derived\nfrom the answers via visibleSteps, never stored — so editing an earlier\nanswer immediately changes the remaining steps. Answers are persisted to\nlocalStorage so a page reload keeps the user's progress.
Stap {{ cursor() + 1 }} van {{ steps.length }}
\n \n }\n @case ('Submitting') {\nAtom: link. Internal router link styled as an RHC/Utrecht link.
\n", "rawdescription": "\nAtom: link. Internal router link styled as an RHC/Utrecht link.", "type": "component", "sourceCode": "import { Component, input } from '@angular/core';\nimport { RouterLink } from '@angular/router';\n\n/** Atom: link. Internal router link styled as an RHC/Utrecht link. */\n@Component({\n selector: 'app-link',\n imports: [RouterLink],\n template: `Organism: DigiD-style mock login. No real auth — just composes atoms/molecules.
\n", "rawdescription": "\nOrganism: DigiD-style mock login. No real auth — just composes atoms/molecules.", "type": "component", "sourceCode": "import { Component, output } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FormFieldComponent } from '@shared/ui/form-field/form-field.component';\nimport { TextInputComponent } from '@shared/ui/text-input/text-input.component';\nimport { ButtonComponent } from '@shared/ui/button/button.component';\n\n/** Organism: DigiD-style mock login. No real auth — just composes atoms/molecules. */\n@Component({\n selector: 'app-login-form',\n imports: [FormsModule, FormFieldComponent, TextInputComponent, ButtonComponent],\n template: `\n \n `,\n})\nexport class LoginFormComponent {\n bsn = '';\n password = '';\n submitted = output{{ intro() }}
\n }\nTemplate: standard page body — optional breadcrumb, optional back-link, a\nheading, optional intro, and projected content. Rendered inside the persistent\nShellComponent via the router outlet, so it owns only the content (not chrome).
\n", "rawdescription": "\nTemplate: standard page body — optional breadcrumb, optional back-link, a\nheading, optional intro, and projected content. Rendered inside the persistent\nShellComponent via the router outlet, so it owns only the content (not chrome).", "type": "component", "sourceCode": "import { Component, input } from '@angular/core';\nimport { HeadingComponent } from '@shared/ui/heading/heading.component';\nimport { LinkComponent } from '@shared/ui/link/link.component';\nimport { BreadcrumbComponent, BreadcrumbItem } from '@shared/layout/breadcrumb/breadcrumb.component';\n\n/** Template: standard page body — optional breadcrumb, optional back-link, a\n heading, optional intro, and projected content. Rendered inside the persistent\n ShellComponent via the router outlet, so it owns only the content (not chrome). */\n@Component({\n selector: 'app-page-shell',\n imports: [HeadingComponent, LinkComponent, BreadcrumbComponent],\n styles: [`\n :host{display:block}\n .body--narrow{max-inline-size:var(--app-form-narrow)}\n .crumb{margin-block-end:var(--rhc-space-max-xl)}\n .intro{margin-block-end:var(--rhc-space-max-2xl)}\n `],\n template: `\n{{ intro() }}
\n }\nAtom: a radio group. Thin wrapper over the Utrecht/RHC radio CSS, wired as a\nform control so it works with ngModel just like the text-input atom.
\n", "rawdescription": "\nAtom: a radio group. Thin wrapper over the Utrecht/RHC radio CSS, wired as a\nform control so it works with ngModel just like the text-input atom.", "type": "component", "sourceCode": "import { Component, forwardRef, input } from '@angular/core';\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\n\nexport interface RadioOption {\n value: string;\n label: string;\n}\n\n/** Atom: a radio group. Thin wrapper over the Utrecht/RHC radio CSS, wired as a\n form control so it works with ngModel just like the text-input atom. */\n@Component({\n selector: 'app-radio-group',\n styles: [`\n .rhc-radio-option {\n display: flex;\n align-items: center;\n gap: var(--rhc-space-max-md);\n padding-block: var(--rhc-space-max-sm);\n }\n `],\n template: `\nPage: register in the BIG-register. Built entirely from existing building\nblocks (page shell + alert + the registratie-wizard organism).
\n", "rawdescription": "\nPage: register in the BIG-register. Built entirely from existing building\nblocks (page shell + alert + the registratie-wizard organism).", "type": "component", "sourceCode": "import { Component } from '@angular/core';\nimport { PageShellComponent } from '@shared/layout/page-shell/page-shell.component';\nimport { AlertComponent } from '@shared/ui/alert/alert.component';\nimport { RegistratieWizardComponent } from '@registratie/ui/registratie-wizard/registratie-wizard.component';\n\n/** Page: register in the BIG-register. Built entirely from existing building\n blocks (page shell + alert + the registratie-wizard organism). */\n@Component({\n selector: 'app-registratie-page',\n imports: [PageShellComponent, AlertComponent, RegistratieWizardComponent],\n template: `\nOptional seed so Storybook / tests can mount any state directly.
\n", "line": 184, "rawdescription": "\nOptional seed so Storybook / tests can mount any state directly.", "required": false } ], "outputsClass": [], "propertiesClass": [ { "name": "actieveVragen", "defaultValue": "() => {...}", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "The policy questions that apply to the current choice (server-decided).
\n", "line": 258, "rawdescription": "\nThe policy questions that apply to the current choice (server-decided).", "modifierKind": [ 124 ] }, { "name": "adresHerkomstLabel", "defaultValue": "computed(() => ({ brp: 'Automatisch uit de BRP', handmatig: 'Handmatig ingevoerd' }[this.draft().adresHerkomst ?? 'handmatig']))", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 207, "modifierKind": [ 124 ] }, { "name": "adresRes", "defaultValue": "this.brp.adresResource()", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 180, "modifierKind": [ 124 ] }, { "name": "adresSamenvatting", "defaultValue": "computed(() => {\n const d = this.draft();\n return [d.straat, [d.postcode, d.woonplaats].filter(Boolean).join(' ')].filter(Boolean).join(', ');\n })", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 202, "modifierKind": [ 124 ] }, { "name": "adresStatus", "defaultValue": "computed<'laden' | 'gevonden' | 'geen' | 'fout'>(() => {\n const st = this.adresRes.status();\n if (st === 'loading' || st === 'reloading') return 'laden';\n if (st === 'error') return 'fout';\n const json = this.adresRes.value();\n const parsed = json !== undefined ? parseBrpAddress(json) : null;\n return parsed && parsed.ok && parsed.value.gevonden ? 'gevonden' : 'geen';\n })", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "BRP lookup outcome. A failure or "geen adres" never blocks the wizard — both\nfall back to manual entry (PRD §7). 'geen' covers both no-address-found and a\nmalformed response; 'fout' is an unreachable BRP.
\n", "line": 214, "rawdescription": "\nBRP lookup outcome. A failure or \"geen adres\" never blocks the wizard — both\nfall back to manual entry (PRD §7). 'geen' covers both no-address-found and a\nmalformed response; 'fout' is an unreachable BRP.", "modifierKind": [ 124 ] }, { "name": "beroepOptions", "defaultValue": "() => {...}", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 255, "modifierKind": [ 124 ] }, { "name": "brp", "defaultValue": "inject(BrpAdapter)", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 176, "modifierKind": [ 123 ] }, { "name": "correspondentieLabel", "defaultValue": "computed(() => ({ email: 'Per e-mail', post: 'Per post' }[this.draft().correspondentie ?? 'post']))", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 208, "modifierKind": [ 124 ] }, { "name": "cursor", "defaultValue": "computed(() => this.invullen()?.cursor ?? 0)", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 196, "modifierKind": [ 124 ] }, { "name": "diplomaHerkomstLabel", "defaultValue": "computed(() => ({ duo: 'Geverifieerd via DUO', handmatig: 'Handmatig ingevoerd (wordt beoordeeld)' }[this.draft().diplomaHerkomst ?? 'handmatig']))", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 209, "modifierKind": [ 124 ] }, { "name": "diplomaKeuze", "defaultValue": "computed(() => (this.handmatigActief() ? HANDMATIG : this.draft().diplomaId ?? ''))", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "The radio selection: a diploma id, or the "not listed" sentinel in manual mode.
\n", "line": 248, "rawdescription": "\nThe radio selection: a diploma id, or the \"not listed\" sentinel in manual mode.", "modifierKind": [ 124 ] }, { "name": "diplomaOptions", "defaultValue": "() => {...}", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 250, "modifierKind": [ 124 ] }, { "name": "diplomasRes", "defaultValue": "this.duo.diplomasResource()", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 181, "modifierKind": [ 123 ] }, { "name": "dispatch", "defaultValue": "this.store.dispatch", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 190, "modifierKind": [ 148 ] }, { "name": "draft", "defaultValue": "computedParsed lookup as a plain value (or null) — used outside the beroep step (the\ncontrole summary) where the
True while the user is entering a diploma manually (not in the DUO list).
\n", "line": 246, "rawdescription": "\nTrue while the user is entering a diploma manually (not in the DUO list).", "modifierKind": [ 124 ] }, { "name": "invullen", "defaultValue": "computed(() => (this.state().tag === 'Invullen' ? (this.state() as ExtractThe DUO lookup (diplomas + manual fallback), validated at the trust boundary.
\n", "line": 224, "rawdescription": "\nThe DUO lookup (diplomas + manual fallback), validated at the trust boundary.", "modifierKind": [ 124 ] }, { "name": "referentie", "defaultValue": "computed(() => (this.state().tag === 'Ingediend' ? (this.state() as ExtractAnswered policy questions for the controle summary (question text + answer).
\n", "line": 264, "rawdescription": "\nAnswered policy questions for the controle summary (question text + answer).", "modifierKind": [ 124 ] }, { "name": "set", "defaultValue": "() => {...}", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 242, "modifierKind": [ 124 ] }, { "name": "setKanaal", "defaultValue": "() => {...}", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 243, "modifierKind": [ 124 ] }, { "name": "state", "defaultValue": "this.store.model", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 189, "modifierKind": [ 148 ] }, { "name": "step", "defaultValue": "computedFocus target: the step heading receives focus on step change (a11y).
\n", "line": 193, "rawdescription": "\nFocus target: the step heading receives focus on step change (a11y).", "modifierKind": [ 123 ] }, { "name": "stepLabels", "defaultValue": "['Adres', 'Beroep', 'Controle']", "deprecated": false, "deprecationMessage": "", "type": "[]", "indexKey": "", "optional": false, "description": "", "line": 187, "modifierKind": [ 148 ] }, { "name": "stepTitle", "defaultValue": "computed(() => this.stepTitles[Math.min(this.cursor(), this.stepTitles.length - 1)])", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 199, "modifierKind": [ 124 ] }, { "name": "stepTitles", "defaultValue": "['Adres en correspondentievoorkeur', 'Beroep op basis van uw diploma', 'Controleren en indienen']", "deprecated": false, "deprecationMessage": "", "type": "[]", "indexKey": "", "optional": false, "description": "", "line": 188, "modifierKind": [ 123 ] }, { "name": "store", "defaultValue": "createStoreReset the wizard to a fresh start. Reload the BRP lookup so the address\nre-prefills, keeping the form and the "vooraf ingevuld" note consistent.
\n" }, { "name": "restore", "args": [], "optional": false, "returnType": "RegistratieState | null", "typeParameters": [], "line": 322, "deprecated": false, "deprecationMessage": "", "modifierKind": [ 123 ] }, { "name": "runIfIndienen", "args": [], "optional": false, "returnType": "any", "typeParameters": [], "line": 353, "deprecated": false, "deprecationMessage": "", "rawdescription": "\nThe effect: when we enter Indienen, call the backend, then dispatch the\noutcome (success carries the confirmation reference).", "description": "The effect: when we enter Indienen, call the backend, then dispatch the\noutcome (success carries the confirmation reference).
\n", "modifierKind": [ 123, 134 ] } ], "deprecated": false, "deprecationMessage": "", "hostBindings": [], "hostListeners": [], "standalone": false, "imports": [ { "name": "FormsModule", "type": "module" }, { "name": "FormFieldComponent", "type": "component" }, { "name": "TextInputComponent", "type": "component" }, { "name": "RadioGroupComponent", "type": "component" }, { "name": "ButtonComponent", "type": "component" }, { "name": "AlertComponent", "type": "component" }, { "name": "SpinnerComponent", "type": "component" }, { "name": "SkeletonComponent", "type": "component" }, { "name": "DataRowComponent", "type": "component" }, { "name": "StepperComponent", "type": "component" }, { "name": "ASYNC" } ], "description": "Organism: the BIG-registration wizard. All state lives in one signal driven by\nthe pure reduce (registratie-wizard.machine.ts). The BRP address prefills the\ndraft via an effect; the DUO diploma list renders through
Organism: registration summary card. Composes data-row molecules + status-badge atom.
\n", "rawdescription": "\nOrganism: registration summary card. Composes data-row molecules + status-badge atom.", "type": "component", "sourceCode": "import { Component, input } from '@angular/core';\nimport { DatePipe } from '@angular/common';\nimport { Registration } from '@registratie/domain/registration';\nimport { statusColor, statusLabel } from '@registratie/domain/registration.policy';\nimport { DataRowComponent } from '@shared/ui/data-row/data-row.component';\nimport { StatusBadgeComponent } from '@shared/ui/status-badge/status-badge.component';\n\n/** Organism: registration summary card. Composes data-row molecules + status-badge atom. */\n@Component({\n selector: 'app-registration-summary',\n imports: [DatePipe, DataRowComponent, StatusBadgeComponent],\n template: `\n| Type | \nOmschrijving | \nDatum | \n
|---|---|---|
| {{ row.type }} | \n{{ row.omschrijving }} | \n{{ row.datum | date:'mediumDate' }} | \n
Organism: table of specialismen/aantekeningen.
\n", "rawdescription": "\nOrganism: table of specialismen/aantekeningen.", "type": "component", "sourceCode": "import { Component, input } from '@angular/core';\nimport { DatePipe } from '@angular/common';\nimport { Aantekening } from '@registratie/domain/registration';\n\n/** Organism: table of specialismen/aantekeningen. */\n@Component({\n selector: 'app-registration-table',\n imports: [DatePipe],\n template: `\n| Type | \nOmschrijving | \nDatum | \n
|---|---|---|
| {{ row.type }} | \n{{ row.omschrijving }} | \n{{ row.datum | date:'mediumDate' }} | \n
Template: persistent app chrome. Header + footer mount once; only the routed\ncontent inside
Organism: site footer.
\n", "rawdescription": "\nOrganism: site footer.", "type": "component", "sourceCode": "import { Component } from '@angular/core';\n\n/** Organism: site footer. */\n@Component({\n selector: 'app-site-footer',\n styles: [`\n :host{display:block}\n .bar{background:var(--rhc-color-donkerblauw-700);color:var(--rhc-color-wit);margin-block-start:var(--rhc-space-max-5xl);inline-size:100%}\n .inner{max-inline-size:var(--app-content-max);margin-inline:auto;padding:var(--rhc-space-max-2xl);display:flex;gap:var(--rhc-space-max-3xl);flex-wrap:wrap;box-sizing:border-box}\n .end{margin-inline-start:auto}\n `],\n template: `\n \n `,\n})\nexport class SiteFooterComponent {}\n", "assetsDirs": [], "styleUrlsData": "", "stylesData": "\n :host{display:block}\n .bar{background:var(--rhc-color-donkerblauw-700);color:var(--rhc-color-wit);margin-block-start:var(--rhc-space-max-5xl);inline-size:100%}\n .inner{max-inline-size:var(--app-content-max);margin-inline:auto;padding:var(--rhc-space-max-2xl);display:flex;gap:var(--rhc-space-max-3xl);flex-wrap:wrap;box-sizing:border-box}\n .end{margin-inline-start:auto}\n \n", "extends": [] }, { "name": "SiteHeaderComponent", "id": "component-SiteHeaderComponent-f5e80a4225213863b1448920f4a6300aec28b9ca4de6a6a0acad2e69a6aa0359cdd8194aa71fd6f8fcff7e0200b6715201f09241ac3bc32314c5af3392a4639e", "file": "src/app/shared/layout/site-header/site-header.component.ts", "encapsulation": [], "entryComponents": [], "inputs": [], "outputs": [], "providers": [], "selector": "app-site-header", "styleUrls": [], "styles": [ "\n :host{display:block}\n .bar{background:var(--rhc-color-lintblauw-700);color:var(--rhc-color-wit);inline-size:100%}\n .inner{display:flex;align-items:center;gap:var(--rhc-space-max-xl);max-inline-size:var(--app-content-max);margin-inline:auto;padding:var(--rhc-space-max-xl) var(--rhc-space-max-2xl);box-sizing:border-box}\n .brand{display:flex;align-items:center;gap:var(--rhc-space-max-lg);color:inherit;text-decoration:none}\n .mark{display:inline-block;inline-size:var(--rhc-space-max-md);block-size:var(--rhc-space-max-4xl);background:var(--rhc-color-wit)}\n .name{font-weight:var(--rhc-text-font-weight-bold);line-height:var(--rhc-text-line-height-sm)}\n .sub{font-weight:var(--rhc-text-font-weight-regular);font-size:var(--rhc-text-font-size-sm)}\n .portal{margin-inline-start:auto;font-weight:var(--rhc-text-font-weight-semi-bold)}\n " ], "template": "Organism: site header with Rijksoverheid-style wordmark + title.\nponytail: text wordmark instead of the licensed Rijksoverheid logo.
\n", "rawdescription": "\nOrganism: site header with Rijksoverheid-style wordmark + title.\nponytail: text wordmark instead of the licensed Rijksoverheid logo.", "type": "component", "sourceCode": "import { Component, input } from '@angular/core';\nimport { RouterLink } from '@angular/router';\n\n/** Organism: site header with Rijksoverheid-style wordmark + title.\n ponytail: text wordmark instead of the licensed Rijksoverheid logo. */\n@Component({\n selector: 'app-site-header',\n imports: [RouterLink],\n // :host display:block so the full-bleed bar fills the flex column (custom\n // elements default to display:inline, which collapsed the bar to its content).\n styles: [`\n :host{display:block}\n .bar{background:var(--rhc-color-lintblauw-700);color:var(--rhc-color-wit);inline-size:100%}\n .inner{display:flex;align-items:center;gap:var(--rhc-space-max-xl);max-inline-size:var(--app-content-max);margin-inline:auto;padding:var(--rhc-space-max-xl) var(--rhc-space-max-2xl);box-sizing:border-box}\n .brand{display:flex;align-items:center;gap:var(--rhc-space-max-lg);color:inherit;text-decoration:none}\n .mark{display:inline-block;inline-size:var(--rhc-space-max-md);block-size:var(--rhc-space-max-4xl);background:var(--rhc-color-wit)}\n .name{font-weight:var(--rhc-text-font-weight-bold);line-height:var(--rhc-text-line-height-sm)}\n .sub{font-weight:var(--rhc-text-font-weight-regular);font-size:var(--rhc-text-font-size-sm)}\n .portal{margin-inline-start:auto;font-weight:var(--rhc-text-font-weight-semi-bold)}\n `],\n template: `\nAtom: skeleton placeholder (grey shimmer). Delay-gated so it never flashes\non fast responses. Render count lines shaped roughly like the content.
Atom: spinner that only appears after delay ms — fast responses never\nflash a spinner, slow ones get feedback.
Atom: a coloured dot + label. Purely presentational and domain-free — the\ncaller decides what colour and label mean (e.g. via registration.policy).\nThis keeps the shared UI kernel free of any domain knowledge.
\n", "rawdescription": "\nAtom: a coloured dot + label. Purely presentational and domain-free — the\ncaller decides what colour and label mean (e.g. via registration.policy).\nThis keeps the shared UI kernel free of any domain knowledge.", "type": "component", "sourceCode": "import { Component, input } from '@angular/core';\n\n/** Atom: a coloured dot + label. Purely presentational and domain-free — the\n caller decides what colour and label mean (e.g. via registration.policy).\n This keeps the shared UI kernel free of any domain knowledge. */\n@Component({\n selector: 'app-status-badge',\n styles: [`.badge{display:inline-flex;align-items:center;gap:var(--rhc-space-max-md)}`],\n template: `\n \n \n {{ label() }}\n \n `,\n})\nexport class StatusBadgeComponent {\n label = input.requiredMolecule: a horizontal step indicator for a multi-step flow. Visual progress\nplus accessible semantics — an ordered list with aria-current="step" on the\nactive step and a visually-hidden "Stap X van Y" summary. Domain-free.
Atom: text input. Utrecht textbox wired up as a form control (ngModel/reactive).
\n", "rawdescription": "\nAtom: text input. Utrecht textbox wired up as a form control (ngModel/reactive).", "type": "component", "sourceCode": "import { Component, forwardRef, input } from '@angular/core';\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\n\n/** Atom: text input. Utrecht textbox wired up as a form control (ngModel/reactive). */\n@Component({\n selector: 'app-text-input',\n template: `\n \n `,\n providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => TextInputComponent), multi: true }],\n})\nexport class TextInputComponent implements ControlValueAccessor {\n type = input<'text' | 'password' | 'email'>('text');\n placeholder = input('');\n invalid = input(false);\n inputId = inputConvenience: import this array to get the wrapper + all slot directives.
\n" }, { "name": "authGuard", "ctype": "miscellaneous", "subtype": "variable", "file": "src/app/auth/auth.guard.ts", "deprecated": false, "deprecationMessage": "", "type": "CanActivateFn", "defaultValue": "() => {\n const store = inject(SessionStore);\n const router = inject(Router);\n return store.isAuthenticated() ? true : router.createUrlTree(['/login']);\n}", "rawdescription": "Route guard: only let authenticated users in; otherwise redirect to /login.", "description": "Route guard: only let authenticated users in; otherwise redirect to /login.
\n" }, { "name": "EMPTY", "ctype": "miscellaneous", "subtype": "variable", "file": "src/app/registratie/infrastructure/duo.adapter.ts", "deprecated": false, "deprecationMessage": "", "type": "DuoLookupDto", "defaultValue": "{ diplomas: [], handmatig: { beroepen: [], policyQuestions: [] } }" }, { "name": "emptyDraft", "ctype": "miscellaneous", "subtype": "variable", "file": "src/app/registratie/domain/registratie-wizard.machine.ts", "deprecated": false, "deprecationMessage": "", "type": "Draft", "defaultValue": "{ antwoorden: {} }" }, { "name": "err", "ctype": "miscellaneous", "subtype": "variable", "file": "src/app/shared/kernel/fp.ts", "deprecated": false, "deprecationMessage": "", "type": "unknown", "defaultValue": "Demo-only: rewrites the timing/outcome of mock data requests based on\n?scenario= so loading / empty / error states can be shown on demand.\nReal requests are untouched.
\n" }, { "name": "SCHOLING_THRESHOLD_DEFAULT", "ctype": "miscellaneous", "subtype": "variable", "file": "src/app/herregistratie/domain/intake.machine.ts", "deprecated": false, "deprecationMessage": "", "type": "number", "defaultValue": "1000", "rawdescription": "Demo fallback only — the real threshold is a SERVER-OWNED policy value fetched\nat runtime (see IntakePolicyDto / SetPolicy). ponytail: default is the offline\nfallback; the server value wins.", "description": "Demo fallback only — the real threshold is a SERVER-OWNED policy value fetched\nat runtime (see IntakePolicyDto / SetPolicy). ponytail: default is the offline\nfallback; the server value wins.
\n" }, { "name": "STEPS", "ctype": "miscellaneous", "subtype": "variable", "file": "src/app/herregistratie/domain/intake.machine.ts", "deprecated": false, "deprecationMessage": "", "type": "StepId[]", "defaultValue": "['buitenland', 'werk', 'review']", "rawdescription": "The fixed step list. Number of steps never changes; questions reveal inline.", "description": "The fixed step list. Number of steps never changes; questions reveal inline.
\n" }, { "name": "STEPS", "ctype": "miscellaneous", "subtype": "variable", "file": "src/app/registratie/domain/registratie-wizard.machine.ts", "deprecated": false, "deprecationMessage": "", "type": "StepId[]", "defaultValue": "['adres', 'beroep', 'controle']", "rawdescription": "The fixed step list. Number of steps never changes; questions reveal inline.", "description": "The fixed step list. Number of steps never changes; questions reveal inline.
\n" }, { "name": "STORAGE_KEY", "ctype": "miscellaneous", "subtype": "variable", "file": "src/app/auth/application/session.store.ts", "deprecated": false, "deprecationMessage": "", "type": "string", "defaultValue": "'session-v1'" }, { "name": "STORAGE_KEY", "ctype": "miscellaneous", "subtype": "variable", "file": "src/app/herregistratie/ui/intake-wizard/intake-wizard.component.ts", "deprecated": false, "deprecationMessage": "", "type": "string", "defaultValue": "'intake-v3'" }, { "name": "STORAGE_KEY", "ctype": "miscellaneous", "subtype": "variable", "file": "src/app/registratie/ui/registratie-wizard/registratie-wizard.component.ts", "deprecated": false, "deprecationMessage": "", "type": "string", "defaultValue": "'registratie-v1'" }, { "name": "VALID", "ctype": "miscellaneous", "subtype": "variable", "file": "src/app/shared/infrastructure/scenario.ts", "deprecated": false, "deprecationMessage": "", "type": "Scenario[]", "defaultValue": "['default', 'slow', 'loading', 'empty', 'error']" } ], "functions": [ { "name": "andThen", "file": "src/app/shared/application/remote-data.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "Chain a second source that depends on the first one's value.
\n", "args": [ { "name": "rd", "type": "RemoteData", "deprecated": false, "deprecationMessage": "" }, { "name": "f", "deprecated": false, "deprecationMessage": "" } ], "returnType": "RemoteDataTiny native-TS functional toolkit. No dependency — this is the whole "library".\nReused by every "impossible states" concept in the POC.
\n", "args": [ { "name": "x", "type": "never", "deprecated": false, "deprecationMessage": "" } ], "returnType": "never", "jsdoctags": [ { "name": "x", "type": "never", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "back", "file": "src/app/herregistratie/domain/herregistratie.machine.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "", "args": [ { "name": "s", "type": "WizardState", "deprecated": false, "deprecationMessage": "" } ], "returnType": "WizardState", "jsdoctags": [ { "name": "s", "type": "WizardState", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "back", "file": "src/app/herregistratie/domain/intake.machine.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "", "args": [ { "name": "s", "type": "IntakeState", "deprecated": false, "deprecationMessage": "" } ], "returnType": "IntakeState", "jsdoctags": [ { "name": "s", "type": "IntakeState", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "back", "file": "src/app/registratie/domain/registratie-wizard.machine.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "", "args": [ { "name": "s", "type": "RegistratieState", "deprecated": false, "deprecationMessage": "" } ], "returnType": "RegistratieState", "jsdoctags": [ { "name": "s", "type": "RegistratieState", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "createStore", "file": "src/app/shared/application/store.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "", "args": [ { "name": "init", "type": "Model", "deprecated": false, "deprecationMessage": "" }, { "name": "update", "deprecated": false, "deprecationMessage": "" } ], "returnType": "StoreReads ?scenario= from the URL so a demo can force each async state.
\n", "args": [], "returnType": "Scenario" }, { "name": "currentStep", "file": "src/app/herregistratie/domain/intake.machine.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "Which step the cursor currently points at (clamped to the fixed list).
\n", "args": [ { "name": "s", "type": "Extract", "deprecated": false, "deprecationMessage": "" } ], "returnType": "StepId", "jsdoctags": [ { "name": "s", "type": "Extract", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "currentStep", "file": "src/app/registratie/domain/registratie-wizard.machine.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "Which step the cursor currently points at (clamped to the fixed list).
\n", "args": [ { "name": "s", "type": "Extract", "deprecated": false, "deprecationMessage": "" } ], "returnType": "StepId", "jsdoctags": [ { "name": "s", "type": "Extract", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "declareerBeroep", "file": "src/app/registratie/domain/registratie-wizard.machine.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "Declare the beroep for a manually-entered diploma (chosen from a fixed list).
\n", "args": [ { "name": "s", "type": "RegistratieState", "deprecated": false, "deprecationMessage": "" }, { "name": "beroep", "type": "string", "deprecated": false, "deprecationMessage": "" } ], "returnType": "RegistratieState", "jsdoctags": [ { "name": "s", "type": "RegistratieState", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } }, { "name": "beroep", "type": "string", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "fakeResource", "file": "src/app/showcase/concepts.page.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "Minimal fake Resource so
Exhaustive fold: you must handle every case, checked at compile time.
\n", "args": [ { "name": "rd", "type": "RemoteData", "deprecated": false, "deprecationMessage": "" }, { "name": "h", "deprecated": false, "deprecationMessage": "" } ], "returnType": "R", "jsdoctags": [ { "name": "rd", "type": "RemoteData", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } }, { "name": "h", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "fromResource", "file": "src/app/shared/application/remote-data.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "Project Angular's loosely-typed Resource into a RemoteData value.
\n", "args": [ { "name": "r", "type": "Resource", "deprecated": false, "deprecationMessage": "" }, { "name": "isEmpty", "deprecated": false, "deprecationMessage": "", "defaultValue": "() => false" } ], "returnType": "RemoteDataJump back to an earlier step to correct data (controle → step N). Forward\njumps are not allowed (would skip validation). Preserves the draft.
\n", "args": [ { "name": "s", "type": "RegistratieState", "deprecated": false, "deprecationMessage": "" }, { "name": "cursor", "type": "number", "deprecated": false, "deprecationMessage": "" } ], "returnType": "RegistratieState", "jsdoctags": [ { "name": "s", "type": "RegistratieState", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } }, { "name": "cursor", "type": "number", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "herregistratieDeadline", "file": "src/app/registratie/domain/registration.policy.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "The herregistratie deadline, if the status has one (only the active state does).
\n", "args": [ { "name": "reg", "type": "Registration", "deprecated": false, "deprecationMessage": "" } ], "returnType": "Date | null", "jsdoctags": [ { "name": "reg", "type": "Registration", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "isAuthenticated", "file": "src/app/auth/domain/session.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "", "args": [ { "name": "s", "deprecated": false, "deprecationMessage": "" } ], "returnType": "Session", "jsdoctags": [ { "name": "s", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "isHerregistratieEligible", "file": "src/app/registratie/domain/registration.policy.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "A registration may apply for herregistratie only while active and within the\nwindow before its deadline. A struck-off or suspended registration may not.\nSERVER-OWNED RULE: this now runs on the backend (BFF), which ships the result\nas decisions.eligibleForHerregistratie in the dashboard view. Kept here as\nthe reference implementation + unit test; the frontend no longer calls it.
Invariant check used in tests/demos: a non-active status must not carry a\nherregistratie date. The union already enforces this structurally; this is\nthe runtime statement of the same rule.
\n", "args": [ { "name": "status", "type": "RegistrationStatus", "deprecated": false, "deprecationMessage": "" } ], "returnType": "boolean", "jsdoctags": [ { "name": "status", "type": "RegistrationStatus", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "kiesDiploma", "file": "src/app/registratie/domain/registratie-wizard.machine.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "Pick a DUO diploma; the beroep is derived from it and the applicable policy\nquestions (vraagIds) come with it (both server-computed, passed in).
Switch to manual diploma entry: the diploma isn't in DUO, so the MAXIMAL\npolicy-question set applies and the entry is flagged handmatig/unverified. The\nberoep is declared separately (declareerBeroep).
\n", "args": [ { "name": "s", "type": "RegistratieState", "deprecated": false, "deprecationMessage": "" }, { "name": "vraagIds", "deprecated": false, "deprecationMessage": "" } ], "returnType": "RegistratieState", "jsdoctags": [ { "name": "s", "type": "RegistratieState", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } }, { "name": "vraagIds", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "lageUren", "file": "src/app/herregistratie/domain/intake.machine.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "True when NL-hours are low enough that the scholing question must be answered.\nThe threshold is passed in (server-owned), not hardcoded.
\n", "args": [ { "name": "a", "type": "Answers", "deprecated": false, "deprecationMessage": "" }, { "name": "scholingThreshold", "type": "unknown", "deprecated": false, "deprecationMessage": "", "defaultValue": "SCHOLING_THRESHOLD_DEFAULT" } ], "returnType": "boolean", "jsdoctags": [ { "name": "a", "type": "Answers", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } }, { "name": "scholingThreshold", "type": "unknown", "deprecated": false, "deprecationMessage": "", "defaultValue": "SCHOLING_THRESHOLD_DEFAULT", "tagName": { "text": "param" } } ] }, { "name": "map", "file": "src/app/shared/application/remote-data.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "Transform the value inside a Success; pass other states through unchanged.
\n", "args": [ { "name": "rd", "type": "RemoteData", "deprecated": false, "deprecationMessage": "" }, { "name": "f", "deprecated": false, "deprecationMessage": "" } ], "returnType": "RemoteDataCombine two sources into one. Use this to merge e.g. a BIG-register call\nand a BRP call into a single state the page can render.
\n", "args": [ { "name": "a", "type": "RemoteData", "deprecated": false, "deprecationMessage": "" }, { "name": "b", "type": "RemoteData", "deprecated": false, "deprecationMessage": "" }, { "name": "f", "deprecated": false, "deprecationMessage": "" } ], "returnType": "RemoteDataCombine three sources (built on map2).
\n", "args": [ { "name": "a", "type": "RemoteData", "deprecated": false, "deprecationMessage": "" }, { "name": "b", "type": "RemoteData", "deprecated": false, "deprecationMessage": "" }, { "name": "c", "type": "RemoteData", "deprecated": false, "deprecationMessage": "" }, { "name": "f", "deprecated": false, "deprecationMessage": "" } ], "returnType": "RemoteDataStep 1 → 2: advance only when BOTH step-1 fields parse. Illegal elsewhere = no-op.
\n", "args": [ { "name": "s", "type": "WizardState", "deprecated": false, "deprecationMessage": "" } ], "returnType": "WizardState", "jsdoctags": [ { "name": "s", "type": "WizardState", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "next", "file": "src/app/herregistratie/domain/intake.machine.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "", "args": [ { "name": "s", "type": "IntakeState", "deprecated": false, "deprecationMessage": "" } ], "returnType": "IntakeState", "jsdoctags": [ { "name": "s", "type": "IntakeState", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "next", "file": "src/app/registratie/domain/registratie-wizard.machine.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "", "args": [ { "name": "s", "type": "RegistratieState", "deprecated": false, "deprecationMessage": "" } ], "returnType": "RegistratieState", "jsdoctags": [ { "name": "s", "type": "RegistratieState", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "parseBigNummer", "file": "src/app/registratie/domain/value-objects/big-nummer.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "", "args": [ { "name": "raw", "type": "string", "deprecated": false, "deprecationMessage": "" } ], "returnType": "ResultTrust-boundary parse: validate the untrusted response shape. "Geen adres" is a\nvalid outcome (gevonden: false), not a malformed response. ponytail: hand-written;\nreach for a schema lib once the contract count grows.
\n", "args": [ { "name": "json", "deprecated": false, "deprecationMessage": "" } ], "returnType": "ResultTrust-boundary parse: validate the untrusted response shape and map the DTO\nonto our own domain model. Hand-written on purpose — no Zod for a single\ncontract. ponytail: reach for a schema lib once the contract count grows.
\n", "args": [ { "name": "json", "deprecated": false, "deprecationMessage": "" } ], "returnType": "ResultTrust-boundary parse: validate the untrusted response shape (diplomas, each\nwith derived beroep + policy questions, plus the manual-entry fallback).
\n", "args": [ { "name": "json", "deprecated": false, "deprecationMessage": "" } ], "returnType": "ResultPrefill the address from a BRP lookup and flag its origin (PRD §7).
\n", "args": [ { "name": "s", "type": "RegistratieState", "deprecated": false, "deprecationMessage": "" }, { "name": "straat", "type": "string", "deprecated": false, "deprecationMessage": "" }, { "name": "postcode", "type": "string", "deprecated": false, "deprecationMessage": "" }, { "name": "woonplaats", "type": "string", "deprecated": false, "deprecationMessage": "" } ], "returnType": "RegistratieState", "jsdoctags": [ { "name": "s", "type": "RegistratieState", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } }, { "name": "straat", "type": "string", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } }, { "name": "postcode", "type": "string", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } }, { "name": "woonplaats", "type": "string", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "reduce", "file": "src/app/herregistratie/domain/herregistratie.machine.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "", "args": [ { "name": "s", "type": "WizardState", "deprecated": false, "deprecationMessage": "" }, { "name": "m", "type": "WizardMsg", "deprecated": false, "deprecationMessage": "" } ], "returnType": "WizardState", "jsdoctags": [ { "name": "s", "type": "WizardState", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } }, { "name": "m", "type": "WizardMsg", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "reduce", "file": "src/app/herregistratie/domain/intake.machine.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "", "args": [ { "name": "s", "type": "IntakeState", "deprecated": false, "deprecationMessage": "" }, { "name": "m", "type": "IntakeMsg", "deprecated": false, "deprecationMessage": "" } ], "returnType": "IntakeState", "jsdoctags": [ { "name": "s", "type": "IntakeState", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } }, { "name": "m", "type": "IntakeMsg", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "reduce", "file": "src/app/registratie/domain/registratie-wizard.machine.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "", "args": [ { "name": "s", "type": "RegistratieState", "deprecated": false, "deprecationMessage": "" }, { "name": "m", "type": "RegistratieMsg", "deprecated": false, "deprecationMessage": "" } ], "returnType": "RegistratieState", "jsdoctags": [ { "name": "s", "type": "RegistratieState", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } }, { "name": "m", "type": "RegistratieMsg", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "resolve", "file": "src/app/herregistratie/domain/herregistratie.machine.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "Resolve the async submit. Only meaningful while Submitting.
\n", "args": [ { "name": "s", "type": "WizardState", "deprecated": false, "deprecationMessage": "" }, { "name": "r", "type": "Result", "deprecated": false, "deprecationMessage": "" } ], "returnType": "WizardState", "jsdoctags": [ { "name": "s", "type": "WizardState", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } }, { "name": "r", "type": "Result", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "resolve", "file": "src/app/herregistratie/domain/intake.machine.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "", "args": [ { "name": "s", "type": "IntakeState", "deprecated": false, "deprecationMessage": "" }, { "name": "r", "type": "Result", "deprecated": false, "deprecationMessage": "" } ], "returnType": "IntakeState", "jsdoctags": [ { "name": "s", "type": "IntakeState", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } }, { "name": "r", "type": "Result", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "resolve", "file": "src/app/registratie/domain/registratie-wizard.machine.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "", "args": [ { "name": "s", "type": "RegistratieState", "deprecated": false, "deprecationMessage": "" }, { "name": "r", "type": "Result", "deprecated": false, "deprecationMessage": "" } ], "returnType": "RegistratieState", "jsdoctags": [ { "name": "s", "type": "RegistratieState", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } }, { "name": "r", "type": "Result", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "restore", "file": "src/app/auth/application/session.store.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "Restore a persisted session (best-effort; corrupt entry → logged out).
\n", "args": [], "returnType": "Session | null" }, { "name": "setAnswer", "file": "src/app/herregistratie/domain/intake.machine.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "", "args": [ { "name": "s", "type": "IntakeState", "deprecated": false, "deprecationMessage": "" }, { "name": "key", "deprecated": false, "deprecationMessage": "" }, { "name": "value", "type": "string", "deprecated": false, "deprecationMessage": "" } ], "returnType": "IntakeState", "jsdoctags": [ { "name": "s", "type": "IntakeState", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } }, { "name": "key", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } }, { "name": "value", "type": "string", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "setAntwoord", "file": "src/app/registratie/domain/registratie-wizard.machine.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "", "args": [ { "name": "s", "type": "RegistratieState", "deprecated": false, "deprecationMessage": "" }, { "name": "vraagId", "type": "string", "deprecated": false, "deprecationMessage": "" }, { "name": "value", "type": "string", "deprecated": false, "deprecationMessage": "" } ], "returnType": "RegistratieState", "jsdoctags": [ { "name": "s", "type": "RegistratieState", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } }, { "name": "vraagId", "type": "string", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } }, { "name": "value", "type": "string", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "setCorrespondentie", "file": "src/app/registratie/domain/registratie-wizard.machine.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "", "args": [ { "name": "s", "type": "RegistratieState", "deprecated": false, "deprecationMessage": "" }, { "name": "value", "type": "Correspondentie", "deprecated": false, "deprecationMessage": "" } ], "returnType": "RegistratieState", "jsdoctags": [ { "name": "s", "type": "RegistratieState", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } }, { "name": "value", "type": "Correspondentie", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "setField", "file": "src/app/herregistratie/domain/herregistratie.machine.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "Update one draft field while editing; ignored in any other state.
\n", "args": [ { "name": "s", "type": "WizardState", "deprecated": false, "deprecationMessage": "" }, { "name": "key", "deprecated": false, "deprecationMessage": "" }, { "name": "value", "type": "string", "deprecated": false, "deprecationMessage": "" } ], "returnType": "WizardState", "jsdoctags": [ { "name": "s", "type": "WizardState", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } }, { "name": "key", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } }, { "name": "value", "type": "string", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "setField", "file": "src/app/registratie/domain/registratie-wizard.machine.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "", "args": [ { "name": "s", "type": "RegistratieState", "deprecated": false, "deprecationMessage": "" }, { "name": "key", "type": "DraftField", "deprecated": false, "deprecationMessage": "" }, { "name": "value", "type": "string", "deprecated": false, "deprecationMessage": "" } ], "returnType": "RegistratieState", "jsdoctags": [ { "name": "s", "type": "RegistratieState", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } }, { "name": "key", "type": "DraftField", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } }, { "name": "value", "type": "string", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "setPolicy", "file": "src/app/herregistratie/domain/intake.machine.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "Apply a server-owned policy value (e.g. the scholing threshold).
\n", "args": [ { "name": "s", "type": "IntakeState", "deprecated": false, "deprecationMessage": "" }, { "name": "scholingThreshold", "type": "number", "deprecated": false, "deprecationMessage": "" } ], "returnType": "IntakeState", "jsdoctags": [ { "name": "s", "type": "IntakeState", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } }, { "name": "scholingThreshold", "type": "number", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "statusColor", "file": "src/app/registratie/domain/registration.policy.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "Brand colour token for a status. assertNever forces a colour for every new\nstatus variant at compile time.
\n", "args": [ { "name": "tag", "type": "StatusTag", "deprecated": false, "deprecationMessage": "" } ], "returnType": "string", "jsdoctags": [ { "name": "tag", "type": "StatusTag", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "statusLabel", "file": "src/app/registratie/domain/registration.policy.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "Domain logic for a registration — pure functions, NO Angular. This is where\n"what the business rules say" lives, separate from "how it looks" (UI) and\n"where the data comes from" (infrastructure). Keeping it framework-free means\nit is trivial to read and unit-test.
\n", "args": [ { "name": "tag", "type": "StatusTag", "deprecated": false, "deprecationMessage": "" } ], "returnType": "string", "jsdoctags": [ { "name": "tag", "type": "StatusTag", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "submit", "file": "src/app/herregistratie/domain/herregistratie.machine.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "Step 2 submit: parse everything; move to Submitting only with Valid data.
\n", "args": [ { "name": "s", "type": "WizardState", "deprecated": false, "deprecationMessage": "" } ], "returnType": "WizardState", "jsdoctags": [ { "name": "s", "type": "WizardState", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "submit", "file": "src/app/herregistratie/domain/intake.machine.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "", "args": [ { "name": "s", "type": "IntakeState", "deprecated": false, "deprecationMessage": "" } ], "returnType": "IntakeState", "jsdoctags": [ { "name": "s", "type": "IntakeState", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "submit", "file": "src/app/registratie/domain/registratie-wizard.machine.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "", "args": [ { "name": "s", "type": "RegistratieState", "deprecated": false, "deprecationMessage": "" } ], "returnType": "RegistratieState", "jsdoctags": [ { "name": "s", "type": "RegistratieState", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "submitHerregistratie", "file": "src/app/herregistratie/application/submit-herregistratie.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "The mutation/command: send a herregistratie application to the backend.\nReturns a Result so the caller can branch on success/failure without\ntry/catch. ponytail: faked with a timer; swap for a real POST when there's\nan API. The "uren must be > 0" rule lets the demo show a failure path.
\n", "args": [ { "name": "data", "type": "Valid", "deprecated": false, "deprecationMessage": "" } ], "returnType": "PromiseCommand: send the intake questionnaire to the backend. Returns a Result so the\ncaller branches on success/failure without try/catch. ponytail: faked with a\ntimer; swap for a real POST when there's an API. The "uren must be > 0" rule\nlets the demo show the failure path.
\n", "args": [ { "name": "data", "type": "ValidIntake", "deprecated": false, "deprecationMessage": "" } ], "returnType": "PromiseCommand: send the completed registration to the backend, which invokes the\ndomain command to create/finalize the registration aggregate. Returns a Result\nso the caller branches on success/failure without try/catch; on success it\nyields the confirmation reference (PRD §9). ponytail: faked with a timer; swap\nfor a real POST when there's an API. The "manually entered diploma" rule lets\nthe demo show the failure path.
\n", "args": [ { "name": "data", "type": "ValidRegistratie", "deprecated": false, "deprecationMessage": "" } ], "returnType": "PromiseParse every field; on success hand back a Valid, else the per-field errors.
\n", "args": [ { "name": "draft", "type": "Draft", "deprecated": false, "deprecationMessage": "" } ], "returnType": "ResultParse the whole questionnaire into a ValidIntake (called on submit).
\n", "args": [ { "name": "a", "type": "Answers", "deprecated": false, "deprecationMessage": "" }, { "name": "scholingThreshold", "type": "number", "deprecated": false, "deprecationMessage": "" } ], "returnType": "ResultParse the whole wizard into a ValidRegistratie (called on submit).
\n", "args": [ { "name": "d", "type": "Draft", "deprecated": false, "deprecationMessage": "" } ], "returnType": "ResultValidate every question currently visible in ONE step. Errors keyed per field.
\n", "args": [ { "name": "step", "type": "StepId", "deprecated": false, "deprecationMessage": "" }, { "name": "a", "type": "Answers", "deprecated": false, "deprecationMessage": "" }, { "name": "scholingThreshold", "type": "number", "deprecated": false, "deprecationMessage": "" } ], "returnType": "ResultValidate every question currently visible in ONE step. Errors keyed per field.
\n", "args": [ { "name": "step", "type": "StepId", "deprecated": false, "deprecationMessage": "" }, { "name": "d", "type": "Draft", "deprecated": false, "deprecationMessage": "" } ], "returnType": "ResultA note is either a recognised specialism or a plain annotation — a closed set,\nnot an open string, so a typo can't slip through.
\n", "kind": 193 }, { "name": "AdresHerkomst", "ctype": "miscellaneous", "subtype": "typealias", "rawtype": "\"brp\" | \"handmatig\"", "file": "src/app/registratie/domain/registratie-wizard.machine.ts", "deprecated": false, "deprecationMessage": "", "description": "Where a piece of data came from — recorded on the aggregate (PRD §5).
\n", "kind": 193 }, { "name": "AlertType", "ctype": "miscellaneous", "subtype": "typealias", "rawtype": "\"info\" | \"ok\" | \"warning\" | \"error\"", "file": "src/app/shared/ui/alert/alert.component.ts", "deprecated": false, "deprecationMessage": "", "description": "", "kind": 193 }, { "name": "BigNummer", "ctype": "miscellaneous", "subtype": "typealias", "rawtype": "BrandValue object: a BIG registration number — 11 digits.
\n", "kind": 184 }, { "name": "Brand", "ctype": "miscellaneous", "subtype": "typealias", "rawtype": "unknown", "file": "src/app/shared/kernel/fp.ts", "deprecated": false, "deprecationMessage": "", "description": "Nominal typing: Brand<string, 'Postcode'> is assignable from a plain string\nonly through an explicit cast — so a smart constructor is the only minter.
\n", "kind": 194 }, { "name": "Correspondentie", "ctype": "miscellaneous", "subtype": "typealias", "rawtype": "\"email\" | \"post\"", "file": "src/app/registratie/domain/registratie-wizard.machine.ts", "deprecated": false, "deprecationMessage": "", "description": "", "kind": 193 }, { "name": "DiplomaHerkomst", "ctype": "miscellaneous", "subtype": "typealias", "rawtype": "\"duo\" | \"handmatig\"", "file": "src/app/registratie/domain/registratie-wizard.machine.ts", "deprecated": false, "deprecationMessage": "", "description": "", "kind": 193 }, { "name": "DraftField", "ctype": "miscellaneous", "subtype": "typealias", "rawtype": "\"straat\" | \"postcode\" | \"woonplaats\" | \"email\"", "file": "src/app/registratie/domain/registratie-wizard.machine.ts", "deprecated": false, "deprecationMessage": "", "description": "Text fields settable via SetField.
\n", "kind": 193 }, { "name": "Email", "ctype": "miscellaneous", "subtype": "typealias", "rawtype": "Brand