Files
atomic-design-poc/documentation.json
Edwin van den Houdt 8b590a50d9 Regenerate compodoc documentation.json
Reflects the bounded-context restructuring and new state-management modules.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 07:20:23 +02:00

7396 lines
398 KiB
JSON

{
"pipes": [],
"interfaces": [
{
"name": "Aantekening",
"id": "interface-Aantekening-2ecca36e413e22c1c5967d07b811fa4171ff578eb6b47a7275723bcca44e93a2db27d77a765b82e5f6182492464cc8b9268c9724e13b400718d30da7bc4ba50c",
"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\nexport interface Aantekening {\n type: string; // specialisme of aantekening\n omschrijving: string;\n datum: string;\n}\n",
"properties": [
{
"name": "datum",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 28
},
{
"name": "omschrijving",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 27
},
{
"name": "type",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 26
}
],
"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": "<p>Person identity as supplied by the BRP (Basisregistratie Personen).</p>\n",
"rawdescription": "\nPerson identity as supplied by the BRP (Basisregistratie Personen).",
"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": "<p>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.</p>\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": "ChangeRequest",
"id": "interface-ChangeRequest-8d79b6a9ce75f62f4e04f9d3ed0867e00d005c9c05cf267503536c4eec9813372aff51a3c8686927fd07f46503b60ddb4107edcc5f57fdfa1b6b52fe2a98026c",
"file": "src/app/registratie/ui/change-request-form/change-request-form.component.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "interface",
"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 <app-heading [level]=\"2\">Adreswijziging doorgeven</app-heading>\n <form (ngSubmit)=\"onSubmit()\" style=\"max-width:28rem\">\n <app-form-field label=\"Straat en huisnummer\" fieldId=\"street\" [error]=\"streetError()\">\n <app-text-input inputId=\"street\" [(ngModel)]=\"street\" name=\"street\" [invalid]=\"!!streetError()\" />\n </app-form-field>\n <app-form-field label=\"Postcode\" fieldId=\"zip\" [error]=\"zipError()\">\n <app-text-input inputId=\"zip\" [(ngModel)]=\"zip\" name=\"zip\" placeholder=\"1234 AB\" [invalid]=\"!!zipError()\" />\n </app-form-field>\n <app-form-field label=\"Woonplaats\" fieldId=\"city\">\n <app-text-input inputId=\"city\" [(ngModel)]=\"city\" name=\"city\" />\n </app-form-field>\n <div style=\"margin-top:1rem\">\n <app-button type=\"submit\" variant=\"primary\">Wijziging indienen</app-button>\n </div>\n </form>\n `,\n})\nexport class ChangeRequestFormComponent {\n street = '';\n zip = '';\n city = '';\n streetError = signal('');\n zipError = signal('');\n submitted = output<ChangeRequest>();\n\n onSubmit() {\n const street = this.street.trim();\n this.streetError.set(street ? '' : 'Vul straat en huisnummer in.');\n\n const postcode = parsePostcode(this.zip);\n this.zipError.set(postcode.ok ? '' : postcode.error);\n\n if (!street || !postcode.ok) return;\n this.submitted.emit({ street, zip: postcode.value, city: this.city.trim() });\n }\n}\n",
"properties": [
{
"name": "city",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 14
},
{
"name": "street",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 12
},
{
"name": "zip",
"deprecated": false,
"deprecationMessage": "",
"type": "Postcode",
"indexKey": "",
"optional": false,
"description": "",
"line": 13
}
],
"indexSignatures": [],
"kind": 172,
"description": "<p>A submitted change request carries a <em>parsed</em> postcode (branded Postcode),\nnot a raw string — downstream code can&#39;t receive an unvalidated one.</p>\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": "Draft",
"id": "interface-Draft-6d0ec48dfedad1e9d3dc32caaf0639d35f1430f1e8081a0a719ad0675d06912a90de0d8159326e13c9cc3c8f82521e3fded8d06a5feb1480be4c084a967e6aad",
"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 punten: string;\n}\n\n/** What we have AFTER parsing — branded/typed, guaranteed valid. */\nexport interface Valid {\n uren: Uren;\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: Partial<Record<keyof Draft, string>> }\n | { tag: 'Submitting'; data: Valid }\n | { tag: 'Submitted'; data: Valid }\n | { tag: 'Failed'; data: Valid; error: string };\n\nexport const initial: WizardState = { tag: 'Editing', step: 1, draft: { uren: '', punten: '' }, errors: {} };\n\n/** Parse every field; on success hand back a Valid, else the per-field errors. */\nfunction validate(draft: Draft): Result<Partial<Record<keyof Draft, string>>, Valid> {\n const uren = parseUren(draft.uren);\n const punten = parseUren(draft.punten);\n const errors: Partial<Record<keyof Draft, string>> = {};\n if (!uren.ok) errors.uren = uren.error;\n if (!punten.ok) errors.punten = punten.error;\n if (uren.ok && punten.ok) return { ok: true, value: { uren: uren.value, punten: punten.value } };\n return { ok: false, error: errors };\n}\n\n/** Step 1 → 2: only advance if the uren field parses. Illegal elsewhere = no-op. */\nexport function next(s: WizardState): WizardState {\n if (s.tag !== 'Editing' || s.step !== 1) return s;\n const uren = parseUren(s.draft.uren);\n return uren.ok\n ? { ...s, step: 2, errors: {} }\n : { ...s, errors: { uren: uren.error } };\n}\n\nexport function back(s: WizardState): WizardState {\n if (s.tag !== 'Editing' || s.step !== 2) return s;\n return { ...s, step: 1, errors: {} };\n}\n\n/** Step 2 submit: parse everything; move to Submitting only with Valid data. */\nexport function submit(s: WizardState): WizardState {\n if (s.tag !== 'Editing' || s.step !== 2) return s;\n const result = validate(s.draft);\n return result.ok ? { tag: 'Submitting', data: result.value } : { ...s, errors: result.error };\n}\n\n/** Resolve the async submit. Only meaningful while Submitting. */\nexport function resolve(s: WizardState, r: Result<string, void>): WizardState {\n if (s.tag !== 'Submitting') return s;\n return r.ok ? { tag: 'Submitted', data: s.data } : { tag: 'Failed', data: s.data, error: r.error };\n}\n\n/** Update one draft field while editing; ignored in any other state. */\nexport function setField(s: WizardState, key: keyof Draft, value: string): WizardState {\n if (s.tag !== 'Editing') return s;\n return { ...s, draft: { ...s.draft, [key]: value } };\n}\n\n/**\n * Every event that can happen to the wizard, as one message type. The component\n * sends a WizardMsg; `reduce` decides the next state. This is the Elm\n * Model+Msg+update pattern: ONE pure function describes all state changes.\n */\nexport type WizardMsg =\n | { tag: 'SetField'; key: keyof Draft; value: string }\n | { tag: 'Next' }\n | { tag: 'Back' }\n | { tag: 'Submit' }\n | { tag: 'Retry' }\n | { tag: 'SubmitConfirmed' }\n | { tag: 'SubmitFailed'; error: string }\n | { tag: 'Seed'; state: WizardState }; // mount a specific state (stories/showcase)\n\nexport function reduce(s: WizardState, m: WizardMsg): WizardState {\n switch (m.tag) {\n case 'SetField':\n return setField(s, m.key, m.value);\n case 'Next':\n return next(s);\n case 'Back':\n return back(s);\n case 'Submit':\n return submit(s);\n case 'Retry':\n return s.tag === 'Failed' ? { tag: 'Submitting', data: s.data } : s;\n case 'SubmitConfirmed':\n return s.tag === 'Submitting' ? { tag: 'Submitted', data: s.data } : s;\n case 'SubmitFailed':\n return s.tag === 'Submitting' ? { tag: 'Failed', data: s.data, error: m.error } : s;\n case 'Seed':\n return m.state;\n default:\n return assertNever(m);\n }\n}\n",
"properties": [
{
"name": "punten",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 7
},
{
"name": "uren",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 6
}
],
"indexSignatures": [],
"kind": 172,
"description": "<p>What the user is typing (raw, possibly invalid).</p>\n",
"rawdescription": "\nWhat the user is typing (raw, possibly invalid).",
"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": "Registration",
"id": "interface-Registration-2ecca36e413e22c1c5967d07b811fa4171ff578eb6b47a7275723bcca44e93a2db27d77a765b82e5f6182492464cc8b9268c9724e13b400718d30da7bc4ba50c",
"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\nexport interface Aantekening {\n type: string; // specialisme of aantekening\n omschrijving: string;\n datum: string;\n}\n",
"properties": [
{
"name": "beroep",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 19
},
{
"name": "bigNummer",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 17
},
{
"name": "geboortedatum",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 21
},
{
"name": "naam",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 18
},
{
"name": "registratiedatum",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 20
},
{
"name": "status",
"deprecated": false,
"deprecationMessage": "",
"type": "RegistrationStatus",
"indexKey": "",
"optional": false,
"description": "",
"line": 22
}
],
"indexSignatures": [],
"kind": 172,
"methods": [],
"extends": []
},
{
"name": "Session",
"id": "interface-Session-4f483129ecb1f3747a600d06904b954a4950b10c4da782d9635896d2c39feaa7777d0e9ed018efa5d4252fd44a29035a431e7dcc15ec19c903f710b163e162f2",
"file": "src/app/auth/domain/session.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "interface",
"sourceCode": "export interface Session {\n readonly bsn: string;\n readonly naam: string;\n}\n\nexport function isAuthenticated(s: Session | null): s is Session {\n return s !== null;\n}\n",
"properties": [
{
"name": "bsn",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 3,
"modifierKind": [
148
]
},
{
"name": "naam",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 4,
"modifierKind": [
148
]
}
],
"indexSignatures": [],
"kind": 172,
"description": "<p>Who is logged in. Framework-free domain type.</p>\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 Store<Model, Msg> {\n /** The current state, as a read-only Angular signal. */\n readonly model: Signal<Model>;\n /** Send a message; the model becomes update(model, msg). */\n dispatch(msg: Msg): void;\n}\n\nexport function createStore<Model, Msg>(\n init: Model,\n update: (model: Model, msg: Msg) => Model,\n): Store<Model, Msg> {\n const model = signal(init);\n return {\n model: model.asReadonly(),\n dispatch: (msg) => model.set(update(model(), msg)),\n };\n}\n",
"properties": [
{
"name": "model",
"deprecated": false,
"deprecationMessage": "",
"type": "Signal<Model>",
"indexKey": "",
"optional": false,
"description": "<p>The current state, as a read-only Angular signal.</p>\n",
"line": 15,
"rawdescription": "\nThe current state, as a read-only Angular signal.",
"modifierKind": [
148
]
}
],
"indexSignatures": [],
"kind": 174,
"description": "<p>A tiny &quot;Elm-style&quot; 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 <code>update(model, msg)</code> that returns the next Model. Nothing else\nmutates state, so to understand the app you only read the update function.</p>\n<p>Side effects (HTTP, timers) do NOT go in <code>update</code> — that stays pure and easy\nto test. Instead, effectful &quot;command&quot; functions call the network and then\n<code>dispatch</code> a message describing what happened (e.g. Loaded / Failed).</p>\n",
"rawdescription": "\n\nA 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.\n\nSide effects (HTTP, timers) do NOT go in `update` — that stays pure and easy\nto test. Instead, effectful \"command\" functions call the network and then\n`dispatch` a message describing what happened (e.g. Loaded / Failed).\n",
"methods": [
{
"name": "dispatch",
"args": [
{
"name": "msg",
"type": "Msg",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": ""
}
],
"optional": false,
"returnType": "void",
"typeParameters": [],
"line": 17,
"deprecated": false,
"deprecationMessage": "",
"rawdescription": "\nSend a message; the model becomes update(model, msg).",
"description": "<p>Send a message; the model becomes update(model, msg).</p>\n",
"jsdoctags": [
{
"name": "msg",
"type": "Msg",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
}
],
"extends": []
},
{
"name": "Valid",
"id": "interface-Valid-6d0ec48dfedad1e9d3dc32caaf0639d35f1430f1e8081a0a719ad0675d06912a90de0d8159326e13c9cc3c8f82521e3fded8d06a5feb1480be4c084a967e6aad",
"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 punten: string;\n}\n\n/** What we have AFTER parsing — branded/typed, guaranteed valid. */\nexport interface Valid {\n uren: Uren;\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: Partial<Record<keyof Draft, string>> }\n | { tag: 'Submitting'; data: Valid }\n | { tag: 'Submitted'; data: Valid }\n | { tag: 'Failed'; data: Valid; error: string };\n\nexport const initial: WizardState = { tag: 'Editing', step: 1, draft: { uren: '', punten: '' }, errors: {} };\n\n/** Parse every field; on success hand back a Valid, else the per-field errors. */\nfunction validate(draft: Draft): Result<Partial<Record<keyof Draft, string>>, Valid> {\n const uren = parseUren(draft.uren);\n const punten = parseUren(draft.punten);\n const errors: Partial<Record<keyof Draft, string>> = {};\n if (!uren.ok) errors.uren = uren.error;\n if (!punten.ok) errors.punten = punten.error;\n if (uren.ok && punten.ok) return { ok: true, value: { uren: uren.value, punten: punten.value } };\n return { ok: false, error: errors };\n}\n\n/** Step 1 → 2: only advance if the uren field parses. Illegal elsewhere = no-op. */\nexport function next(s: WizardState): WizardState {\n if (s.tag !== 'Editing' || s.step !== 1) return s;\n const uren = parseUren(s.draft.uren);\n return uren.ok\n ? { ...s, step: 2, errors: {} }\n : { ...s, errors: { uren: uren.error } };\n}\n\nexport function back(s: WizardState): WizardState {\n if (s.tag !== 'Editing' || s.step !== 2) return s;\n return { ...s, step: 1, errors: {} };\n}\n\n/** Step 2 submit: parse everything; move to Submitting only with Valid data. */\nexport function submit(s: WizardState): WizardState {\n if (s.tag !== 'Editing' || s.step !== 2) return s;\n const result = validate(s.draft);\n return result.ok ? { tag: 'Submitting', data: result.value } : { ...s, errors: result.error };\n}\n\n/** Resolve the async submit. Only meaningful while Submitting. */\nexport function resolve(s: WizardState, r: Result<string, void>): WizardState {\n if (s.tag !== 'Submitting') return s;\n return r.ok ? { tag: 'Submitted', data: s.data } : { tag: 'Failed', data: s.data, error: r.error };\n}\n\n/** Update one draft field while editing; ignored in any other state. */\nexport function setField(s: WizardState, key: keyof Draft, value: string): WizardState {\n if (s.tag !== 'Editing') return s;\n return { ...s, draft: { ...s.draft, [key]: value } };\n}\n\n/**\n * Every event that can happen to the wizard, as one message type. The component\n * sends a WizardMsg; `reduce` decides the next state. This is the Elm\n * Model+Msg+update pattern: ONE pure function describes all state changes.\n */\nexport type WizardMsg =\n | { tag: 'SetField'; key: keyof Draft; value: string }\n | { tag: 'Next' }\n | { tag: 'Back' }\n | { tag: 'Submit' }\n | { tag: 'Retry' }\n | { tag: 'SubmitConfirmed' }\n | { tag: 'SubmitFailed'; error: string }\n | { tag: 'Seed'; state: WizardState }; // mount a specific state (stories/showcase)\n\nexport function reduce(s: WizardState, m: WizardMsg): WizardState {\n switch (m.tag) {\n case 'SetField':\n return setField(s, m.key, m.value);\n case 'Next':\n return next(s);\n case 'Back':\n return back(s);\n case 'Submit':\n return submit(s);\n case 'Retry':\n return s.tag === 'Failed' ? { tag: 'Submitting', data: s.data } : s;\n case 'SubmitConfirmed':\n return s.tag === 'Submitting' ? { tag: 'Submitted', data: s.data } : s;\n case 'SubmitFailed':\n return s.tag === 'Submitting' ? { tag: 'Failed', data: s.data, error: m.error } : s;\n case 'Seed':\n return m.state;\n default:\n return assertNever(m);\n }\n}\n",
"properties": [
{
"name": "punten",
"deprecated": false,
"deprecationMessage": "",
"type": "number",
"indexKey": "",
"optional": false,
"description": "",
"line": 13
},
{
"name": "uren",
"deprecated": false,
"deprecationMessage": "",
"type": "Uren",
"indexKey": "",
"optional": false,
"description": "",
"line": 12
}
],
"indexSignatures": [],
"kind": 172,
"description": "<p>What we have AFTER parsing — branded/typed, guaranteed valid.</p>\n",
"rawdescription": "\nWhat we have AFTER parsing — branded/typed, guaranteed valid.",
"methods": [],
"extends": []
}
],
"injectables": [
{
"name": "BigProfileStore",
"id": "injectable-BigProfileStore-d0fd61e9f3ea54ee7ebca6eb9a097da261a7447f337e972e7bbb2a8c238f15a8f175b1fddac6c031fc95f77ab8d2778748a149f358ef5f5ec22ecaa23971ef9a",
"file": "src/app/registratie/application/big-profile.store.ts",
"properties": [
{
"name": "aantekeningen",
"defaultValue": "computed<RemoteData<Err, Aantekening[]>>(() =>\n fromResource(this.aantekeningenRes, (v) => v.length === 0),\n )",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "<p>Specialisms/notes stay a separate stream (they have their own empty state).</p>\n",
"line": 41,
"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": 26,
"modifierKind": [
123
]
},
{
"name": "big",
"defaultValue": "inject(BigRegisterAdapter)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 22,
"modifierKind": [
123
]
},
{
"name": "brp",
"defaultValue": "inject(BrpAdapter)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 23,
"modifierKind": [
123
]
},
{
"name": "pending",
"defaultValue": "signal(false)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 46,
"modifierKind": [
123
]
},
{
"name": "pendingHerregistratie",
"defaultValue": "this.pending.asReadonly()",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "<p>True while a herregistratie submission is in flight or just submitted.</p>\n",
"line": 48,
"rawdescription": "\nTrue while a herregistratie submission is in flight or just submitted.",
"modifierKind": [
148
]
},
{
"name": "personRes",
"defaultValue": "this.brp.personResource()",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 27,
"modifierKind": [
123
]
},
{
"name": "profile",
"defaultValue": "computed<RemoteData<Err, BigProfile>>(() =>\n map2(\n fromResource(this.registrationRes),\n fromResource(this.personRes),\n // httpResource types value as T | undefined; in the Success branch it is\n // always present, so narrowing here is safe.\n (registration, person) => ({ registration: registration!, person: person! }),\n ),\n )",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "<p>BIG-register + BRP folded into one state.</p>\n",
"line": 30,
"rawdescription": "\nBIG-register + BRP folded into one state.",
"modifierKind": [
148
]
},
{
"name": "registrationRes",
"defaultValue": "this.big.registrationResource()",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 25,
"modifierKind": [
123
]
}
],
"methods": [
{
"name": "beginHerregistratie",
"args": [],
"optional": false,
"returnType": "void",
"typeParameters": [],
"line": 50,
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "confirmHerregistratie",
"args": [],
"optional": false,
"returnType": "void",
"typeParameters": [],
"line": 53,
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "rollbackHerregistratie",
"args": [],
"optional": false,
"returnType": "void",
"typeParameters": [],
"line": 57,
"deprecated": false,
"deprecationMessage": ""
}
],
"deprecated": false,
"deprecationMessage": "",
"description": "<p>The single source of truth for the logged-in professional&#39;s profile, shared\nacross pages (providedIn:&#39;root&#39; = one instance). It owns the httpResources\n(created here, in the required injection context) and exposes them as\nRemoteData signals.</p>\n<p>The headline trick: <code>profile</code> combines TWO independent services — the\nBIG-register and the BRP — into ONE RemoteData via map2. A page renders a\nsingle state (loading / error / loaded), never juggling three.</p>\n",
"rawdescription": "\n\nThe 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.\n\nThe headline trick: `profile` combines TWO independent services — the\nBIG-register and the BRP — into ONE RemoteData via map2. A page renders a\nsingle state (loading / error / loaded), never juggling three.\n",
"sourceCode": "import { Injectable, computed, inject, signal } from '@angular/core';\nimport { RemoteData, fromResource, map2 } from '@shared/application/remote-data';\nimport { Aantekening } from '../domain/registration';\nimport { BigProfile } from '../domain/big-profile';\nimport { BigRegisterAdapter } from '../infrastructure/big-register.adapter';\nimport { BrpAdapter } from '../infrastructure/brp.adapter';\n\ntype Err = Error | undefined;\n\n/**\n * The single source of truth for the logged-in professional's profile, shared\n * across pages (providedIn:'root' = one instance). It owns the httpResources\n * (created here, in the required injection context) and exposes them as\n * RemoteData signals.\n *\n * The headline trick: `profile` combines TWO independent services — the\n * BIG-register and the BRP — into ONE RemoteData via map2. A page renders a\n * single state (loading / error / loaded), never juggling three.\n */\n@Injectable({ providedIn: 'root' })\nexport class BigProfileStore {\n private big = inject(BigRegisterAdapter);\n private brp = inject(BrpAdapter);\n\n private registrationRes = this.big.registrationResource();\n private aantekeningenRes = this.big.aantekeningenResource();\n private personRes = this.brp.personResource();\n\n /** BIG-register + BRP folded into one state. */\n readonly profile = computed<RemoteData<Err, BigProfile>>(() =>\n map2(\n fromResource(this.registrationRes),\n fromResource(this.personRes),\n // httpResource types value as T | undefined; in the Success branch it is\n // always present, so narrowing here is safe.\n (registration, person) => ({ registration: registration!, person: person! }),\n ),\n );\n\n /** Specialisms/notes stay a separate stream (they have their own empty state). */\n readonly aantekeningen = computed<RemoteData<Err, Aantekening[]>>(() =>\n fromResource(this.aantekeningenRes, (v) => v.length === 0),\n );\n\n // --- Optimistic herregistratie state, shared with the dashboard -----------\n private pending = signal(false);\n /** True while a herregistratie submission is in flight or just submitted. */\n readonly pendingHerregistratie = this.pending.asReadonly();\n\n beginHerregistratie() {\n this.pending.set(true); // optimistic: show it immediately on the dashboard\n }\n confirmHerregistratie() {\n this.pending.set(false);\n this.registrationRes.reload(); // invalidate: re-fetch the now-updated registration\n }\n rollbackHerregistratie() {\n this.pending.set(false); // submission failed — undo the optimistic flag\n }\n}\n",
"extends": [],
"type": "injectable"
},
{
"name": "BigRegisterAdapter",
"id": "injectable-BigRegisterAdapter-b658d9915e8f09eed460d1f75d5dc229398186277cfa4d35fd143799842c80174c41daf2f30936090fda88e72f3bbfc3e9422cbfa7b1d1342eb004cc2d80e3ae",
"file": "src/app/registratie/infrastructure/big-register.adapter.ts",
"properties": [],
"methods": [
{
"name": "aantekeningenResource",
"args": [],
"optional": false,
"returnType": "any",
"typeParameters": [],
"line": 17,
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "registrationResource",
"args": [],
"optional": false,
"returnType": "any",
"typeParameters": [],
"line": 13,
"deprecated": false,
"deprecationMessage": ""
}
],
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Infrastructure adapter for the BIG-register source. Exposes signal-based\nresources (Angular&#39;s httpResource); each returns a Resource with\nstatus()/value()/error()/reload(). Call from an injection context\n(a field initializer in the store).</p>\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",
"sourceCode": "import { Injectable } from '@angular/core';\nimport { httpResource } from '@angular/common/http';\nimport { Registration, 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@Injectable({ providedIn: 'root' })\nexport class BigRegisterAdapter {\n registrationResource() {\n return httpResource<Registration>(() => 'mock/registration.json');\n }\n\n aantekeningenResource() {\n return httpResource<Aantekening[]>(() => 'mock/notes.json', { defaultValue: [] });\n }\n}\n",
"extends": [],
"type": "injectable"
},
{
"name": "BrpAdapter",
"id": "injectable-BrpAdapter-66b7fdb8331dd6cebe24a4713e26a6b025c4c97b239a8de8a81f9b72167dc376459e44aca001b24a7c44bdba6b97fa82d248762bbd1fca3a476993f709834b89",
"file": "src/app/registratie/infrastructure/brp.adapter.ts",
"properties": [],
"methods": [
{
"name": "personResource",
"args": [],
"optional": false,
"returnType": "any",
"typeParameters": [],
"line": 8,
"deprecated": false,
"deprecationMessage": ""
}
],
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Infrastructure adapter for the BRP (Basisregistratie Personen) source.</p>\n",
"rawdescription": "\nInfrastructure adapter for the BRP (Basisregistratie Personen) source.",
"sourceCode": "import { Injectable } from '@angular/core';\nimport { httpResource } from '@angular/common/http';\nimport { Person } from '../domain/person';\n\n/** Infrastructure adapter for the BRP (Basisregistratie Personen) source. */\n@Injectable({ providedIn: 'root' })\nexport class BrpAdapter {\n personResource() {\n return httpResource<Person>(() => 'mock/brp.json');\n }\n}\n",
"extends": [],
"type": "injectable"
},
{
"name": "DigidAdapter",
"id": "injectable-DigidAdapter-6b0a6d77a6f7411602d1c257ac45d4d45631556b1a468f7f38abfbbe375a3ac5e566fa6024ba56cb59f8418174ed2dbc6ea937b7b7999e58655acf01c7d7ecc9",
"file": "src/app/auth/infrastructure/digid.adapter.ts",
"properties": [],
"methods": [
{
"name": "authenticate",
"args": [
{
"name": "bsn",
"type": "string",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": ""
}
],
"optional": false,
"returnType": "Promise<Result<string, Session>>",
"typeParameters": [],
"line": 10,
"deprecated": false,
"deprecationMessage": "",
"modifierKind": [
134
],
"jsdoctags": [
{
"name": "bsn",
"type": "string",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
}
],
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Infrastructure: talks to the (mock) DigiD identity provider.</p>\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): Promise<Result<string, Session>> {\n const t = bsn.trim();\n if (!/^\\d{9}$/.test(t)) return err('Voer een geldig BSN van 9 cijfers in.');\n return ok({ bsn: t, naam: 'Dr. A. (Anna) de Vries' });\n }\n}\n",
"extends": [],
"type": "injectable"
},
{
"name": "SessionStore",
"id": "injectable-SessionStore-73a990a2a5a1c0f7177443b4e29c7af3da44fcbabcc4e6637486764225143283202ac5da0ee355ed30f829eab6f88a25f05dac7fce22d60cbf2dda7e0956b949",
"file": "src/app/auth/application/session.store.ts",
"properties": [
{
"name": "_session",
"defaultValue": "signal<Session | null>(null)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 15,
"modifierKind": [
123
]
},
{
"name": "digid",
"defaultValue": "inject(DigidAdapter)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 14,
"modifierKind": [
123
]
},
{
"name": "isAuthenticated",
"defaultValue": "computed(() => this._session() !== null)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 18,
"modifierKind": [
148
]
},
{
"name": "session",
"defaultValue": "this._session.asReadonly()",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 17,
"modifierKind": [
148
]
}
],
"methods": [
{
"name": "login",
"args": [
{
"name": "bsn",
"type": "string",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": ""
}
],
"optional": false,
"returnType": "Promise<Result<string, Session>>",
"typeParameters": [],
"line": 21,
"deprecated": false,
"deprecationMessage": "",
"rawdescription": "\nEffectful command: authenticate, then store the session on success.",
"description": "<p>Effectful command: authenticate, then store the session on success.</p>\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": 27,
"deprecated": false,
"deprecationMessage": ""
}
],
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Holds the current session for the whole app. Because it is providedIn:&#39;root&#39;\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.). ponytail: in-memory only; a refresh logs you out.</p>\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.). ponytail: in-memory only; a refresh logs you out.\n",
"sourceCode": "import { Injectable, computed, inject, signal } from '@angular/core';\nimport { Result } from '@shared/kernel/fp';\nimport { Session } from '../domain/session';\nimport { DigidAdapter } from '../infrastructure/digid.adapter';\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.). ponytail: in-memory only; a refresh logs you out.\n */\n@Injectable({ providedIn: 'root' })\nexport class SessionStore {\n private digid = inject(DigidAdapter);\n private _session = signal<Session | null>(null);\n\n readonly session = this._session.asReadonly();\n readonly isAuthenticated = computed(() => this._session() !== null);\n\n /** Effectful command: authenticate, then store the session on success. */\n async login(bsn: string): Promise<Result<string, Session>> {\n const r = await this.digid.authenticate(bsn);\n if (r.ok) this._session.set(r.value);\n return r;\n }\n\n logout() {\n this._session.set(null);\n }\n}\n",
"extends": [],
"type": "injectable"
}
],
"guards": [],
"interceptors": [],
"classes": [],
"directives": [
{
"name": "AsyncEmptyDirective",
"id": "directive-AsyncEmptyDirective-b3cfb3c4a98444c42ba42c11d432aca9cf324dba35b23ccb8af26360530e37b4edcc64b110afd78fb4d7e4eef1b24c72be872007aaa92127f22e76e1ae7c0964",
"file": "src/app/shared/ui/async/async.component.ts",
"type": "directive",
"description": "",
"rawdescription": "\n",
"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 on <ng-template> children of <app-async>. */\n@Directive({ selector: '[appAsyncLoaded]' })\nexport class AsyncLoadedDirective {\n constructor(public tpl: TemplateRef<{ $implicit: unknown }>) {}\n}\n@Directive({ selector: '[appAsyncLoading]' })\nexport class AsyncLoadingDirective {\n constructor(public tpl: TemplateRef<unknown>) {}\n}\n@Directive({ selector: '[appAsyncEmpty]' })\nexport class AsyncEmptyDirective {\n constructor(public tpl: TemplateRef<unknown>) {}\n}\n@Directive({ selector: '[appAsyncError]' })\nexport class AsyncErrorDirective {\n constructor(public tpl: TemplateRef<{ $implicit: Error | undefined; retry: () => void }>) {}\n}\n\n/**\n * Renders exactly ONE of loading / empty / error / loaded for a signal-based\n * resource (e.g. httpResource). Built on a RemoteData tagged union (see\n * core/remote-data.ts), so the states are mutually exclusive by construction —\n * the UI can never show two at once (\"impossible states\"). Unprovided slots\n * fall back to sensible defaults.\n */\n@Component({\n selector: 'app-async',\n imports: [NgTemplateOutlet, SpinnerComponent, AlertComponent, ButtonComponent],\n template: `\n @switch (rd().tag) {\n @case ('Loading') {\n @if (loadingTpl()) { <ng-container [ngTemplateOutlet]=\"loadingTpl()!.tpl\" /> }\n @else { <app-spinner /> }\n }\n @case ('Failure') {\n @if (errorTpl()) {\n <ng-container [ngTemplateOutlet]=\"errorTpl()!.tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: error(), retry: retry }\" />\n } @else {\n <app-alert type=\"error\">Er ging iets mis bij het laden van de gegevens.</app-alert>\n <div style=\"margin-top:1rem\">\n <app-button variant=\"secondary\" (click)=\"retry()\">Opnieuw proberen</app-button>\n </div>\n }\n }\n @case ('Empty') {\n @if (emptyTpl()) { <ng-container [ngTemplateOutlet]=\"emptyTpl()!.tpl\" /> }\n @else { <p class=\"rhc-paragraph\">Geen gegevens gevonden.</p> }\n }\n @case ('Success') {\n <ng-container [ngTemplateOutlet]=\"loadedTpl().tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: value() }\" />\n }\n }\n `,\n})\nexport class AsyncComponent<T> {\n // Two ways to feed this component:\n // [resource] — a raw httpResource (the common case), or\n // [data] — an already-combined RemoteData (e.g. from a store via map2).\n resource = input<Resource<T>>();\n data = input<RemoteData<Error | undefined, T>>();\n isEmpty = input<(v: T) => boolean>(() => false);\n\n loadedTpl = contentChild.required(AsyncLoadedDirective);\n loadingTpl = contentChild(AsyncLoadingDirective);\n emptyTpl = contentChild(AsyncEmptyDirective);\n errorTpl = contentChild(AsyncErrorDirective);\n\n // Single source of truth: the supplied RemoteData, or the resource projected into one.\n protected rd = computed<RemoteData<Error | undefined, T>>(() => {\n const data = this.data();\n if (data) return data;\n const r = this.resource();\n return r ? fromResource(r, this.isEmpty()) : { tag: 'Loading' };\n });\n\n // value/error are pulled out via the exhaustive fold — only Success carries a\n // value, only Failure carries an error, so these can't lie.\n protected value = computed(() =>\n foldRemote(this.rd(), { loading: () => undefined, empty: () => undefined, failure: () => undefined, success: (v) => v }),\n );\n protected error = computed(() =>\n foldRemote(this.rd(), { loading: () => undefined, empty: () => undefined, failure: (e) => e, success: () => undefined }),\n );\n\n retry = () => {\n const r = this.resource();\n if (r && 'reload' in r && typeof (r as { reload?: unknown }).reload === 'function') {\n (r as { reload: () => void }).reload();\n }\n };\n}\n\n/** Convenience: import this array to get the wrapper + all slot directives. */\nexport const ASYNC = [\n AsyncComponent, AsyncLoadedDirective, AsyncLoadingDirective,\n AsyncEmptyDirective, AsyncErrorDirective,\n] as const;\n",
"selector": "[appAsyncEmpty]",
"providers": [],
"hostDirectives": [],
"standalone": false,
"inputsClass": [],
"outputsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"propertiesClass": [
{
"name": "tpl",
"deprecated": false,
"deprecationMessage": "",
"type": "TemplateRef<unknown>",
"indexKey": "",
"optional": false,
"description": "",
"line": 20,
"modifierKind": [
125
]
}
],
"methodsClass": [],
"extends": [],
"constructorObj": {
"name": "constructor",
"description": "",
"deprecated": false,
"deprecationMessage": "",
"args": [
{
"name": "tpl",
"type": "TemplateRef<unknown>",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": ""
}
],
"line": 19,
"jsdoctags": [
{
"name": "tpl",
"type": "TemplateRef<unknown>",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
}
},
{
"name": "AsyncErrorDirective",
"id": "directive-AsyncErrorDirective-b3cfb3c4a98444c42ba42c11d432aca9cf324dba35b23ccb8af26360530e37b4edcc64b110afd78fb4d7e4eef1b24c72be872007aaa92127f22e76e1ae7c0964",
"file": "src/app/shared/ui/async/async.component.ts",
"type": "directive",
"description": "",
"rawdescription": "\n",
"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 on <ng-template> children of <app-async>. */\n@Directive({ selector: '[appAsyncLoaded]' })\nexport class AsyncLoadedDirective {\n constructor(public tpl: TemplateRef<{ $implicit: unknown }>) {}\n}\n@Directive({ selector: '[appAsyncLoading]' })\nexport class AsyncLoadingDirective {\n constructor(public tpl: TemplateRef<unknown>) {}\n}\n@Directive({ selector: '[appAsyncEmpty]' })\nexport class AsyncEmptyDirective {\n constructor(public tpl: TemplateRef<unknown>) {}\n}\n@Directive({ selector: '[appAsyncError]' })\nexport class AsyncErrorDirective {\n constructor(public tpl: TemplateRef<{ $implicit: Error | undefined; retry: () => void }>) {}\n}\n\n/**\n * Renders exactly ONE of loading / empty / error / loaded for a signal-based\n * resource (e.g. httpResource). Built on a RemoteData tagged union (see\n * core/remote-data.ts), so the states are mutually exclusive by construction —\n * the UI can never show two at once (\"impossible states\"). Unprovided slots\n * fall back to sensible defaults.\n */\n@Component({\n selector: 'app-async',\n imports: [NgTemplateOutlet, SpinnerComponent, AlertComponent, ButtonComponent],\n template: `\n @switch (rd().tag) {\n @case ('Loading') {\n @if (loadingTpl()) { <ng-container [ngTemplateOutlet]=\"loadingTpl()!.tpl\" /> }\n @else { <app-spinner /> }\n }\n @case ('Failure') {\n @if (errorTpl()) {\n <ng-container [ngTemplateOutlet]=\"errorTpl()!.tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: error(), retry: retry }\" />\n } @else {\n <app-alert type=\"error\">Er ging iets mis bij het laden van de gegevens.</app-alert>\n <div style=\"margin-top:1rem\">\n <app-button variant=\"secondary\" (click)=\"retry()\">Opnieuw proberen</app-button>\n </div>\n }\n }\n @case ('Empty') {\n @if (emptyTpl()) { <ng-container [ngTemplateOutlet]=\"emptyTpl()!.tpl\" /> }\n @else { <p class=\"rhc-paragraph\">Geen gegevens gevonden.</p> }\n }\n @case ('Success') {\n <ng-container [ngTemplateOutlet]=\"loadedTpl().tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: value() }\" />\n }\n }\n `,\n})\nexport class AsyncComponent<T> {\n // Two ways to feed this component:\n // [resource] — a raw httpResource (the common case), or\n // [data] — an already-combined RemoteData (e.g. from a store via map2).\n resource = input<Resource<T>>();\n data = input<RemoteData<Error | undefined, T>>();\n isEmpty = input<(v: T) => boolean>(() => false);\n\n loadedTpl = contentChild.required(AsyncLoadedDirective);\n loadingTpl = contentChild(AsyncLoadingDirective);\n emptyTpl = contentChild(AsyncEmptyDirective);\n errorTpl = contentChild(AsyncErrorDirective);\n\n // Single source of truth: the supplied RemoteData, or the resource projected into one.\n protected rd = computed<RemoteData<Error | undefined, T>>(() => {\n const data = this.data();\n if (data) return data;\n const r = this.resource();\n return r ? fromResource(r, this.isEmpty()) : { tag: 'Loading' };\n });\n\n // value/error are pulled out via the exhaustive fold — only Success carries a\n // value, only Failure carries an error, so these can't lie.\n protected value = computed(() =>\n foldRemote(this.rd(), { loading: () => undefined, empty: () => undefined, failure: () => undefined, success: (v) => v }),\n );\n protected error = computed(() =>\n foldRemote(this.rd(), { loading: () => undefined, empty: () => undefined, failure: (e) => e, success: () => undefined }),\n );\n\n retry = () => {\n const r = this.resource();\n if (r && 'reload' in r && typeof (r as { reload?: unknown }).reload === 'function') {\n (r as { reload: () => void }).reload();\n }\n };\n}\n\n/** Convenience: import this array to get the wrapper + all slot directives. */\nexport const ASYNC = [\n AsyncComponent, AsyncLoadedDirective, AsyncLoadingDirective,\n AsyncEmptyDirective, AsyncErrorDirective,\n] as const;\n",
"selector": "[appAsyncError]",
"providers": [],
"hostDirectives": [],
"standalone": false,
"inputsClass": [],
"outputsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"propertiesClass": [
{
"name": "tpl",
"deprecated": false,
"deprecationMessage": "",
"type": "TemplateRef<literal type>",
"indexKey": "",
"optional": false,
"description": "",
"line": 24,
"modifierKind": [
125
]
}
],
"methodsClass": [],
"extends": [],
"constructorObj": {
"name": "constructor",
"description": "",
"deprecated": false,
"deprecationMessage": "",
"args": [
{
"name": "tpl",
"type": "TemplateRef<literal type>",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": ""
}
],
"line": 23,
"jsdoctags": [
{
"name": "tpl",
"type": "TemplateRef<literal type>",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
}
},
{
"name": "AsyncLoadedDirective",
"id": "directive-AsyncLoadedDirective-b3cfb3c4a98444c42ba42c11d432aca9cf324dba35b23ccb8af26360530e37b4edcc64b110afd78fb4d7e4eef1b24c72be872007aaa92127f22e76e1ae7c0964",
"file": "src/app/shared/ui/async/async.component.ts",
"type": "directive",
"description": "",
"rawdescription": "\n",
"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 on <ng-template> children of <app-async>. */\n@Directive({ selector: '[appAsyncLoaded]' })\nexport class AsyncLoadedDirective {\n constructor(public tpl: TemplateRef<{ $implicit: unknown }>) {}\n}\n@Directive({ selector: '[appAsyncLoading]' })\nexport class AsyncLoadingDirective {\n constructor(public tpl: TemplateRef<unknown>) {}\n}\n@Directive({ selector: '[appAsyncEmpty]' })\nexport class AsyncEmptyDirective {\n constructor(public tpl: TemplateRef<unknown>) {}\n}\n@Directive({ selector: '[appAsyncError]' })\nexport class AsyncErrorDirective {\n constructor(public tpl: TemplateRef<{ $implicit: Error | undefined; retry: () => void }>) {}\n}\n\n/**\n * Renders exactly ONE of loading / empty / error / loaded for a signal-based\n * resource (e.g. httpResource). Built on a RemoteData tagged union (see\n * core/remote-data.ts), so the states are mutually exclusive by construction —\n * the UI can never show two at once (\"impossible states\"). Unprovided slots\n * fall back to sensible defaults.\n */\n@Component({\n selector: 'app-async',\n imports: [NgTemplateOutlet, SpinnerComponent, AlertComponent, ButtonComponent],\n template: `\n @switch (rd().tag) {\n @case ('Loading') {\n @if (loadingTpl()) { <ng-container [ngTemplateOutlet]=\"loadingTpl()!.tpl\" /> }\n @else { <app-spinner /> }\n }\n @case ('Failure') {\n @if (errorTpl()) {\n <ng-container [ngTemplateOutlet]=\"errorTpl()!.tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: error(), retry: retry }\" />\n } @else {\n <app-alert type=\"error\">Er ging iets mis bij het laden van de gegevens.</app-alert>\n <div style=\"margin-top:1rem\">\n <app-button variant=\"secondary\" (click)=\"retry()\">Opnieuw proberen</app-button>\n </div>\n }\n }\n @case ('Empty') {\n @if (emptyTpl()) { <ng-container [ngTemplateOutlet]=\"emptyTpl()!.tpl\" /> }\n @else { <p class=\"rhc-paragraph\">Geen gegevens gevonden.</p> }\n }\n @case ('Success') {\n <ng-container [ngTemplateOutlet]=\"loadedTpl().tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: value() }\" />\n }\n }\n `,\n})\nexport class AsyncComponent<T> {\n // Two ways to feed this component:\n // [resource] — a raw httpResource (the common case), or\n // [data] — an already-combined RemoteData (e.g. from a store via map2).\n resource = input<Resource<T>>();\n data = input<RemoteData<Error | undefined, T>>();\n isEmpty = input<(v: T) => boolean>(() => false);\n\n loadedTpl = contentChild.required(AsyncLoadedDirective);\n loadingTpl = contentChild(AsyncLoadingDirective);\n emptyTpl = contentChild(AsyncEmptyDirective);\n errorTpl = contentChild(AsyncErrorDirective);\n\n // Single source of truth: the supplied RemoteData, or the resource projected into one.\n protected rd = computed<RemoteData<Error | undefined, T>>(() => {\n const data = this.data();\n if (data) return data;\n const r = this.resource();\n return r ? fromResource(r, this.isEmpty()) : { tag: 'Loading' };\n });\n\n // value/error are pulled out via the exhaustive fold — only Success carries a\n // value, only Failure carries an error, so these can't lie.\n protected value = computed(() =>\n foldRemote(this.rd(), { loading: () => undefined, empty: () => undefined, failure: () => undefined, success: (v) => v }),\n );\n protected error = computed(() =>\n foldRemote(this.rd(), { loading: () => undefined, empty: () => undefined, failure: (e) => e, success: () => undefined }),\n );\n\n retry = () => {\n const r = this.resource();\n if (r && 'reload' in r && typeof (r as { reload?: unknown }).reload === 'function') {\n (r as { reload: () => void }).reload();\n }\n };\n}\n\n/** Convenience: import this array to get the wrapper + all slot directives. */\nexport const ASYNC = [\n AsyncComponent, AsyncLoadedDirective, AsyncLoadingDirective,\n AsyncEmptyDirective, AsyncErrorDirective,\n] as const;\n",
"selector": "[appAsyncLoaded]",
"providers": [],
"hostDirectives": [],
"standalone": false,
"inputsClass": [],
"outputsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"propertiesClass": [
{
"name": "tpl",
"deprecated": false,
"deprecationMessage": "",
"type": "TemplateRef<literal type>",
"indexKey": "",
"optional": false,
"description": "",
"line": 12,
"modifierKind": [
125
]
}
],
"methodsClass": [],
"extends": [],
"constructorObj": {
"name": "constructor",
"description": "",
"deprecated": false,
"deprecationMessage": "",
"args": [
{
"name": "tpl",
"type": "TemplateRef<literal type>",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": ""
}
],
"line": 11,
"jsdoctags": [
{
"name": "tpl",
"type": "TemplateRef<literal type>",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
}
},
{
"name": "AsyncLoadingDirective",
"id": "directive-AsyncLoadingDirective-b3cfb3c4a98444c42ba42c11d432aca9cf324dba35b23ccb8af26360530e37b4edcc64b110afd78fb4d7e4eef1b24c72be872007aaa92127f22e76e1ae7c0964",
"file": "src/app/shared/ui/async/async.component.ts",
"type": "directive",
"description": "",
"rawdescription": "\n",
"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 on <ng-template> children of <app-async>. */\n@Directive({ selector: '[appAsyncLoaded]' })\nexport class AsyncLoadedDirective {\n constructor(public tpl: TemplateRef<{ $implicit: unknown }>) {}\n}\n@Directive({ selector: '[appAsyncLoading]' })\nexport class AsyncLoadingDirective {\n constructor(public tpl: TemplateRef<unknown>) {}\n}\n@Directive({ selector: '[appAsyncEmpty]' })\nexport class AsyncEmptyDirective {\n constructor(public tpl: TemplateRef<unknown>) {}\n}\n@Directive({ selector: '[appAsyncError]' })\nexport class AsyncErrorDirective {\n constructor(public tpl: TemplateRef<{ $implicit: Error | undefined; retry: () => void }>) {}\n}\n\n/**\n * Renders exactly ONE of loading / empty / error / loaded for a signal-based\n * resource (e.g. httpResource). Built on a RemoteData tagged union (see\n * core/remote-data.ts), so the states are mutually exclusive by construction —\n * the UI can never show two at once (\"impossible states\"). Unprovided slots\n * fall back to sensible defaults.\n */\n@Component({\n selector: 'app-async',\n imports: [NgTemplateOutlet, SpinnerComponent, AlertComponent, ButtonComponent],\n template: `\n @switch (rd().tag) {\n @case ('Loading') {\n @if (loadingTpl()) { <ng-container [ngTemplateOutlet]=\"loadingTpl()!.tpl\" /> }\n @else { <app-spinner /> }\n }\n @case ('Failure') {\n @if (errorTpl()) {\n <ng-container [ngTemplateOutlet]=\"errorTpl()!.tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: error(), retry: retry }\" />\n } @else {\n <app-alert type=\"error\">Er ging iets mis bij het laden van de gegevens.</app-alert>\n <div style=\"margin-top:1rem\">\n <app-button variant=\"secondary\" (click)=\"retry()\">Opnieuw proberen</app-button>\n </div>\n }\n }\n @case ('Empty') {\n @if (emptyTpl()) { <ng-container [ngTemplateOutlet]=\"emptyTpl()!.tpl\" /> }\n @else { <p class=\"rhc-paragraph\">Geen gegevens gevonden.</p> }\n }\n @case ('Success') {\n <ng-container [ngTemplateOutlet]=\"loadedTpl().tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: value() }\" />\n }\n }\n `,\n})\nexport class AsyncComponent<T> {\n // Two ways to feed this component:\n // [resource] — a raw httpResource (the common case), or\n // [data] — an already-combined RemoteData (e.g. from a store via map2).\n resource = input<Resource<T>>();\n data = input<RemoteData<Error | undefined, T>>();\n isEmpty = input<(v: T) => boolean>(() => false);\n\n loadedTpl = contentChild.required(AsyncLoadedDirective);\n loadingTpl = contentChild(AsyncLoadingDirective);\n emptyTpl = contentChild(AsyncEmptyDirective);\n errorTpl = contentChild(AsyncErrorDirective);\n\n // Single source of truth: the supplied RemoteData, or the resource projected into one.\n protected rd = computed<RemoteData<Error | undefined, T>>(() => {\n const data = this.data();\n if (data) return data;\n const r = this.resource();\n return r ? fromResource(r, this.isEmpty()) : { tag: 'Loading' };\n });\n\n // value/error are pulled out via the exhaustive fold — only Success carries a\n // value, only Failure carries an error, so these can't lie.\n protected value = computed(() =>\n foldRemote(this.rd(), { loading: () => undefined, empty: () => undefined, failure: () => undefined, success: (v) => v }),\n );\n protected error = computed(() =>\n foldRemote(this.rd(), { loading: () => undefined, empty: () => undefined, failure: (e) => e, success: () => undefined }),\n );\n\n retry = () => {\n const r = this.resource();\n if (r && 'reload' in r && typeof (r as { reload?: unknown }).reload === 'function') {\n (r as { reload: () => void }).reload();\n }\n };\n}\n\n/** Convenience: import this array to get the wrapper + all slot directives. */\nexport const ASYNC = [\n AsyncComponent, AsyncLoadedDirective, AsyncLoadingDirective,\n AsyncEmptyDirective, AsyncErrorDirective,\n] as const;\n",
"selector": "[appAsyncLoading]",
"providers": [],
"hostDirectives": [],
"standalone": false,
"inputsClass": [],
"outputsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"propertiesClass": [
{
"name": "tpl",
"deprecated": false,
"deprecationMessage": "",
"type": "TemplateRef<unknown>",
"indexKey": "",
"optional": false,
"description": "",
"line": 16,
"modifierKind": [
125
]
}
],
"methodsClass": [],
"extends": [],
"constructorObj": {
"name": "constructor",
"description": "",
"deprecated": false,
"deprecationMessage": "",
"args": [
{
"name": "tpl",
"type": "TemplateRef<unknown>",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": ""
}
],
"line": 15,
"jsdoctags": [
{
"name": "tpl",
"type": "TemplateRef<unknown>",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
}
}
],
"components": [
{
"name": "AlertComponent",
"id": "component-AlertComponent-7d03ee2c0179c2f8d44795112c823951406810027571b5471bc765873f1aeaee550dcb89c6ebd8514ee36f2d96c8c6ba118293bf44a4a1316f61e91fa3c06f4e",
"file": "src/app/shared/ui/alert/alert.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-alert",
"styleUrls": [],
"styles": [],
"template": "<div\n class=\"utrecht-alert rhc-alert\"\n [class.utrecht-alert--info]=\"type() === 'info'\"\n [class.utrecht-alert--ok]=\"type() === 'ok'\"\n [class.utrecht-alert--warning]=\"type() === 'warning'\"\n [class.utrecht-alert--error]=\"type() === 'error'\"\n role=\"status\">\n <ng-content />\n</div>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [
{
"name": "type",
"defaultValue": "'info'",
"deprecated": false,
"deprecationMessage": "",
"type": "AlertType",
"indexKey": "",
"optional": false,
"description": "",
"line": 21,
"required": false
}
],
"outputsClass": [],
"propertiesClass": [],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [],
"description": "<p>Atom: alert/message banner.</p>\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: `\n <div\n class=\"utrecht-alert rhc-alert\"\n [class.utrecht-alert--info]=\"type() === 'info'\"\n [class.utrecht-alert--ok]=\"type() === 'ok'\"\n [class.utrecht-alert--warning]=\"type() === 'warning'\"\n [class.utrecht-alert--error]=\"type() === 'error'\"\n role=\"status\">\n <ng-content />\n </div>\n `,\n})\nexport class AlertComponent {\n type = input<AlertType>('info');\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "App",
"id": "component-App-a5889755e6aaa6ebd2f471f1253c27e411d38a42361e18619621ef0e6c5a91de3cf6ba4ace13bbe1756691f1f5e80728717fd18aab2cef50180bd579fa218a6d",
"file": "src/app/app.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-root",
"styleUrls": [],
"styles": [],
"template": "<router-outlet />",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [],
"outputsClass": [],
"propertiesClass": [],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [
{
"name": "RouterOutlet"
}
],
"description": "",
"rawdescription": "\n",
"type": "component",
"sourceCode": "import { Component } from '@angular/core';\nimport { RouterOutlet } from '@angular/router';\n\n@Component({\n selector: 'app-root',\n imports: [RouterOutlet],\n template: '<router-outlet />',\n})\nexport class App {}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "AsyncComponent",
"id": "component-AsyncComponent-b3cfb3c4a98444c42ba42c11d432aca9cf324dba35b23ccb8af26360530e37b4edcc64b110afd78fb4d7e4eef1b24c72be872007aaa92127f22e76e1ae7c0964",
"file": "src/app/shared/ui/async/async.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-async",
"styleUrls": [],
"styles": [],
"template": "@switch (rd().tag) {\n @case ('Loading') {\n @if (loadingTpl()) { <ng-container [ngTemplateOutlet]=\"loadingTpl()!.tpl\" /> }\n @else { <app-spinner /> }\n }\n @case ('Failure') {\n @if (errorTpl()) {\n <ng-container [ngTemplateOutlet]=\"errorTpl()!.tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: error(), retry: retry }\" />\n } @else {\n <app-alert type=\"error\">Er ging iets mis bij het laden van de gegevens.</app-alert>\n <div style=\"margin-top:1rem\">\n <app-button variant=\"secondary\" (click)=\"retry()\">Opnieuw proberen</app-button>\n </div>\n }\n }\n @case ('Empty') {\n @if (emptyTpl()) { <ng-container [ngTemplateOutlet]=\"emptyTpl()!.tpl\" /> }\n @else { <p class=\"rhc-paragraph\">Geen gegevens gevonden.</p> }\n }\n @case ('Success') {\n <ng-container [ngTemplateOutlet]=\"loadedTpl().tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: value() }\" />\n }\n}\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [
{
"name": "data",
"deprecated": false,
"deprecationMessage": "",
"type": "RemoteData<Error | undefined, T>",
"indexKey": "",
"optional": false,
"description": "",
"line": 70,
"required": false
},
{
"name": "isEmpty",
"defaultValue": "() => false",
"deprecated": false,
"deprecationMessage": "",
"type": "(v: T) => boolean",
"indexKey": "",
"optional": false,
"description": "",
"line": 71,
"required": false
},
{
"name": "resource",
"deprecated": false,
"deprecationMessage": "",
"type": "Resource<T>",
"indexKey": "",
"optional": false,
"description": "",
"line": 69,
"required": false
}
],
"outputsClass": [],
"propertiesClass": [
{
"name": "emptyTpl",
"defaultValue": "contentChild(AsyncEmptyDirective)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 75
},
{
"name": "error",
"defaultValue": "computed(() =>\n foldRemote(this.rd(), { loading: () => undefined, empty: () => undefined, failure: (e) => e, success: () => undefined }),\n )",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 91,
"modifierKind": [
124
]
},
{
"name": "errorTpl",
"defaultValue": "contentChild(AsyncErrorDirective)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 76
},
{
"name": "loadedTpl",
"defaultValue": "contentChild.required(AsyncLoadedDirective)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 73
},
{
"name": "loadingTpl",
"defaultValue": "contentChild(AsyncLoadingDirective)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 74
},
{
"name": "rd",
"defaultValue": "computed<RemoteData<Error | undefined, T>>(() => {\n const data = this.data();\n if (data) return data;\n const r = this.resource();\n return r ? fromResource(r, this.isEmpty()) : { tag: 'Loading' };\n })",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 79,
"modifierKind": [
124
]
},
{
"name": "retry",
"defaultValue": "() => {...}",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 95
},
{
"name": "value",
"defaultValue": "computed(() =>\n foldRemote(this.rd(), { loading: () => undefined, empty: () => undefined, failure: () => undefined, success: (v) => v }),\n )",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 88,
"modifierKind": [
124
]
}
],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [
{
"name": "NgTemplateOutlet"
},
{
"name": "SpinnerComponent",
"type": "component"
},
{
"name": "AlertComponent",
"type": "component"
},
{
"name": "ButtonComponent",
"type": "component"
}
],
"description": "<p>Renders 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 (&quot;impossible states&quot;). Unprovided slots\nfall back to sensible defaults.</p>\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 on <ng-template> children of <app-async>. */\n@Directive({ selector: '[appAsyncLoaded]' })\nexport class AsyncLoadedDirective {\n constructor(public tpl: TemplateRef<{ $implicit: unknown }>) {}\n}\n@Directive({ selector: '[appAsyncLoading]' })\nexport class AsyncLoadingDirective {\n constructor(public tpl: TemplateRef<unknown>) {}\n}\n@Directive({ selector: '[appAsyncEmpty]' })\nexport class AsyncEmptyDirective {\n constructor(public tpl: TemplateRef<unknown>) {}\n}\n@Directive({ selector: '[appAsyncError]' })\nexport class AsyncErrorDirective {\n constructor(public tpl: TemplateRef<{ $implicit: Error | undefined; retry: () => void }>) {}\n}\n\n/**\n * Renders exactly ONE of loading / empty / error / loaded for a signal-based\n * resource (e.g. httpResource). Built on a RemoteData tagged union (see\n * core/remote-data.ts), so the states are mutually exclusive by construction —\n * the UI can never show two at once (\"impossible states\"). Unprovided slots\n * fall back to sensible defaults.\n */\n@Component({\n selector: 'app-async',\n imports: [NgTemplateOutlet, SpinnerComponent, AlertComponent, ButtonComponent],\n template: `\n @switch (rd().tag) {\n @case ('Loading') {\n @if (loadingTpl()) { <ng-container [ngTemplateOutlet]=\"loadingTpl()!.tpl\" /> }\n @else { <app-spinner /> }\n }\n @case ('Failure') {\n @if (errorTpl()) {\n <ng-container [ngTemplateOutlet]=\"errorTpl()!.tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: error(), retry: retry }\" />\n } @else {\n <app-alert type=\"error\">Er ging iets mis bij het laden van de gegevens.</app-alert>\n <div style=\"margin-top:1rem\">\n <app-button variant=\"secondary\" (click)=\"retry()\">Opnieuw proberen</app-button>\n </div>\n }\n }\n @case ('Empty') {\n @if (emptyTpl()) { <ng-container [ngTemplateOutlet]=\"emptyTpl()!.tpl\" /> }\n @else { <p class=\"rhc-paragraph\">Geen gegevens gevonden.</p> }\n }\n @case ('Success') {\n <ng-container [ngTemplateOutlet]=\"loadedTpl().tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: value() }\" />\n }\n }\n `,\n})\nexport class AsyncComponent<T> {\n // Two ways to feed this component:\n // [resource] — a raw httpResource (the common case), or\n // [data] — an already-combined RemoteData (e.g. from a store via map2).\n resource = input<Resource<T>>();\n data = input<RemoteData<Error | undefined, T>>();\n isEmpty = input<(v: T) => boolean>(() => false);\n\n loadedTpl = contentChild.required(AsyncLoadedDirective);\n loadingTpl = contentChild(AsyncLoadingDirective);\n emptyTpl = contentChild(AsyncEmptyDirective);\n errorTpl = contentChild(AsyncErrorDirective);\n\n // Single source of truth: the supplied RemoteData, or the resource projected into one.\n protected rd = computed<RemoteData<Error | undefined, T>>(() => {\n const data = this.data();\n if (data) return data;\n const r = this.resource();\n return r ? fromResource(r, this.isEmpty()) : { tag: 'Loading' };\n });\n\n // value/error are pulled out via the exhaustive fold — only Success carries a\n // value, only Failure carries an error, so these can't lie.\n protected value = computed(() =>\n foldRemote(this.rd(), { loading: () => undefined, empty: () => undefined, failure: () => undefined, success: (v) => v }),\n );\n protected error = computed(() =>\n foldRemote(this.rd(), { loading: () => undefined, empty: () => undefined, failure: (e) => e, success: () => undefined }),\n );\n\n retry = () => {\n const r = this.resource();\n if (r && 'reload' in r && typeof (r as { reload?: unknown }).reload === 'function') {\n (r as { reload: () => void }).reload();\n }\n };\n}\n\n/** Convenience: import this array to get the wrapper + all slot directives. */\nexport const ASYNC = [\n AsyncComponent, AsyncLoadedDirective, AsyncLoadingDirective,\n AsyncEmptyDirective, AsyncErrorDirective,\n] as const;\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "ButtonComponent",
"id": "component-ButtonComponent-6eb936521438d91cc3a2276d1b8e366496e907e8a01d7b84b327c3cc31fa1dfadbb9502c6646472736722cf7ced9950fcaa4d8435ddf28224b3e7c9b7bd29505",
"file": "src/app/shared/ui/button/button.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-button",
"styleUrls": [],
"styles": [],
"template": "<button\n [type]=\"type()\"\n [disabled]=\"disabled()\"\n class=\"utrecht-button rhc-button\"\n [class.utrecht-button--primary-action]=\"variant() === 'primary'\"\n [class.utrecht-button--secondary-action]=\"variant() === 'secondary'\"\n [class.utrecht-button--subtle]=\"variant() === 'subtle'\"\n [class.utrecht-button--danger]=\"variant() === 'danger'\"\n [class.utrecht-button--disabled]=\"disabled()\">\n <ng-content />\n</button>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [
{
"name": "disabled",
"defaultValue": "false",
"deprecated": false,
"deprecationMessage": "",
"indexKey": "",
"optional": false,
"description": "",
"line": 25,
"required": false
},
{
"name": "type",
"defaultValue": "'button'",
"deprecated": false,
"deprecationMessage": "",
"type": "\"button\" | \"submit\"",
"indexKey": "",
"optional": false,
"description": "",
"line": 24,
"required": false
},
{
"name": "variant",
"defaultValue": "'primary'",
"deprecated": false,
"deprecationMessage": "",
"type": "Variant",
"indexKey": "",
"optional": false,
"description": "",
"line": 23,
"required": false
}
],
"outputsClass": [],
"propertiesClass": [],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [],
"description": "<p>Atom: button. Thin wrapper over the Utrecht/RHC button CSS.</p>\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 <button\n [type]=\"type()\"\n [disabled]=\"disabled()\"\n class=\"utrecht-button rhc-button\"\n [class.utrecht-button--primary-action]=\"variant() === 'primary'\"\n [class.utrecht-button--secondary-action]=\"variant() === 'secondary'\"\n [class.utrecht-button--subtle]=\"variant() === 'subtle'\"\n [class.utrecht-button--danger]=\"variant() === 'danger'\"\n [class.utrecht-button--disabled]=\"disabled()\">\n <ng-content />\n </button>\n `,\n})\nexport class ButtonComponent {\n variant = input<Variant>('primary');\n type = input<'button' | 'submit'>('button');\n disabled = input(false);\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "ChangeRequestFormComponent",
"id": "component-ChangeRequestFormComponent-8d79b6a9ce75f62f4e04f9d3ed0867e00d005c9c05cf267503536c4eec9813372aff51a3c8686927fd07f46503b60ddb4107edcc5f57fdfa1b6b52fe2a98026c",
"file": "src/app/registratie/ui/change-request-form/change-request-form.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-change-request-form",
"styleUrls": [],
"styles": [],
"template": "<app-heading [level]=\"2\">Adreswijziging doorgeven</app-heading>\n<form (ngSubmit)=\"onSubmit()\" style=\"max-width:28rem\">\n <app-form-field label=\"Straat en huisnummer\" fieldId=\"street\" [error]=\"streetError()\">\n <app-text-input inputId=\"street\" [(ngModel)]=\"street\" name=\"street\" [invalid]=\"!!streetError()\" />\n </app-form-field>\n <app-form-field label=\"Postcode\" fieldId=\"zip\" [error]=\"zipError()\">\n <app-text-input inputId=\"zip\" [(ngModel)]=\"zip\" name=\"zip\" placeholder=\"1234 AB\" [invalid]=\"!!zipError()\" />\n </app-form-field>\n <app-form-field label=\"Woonplaats\" fieldId=\"city\">\n <app-text-input inputId=\"city\" [(ngModel)]=\"city\" name=\"city\" />\n </app-form-field>\n <div style=\"margin-top:1rem\">\n <app-button type=\"submit\" variant=\"primary\">Wijziging indienen</app-button>\n </div>\n</form>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [],
"outputsClass": [
{
"name": "submitted",
"deprecated": false,
"deprecationMessage": "",
"type": "ChangeRequest",
"indexKey": "",
"optional": false,
"description": "",
"line": 47,
"required": false
}
],
"propertiesClass": [
{
"name": "city",
"defaultValue": "''",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 44
},
{
"name": "street",
"defaultValue": "''",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 42
},
{
"name": "streetError",
"defaultValue": "signal('')",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 45
},
{
"name": "zip",
"defaultValue": "''",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 43
},
{
"name": "zipError",
"defaultValue": "signal('')",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 46
}
],
"methodsClass": [
{
"name": "onSubmit",
"args": [],
"optional": false,
"returnType": "void",
"typeParameters": [],
"line": 49,
"deprecated": false,
"deprecationMessage": ""
}
],
"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": "HeadingComponent",
"type": "component"
}
],
"description": "<p>Organism: 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&#39;s Result — no parallel &quot;is it valid&quot; flag to drift.</p>\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 <app-heading [level]=\"2\">Adreswijziging doorgeven</app-heading>\n <form (ngSubmit)=\"onSubmit()\" style=\"max-width:28rem\">\n <app-form-field label=\"Straat en huisnummer\" fieldId=\"street\" [error]=\"streetError()\">\n <app-text-input inputId=\"street\" [(ngModel)]=\"street\" name=\"street\" [invalid]=\"!!streetError()\" />\n </app-form-field>\n <app-form-field label=\"Postcode\" fieldId=\"zip\" [error]=\"zipError()\">\n <app-text-input inputId=\"zip\" [(ngModel)]=\"zip\" name=\"zip\" placeholder=\"1234 AB\" [invalid]=\"!!zipError()\" />\n </app-form-field>\n <app-form-field label=\"Woonplaats\" fieldId=\"city\">\n <app-text-input inputId=\"city\" [(ngModel)]=\"city\" name=\"city\" />\n </app-form-field>\n <div style=\"margin-top:1rem\">\n <app-button type=\"submit\" variant=\"primary\">Wijziging indienen</app-button>\n </div>\n </form>\n `,\n})\nexport class ChangeRequestFormComponent {\n street = '';\n zip = '';\n city = '';\n streetError = signal('');\n zipError = signal('');\n submitted = output<ChangeRequest>();\n\n onSubmit() {\n const street = this.street.trim();\n this.streetError.set(street ? '' : 'Vul straat en huisnummer in.');\n\n const postcode = parsePostcode(this.zip);\n this.zipError.set(postcode.ok ? '' : postcode.error);\n\n if (!street || !postcode.ok) return;\n this.submitted.emit({ street, zip: postcode.value, city: this.city.trim() });\n }\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "ConceptsPage",
"id": "component-ConceptsPage-951fb54ea356331be584db1248fbc5d516618c3b5b9f960359a4a642e7d9ce7d4d240852a31bbbcfea0e0bec6c0feeb398ae79c181480422a7477c3b600c88a5",
"file": "src/app/showcase/concepts.page.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-concepts-page",
"styleUrls": [],
"styles": [
"\n .cols { display:flex; flex-wrap:wrap; gap:1.5rem; margin:1rem 0 2.5rem }\n .col { flex:1 1 20rem; min-width:18rem }\n .tag { font-weight:700; font-size:0.8rem; text-transform:uppercase; letter-spacing:0.04em }\n .bad { color:var(--rhc-color-rood-500) }\n .good { color:var(--rhc-color-groen-500) }\n pre { background:var(--rhc-color-grijs-100,#f3f3f3); padding:1rem; border-radius:4px; overflow:auto; font-size:0.85rem }\n "
],
"template": "<app-page-shell heading=\"Onmogelijke toestanden onmogelijk maken\" backLink=\"/dashboard\">\n <app-alert type=\"info\">\n Vier functionele patronen die met atomic design makkelijker te tonen zijn — telkens \"fout\"\n (de oude vorm liet het toe) naast \"goed\" (het type maakt het onmogelijk).\n </app-alert>\n\n <!-- 1. Discriminated unions -->\n <app-heading [level]=\"2\">1 · Discriminated unions</app-heading>\n <div class=\"cols\">\n <div class=\"col\">\n <p class=\"tag bad\">Fout — vlakke interface</p>\n <pre>{{ unionBad }}</pre>\n <p class=\"rhc-paragraph\">Een doorgehaalde registratie houdt tóch een herregistratiedatum: onmogelijke toestand.</p>\n </div>\n <div class=\"col\">\n <p class=\"tag good\">Goed — sum type</p>\n <app-registration-summary [reg]=\"doorgehaald\" />\n <p class=\"rhc-paragraph\">De variant <code>Doorgehaald</code> kent geen herregistratiedatum, dus de rij bestaat simpelweg niet.</p>\n </div>\n </div>\n\n <!-- 2. RemoteData fold -->\n <app-heading [level]=\"2\">2 · RemoteData fold</app-heading>\n <div class=\"cols\">\n <div class=\"col\">\n <p class=\"tag good\">Eén molecuul, vier elkaar uitsluitende toestanden</p>\n <p class=\"tag\">Loading</p>\n <app-async [resource]=\"loadingRes\"><ng-template appAsyncLoaded let-v>{{ v }}</ng-template><ng-template appAsyncLoading><app-skeleton [count]=\"2\" height=\"1.2rem\" [delay]=\"0\" /></ng-template></app-async>\n <p class=\"tag\">Empty</p>\n <app-async [resource]=\"emptyRes\" [isEmpty]=\"isEmpty\"><ng-template appAsyncLoaded let-v>{{ v }}</ng-template></app-async>\n <p class=\"tag\">Failure</p>\n <app-async [resource]=\"errorRes\"><ng-template appAsyncLoaded let-v>{{ v }}</ng-template></app-async>\n <p class=\"tag\">Success</p>\n <app-async [resource]=\"successRes\" [isEmpty]=\"isEmpty\"><ng-template appAsyncLoaded let-v><ul class=\"rhc-unordered-list\">@for (i of v; track i) {<li>{{ i }}</li>}</ul></ng-template></app-async>\n </div>\n <div class=\"col\">\n <p class=\"tag good\">De exhaustieve fold</p>\n <pre>{{ foldCode }}</pre>\n <p class=\"rhc-paragraph\">Een nieuwe variant toevoegen breekt de compile via <code>assertNever</code> tot je hem afhandelt.</p>\n </div>\n </div>\n\n <!-- 3. Parse, don't validate -->\n <app-heading [level]=\"2\">3 · Parse, don't validate</app-heading>\n <div class=\"cols\">\n <div class=\"col\">\n <p class=\"tag good\">Smart constructor → Result</p>\n <app-text-input inputId=\"pc\" [ngModel]=\"raw()\" (ngModelChange)=\"raw.set($event)\" name=\"pc\" placeholder=\"Typ een postcode, bijv. 1234 AB\" />\n </div>\n <div class=\"col\">\n @if (parsed().ok) {\n <p class=\"tag good\">ok</p>\n <pre>Postcode = \"{{ parsed().ok ? $any(parsed()).value : '' }}\"</pre>\n <p class=\"rhc-paragraph\">Een gevalideerde <code>Postcode</code> is een ander type dan een ruwe string.</p>\n } @else {\n <p class=\"tag bad\">err</p>\n <pre>{{ $any(parsed()).error }}</pre>\n }\n </div>\n </div>\n\n <!-- 4. State machine / wizard -->\n <app-heading [level]=\"2\">4 · Form als state machine</app-heading>\n <div class=\"cols\">\n <div class=\"col\">\n <p class=\"tag bad\">Fout — losse booleans</p>\n <pre>{{ machineBad }}</pre>\n <p class=\"rhc-paragraph\">Niets verhindert \"submitting\" mét validatiefouten of een successcherm met errors.</p>\n </div>\n <div class=\"col\">\n <p class=\"tag good\">Goed — één tagged union stuurt de UI</p>\n <app-herregistratie-wizard />\n </div>\n </div>\n</app-page-shell>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [],
"outputsClass": [],
"propertiesClass": [
{
"name": "doorgehaald",
"defaultValue": "{\n bigNummer: '19012345601', naam: 'Dr. A. (Anna) de Vries', beroep: 'Arts',\n registratiedatum: '2012-09-01', geboortedatum: '1985-03-14',\n status: { tag: 'Doorgehaald', doorgehaaldOp: '2024-05-01', reden: 'Op eigen verzoek' },\n }",
"deprecated": false,
"deprecationMessage": "",
"type": "Registration",
"indexKey": "",
"optional": false,
"description": "",
"line": 117
},
{
"name": "emptyRes",
"defaultValue": "fakeResource<string[]>('resolved', [])",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 124
},
{
"name": "errorRes",
"defaultValue": "fakeResource<string[]>('error', undefined, new Error('Demo'))",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 125
},
{
"name": "foldCode",
"defaultValue": "`foldRemote(rd, {\n loading: () => spinner,\n empty: () => 'geen data',\n failure: (e) => alert(e),\n success: (v) => render(v),\n}); // mist er één → compile-fout`",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 136
},
{
"name": "isEmpty",
"defaultValue": "() => {...}",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 115
},
{
"name": "loadingRes",
"defaultValue": "fakeResource<string[]>('loading')",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 123
},
{
"name": "machineBad",
"defaultValue": "`submitting = signal(false);\nsubmitted = signal(false);\nerrors = signal<...>({});\n// submitting === true && errors.size > 0 ? 🤷`",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 143
},
{
"name": "parsed",
"defaultValue": "computed(() => parsePostcode(this.raw()))",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 129
},
{
"name": "raw",
"defaultValue": "signal('')",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 128
},
{
"name": "successRes",
"defaultValue": "fakeResource<string[]>('resolved', ['Huisartsgeneeskunde', 'Spoedeisende hulp'])",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 126
},
{
"name": "unionBad",
"defaultValue": "`interface Registration {\n status: 'Geregistreerd' | 'Doorgehaald';\n herregistratieDatum: string; // altijd aanwezig 😬\n}`",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 131
}
],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [
{
"name": "FormsModule",
"type": "module"
},
{
"name": "PageShellComponent",
"type": "component"
},
{
"name": "HeadingComponent",
"type": "component"
},
{
"name": "AlertComponent",
"type": "component"
},
{
"name": "TextInputComponent",
"type": "component"
},
{
"name": "ASYNC"
},
{
"name": "SkeletonComponent",
"type": "component"
},
{
"name": "RegistrationSummaryComponent",
"type": "component"
},
{
"name": "HerregistratieWizardComponent",
"type": "component"
}
],
"description": "<p>Teaching showcase: each section pairs the impossible-state-permitting &quot;before&quot;\nwith the &quot;after&quot; where the type system rules it out. Composition-only.</p>\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 { AlertComponent } from '@shared/ui/alert/alert.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 { Registration } from '@registratie/domain/registration';\nimport { parsePostcode } from '@registratie/domain/value-objects/postcode';\n\n/** Minimal fake Resource so <app-async> can be driven through every state without HTTP. */\nfunction fakeResource<T>(status: string, value?: T, error?: Error): Resource<T> {\n return { value: () => value as T, status: () => status, error: () => error, hasValue: () => value !== undefined, reload: () => {} } as unknown as Resource<T>;\n}\n\n/** Teaching showcase: each section pairs the impossible-state-permitting \"before\"\n with the \"after\" where the type system rules it out. Composition-only. */\n@Component({\n selector: 'app-concepts-page',\n imports: [\n FormsModule, PageShellComponent, HeadingComponent, AlertComponent, TextInputComponent,\n ...ASYNC, SkeletonComponent, RegistrationSummaryComponent, HerregistratieWizardComponent,\n ],\n styles: [`\n .cols { display:flex; flex-wrap:wrap; gap:1.5rem; margin:1rem 0 2.5rem }\n .col { flex:1 1 20rem; min-width:18rem }\n .tag { font-weight:700; font-size:0.8rem; text-transform:uppercase; letter-spacing:0.04em }\n .bad { color:var(--rhc-color-rood-500) }\n .good { color:var(--rhc-color-groen-500) }\n pre { background:var(--rhc-color-grijs-100,#f3f3f3); padding:1rem; border-radius:4px; overflow:auto; font-size:0.85rem }\n `],\n template: `\n <app-page-shell heading=\"Onmogelijke toestanden onmogelijk maken\" backLink=\"/dashboard\">\n <app-alert type=\"info\">\n Vier functionele patronen die met atomic design makkelijker te tonen zijn — telkens \"fout\"\n (de oude vorm liet het toe) naast \"goed\" (het type maakt het onmogelijk).\n </app-alert>\n\n <!-- 1. Discriminated unions -->\n <app-heading [level]=\"2\">1 · Discriminated unions</app-heading>\n <div class=\"cols\">\n <div class=\"col\">\n <p class=\"tag bad\">Fout — vlakke interface</p>\n <pre>{{ unionBad }}</pre>\n <p class=\"rhc-paragraph\">Een doorgehaalde registratie houdt tóch een herregistratiedatum: onmogelijke toestand.</p>\n </div>\n <div class=\"col\">\n <p class=\"tag good\">Goed — sum type</p>\n <app-registration-summary [reg]=\"doorgehaald\" />\n <p class=\"rhc-paragraph\">De variant <code>Doorgehaald</code> kent geen herregistratiedatum, dus de rij bestaat simpelweg niet.</p>\n </div>\n </div>\n\n <!-- 2. RemoteData fold -->\n <app-heading [level]=\"2\">2 · RemoteData fold</app-heading>\n <div class=\"cols\">\n <div class=\"col\">\n <p class=\"tag good\">Eén molecuul, vier elkaar uitsluitende toestanden</p>\n <p class=\"tag\">Loading</p>\n <app-async [resource]=\"loadingRes\"><ng-template appAsyncLoaded let-v>{{ v }}</ng-template><ng-template appAsyncLoading><app-skeleton [count]=\"2\" height=\"1.2rem\" [delay]=\"0\" /></ng-template></app-async>\n <p class=\"tag\">Empty</p>\n <app-async [resource]=\"emptyRes\" [isEmpty]=\"isEmpty\"><ng-template appAsyncLoaded let-v>{{ v }}</ng-template></app-async>\n <p class=\"tag\">Failure</p>\n <app-async [resource]=\"errorRes\"><ng-template appAsyncLoaded let-v>{{ v }}</ng-template></app-async>\n <p class=\"tag\">Success</p>\n <app-async [resource]=\"successRes\" [isEmpty]=\"isEmpty\"><ng-template appAsyncLoaded let-v><ul class=\"rhc-unordered-list\">@for (i of v; track i) {<li>{{ i }}</li>}</ul></ng-template></app-async>\n </div>\n <div class=\"col\">\n <p class=\"tag good\">De exhaustieve fold</p>\n <pre>{{ foldCode }}</pre>\n <p class=\"rhc-paragraph\">Een nieuwe variant toevoegen breekt de compile via <code>assertNever</code> tot je hem afhandelt.</p>\n </div>\n </div>\n\n <!-- 3. Parse, don't validate -->\n <app-heading [level]=\"2\">3 · Parse, don't validate</app-heading>\n <div class=\"cols\">\n <div class=\"col\">\n <p class=\"tag good\">Smart constructor → Result</p>\n <app-text-input inputId=\"pc\" [ngModel]=\"raw()\" (ngModelChange)=\"raw.set($event)\" name=\"pc\" placeholder=\"Typ een postcode, bijv. 1234 AB\" />\n </div>\n <div class=\"col\">\n @if (parsed().ok) {\n <p class=\"tag good\">ok</p>\n <pre>Postcode = \"{{ parsed().ok ? $any(parsed()).value : '' }}\"</pre>\n <p class=\"rhc-paragraph\">Een gevalideerde <code>Postcode</code> is een ander type dan een ruwe string.</p>\n } @else {\n <p class=\"tag bad\">err</p>\n <pre>{{ $any(parsed()).error }}</pre>\n }\n </div>\n </div>\n\n <!-- 4. State machine / wizard -->\n <app-heading [level]=\"2\">4 · Form als state machine</app-heading>\n <div class=\"cols\">\n <div class=\"col\">\n <p class=\"tag bad\">Fout — losse booleans</p>\n <pre>{{ machineBad }}</pre>\n <p class=\"rhc-paragraph\">Niets verhindert \"submitting\" mét validatiefouten of een successcherm met errors.</p>\n </div>\n <div class=\"col\">\n <p class=\"tag good\">Goed — één tagged union stuurt de UI</p>\n <app-herregistratie-wizard />\n </div>\n </div>\n </app-page-shell>\n `,\n})\nexport class ConceptsPage {\n isEmpty = (v: string[]) => !v || v.length === 0;\n\n doorgehaald: Registration = {\n bigNummer: '19012345601', naam: 'Dr. A. (Anna) de Vries', beroep: 'Arts',\n registratiedatum: '2012-09-01', geboortedatum: '1985-03-14',\n status: { tag: 'Doorgehaald', doorgehaaldOp: '2024-05-01', reden: 'Op eigen verzoek' },\n };\n\n loadingRes = fakeResource<string[]>('loading');\n emptyRes = fakeResource<string[]>('resolved', []);\n errorRes = fakeResource<string[]>('error', undefined, new Error('Demo'));\n successRes = fakeResource<string[]>('resolved', ['Huisartsgeneeskunde', 'Spoedeisende hulp']);\n\n raw = signal('');\n parsed = computed(() => parsePostcode(this.raw()));\n\n unionBad = `interface Registration {\n status: 'Geregistreerd' | 'Doorgehaald';\n herregistratieDatum: string; // altijd aanwezig 😬\n}`;\n\n foldCode = `foldRemote(rd, {\n loading: () => spinner,\n empty: () => 'geen data',\n failure: (e) => alert(e),\n success: (v) => render(v),\n}); // mist er één → compile-fout`;\n\n machineBad = `submitting = signal(false);\nsubmitted = signal(false);\nerrors = signal<...>({});\n// submitting === true && errors.size > 0 ? 🤷`;\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "\n .cols { display:flex; flex-wrap:wrap; gap:1.5rem; margin:1rem 0 2.5rem }\n .col { flex:1 1 20rem; min-width:18rem }\n .tag { font-weight:700; font-size:0.8rem; text-transform:uppercase; letter-spacing:0.04em }\n .bad { color:var(--rhc-color-rood-500) }\n .good { color:var(--rhc-color-groen-500) }\n pre { background:var(--rhc-color-grijs-100,#f3f3f3); padding:1rem; border-radius:4px; overflow:auto; font-size:0.85rem }\n \n",
"extends": []
},
{
"name": "DashboardPage",
"id": "component-DashboardPage-3876b122573c06608aa1fa82196e04af53fa3720906e138b095aa46a13efbd18be0b42e0a6024ee8df168faecfbf50c6a9ad9a5a7afff5447fec52dcafc73d49",
"file": "src/app/registratie/ui/dashboard.page.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-dashboard-page",
"styleUrls": [],
"styles": [],
"template": "<app-page-shell heading=\"Mijn BIG-registratie\">\n @if (store.pendingHerregistratie()) {\n <app-alert type=\"info\">Uw herregistratie-aanvraag is in behandeling.</app-alert>\n }\n\n <!-- ONE state for two combined services (BIG-register + BRP). -->\n <app-async [data]=\"store.profile()\">\n <ng-template appAsyncLoaded let-p>\n <app-registration-summary [reg]=\"$any(p).registration\" />\n <div class=\"rhc-card rhc-card--default\" style=\"margin-top:1rem\">\n <app-heading [level]=\"2\">Persoonsgegevens (BRP)</app-heading>\n <dl class=\"rhc-data-summary rhc-data-summary--row\">\n <app-data-row key=\"Straat\" [value]=\"$any(p).person.adres.straat\" />\n <app-data-row key=\"Postcode\" [value]=\"$any(p).person.adres.postcode\" />\n <app-data-row key=\"Woonplaats\" [value]=\"$any(p).person.adres.woonplaats\" />\n </dl>\n </div>\n </ng-template>\n <ng-template appAsyncLoading>\n <app-skeleton height=\"2.5rem\" [count]=\"6\" />\n </ng-template>\n </app-async>\n\n <div style=\"margin-top:2rem\">\n <app-heading [level]=\"2\">Specialismen en aantekeningen</app-heading>\n <app-async [data]=\"store.aantekeningen()\">\n <ng-template appAsyncLoaded let-r>\n <app-registration-table [rows]=\"$any(r)\" />\n </ng-template>\n <ng-template appAsyncLoading>\n <app-skeleton height=\"2.5rem\" [count]=\"3\" />\n </ng-template>\n <ng-template appAsyncEmpty>\n <p class=\"rhc-paragraph\">U heeft nog geen specialismen of aantekeningen.</p>\n </ng-template>\n </app-async>\n </div>\n\n <p style=\"margin-top:2rem\">\n <app-link to=\"/registratie\">Gegevens bekijken of een wijziging doorgeven →</app-link>\n </p>\n <p>\n <app-link to=\"/herregistratie\">Herregistratie aanvragen →</app-link>\n </p>\n <p>\n <app-link to=\"/concepts\">Functionele patronen (impossible states) →</app-link>\n </p>\n</app-page-shell>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [],
"outputsClass": [],
"propertiesClass": [
{
"name": "store",
"defaultValue": "inject(BigProfileStore)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 71,
"modifierKind": [
124
]
}
],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [
{
"name": "PageShellComponent",
"type": "component"
},
{
"name": "HeadingComponent",
"type": "component"
},
{
"name": "LinkComponent",
"type": "component"
},
{
"name": "AlertComponent",
"type": "component"
},
{
"name": "SkeletonComponent",
"type": "component"
},
{
"name": "DataRowComponent",
"type": "component"
},
{
"name": "ASYNC"
},
{
"name": "RegistrationSummaryComponent",
"type": "component"
},
{
"name": "RegistrationTableComponent",
"type": "component"
}
],
"description": "",
"rawdescription": "\n",
"type": "component",
"sourceCode": "import { Component, inject } from '@angular/core';\nimport { PageShellComponent } from '@shared/layout/page-shell/page-shell.component';\nimport { HeadingComponent } from '@shared/ui/heading/heading.component';\nimport { LinkComponent } from '@shared/ui/link/link.component';\nimport { AlertComponent } from '@shared/ui/alert/alert.component';\nimport { SkeletonComponent } from '@shared/ui/skeleton/skeleton.component';\nimport { DataRowComponent } from '@shared/ui/data-row/data-row.component';\nimport { ASYNC } from '@shared/ui/async/async.component';\nimport { RegistrationSummaryComponent } from '@registratie/ui/registration-summary/registration-summary.component';\nimport { RegistrationTableComponent } from '@registratie/ui/registration-table/registration-table.component';\nimport { BigProfileStore } from '@registratie/application/big-profile.store';\n\n@Component({\n selector: 'app-dashboard-page',\n imports: [\n PageShellComponent, HeadingComponent, LinkComponent, AlertComponent, SkeletonComponent,\n DataRowComponent, ...ASYNC, RegistrationSummaryComponent, RegistrationTableComponent,\n ],\n template: `\n <app-page-shell heading=\"Mijn BIG-registratie\">\n @if (store.pendingHerregistratie()) {\n <app-alert type=\"info\">Uw herregistratie-aanvraag is in behandeling.</app-alert>\n }\n\n <!-- ONE state for two combined services (BIG-register + BRP). -->\n <app-async [data]=\"store.profile()\">\n <ng-template appAsyncLoaded let-p>\n <app-registration-summary [reg]=\"$any(p).registration\" />\n <div class=\"rhc-card rhc-card--default\" style=\"margin-top:1rem\">\n <app-heading [level]=\"2\">Persoonsgegevens (BRP)</app-heading>\n <dl class=\"rhc-data-summary rhc-data-summary--row\">\n <app-data-row key=\"Straat\" [value]=\"$any(p).person.adres.straat\" />\n <app-data-row key=\"Postcode\" [value]=\"$any(p).person.adres.postcode\" />\n <app-data-row key=\"Woonplaats\" [value]=\"$any(p).person.adres.woonplaats\" />\n </dl>\n </div>\n </ng-template>\n <ng-template appAsyncLoading>\n <app-skeleton height=\"2.5rem\" [count]=\"6\" />\n </ng-template>\n </app-async>\n\n <div style=\"margin-top:2rem\">\n <app-heading [level]=\"2\">Specialismen en aantekeningen</app-heading>\n <app-async [data]=\"store.aantekeningen()\">\n <ng-template appAsyncLoaded let-r>\n <app-registration-table [rows]=\"$any(r)\" />\n </ng-template>\n <ng-template appAsyncLoading>\n <app-skeleton height=\"2.5rem\" [count]=\"3\" />\n </ng-template>\n <ng-template appAsyncEmpty>\n <p class=\"rhc-paragraph\">U heeft nog geen specialismen of aantekeningen.</p>\n </ng-template>\n </app-async>\n </div>\n\n <p style=\"margin-top:2rem\">\n <app-link to=\"/registratie\">Gegevens bekijken of een wijziging doorgeven →</app-link>\n </p>\n <p>\n <app-link to=\"/herregistratie\">Herregistratie aanvragen →</app-link>\n </p>\n <p>\n <app-link to=\"/concepts\">Functionele patronen (impossible states) →</app-link>\n </p>\n </app-page-shell>\n `,\n})\nexport class DashboardPage {\n protected store = inject(BigProfileStore);\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "DataRowComponent",
"id": "component-DataRowComponent-bf012e0b5e277c5c6d53311a7649373316677ab4f6d5ba0b313f5eaeb5a061ea55cb08b0af237c487dcc3be5b15014d5c2b21b6f6903ff7689881fc8607eb1b2",
"file": "src/app/shared/ui/data-row/data-row.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-data-row",
"styleUrls": [],
"styles": [],
"template": "<div class=\"rhc-data-summary__item\">\n <dt class=\"rhc-data-summary__item-key\">{{ key() }}</dt>\n <dd class=\"rhc-data-summary__item-value\"><ng-content>{{ value() }}</ng-content></dd>\n</div>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [
{
"name": "key",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 15,
"required": true
},
{
"name": "value",
"defaultValue": "''",
"deprecated": false,
"deprecationMessage": "",
"type": "string | null",
"indexKey": "",
"optional": false,
"description": "",
"line": 16,
"required": false
}
],
"outputsClass": [],
"propertiesClass": [],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [],
"description": "<p>Molecule: one key/value row inside an RHC data-summary.\nWrap several of these in .rhc-data-summary (see registration-summary).</p>\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 template: `\n <div class=\"rhc-data-summary__item\">\n <dt class=\"rhc-data-summary__item-key\">{{ key() }}</dt>\n <dd class=\"rhc-data-summary__item-value\"><ng-content>{{ value() }}</ng-content></dd>\n </div>\n `,\n})\nexport class DataRowComponent {\n key = input.required<string>();\n value = input<string | null>('');\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "FormFieldComponent",
"id": "component-FormFieldComponent-9f7fb7fac967056161f8440bccbd87825bc2897463f63a612a12ac6154cfaa4e17a2a6469fbe936deba74319ac6029c6aa024abfc07095b226f5980e654cb12c",
"file": "src/app/shared/ui/form-field/form-field.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-form-field",
"styleUrls": [],
"styles": [],
"template": "<div class=\"rhc-form-field utrecht-form-field\" [class.utrecht-form-field--invalid]=\"!!error()\">\n <label class=\"utrecht-form-label\" [for]=\"fieldId()\">{{ label() }}</label>\n @if (description()) {\n <div class=\"utrecht-form-field-description\">{{ description() }}</div>\n }\n <ng-content />\n @if (error()) {\n <div class=\"utrecht-form-field-error-message\" role=\"alert\">{{ error() }}</div>\n }\n</div>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [
{
"name": "description",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 23,
"required": false
},
{
"name": "error",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 24,
"required": false
},
{
"name": "fieldId",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 22,
"required": true
},
{
"name": "label",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 21,
"required": true
}
],
"outputsClass": [],
"propertiesClass": [],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [],
"description": "<p>Molecule: form field = label + projected control + optional error/description.\nReused by both the login form and the change-request form.</p>\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: `\n <div class=\"rhc-form-field utrecht-form-field\" [class.utrecht-form-field--invalid]=\"!!error()\">\n <label class=\"utrecht-form-label\" [for]=\"fieldId()\">{{ label() }}</label>\n @if (description()) {\n <div class=\"utrecht-form-field-description\">{{ description() }}</div>\n }\n <ng-content />\n @if (error()) {\n <div class=\"utrecht-form-field-error-message\" role=\"alert\">{{ error() }}</div>\n }\n </div>\n `,\n})\nexport class FormFieldComponent {\n label = input.required<string>();\n fieldId = input.required<string>();\n description = input<string>();\n error = input<string>();\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "HeadingComponent",
"id": "component-HeadingComponent-0f0b442fc9ccbfde8481137b728000bb093868ddc931f507bbd4a86ee528820cf4c6dab36a9a82b4a940bb96c2355f42bc34a94700acc7df3e7dfeea627be67c",
"file": "src/app/shared/ui/heading/heading.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-heading",
"styleUrls": [],
"styles": [],
"template": "<ng-template #content><ng-content /></ng-template>\n@switch (level()) {\n @case (1) { <h1 class=\"rhc-heading nl-heading--level-1\"><ng-container [ngTemplateOutlet]=\"content\" /></h1> }\n @case (2) { <h2 class=\"rhc-heading nl-heading--level-2\"><ng-container [ngTemplateOutlet]=\"content\" /></h2> }\n @case (3) { <h3 class=\"rhc-heading nl-heading--level-3\"><ng-container [ngTemplateOutlet]=\"content\" /></h3> }\n @case (4) { <h4 class=\"rhc-heading nl-heading--level-4\"><ng-container [ngTemplateOutlet]=\"content\" /></h4> }\n @default { <h5 class=\"rhc-heading nl-heading--level-5\"><ng-container [ngTemplateOutlet]=\"content\" /></h5> }\n}\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [
{
"name": "level",
"defaultValue": "2",
"deprecated": false,
"deprecationMessage": "",
"type": "1 | 2 | 3 | 4 | 5",
"indexKey": "",
"optional": false,
"description": "",
"line": 22,
"required": false
}
],
"outputsClass": [],
"propertiesClass": [],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [
{
"name": "NgTemplateOutlet"
}
],
"description": "<p>Atom: heading. Renders the right h1..h5 with RHC heading styling.\nSingle <ng-content> captured in a template — multiple ng-content across</p>\n",
"rawdescription": "\nAtom: heading. Renders the right h1..h5 with RHC heading styling.\nSingle <ng-content> captured in a template — multiple ng-content across",
"type": "component",
"sourceCode": "import { Component, input } from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\n\n/** Atom: heading. Renders the right h1..h5 with RHC heading styling.\n Single <ng-content> captured in a template — multiple ng-content across\n @switch branches silently drops the projected content. */\n@Component({\n selector: 'app-heading',\n imports: [NgTemplateOutlet],\n template: `\n <ng-template #content><ng-content /></ng-template>\n @switch (level()) {\n @case (1) { <h1 class=\"rhc-heading nl-heading--level-1\"><ng-container [ngTemplateOutlet]=\"content\" /></h1> }\n @case (2) { <h2 class=\"rhc-heading nl-heading--level-2\"><ng-container [ngTemplateOutlet]=\"content\" /></h2> }\n @case (3) { <h3 class=\"rhc-heading nl-heading--level-3\"><ng-container [ngTemplateOutlet]=\"content\" /></h3> }\n @case (4) { <h4 class=\"rhc-heading nl-heading--level-4\"><ng-container [ngTemplateOutlet]=\"content\" /></h4> }\n @default { <h5 class=\"rhc-heading nl-heading--level-5\"><ng-container [ngTemplateOutlet]=\"content\" /></h5> }\n }\n `,\n})\nexport class HeadingComponent {\n level = input<1 | 2 | 3 | 4 | 5>(2);\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "HerregistratiePage",
"id": "component-HerregistratiePage-320bc6fae5182789d36effc63292c612ce5b125b9cf1bb77b7bdc1be837ca444255723e8a2a48eb9abcada973007eec4badbaf82e60644b869c5d66ffd68d97d",
"file": "src/app/herregistratie/ui/herregistratie.page.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-herregistratie-page",
"styleUrls": [],
"styles": [],
"template": "<app-page-shell heading=\"Herregistratie aanvragen\" backLink=\"/dashboard\">\n <app-async [data]=\"eligibility()\">\n <ng-template appAsyncLoaded let-eligible>\n @if (eligible) {\n <app-alert type=\"info\">\n Uw huidige registratie verloopt binnenkort. Vraag tijdig herregistratie aan.\n </app-alert>\n <div style=\"margin-top:1.5rem\">\n <app-herregistratie-wizard />\n </div>\n } @else {\n <app-alert type=\"warning\">\n Voor uw huidige registratiestatus is herregistratie niet mogelijk.\n </app-alert>\n }\n </ng-template>\n </app-async>\n</app-page-shell>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [],
"outputsClass": [],
"propertiesClass": [
{
"name": "eligibility",
"defaultValue": "computed(() =>\n map(this.store.profile(), (p) => isHerregistratieEligible(p.registration, new Date())),\n )",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 39,
"modifierKind": [
124
]
},
{
"name": "store",
"defaultValue": "inject(BigProfileStore)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 37,
"modifierKind": [
123
]
}
],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [
{
"name": "PageShellComponent",
"type": "component"
},
{
"name": "AlertComponent",
"type": "component"
},
{
"name": "ASYNC"
},
{
"name": "HerregistratieWizardComponent",
"type": "component"
}
],
"description": "<p>A whole new page built from existing building blocks. Eligibility is a pure\ndomain rule (registration.policy) read from the shared profile state.</p>\n",
"rawdescription": "\nA whole new page built from existing building blocks. Eligibility is a pure\ndomain rule (registration.policy) read from the shared profile state.",
"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 { isHerregistratieEligible } from '@registratie/domain/registration.policy';\nimport { HerregistratieWizardComponent } from '@herregistratie/ui/herregistratie-wizard/herregistratie-wizard.component';\n\n/** A whole new page built from existing building blocks. Eligibility is a pure\n domain rule (registration.policy) read from the shared profile state. */\n@Component({\n selector: 'app-herregistratie-page',\n imports: [PageShellComponent, AlertComponent, ...ASYNC, HerregistratieWizardComponent],\n template: `\n <app-page-shell heading=\"Herregistratie aanvragen\" backLink=\"/dashboard\">\n <app-async [data]=\"eligibility()\">\n <ng-template appAsyncLoaded let-eligible>\n @if (eligible) {\n <app-alert type=\"info\">\n Uw huidige registratie verloopt binnenkort. Vraag tijdig herregistratie aan.\n </app-alert>\n <div style=\"margin-top:1.5rem\">\n <app-herregistratie-wizard />\n </div>\n } @else {\n <app-alert type=\"warning\">\n Voor uw huidige registratiestatus is herregistratie niet mogelijk.\n </app-alert>\n }\n </ng-template>\n </app-async>\n </app-page-shell>\n `,\n})\nexport class HerregistratiePage {\n private store = inject(BigProfileStore);\n // Derive a boolean RemoteData from the combined profile via map (pure).\n protected eligibility = computed(() =>\n map(this.store.profile(), (p) => isHerregistratieEligible(p.registration, new Date())),\n );\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "HerregistratieWizardComponent",
"id": "component-HerregistratieWizardComponent-45976389894f1e7f8d41c6517df80210bfb72ce0c6d94a26e8efaea3128977466c34eab7a568b372079d6c5295253c988e2b3d96ffc7267e02a1160e75cef160",
"file": "src/app/herregistratie/ui/herregistratie-wizard/herregistratie-wizard.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-herregistratie-wizard",
"styleUrls": [],
"styles": [],
"template": "@switch (state().tag) {\n @case ('Editing') {\n <p class=\"rhc-paragraph\" style=\"color:var(--rhc-color-grijs-700)\">Stap {{ step() }} van 2</p>\n <form (ngSubmit)=\"onPrimary()\" style=\"max-width:28rem\">\n @if (step() === 1) {\n <app-form-field label=\"Gewerkte uren (afgelopen 5 jaar)\" fieldId=\"uren\" [error]=\"errUren()\">\n <app-text-input inputId=\"uren\" [ngModel]=\"draft().uren\" (ngModelChange)=\"dispatch({ tag: 'SetField', key: 'uren', value: $event })\"\n name=\"uren\" [invalid]=\"!!errUren()\" placeholder=\"bijv. 4160\" />\n </app-form-field>\n <app-button type=\"submit\" variant=\"primary\">Volgende</app-button>\n } @else {\n <app-form-field label=\"Behaalde nascholingspunten\" fieldId=\"punten\" [error]=\"errPunten()\">\n <app-text-input inputId=\"punten\" [ngModel]=\"draft().punten\" (ngModelChange)=\"dispatch({ tag: 'SetField', key: 'punten', value: $event })\"\n name=\"punten\" [invalid]=\"!!errPunten()\" placeholder=\"bijv. 200\" />\n </app-form-field>\n <div style=\"display:flex;gap:0.5rem\">\n <app-button type=\"button\" variant=\"secondary\" (click)=\"dispatch({ tag: 'Back' })\">Vorige</app-button>\n <app-button type=\"submit\" variant=\"primary\">Herregistratie aanvragen</app-button>\n </div>\n }\n </form>\n }\n @case ('Submitting') {\n <app-spinner /> <span>Aanvraag wordt verwerkt…</span>\n }\n @case ('Submitted') {\n <app-alert type=\"ok\">Uw aanvraag tot herregistratie is ontvangen.</app-alert>\n }\n @case ('Failed') {\n <app-alert type=\"error\">Indienen mislukt: {{ failedError() }}</app-alert>\n <div style=\"margin-top:1rem\">\n <app-button variant=\"secondary\" (click)=\"onRetry()\">Opnieuw proberen</app-button>\n </div>\n }\n}\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [
{
"name": "seed",
"defaultValue": "initial",
"deprecated": false,
"deprecationMessage": "",
"type": "WizardState",
"indexKey": "",
"optional": false,
"description": "<p>Optional seed so Storybook / the showcase can mount any state directly.</p>\n",
"line": 65,
"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": 68,
"modifierKind": [
124
]
},
{
"name": "draft",
"defaultValue": "computed<Draft>(() => this.editing()?.draft ?? { uren: '', punten: '' })",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 72,
"modifierKind": [
124
]
},
{
"name": "editing",
"defaultValue": "computed(() => (this.state().tag === 'Editing' ? (this.state() as Extract<WizardState, { tag: 'Editing' }>) : null))",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 70,
"modifierKind": [
123
]
},
{
"name": "errPunten",
"defaultValue": "computed(() => this.editing()?.errors.punten ?? '')",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 74,
"modifierKind": [
124
]
},
{
"name": "errUren",
"defaultValue": "computed(() => this.editing()?.errors.uren ?? '')",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 73,
"modifierKind": [
124
]
},
{
"name": "failedError",
"defaultValue": "computed(() => (this.state().tag === 'Failed' ? (this.state() as Extract<WizardState, { tag: 'Failed' }>).error : ''))",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 75,
"modifierKind": [
124
]
},
{
"name": "profile",
"defaultValue": "inject(BigProfileStore)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 61,
"modifierKind": [
123
]
},
{
"name": "state",
"defaultValue": "this.store.model",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 67,
"modifierKind": [
124
]
},
{
"name": "step",
"defaultValue": "computed(() => this.editing()?.step ?? 1)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 71,
"modifierKind": [
124
]
},
{
"name": "store",
"defaultValue": "createStore<WizardState, WizardMsg>(initial, reduce)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 62,
"modifierKind": [
123
]
}
],
"methodsClass": [
{
"name": "onPrimary",
"args": [],
"optional": false,
"returnType": "void",
"typeParameters": [],
"line": 81,
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "onRetry",
"args": [],
"optional": false,
"returnType": "void",
"typeParameters": [],
"line": 88,
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "runIfSubmitting",
"args": [],
"optional": false,
"returnType": "any",
"typeParameters": [],
"line": 95,
"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": "<p>The effect: when we entered Submitting, call the backend command, flip the\noptimistic cross-page flag, then dispatch the result (and commit/rollback).</p>\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": "<p>Organism: multi-step herregistratie wizard. ALL state lives in one signal\ndriven by the pure <code>reduce</code> function (see herregistratie.machine.ts) via an\nElm-style store. The UI just sends messages and folds over the state&#39;s tag —\nno booleans like <code>submitting</code>/<code>submitted</code> that could contradict each other.\nSubmitting also flips an optimistic flag on the shared BigProfileStore, so\nthe dashboard shows &quot;in behandeling&quot; immediately.</p>\n",
"rawdescription": "\nOrganism: 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.",
"type": "component",
"sourceCode": "import { Component, computed, inject, input } 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 { AlertComponent } from '@shared/ui/alert/alert.component';\nimport { SpinnerComponent } from '@shared/ui/spinner/spinner.component';\nimport { createStore } from '@shared/application/store';\nimport { BigProfileStore } from '@registratie/application/big-profile.store';\nimport { WizardState, WizardMsg, Draft, initial, reduce } from '@herregistratie/domain/herregistratie.machine';\nimport { submitHerregistratie } from '@herregistratie/application/submit-herregistratie';\n\n/** Organism: multi-step herregistratie wizard. ALL state lives in one signal\n driven by the pure `reduce` function (see herregistratie.machine.ts) via an\n Elm-style store. The UI just sends messages and folds over the state's tag —\n no booleans like `submitting`/`submitted` that could contradict each other.\n Submitting also flips an optimistic flag on the shared BigProfileStore, so\n the dashboard shows \"in behandeling\" immediately. */\n@Component({\n selector: 'app-herregistratie-wizard',\n imports: [FormsModule, FormFieldComponent, TextInputComponent, ButtonComponent, AlertComponent, SpinnerComponent],\n template: `\n @switch (state().tag) {\n @case ('Editing') {\n <p class=\"rhc-paragraph\" style=\"color:var(--rhc-color-grijs-700)\">Stap {{ step() }} van 2</p>\n <form (ngSubmit)=\"onPrimary()\" style=\"max-width:28rem\">\n @if (step() === 1) {\n <app-form-field label=\"Gewerkte uren (afgelopen 5 jaar)\" fieldId=\"uren\" [error]=\"errUren()\">\n <app-text-input inputId=\"uren\" [ngModel]=\"draft().uren\" (ngModelChange)=\"dispatch({ tag: 'SetField', key: 'uren', value: $event })\"\n name=\"uren\" [invalid]=\"!!errUren()\" placeholder=\"bijv. 4160\" />\n </app-form-field>\n <app-button type=\"submit\" variant=\"primary\">Volgende</app-button>\n } @else {\n <app-form-field label=\"Behaalde nascholingspunten\" fieldId=\"punten\" [error]=\"errPunten()\">\n <app-text-input inputId=\"punten\" [ngModel]=\"draft().punten\" (ngModelChange)=\"dispatch({ tag: 'SetField', key: 'punten', value: $event })\"\n name=\"punten\" [invalid]=\"!!errPunten()\" placeholder=\"bijv. 200\" />\n </app-form-field>\n <div style=\"display:flex;gap:0.5rem\">\n <app-button type=\"button\" variant=\"secondary\" (click)=\"dispatch({ tag: 'Back' })\">Vorige</app-button>\n <app-button type=\"submit\" variant=\"primary\">Herregistratie aanvragen</app-button>\n </div>\n }\n </form>\n }\n @case ('Submitting') {\n <app-spinner /> <span>Aanvraag wordt verwerkt…</span>\n }\n @case ('Submitted') {\n <app-alert type=\"ok\">Uw aanvraag tot herregistratie is ontvangen.</app-alert>\n }\n @case ('Failed') {\n <app-alert type=\"error\">Indienen mislukt: {{ failedError() }}</app-alert>\n <div style=\"margin-top:1rem\">\n <app-button variant=\"secondary\" (click)=\"onRetry()\">Opnieuw proberen</app-button>\n </div>\n }\n }\n `,\n})\nexport class HerregistratieWizardComponent {\n private profile = inject(BigProfileStore);\n private store = createStore<WizardState, WizardMsg>(initial, reduce);\n\n /** Optional seed so Storybook / the showcase can mount any state directly. */\n seed = input<WizardState>(initial);\n\n protected state = this.store.model;\n protected dispatch = this.store.dispatch;\n\n private editing = computed(() => (this.state().tag === 'Editing' ? (this.state() as Extract<WizardState, { tag: 'Editing' }>) : null));\n protected step = computed(() => this.editing()?.step ?? 1);\n protected draft = computed<Draft>(() => this.editing()?.draft ?? { uren: '', punten: '' });\n protected errUren = computed(() => this.editing()?.errors.uren ?? '');\n protected errPunten = computed(() => this.editing()?.errors.punten ?? '');\n protected failedError = computed(() => (this.state().tag === 'Failed' ? (this.state() as Extract<WizardState, { tag: 'Failed' }>).error : ''));\n\n constructor() {\n queueMicrotask(() => this.dispatch({ tag: 'Seed', state: this.seed() }));\n }\n\n onPrimary() {\n const s = this.state();\n if (s.tag !== 'Editing') return;\n this.dispatch(s.step === 1 ? { tag: 'Next' } : { tag: 'Submit' });\n this.runIfSubmitting();\n }\n\n onRetry() {\n this.dispatch({ tag: 'Retry' });\n this.runIfSubmitting();\n }\n\n /** The effect: when we entered Submitting, call the backend command, flip the\n optimistic cross-page flag, then dispatch the result (and commit/rollback). */\n private async runIfSubmitting() {\n const s = this.state();\n if (s.tag !== 'Submitting') return;\n this.profile.beginHerregistratie();\n const r = await submitHerregistratie(s.data);\n if (r.ok) {\n this.dispatch({ tag: 'SubmitConfirmed' });\n this.profile.confirmHerregistratie();\n } else {\n this.dispatch({ tag: 'SubmitFailed', error: r.error });\n this.profile.rollbackHerregistratie();\n }\n }\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"constructorObj": {
"name": "constructor",
"description": "",
"deprecated": false,
"deprecationMessage": "",
"args": [],
"line": 75
},
"extends": []
},
{
"name": "LinkComponent",
"id": "component-LinkComponent-81d97782386b884f56c43d583cbf6d1005dda96974f169366a9af853aeb8b8f4e99f9cce2f9a7ef0fdafce32f51e6049483a44ab35614c486f82535b65ce2818",
"file": "src/app/shared/ui/link/link.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-link",
"styleUrls": [],
"styles": [],
"template": "<a [routerLink]=\"to()\" class=\"rhc-link nl-link utrecht-link\"><ng-content /></a>",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [
{
"name": "to",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 11,
"required": true
}
],
"outputsClass": [],
"propertiesClass": [],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [
{
"name": "RouterLink"
}
],
"description": "<p>Atom: link. Internal router link styled as an RHC/Utrecht link.</p>\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: `<a [routerLink]=\"to()\" class=\"rhc-link nl-link utrecht-link\"><ng-content /></a>`,\n})\nexport class LinkComponent {\n to = input.required<string>();\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "LoginFormComponent",
"id": "component-LoginFormComponent-5a1ea0dfad0a47819d0884389f35e026337bfc135ed3cb5f34d5874d22b773b812864e1dfdcebf784acf886a77e9f59d3f244c7f3bbe1edafb38f0d8fb866a43",
"file": "src/app/auth/ui/login-form/login-form.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-login-form",
"styleUrls": [],
"styles": [],
"template": "<form (ngSubmit)=\"submit.emit(bsn)\">\n <app-form-field label=\"BSN\" fieldId=\"bsn\" description=\"9 cijfers (demo: vul iets in)\">\n <app-text-input inputId=\"bsn\" [(ngModel)]=\"bsn\" name=\"bsn\" placeholder=\"123456789\" />\n </app-form-field>\n\n <app-form-field label=\"Wachtwoord\" fieldId=\"pw\">\n <app-text-input inputId=\"pw\" type=\"password\" [(ngModel)]=\"password\" name=\"pw\" />\n </app-form-field>\n\n <div style=\"margin-top:1rem\">\n <app-button type=\"submit\" variant=\"primary\">Inloggen met DigiD</app-button>\n </div>\n</form>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [],
"outputsClass": [
{
"name": "submit",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 30,
"required": false
}
],
"propertiesClass": [
{
"name": "bsn",
"defaultValue": "''",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 28
},
{
"name": "password",
"defaultValue": "''",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 29
}
],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [
{
"name": "FormsModule",
"type": "module"
},
{
"name": "FormFieldComponent",
"type": "component"
},
{
"name": "TextInputComponent",
"type": "component"
},
{
"name": "ButtonComponent",
"type": "component"
}
],
"description": "<p>Organism: DigiD-style mock login. No real auth — just composes atoms/molecules.</p>\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 <form (ngSubmit)=\"submit.emit(bsn)\">\n <app-form-field label=\"BSN\" fieldId=\"bsn\" description=\"9 cijfers (demo: vul iets in)\">\n <app-text-input inputId=\"bsn\" [(ngModel)]=\"bsn\" name=\"bsn\" placeholder=\"123456789\" />\n </app-form-field>\n\n <app-form-field label=\"Wachtwoord\" fieldId=\"pw\">\n <app-text-input inputId=\"pw\" type=\"password\" [(ngModel)]=\"password\" name=\"pw\" />\n </app-form-field>\n\n <div style=\"margin-top:1rem\">\n <app-button type=\"submit\" variant=\"primary\">Inloggen met DigiD</app-button>\n </div>\n </form>\n `,\n})\nexport class LoginFormComponent {\n bsn = '';\n password = '';\n submit = output<string>();\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "LoginPage",
"id": "component-LoginPage-9e33c7b584edbd0642e3db190f47b540bad1779cd292050761380e92715a150b03eb5d869d57c6678b4d73523803c07e2d70d6e70183b34461ac31c15cafa95b",
"file": "src/app/auth/ui/login.page.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-login-page",
"styleUrls": [],
"styles": [],
"template": "<app-page-shell heading=\"Inloggen\" width=\"narrow\"\n intro=\"Log in op uw persoonlijke BIG-register omgeving.\">\n @if (error()) { <app-alert type=\"error\">{{ error() }}</app-alert> }\n <app-login-form (submit)=\"login($event)\" />\n</app-page-shell>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [],
"outputsClass": [],
"propertiesClass": [
{
"name": "error",
"defaultValue": "signal('')",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 22
},
{
"name": "router",
"defaultValue": "inject(Router)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 21,
"modifierKind": [
123
]
},
{
"name": "store",
"defaultValue": "inject(SessionStore)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 20,
"modifierKind": [
123
]
}
],
"methodsClass": [
{
"name": "login",
"args": [
{
"name": "bsn",
"type": "string",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": ""
}
],
"optional": false,
"returnType": "any",
"typeParameters": [],
"line": 24,
"deprecated": false,
"deprecationMessage": "",
"modifierKind": [
134
],
"jsdoctags": [
{
"name": "bsn",
"type": "string",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
}
],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [
{
"name": "PageShellComponent",
"type": "component"
},
{
"name": "AlertComponent",
"type": "component"
},
{
"name": "LoginFormComponent",
"type": "component"
}
],
"description": "",
"rawdescription": "\n",
"type": "component",
"sourceCode": "import { Component, inject, signal } from '@angular/core';\nimport { Router } from '@angular/router';\nimport { PageShellComponent } from '@shared/layout/page-shell/page-shell.component';\nimport { AlertComponent } from '@shared/ui/alert/alert.component';\nimport { LoginFormComponent } from '@auth/ui/login-form/login-form.component';\nimport { SessionStore } from '@auth/application/session.store';\n\n@Component({\n selector: 'app-login-page',\n imports: [PageShellComponent, AlertComponent, LoginFormComponent],\n template: `\n <app-page-shell heading=\"Inloggen\" width=\"narrow\"\n intro=\"Log in op uw persoonlijke BIG-register omgeving.\">\n @if (error()) { <app-alert type=\"error\">{{ error() }}</app-alert> }\n <app-login-form (submit)=\"login($event)\" />\n </app-page-shell>\n `,\n})\nexport class LoginPage {\n private store = inject(SessionStore);\n private router = inject(Router);\n error = signal('');\n\n async login(bsn: string) {\n const r = await this.store.login(bsn);\n if (r.ok) this.router.navigate(['/dashboard']);\n else this.error.set(r.error);\n }\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "PageShellComponent",
"id": "component-PageShellComponent-e203d646c83aa0fbb8c86fd2fd55c90f86a13538dcec381ed765f73d2d49424819da915fe6cc8a91700f890997d9d2407b4376630d984875e90277fe97679453",
"file": "src/app/shared/layout/page-shell/page-shell.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-page-shell",
"styleUrls": [],
"styles": [
":host{display:block}"
],
"template": "<div [style.max-width]=\"width() === 'narrow' ? '32rem' : null\">\n @if (backLink()) {\n <p><app-link [to]=\"backLink()!\">← {{ backLabel() }}</app-link></p>\n }\n <app-heading [level]=\"1\">{{ heading() }}</app-heading>\n @if (intro()) {\n <p class=\"rhc-paragraph\" style=\"margin-bottom:1.5rem\">{{ intro() }}</p>\n }\n <ng-content />\n</div>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [
{
"name": "backLabel",
"defaultValue": "'Terug naar overzicht'",
"deprecated": false,
"deprecationMessage": "",
"indexKey": "",
"optional": false,
"description": "",
"line": 29,
"required": false
},
{
"name": "backLink",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 28,
"required": false
},
{
"name": "heading",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 26,
"required": true
},
{
"name": "intro",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 27,
"required": false
},
{
"name": "width",
"defaultValue": "'default'",
"deprecated": false,
"deprecationMessage": "",
"type": "\"default\" | \"narrow\"",
"indexKey": "",
"optional": false,
"description": "",
"line": 30,
"required": false
}
],
"outputsClass": [],
"propertiesClass": [],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [
{
"name": "HeadingComponent",
"type": "component"
},
{
"name": "LinkComponent",
"type": "component"
}
],
"description": "<p>Template: standard page body — optional back-link, a heading, optional intro,\nand projected content. Rendered inside the persistent ShellComponent via the\nrouter outlet, so it owns only the content (not the header/footer chrome).</p>\n",
"rawdescription": "\nTemplate: standard page body — optional back-link, a heading, optional intro,\nand projected content. Rendered inside the persistent ShellComponent via the\nrouter outlet, so it owns only the content (not the header/footer 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';\n\n/** Template: standard page body — optional back-link, a heading, optional intro,\n and projected content. Rendered inside the persistent ShellComponent via the\n router outlet, so it owns only the content (not the header/footer chrome). */\n@Component({\n selector: 'app-page-shell',\n imports: [HeadingComponent, LinkComponent],\n styles: [':host{display:block}'],\n template: `\n <div [style.max-width]=\"width() === 'narrow' ? '32rem' : null\">\n @if (backLink()) {\n <p><app-link [to]=\"backLink()!\">← {{ backLabel() }}</app-link></p>\n }\n <app-heading [level]=\"1\">{{ heading() }}</app-heading>\n @if (intro()) {\n <p class=\"rhc-paragraph\" style=\"margin-bottom:1.5rem\">{{ intro() }}</p>\n }\n <ng-content />\n </div>\n `,\n})\nexport class PageShellComponent {\n heading = input.required<string>();\n intro = input<string>();\n backLink = input<string>();\n backLabel = input('Terug naar overzicht');\n width = input<'default' | 'narrow'>('default');\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": ":host{display:block}\n",
"extends": []
},
{
"name": "RegistrationDetailPage",
"id": "component-RegistrationDetailPage-5aa270b47adfa8bd0334225a51df3a1656468e109d14ca9967660455a734884f4fb358b0f2a6c97e19b4df859f4c5e9773d5dd9c728dbcd785a3d43a60472811",
"file": "src/app/registratie/ui/registration-detail.page.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-registration-detail-page",
"styleUrls": [],
"styles": [],
"template": "<app-page-shell heading=\"Mijn gegevens\" backLink=\"/dashboard\">\n <app-async [data]=\"store.profile()\">\n <ng-template appAsyncLoaded let-p>\n <app-registration-summary [reg]=\"$any(p).registration\" />\n </ng-template>\n <ng-template appAsyncLoading>\n <app-skeleton height=\"2.5rem\" [count]=\"6\" />\n </ng-template>\n </app-async>\n\n <div style=\"margin-top:2rem\">\n @if (submitted()) {\n <app-alert type=\"ok\">Uw adreswijziging is ontvangen. U ontvangt binnen 5 werkdagen bericht.</app-alert>\n } @else {\n <app-change-request-form (submitted)=\"submitted.set(true)\" />\n }\n </div>\n</app-page-shell>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [],
"outputsClass": [],
"propertiesClass": [
{
"name": "store",
"defaultValue": "inject(BigProfileStore)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 38,
"modifierKind": [
124
]
},
{
"name": "submitted",
"defaultValue": "signal(false)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 39
}
],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [
{
"name": "PageShellComponent",
"type": "component"
},
{
"name": "AlertComponent",
"type": "component"
},
{
"name": "SkeletonComponent",
"type": "component"
},
{
"name": "ASYNC"
},
{
"name": "RegistrationSummaryComponent",
"type": "component"
},
{
"name": "ChangeRequestFormComponent",
"type": "component"
}
],
"description": "",
"rawdescription": "\n",
"type": "component",
"sourceCode": "import { Component, inject, signal } from '@angular/core';\nimport { PageShellComponent } from '@shared/layout/page-shell/page-shell.component';\nimport { AlertComponent } from '@shared/ui/alert/alert.component';\nimport { SkeletonComponent } from '@shared/ui/skeleton/skeleton.component';\nimport { ASYNC } from '@shared/ui/async/async.component';\nimport { RegistrationSummaryComponent } from '@registratie/ui/registration-summary/registration-summary.component';\nimport { ChangeRequestFormComponent } from '@registratie/ui/change-request-form/change-request-form.component';\nimport { BigProfileStore } from '@registratie/application/big-profile.store';\n\n@Component({\n selector: 'app-registration-detail-page',\n imports: [\n PageShellComponent, AlertComponent, SkeletonComponent, ...ASYNC,\n RegistrationSummaryComponent, ChangeRequestFormComponent,\n ],\n template: `\n <app-page-shell heading=\"Mijn gegevens\" backLink=\"/dashboard\">\n <app-async [data]=\"store.profile()\">\n <ng-template appAsyncLoaded let-p>\n <app-registration-summary [reg]=\"$any(p).registration\" />\n </ng-template>\n <ng-template appAsyncLoading>\n <app-skeleton height=\"2.5rem\" [count]=\"6\" />\n </ng-template>\n </app-async>\n\n <div style=\"margin-top:2rem\">\n @if (submitted()) {\n <app-alert type=\"ok\">Uw adreswijziging is ontvangen. U ontvangt binnen 5 werkdagen bericht.</app-alert>\n } @else {\n <app-change-request-form (submitted)=\"submitted.set(true)\" />\n }\n </div>\n </app-page-shell>\n `,\n})\nexport class RegistrationDetailPage {\n protected store = inject(BigProfileStore);\n submitted = signal(false);\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "RegistrationSummaryComponent",
"id": "component-RegistrationSummaryComponent-15a446478708503b850ebbf635068398874034b3824504dc3a05802f6743029578088280540988dacfb6c768b92a2ee0371368369f455edc6dda03cf5f179e17",
"file": "src/app/registratie/ui/registration-summary/registration-summary.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-registration-summary",
"styleUrls": [],
"styles": [],
"template": "<div class=\"rhc-card rhc-card--default\">\n <dl class=\"rhc-data-summary rhc-data-summary--row\">\n <app-data-row key=\"BIG-nummer\" [value]=\"reg().bigNummer\" />\n <app-data-row key=\"Naam\" [value]=\"reg().naam\" />\n <app-data-row key=\"Beroep\" [value]=\"reg().beroep\" />\n <app-data-row key=\"Status\">\n <app-status-badge [label]=\"label()\" [color]=\"color()\" />\n </app-data-row>\n <app-data-row key=\"Registratiedatum\" [value]=\"reg().registratiedatum | date:'longDate'\" />\n <!-- Each status variant renders only the row its own data supports. -->\n @switch (reg().status.tag) {\n @case ('Geregistreerd') {\n <app-data-row key=\"Uiterste herregistratie\" [value]=\"$any(reg().status).herregistratieDatum | date:'longDate'\" />\n }\n @case ('Geschorst') {\n <app-data-row key=\"Geschorst tot\" [value]=\"$any(reg().status).geschorstTot | date:'longDate'\" />\n <app-data-row key=\"Reden\" [value]=\"$any(reg().status).reden\" />\n }\n @case ('Doorgehaald') {\n <app-data-row key=\"Doorgehaald op\" [value]=\"$any(reg().status).doorgehaaldOp | date:'longDate'\" />\n <app-data-row key=\"Reden\" [value]=\"$any(reg().status).reden\" />\n }\n }\n </dl>\n</div>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [
{
"name": "reg",
"deprecated": false,
"deprecationMessage": "",
"type": "Registration",
"indexKey": "",
"optional": false,
"description": "",
"line": 41,
"required": true
}
],
"outputsClass": [],
"propertiesClass": [
{
"name": "color",
"defaultValue": "() => {...}",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 43,
"modifierKind": [
124
]
},
{
"name": "label",
"defaultValue": "() => {...}",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 42,
"modifierKind": [
124
]
}
],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [
{
"name": "DatePipe",
"type": "pipe"
},
{
"name": "DataRowComponent",
"type": "component"
},
{
"name": "StatusBadgeComponent",
"type": "component"
}
],
"description": "<p>Organism: registration summary card. Composes data-row molecules + status-badge atom.</p>\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 <div class=\"rhc-card rhc-card--default\">\n <dl class=\"rhc-data-summary rhc-data-summary--row\">\n <app-data-row key=\"BIG-nummer\" [value]=\"reg().bigNummer\" />\n <app-data-row key=\"Naam\" [value]=\"reg().naam\" />\n <app-data-row key=\"Beroep\" [value]=\"reg().beroep\" />\n <app-data-row key=\"Status\">\n <app-status-badge [label]=\"label()\" [color]=\"color()\" />\n </app-data-row>\n <app-data-row key=\"Registratiedatum\" [value]=\"reg().registratiedatum | date:'longDate'\" />\n <!-- Each status variant renders only the row its own data supports. -->\n @switch (reg().status.tag) {\n @case ('Geregistreerd') {\n <app-data-row key=\"Uiterste herregistratie\" [value]=\"$any(reg().status).herregistratieDatum | date:'longDate'\" />\n }\n @case ('Geschorst') {\n <app-data-row key=\"Geschorst tot\" [value]=\"$any(reg().status).geschorstTot | date:'longDate'\" />\n <app-data-row key=\"Reden\" [value]=\"$any(reg().status).reden\" />\n }\n @case ('Doorgehaald') {\n <app-data-row key=\"Doorgehaald op\" [value]=\"$any(reg().status).doorgehaaldOp | date:'longDate'\" />\n <app-data-row key=\"Reden\" [value]=\"$any(reg().status).reden\" />\n }\n }\n </dl>\n </div>\n `,\n})\nexport class RegistrationSummaryComponent {\n reg = input.required<Registration>();\n protected label = () => statusLabel(this.reg().status.tag);\n protected color = () => statusColor(this.reg().status.tag);\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "RegistrationTableComponent",
"id": "component-RegistrationTableComponent-d1fcc222260a33b20e1562a1bf325269cd07ebaed4838e1d74e883be3fbc1ef521d9250ba478316f93f8e133c0c5576cde367822159d6dff36d7b9da2c4d0a79",
"file": "src/app/registratie/ui/registration-table/registration-table.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-registration-table",
"styleUrls": [],
"styles": [],
"template": "<div class=\"utrecht-table-container utrecht-table-container--overflow-inline\">\n <table class=\"utrecht-table utrecht-table--html-table utrecht-table--alternate-row-color\">\n <thead>\n <tr>\n <th class=\"utrecht-table__header-cell\">Type</th>\n <th class=\"utrecht-table__header-cell\">Omschrijving</th>\n <th class=\"utrecht-table__header-cell\">Datum</th>\n </tr>\n </thead>\n <tbody>\n @for (row of rows(); track row.omschrijving) {\n <tr>\n <td class=\"utrecht-table__cell\">{{ row.type }}</td>\n <td class=\"utrecht-table__cell\">{{ row.omschrijving }}</td>\n <td class=\"utrecht-table__cell\">{{ row.datum | date:'mediumDate' }}</td>\n </tr>\n }\n </tbody>\n </table>\n</div>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [
{
"name": "rows",
"deprecated": false,
"deprecationMessage": "",
"type": "Aantekening[]",
"indexKey": "",
"optional": false,
"description": "",
"line": 33,
"required": true
}
],
"outputsClass": [],
"propertiesClass": [],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [
{
"name": "DatePipe",
"type": "pipe"
}
],
"description": "<p>Organism: table of specialismen/aantekeningen.</p>\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 <div class=\"utrecht-table-container utrecht-table-container--overflow-inline\">\n <table class=\"utrecht-table utrecht-table--html-table utrecht-table--alternate-row-color\">\n <thead>\n <tr>\n <th class=\"utrecht-table__header-cell\">Type</th>\n <th class=\"utrecht-table__header-cell\">Omschrijving</th>\n <th class=\"utrecht-table__header-cell\">Datum</th>\n </tr>\n </thead>\n <tbody>\n @for (row of rows(); track row.omschrijving) {\n <tr>\n <td class=\"utrecht-table__cell\">{{ row.type }}</td>\n <td class=\"utrecht-table__cell\">{{ row.omschrijving }}</td>\n <td class=\"utrecht-table__cell\">{{ row.datum | date:'mediumDate' }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n `,\n})\nexport class RegistrationTableComponent {\n rows = input.required<Aantekening[]>();\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "ShellComponent",
"id": "component-ShellComponent-a66788510e6c68711bf080318372cd2c0d790797488b8ff39c17623325904a91e1ac98f1d49d6f6f81f416cc64206126a4d0f1ce50d66403bdd3fb6b6f924279",
"file": "src/app/shared/layout/shell/shell.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-shell",
"styleUrls": [],
"styles": [
":host{display:block}"
],
"template": "<a href=\"#main\" class=\"rhc-skip-link\" style=\"position:absolute;left:-999px\">Naar de inhoud</a>\n<div class=\"utrecht-page-layout utrecht-page-layout--stretch\" style=\"--app-content-max:64rem;min-height:100vh;align-items:stretch\">\n <app-site-header />\n <main id=\"main\" class=\"utrecht-page-content\" style=\"flex:1;width:100%;box-sizing:border-box\">\n <div style=\"max-width:var(--app-content-max);margin:0 auto;padding:2rem 1.5rem;box-sizing:border-box\">\n <router-outlet />\n </div>\n </main>\n <app-site-footer />\n</div>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [],
"outputsClass": [],
"propertiesClass": [],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [
{
"name": "RouterOutlet"
},
{
"name": "SiteHeaderComponent",
"type": "component"
},
{
"name": "SiteFooterComponent",
"type": "component"
}
],
"description": "<p>Template: persistent app chrome. Header + footer mount once; only the routed\ncontent inside <router-outlet> changes (and cross-fades — see styles.scss).</p>\n",
"rawdescription": "\nTemplate: persistent app chrome. Header + footer mount once; only the routed\ncontent inside <router-outlet> changes (and cross-fades — see styles.scss).",
"type": "component",
"sourceCode": "import { Component } from '@angular/core';\nimport { RouterOutlet } from '@angular/router';\nimport { SiteHeaderComponent } from '@shared/layout/site-header/site-header.component';\nimport { SiteFooterComponent } from '@shared/layout/site-footer/site-footer.component';\n\n/** Template: persistent app chrome. Header + footer mount once; only the routed\n content inside <router-outlet> changes (and cross-fades — see styles.scss). */\n@Component({\n selector: 'app-shell',\n imports: [RouterOutlet, SiteHeaderComponent, SiteFooterComponent],\n styles: [':host{display:block}'],\n template: `\n <a href=\"#main\" class=\"rhc-skip-link\" style=\"position:absolute;left:-999px\">Naar de inhoud</a>\n <div class=\"utrecht-page-layout utrecht-page-layout--stretch\" style=\"--app-content-max:64rem;min-height:100vh;align-items:stretch\">\n <app-site-header />\n <main id=\"main\" class=\"utrecht-page-content\" style=\"flex:1;width:100%;box-sizing:border-box\">\n <div style=\"max-width:var(--app-content-max);margin:0 auto;padding:2rem 1.5rem;box-sizing:border-box\">\n <router-outlet />\n </div>\n </main>\n <app-site-footer />\n </div>\n `,\n})\nexport class ShellComponent {}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": ":host{display:block}\n",
"extends": []
},
{
"name": "SiteFooterComponent",
"id": "component-SiteFooterComponent-90391287c6e8f3ad80c034a7a6fdabdd0514fd9c0dcf549a8e4a2d3bc3d885fcd5a45a2eeeb24fa8a4bbcf2cfe865093d712765d9d1ed11b4bfca26d1fb35153",
"file": "src/app/shared/layout/site-footer/site-footer.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-site-footer",
"styleUrls": [],
"styles": [
":host{display:block}"
],
"template": "<footer class=\"utrecht-page-footer\" style=\"background:var(--rhc-color-lintblauw-900,#01689b);color:#fff;margin-top:3rem;width:100%\">\n <div style=\"max-width:var(--app-content-max);margin:0 auto;padding:1.5rem;display:flex;gap:2rem;flex-wrap:wrap;box-sizing:border-box\">\n <span>BIG-register</span>\n <span>CIBG — Ministerie van Volksgezondheid, Welzijn en Sport</span>\n <span style=\"margin-left:auto;opacity:0.85\">Demo / POC — geen echte gegevens</span>\n </div>\n</footer>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [],
"outputsClass": [],
"propertiesClass": [],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [],
"description": "<p>Organism: site footer.</p>\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: [':host{display:block}'],\n template: `\n <footer class=\"utrecht-page-footer\" style=\"background:var(--rhc-color-lintblauw-900,#01689b);color:#fff;margin-top:3rem;width:100%\">\n <div style=\"max-width:var(--app-content-max);margin:0 auto;padding:1.5rem;display:flex;gap:2rem;flex-wrap:wrap;box-sizing:border-box\">\n <span>BIG-register</span>\n <span>CIBG — Ministerie van Volksgezondheid, Welzijn en Sport</span>\n <span style=\"margin-left:auto;opacity:0.85\">Demo / POC — geen echte gegevens</span>\n </div>\n </footer>\n `,\n})\nexport class SiteFooterComponent {}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": ":host{display:block}\n",
"extends": []
},
{
"name": "SiteHeaderComponent",
"id": "component-SiteHeaderComponent-710f1c109f26ae5f1888aa77ac682c58c9534fbba74aeae04b903e169f674c1ce04b8ae9e379a936c8ddef16e53c500e93d132021bcdd4ef743a601e05808f66",
"file": "src/app/shared/layout/site-header/site-header.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-site-header",
"styleUrls": [],
"styles": [
":host{display:block}"
],
"template": "<header class=\"utrecht-page-header\" style=\"background:var(--rhc-color-lintblauw-700,#154273);color:#fff;width:100%\">\n <div style=\"display:flex;align-items:center;gap:1rem;max-width:var(--app-content-max);margin:0 auto;padding:1rem 1.5rem;box-sizing:border-box\">\n <a routerLink=\"/dashboard\" style=\"display:flex;align-items:center;gap:0.75rem;color:inherit;text-decoration:none\">\n <span aria-hidden=\"true\" style=\"display:inline-block;width:0.5rem;height:2.25rem;background:#fff\"></span>\n <span style=\"font-weight:700;line-height:1.1\">\n Rijksoverheid<br><span style=\"font-weight:400;font-size:0.9rem\">BIG-register</span>\n </span>\n </a>\n <span style=\"margin-left:auto;font-weight:500\">{{ subtitle() }}</span>\n </div>\n</header>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [
{
"name": "subtitle",
"defaultValue": "'Mijn omgeving'",
"deprecated": false,
"deprecationMessage": "",
"indexKey": "",
"optional": false,
"description": "",
"line": 27,
"required": false
}
],
"outputsClass": [],
"propertiesClass": [],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [
{
"name": "RouterLink"
}
],
"description": "<p>Organism: site header with Rijksoverheid-style wordmark + title.\nponytail: text wordmark instead of the licensed Rijksoverheid logo.</p>\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: [':host{display:block}'],\n template: `\n <header class=\"utrecht-page-header\" style=\"background:var(--rhc-color-lintblauw-700,#154273);color:#fff;width:100%\">\n <div style=\"display:flex;align-items:center;gap:1rem;max-width:var(--app-content-max);margin:0 auto;padding:1rem 1.5rem;box-sizing:border-box\">\n <a routerLink=\"/dashboard\" style=\"display:flex;align-items:center;gap:0.75rem;color:inherit;text-decoration:none\">\n <span aria-hidden=\"true\" style=\"display:inline-block;width:0.5rem;height:2.25rem;background:#fff\"></span>\n <span style=\"font-weight:700;line-height:1.1\">\n Rijksoverheid<br><span style=\"font-weight:400;font-size:0.9rem\">BIG-register</span>\n </span>\n </a>\n <span style=\"margin-left:auto;font-weight:500\">{{ subtitle() }}</span>\n </div>\n </header>\n `,\n})\nexport class SiteHeaderComponent {\n subtitle = input('Mijn omgeving');\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": ":host{display:block}\n",
"extends": []
},
{
"name": "SkeletonComponent",
"id": "component-SkeletonComponent-608d7384a7cd5705153c042fd961a63d69e4f61409276c2aec354b33db4199192d161fa81305090c262e18ab0a019913f469e85603ccefa6fba5c0dbc40d4f72",
"file": "src/app/shared/ui/skeleton/skeleton.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-skeleton",
"styleUrls": [],
"styles": [
"\n :host{display:block}\n .sk{background:linear-gradient(90deg,#e8ebee 25%,#f3f5f6 37%,#e8ebee 63%);\n background-size:400% 100%;animation:sh 1.4s ease infinite;border-radius:4px;\n margin-block-end:0.6rem}\n @keyframes sh{0%{background-position:100% 0}100%{background-position:0 0}}\n "
],
"template": "@if (visible()) {\n @for (l of lines(); track $index) {\n <div class=\"sk\" [style.width]=\"width()\" [style.height]=\"height()\"></div>\n }\n}\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [
{
"name": "count",
"defaultValue": "1",
"deprecated": false,
"deprecationMessage": "",
"indexKey": "",
"optional": false,
"description": "",
"line": 25,
"required": false
},
{
"name": "delay",
"defaultValue": "150",
"deprecated": false,
"deprecationMessage": "",
"indexKey": "",
"optional": false,
"description": "",
"line": 26,
"required": false
},
{
"name": "height",
"defaultValue": "'1rem'",
"deprecated": false,
"deprecationMessage": "",
"indexKey": "",
"optional": false,
"description": "",
"line": 24,
"required": false
},
{
"name": "width",
"defaultValue": "'100%'",
"deprecated": false,
"deprecationMessage": "",
"indexKey": "",
"optional": false,
"description": "",
"line": 23,
"required": false
}
],
"outputsClass": [],
"propertiesClass": [
{
"name": "lines",
"defaultValue": "computed(() => Array(this.count()).fill(0))",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 28,
"modifierKind": [
124
]
},
{
"name": "timer",
"deprecated": false,
"deprecationMessage": "",
"type": "ReturnType<unknown>",
"indexKey": "",
"optional": true,
"description": "",
"line": 29,
"modifierKind": [
123
]
},
{
"name": "visible",
"defaultValue": "signal(false)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 27,
"modifierKind": [
124
]
}
],
"methodsClass": [
{
"name": "ngOnDestroy",
"args": [],
"optional": false,
"returnType": "void",
"typeParameters": [],
"line": 32,
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "ngOnInit",
"args": [],
"optional": false,
"returnType": "void",
"typeParameters": [],
"line": 31,
"deprecated": false,
"deprecationMessage": ""
}
],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [],
"description": "<p>Atom: skeleton placeholder (grey shimmer). Delay-gated so it never flashes\non fast responses. Render <code>count</code> lines shaped roughly like the content.</p>\n",
"rawdescription": "\nAtom: skeleton placeholder (grey shimmer). Delay-gated so it never flashes\non fast responses. Render `count` lines shaped roughly like the content.",
"type": "component",
"sourceCode": "import { Component, OnDestroy, OnInit, computed, input, signal } from '@angular/core';\n\n/** Atom: skeleton placeholder (grey shimmer). Delay-gated so it never flashes\n on fast responses. Render `count` lines shaped roughly like the content. */\n@Component({\n selector: 'app-skeleton',\n styles: [`\n :host{display:block}\n .sk{background:linear-gradient(90deg,#e8ebee 25%,#f3f5f6 37%,#e8ebee 63%);\n background-size:400% 100%;animation:sh 1.4s ease infinite;border-radius:4px;\n margin-block-end:0.6rem}\n @keyframes sh{0%{background-position:100% 0}100%{background-position:0 0}}\n `],\n template: `\n @if (visible()) {\n @for (l of lines(); track $index) {\n <div class=\"sk\" [style.width]=\"width()\" [style.height]=\"height()\"></div>\n }\n }\n `,\n})\nexport class SkeletonComponent implements OnInit, OnDestroy {\n width = input('100%');\n height = input('1rem');\n count = input(1);\n delay = input(150);\n protected visible = signal(false);\n protected lines = computed(() => Array(this.count()).fill(0));\n private timer?: ReturnType<typeof setTimeout>;\n\n ngOnInit() { this.timer = setTimeout(() => this.visible.set(true), this.delay()); }\n ngOnDestroy() { clearTimeout(this.timer); }\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "\n :host{display:block}\n .sk{background:linear-gradient(90deg,#e8ebee 25%,#f3f5f6 37%,#e8ebee 63%);\n background-size:400% 100%;animation:sh 1.4s ease infinite;border-radius:4px;\n margin-block-end:0.6rem}\n @keyframes sh{0%{background-position:100% 0}100%{background-position:0 0}}\n \n",
"extends": [],
"implements": [
"OnInit",
"OnDestroy"
]
},
{
"name": "SpinnerComponent",
"id": "component-SpinnerComponent-4ac83777af1737425f1eec0d4c22a830297cca57c3140ef014842789163b2c2873312a9ae4e9dc7554241ac3b3dc339b7bab22e02fd8a4fe748a985264126ca4",
"file": "src/app/shared/ui/spinner/spinner.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-spinner",
"styleUrls": [],
"styles": [
"\n :host{display:block}\n .sp{width:2rem;height:2rem;border-radius:50%;\n border:3px solid var(--rhc-color-grijs-300,#cad0d6);\n border-block-start-color:var(--rhc-color-lintblauw-700,#154273);\n animation:sp 0.8s linear infinite;margin:1.5rem auto}\n @keyframes sp{to{transform:rotate(360deg)}}\n "
],
"template": "@if (visible()) {\n <div class=\"sp\" role=\"status\" aria-label=\"Bezig met laden\"></div>\n}\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [
{
"name": "delay",
"defaultValue": "250",
"deprecated": false,
"deprecationMessage": "",
"indexKey": "",
"optional": false,
"description": "",
"line": 22,
"required": false
}
],
"outputsClass": [],
"propertiesClass": [
{
"name": "timer",
"deprecated": false,
"deprecationMessage": "",
"type": "ReturnType<unknown>",
"indexKey": "",
"optional": true,
"description": "",
"line": 24,
"modifierKind": [
123
]
},
{
"name": "visible",
"defaultValue": "signal(false)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 23,
"modifierKind": [
124
]
}
],
"methodsClass": [
{
"name": "ngOnDestroy",
"args": [],
"optional": false,
"returnType": "void",
"typeParameters": [],
"line": 27,
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "ngOnInit",
"args": [],
"optional": false,
"returnType": "void",
"typeParameters": [],
"line": 26,
"deprecated": false,
"deprecationMessage": ""
}
],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [],
"description": "<p>Atom: spinner that only appears after <code>delay</code> ms — fast responses never\nflash a spinner, slow ones get feedback.</p>\n",
"rawdescription": "\nAtom: spinner that only appears after `delay` ms — fast responses never\nflash a spinner, slow ones get feedback.",
"type": "component",
"sourceCode": "import { Component, OnDestroy, OnInit, input, signal } from '@angular/core';\n\n/** Atom: spinner that only appears after `delay` ms — fast responses never\n flash a spinner, slow ones get feedback. */\n@Component({\n selector: 'app-spinner',\n styles: [`\n :host{display:block}\n .sp{width:2rem;height:2rem;border-radius:50%;\n border:3px solid var(--rhc-color-grijs-300,#cad0d6);\n border-block-start-color:var(--rhc-color-lintblauw-700,#154273);\n animation:sp 0.8s linear infinite;margin:1.5rem auto}\n @keyframes sp{to{transform:rotate(360deg)}}\n `],\n template: `\n @if (visible()) {\n <div class=\"sp\" role=\"status\" aria-label=\"Bezig met laden\"></div>\n }\n `,\n})\nexport class SpinnerComponent implements OnInit, OnDestroy {\n delay = input(250);\n protected visible = signal(false);\n private timer?: ReturnType<typeof setTimeout>;\n\n ngOnInit() { this.timer = setTimeout(() => this.visible.set(true), this.delay()); }\n ngOnDestroy() { clearTimeout(this.timer); }\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "\n :host{display:block}\n .sp{width:2rem;height:2rem;border-radius:50%;\n border:3px solid var(--rhc-color-grijs-300,#cad0d6);\n border-block-start-color:var(--rhc-color-lintblauw-700,#154273);\n animation:sp 0.8s linear infinite;margin:1.5rem auto}\n @keyframes sp{to{transform:rotate(360deg)}}\n \n",
"extends": [],
"implements": [
"OnInit",
"OnDestroy"
]
},
{
"name": "StatusBadgeComponent",
"id": "component-StatusBadgeComponent-4f1df6eb29e4abe21602ed3d03fe37881d253c2a9653306c7c95978022565da00b7c482db530f0eea482adf500359371cc588e7abcc8378d7e422cd7a18f00ad",
"file": "src/app/shared/ui/status-badge/status-badge.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-status-badge",
"styleUrls": [],
"styles": [],
"template": "<span style=\"display:inline-flex;align-items:center;gap:0.5rem\">\n <span class=\"rhc-dot-badge\" [style.background-color]=\"color()\" aria-hidden=\"true\"></span>\n <span>{{ label() }}</span>\n</span>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [
{
"name": "color",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 17,
"required": true
},
{
"name": "label",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 16,
"required": true
}
],
"outputsClass": [],
"propertiesClass": [],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [],
"description": "<p>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.</p>\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 template: `\n <span style=\"display:inline-flex;align-items:center;gap:0.5rem\">\n <span class=\"rhc-dot-badge\" [style.background-color]=\"color()\" aria-hidden=\"true\"></span>\n <span>{{ label() }}</span>\n </span>\n `,\n})\nexport class StatusBadgeComponent {\n label = input.required<string>();\n color = input.required<string>();\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "TextInputComponent",
"id": "component-TextInputComponent-9d0cd6c2d7892958e9a016b570670f0186d410ea16a22925126f9eeea1aa178f081a4e5647af633f8a0bc1c458422a9f30169f159f930e9048702995fbb827e6",
"file": "src/app/shared/ui/text-input/text-input.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [
{
"name": ")"
}
],
"selector": "app-text-input",
"styleUrls": [],
"styles": [],
"template": "<input\n class=\"utrecht-textbox rhc-text-input\"\n [class.utrecht-textbox--invalid]=\"invalid()\"\n [type]=\"type()\"\n [id]=\"inputId()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled\"\n [value]=\"value\"\n (input)=\"onInput($event)\"\n (blur)=\"onTouched()\" />\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [
{
"name": "inputId",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 25,
"required": false
},
{
"name": "invalid",
"defaultValue": "false",
"deprecated": false,
"deprecationMessage": "",
"indexKey": "",
"optional": false,
"description": "",
"line": 24,
"required": false
},
{
"name": "placeholder",
"defaultValue": "''",
"deprecated": false,
"deprecationMessage": "",
"indexKey": "",
"optional": false,
"description": "",
"line": 23,
"required": false
},
{
"name": "type",
"defaultValue": "'text'",
"deprecated": false,
"deprecationMessage": "",
"type": "\"text\" | \"password\" | \"email\"",
"indexKey": "",
"optional": false,
"description": "",
"line": 22,
"required": false
}
],
"outputsClass": [],
"propertiesClass": [
{
"name": "disabled",
"defaultValue": "false",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 28
},
{
"name": "onChange",
"defaultValue": "() => {...}",
"deprecated": false,
"deprecationMessage": "",
"type": "function",
"indexKey": "",
"optional": false,
"description": "",
"line": 29
},
{
"name": "onTouched",
"defaultValue": "() => {...}",
"deprecated": false,
"deprecationMessage": "",
"type": "function",
"indexKey": "",
"optional": false,
"description": "",
"line": 30
},
{
"name": "value",
"defaultValue": "''",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 27
}
],
"methodsClass": [
{
"name": "onInput",
"args": [
{
"name": "e",
"type": "Event",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": ""
}
],
"optional": false,
"returnType": "void",
"typeParameters": [],
"line": 32,
"deprecated": false,
"deprecationMessage": "",
"jsdoctags": [
{
"name": "e",
"type": "Event",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "registerOnChange",
"args": [
{
"name": "fn",
"type": "function",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": "",
"function": [
{
"name": "v",
"type": "string",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": ""
}
]
}
],
"optional": false,
"returnType": "void",
"typeParameters": [],
"line": 37,
"deprecated": false,
"deprecationMessage": "",
"jsdoctags": [
{
"name": "fn",
"type": "function",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": "",
"function": [
{
"name": "v",
"type": "string",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": ""
}
],
"tagName": {
"text": "param"
}
}
]
},
{
"name": "registerOnTouched",
"args": [
{
"name": "fn",
"type": "function",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": "",
"function": []
}
],
"optional": false,
"returnType": "void",
"typeParameters": [],
"line": 38,
"deprecated": false,
"deprecationMessage": "",
"jsdoctags": [
{
"name": "fn",
"type": "function",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": "",
"function": [],
"tagName": {
"text": "param"
}
}
]
},
{
"name": "setDisabledState",
"args": [
{
"name": "d",
"type": "boolean",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": ""
}
],
"optional": false,
"returnType": "void",
"typeParameters": [],
"line": 39,
"deprecated": false,
"deprecationMessage": "",
"jsdoctags": [
{
"name": "d",
"type": "boolean",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "writeValue",
"args": [
{
"name": "v",
"type": "string",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": ""
}
],
"optional": false,
"returnType": "void",
"typeParameters": [],
"line": 36,
"deprecated": false,
"deprecationMessage": "",
"jsdoctags": [
{
"name": "v",
"type": "string",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
}
],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [],
"description": "<p>Atom: text input. Utrecht textbox wired up as a form control (ngModel/reactive).</p>\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 <input\n class=\"utrecht-textbox rhc-text-input\"\n [class.utrecht-textbox--invalid]=\"invalid()\"\n [type]=\"type()\"\n [id]=\"inputId()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled\"\n [value]=\"value\"\n (input)=\"onInput($event)\"\n (blur)=\"onTouched()\" />\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 = input<string>();\n\n value = '';\n disabled = false;\n onChange: (v: string) => void = () => {};\n onTouched: () => void = () => {};\n\n onInput(e: Event) {\n this.value = (e.target as HTMLInputElement).value;\n this.onChange(this.value);\n }\n writeValue(v: string) { this.value = v ?? ''; }\n registerOnChange(fn: (v: string) => void) { this.onChange = fn; }\n registerOnTouched(fn: () => void) { this.onTouched = fn; }\n setDisabledState(d: boolean) { this.disabled = d; }\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": [],
"implements": [
"ControlValueAccessor"
]
}
],
"modules": [],
"miscellaneous": {
"variables": [
{
"name": "appConfig",
"ctype": "miscellaneous",
"subtype": "variable",
"file": "src/app/app.config.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "ApplicationConfig",
"defaultValue": "{\n providers: [\n provideBrowserGlobalErrorListeners(),\n provideRouter(routes, withViewTransitions()),\n provideHttpClient(withInterceptors([scenarioInterceptor])),\n { provide: LOCALE_ID, useValue: 'nl' },\n ]\n}"
},
{
"name": "ASYNC",
"ctype": "miscellaneous",
"subtype": "variable",
"file": "src/app/shared/ui/async/async.component.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"defaultValue": "[\n AsyncComponent, AsyncLoadedDirective, AsyncLoadingDirective,\n AsyncEmptyDirective, AsyncErrorDirective,\n] as const",
"rawdescription": "Convenience: import this array to get the wrapper + all slot directives.",
"description": "<p>Convenience: import this array to get the wrapper + all slot directives.</p>\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": "<p>Route guard: only let authenticated users in; otherwise redirect to /login.</p>\n"
},
{
"name": "err",
"ctype": "miscellaneous",
"subtype": "variable",
"file": "src/app/shared/kernel/fp.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"defaultValue": "<E>(error: E): Result<E, never> => ({ ok: false, error })"
},
{
"name": "initial",
"ctype": "miscellaneous",
"subtype": "variable",
"file": "src/app/herregistratie/domain/herregistratie.machine.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "WizardState",
"defaultValue": "{ tag: 'Editing', step: 1, draft: { uren: '', punten: '' }, errors: {} }"
},
{
"name": "ok",
"ctype": "miscellaneous",
"subtype": "variable",
"file": "src/app/shared/kernel/fp.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"defaultValue": "<T>(value: T): Result<never, T> => ({ ok: true, value })"
},
{
"name": "routes",
"ctype": "miscellaneous",
"subtype": "variable",
"file": "src/app/app.routes.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "Routes",
"defaultValue": "[\n {\n path: '',\n component: ShellComponent, // persistent header/footer; only children swap\n children: [\n { path: '', pathMatch: 'full', redirectTo: 'login' },\n { path: 'login', loadComponent: () => \"import('@auth/ui/login.page').then(m => m.LoginPage)\" },\n { path: 'dashboard', canActivate: [authGuard], loadComponent: () => \"import('@registratie/ui/dashboard.page').then(m => m.DashboardPage)\" },\n { path: 'registratie', canActivate: [authGuard], loadComponent: () => \"import('@registratie/ui/registration-detail.page').then(m => m.RegistrationDetailPage)\" },\n { path: 'herregistratie', canActivate: [authGuard], loadComponent: () => \"import('@herregistratie/ui/herregistratie.page').then(m => m.HerregistratiePage)\" },\n { path: 'concepts', loadComponent: () => \"import('./showcase/concepts.page').then(m => m.ConceptsPage)\" },\n { path: '**', redirectTo: 'login' },\n ],\n },\n]"
},
{
"name": "scenarioInterceptor",
"ctype": "miscellaneous",
"subtype": "variable",
"file": "src/app/shared/infrastructure/scenario.interceptor.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "HttpInterceptorFn",
"defaultValue": "(req, next) => {\n if (!req.url.includes('mock/')) return next(req);\n\n switch (currentScenario()) {\n case 'slow':\n return next(req).pipe(delay(2500));\n case 'loading':\n return next(req).pipe(delay(600_000)); // effectively never resolves\n case 'empty':\n return of(new HttpResponse({ status: 200, body: [] })).pipe(delay(400));\n case 'error':\n return timer(400).pipe(\n switchMap(() => throwError(() =>\n new HttpErrorResponse({ status: 500, statusText: 'Demo-fout', url: req.url }))),\n );\n default:\n return next(req);\n }\n}",
"rawdescription": "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.",
"description": "<p>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.</p>\n"
},
{
"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": "<p>Chain a second source that depends on the first one&#39;s value.</p>\n",
"args": [
{
"name": "rd",
"type": "RemoteData",
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "f",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "RemoteData<E, B>",
"jsdoctags": [
{
"name": "rd",
"type": "RemoteData",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
},
{
"name": "f",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "assertNever",
"file": "src/app/shared/kernel/fp.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Tiny native-TS functional toolkit. No dependency — this is the whole &quot;library&quot;.\nReused by every &quot;impossible states&quot; concept in the POC.</p>\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": "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": "Store<Model, Msg>",
"jsdoctags": [
{
"name": "init",
"type": "Model",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
},
{
"name": "update",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "currentScenario",
"file": "src/app/shared/infrastructure/scenario.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Reads ?scenario= from the URL so a demo can force each async state.</p>\n",
"args": [],
"returnType": "Scenario"
},
{
"name": "fakeResource",
"file": "src/app/showcase/concepts.page.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Minimal fake Resource so <app-async> can be driven through every state without HTTP.</p>\n",
"args": [
{
"name": "status",
"type": "string",
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "value",
"type": "T",
"deprecated": false,
"deprecationMessage": "",
"optional": true
},
{
"name": "error",
"type": "Error",
"deprecated": false,
"deprecationMessage": "",
"optional": true
}
],
"returnType": "Resource<T>",
"jsdoctags": [
{
"name": "status",
"type": "string",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
},
{
"name": "value",
"type": "T",
"deprecated": false,
"deprecationMessage": "",
"optional": true,
"tagName": {
"text": "param"
}
},
{
"name": "error",
"type": "Error",
"deprecated": false,
"deprecationMessage": "",
"optional": true,
"tagName": {
"text": "param"
}
}
]
},
{
"name": "foldRemote",
"file": "src/app/shared/application/remote-data.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Exhaustive fold: you must handle every case, checked at compile time.</p>\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": "<p>Project Angular&#39;s loosely-typed Resource into a RemoteData value.</p>\n",
"args": [
{
"name": "r",
"type": "Resource",
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "isEmpty",
"deprecated": false,
"deprecationMessage": "",
"defaultValue": "() => false"
}
],
"returnType": "RemoteData<Error | undefined, T>",
"jsdoctags": [
{
"name": "r",
"type": "Resource",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
},
{
"name": "isEmpty",
"deprecated": false,
"deprecationMessage": "",
"defaultValue": "() => false",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "herregistratieDeadline",
"file": "src/app/registratie/domain/registration.policy.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>The herregistratie deadline, if the status has one (only the active state does).</p>\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": "<p>A registration may apply for herregistratie only while active and within the\nwindow before its deadline. A struck-off or suspended registration may not.</p>\n",
"args": [
{
"name": "reg",
"type": "Registration",
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "today",
"type": "Date",
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "windowMonths",
"type": "number",
"deprecated": false,
"deprecationMessage": "",
"defaultValue": "12"
}
],
"returnType": "boolean",
"jsdoctags": [
{
"name": "reg",
"type": "Registration",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
},
{
"name": "today",
"type": "Date",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
},
{
"name": "windowMonths",
"type": "number",
"deprecated": false,
"deprecationMessage": "",
"defaultValue": "12",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "isStatusConsistent",
"file": "src/app/registratie/domain/registration.policy.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>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.</p>\n",
"args": [
{
"name": "status",
"type": "RegistrationStatus",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "boolean",
"jsdoctags": [
{
"name": "status",
"type": "RegistrationStatus",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "map",
"file": "src/app/shared/application/remote-data.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Transform the value inside a Success; pass other states through unchanged.</p>\n",
"args": [
{
"name": "rd",
"type": "RemoteData",
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "f",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "RemoteData<E, B>",
"jsdoctags": [
{
"name": "rd",
"type": "RemoteData",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
},
{
"name": "f",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "map2",
"file": "src/app/shared/application/remote-data.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Combine 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.</p>\n",
"args": [
{
"name": "a",
"type": "RemoteData",
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "b",
"type": "RemoteData",
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "f",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "RemoteData<E, R>",
"jsdoctags": [
{
"name": "a",
"type": "RemoteData",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
},
{
"name": "b",
"type": "RemoteData",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
},
{
"name": "f",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "map3",
"file": "src/app/shared/application/remote-data.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Combine three sources (built on map2).</p>\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": "RemoteData<E, R>",
"jsdoctags": [
{
"name": "a",
"type": "RemoteData",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
},
{
"name": "b",
"type": "RemoteData",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
},
{
"name": "c",
"type": "RemoteData",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
},
{
"name": "f",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "next",
"file": "src/app/herregistratie/domain/herregistratie.machine.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Step 1 → 2: only advance if the uren field parses. Illegal elsewhere = no-op.</p>\n",
"args": [
{
"name": "s",
"type": "WizardState",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "WizardState",
"jsdoctags": [
{
"name": "s",
"type": "WizardState",
"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": "Result<string, BigNummer>",
"jsdoctags": [
{
"name": "raw",
"type": "string",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "parsePostcode",
"file": "src/app/registratie/domain/value-objects/postcode.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "",
"args": [
{
"name": "raw",
"type": "string",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "Result<string, Postcode>",
"jsdoctags": [
{
"name": "raw",
"type": "string",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "parseUren",
"file": "src/app/registratie/domain/value-objects/uren.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "",
"args": [
{
"name": "raw",
"type": "string",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "Result<string, Uren>",
"jsdoctags": [
{
"name": "raw",
"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": "resolve",
"file": "src/app/herregistratie/domain/herregistratie.machine.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Resolve the async submit. Only meaningful while Submitting.</p>\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": "setField",
"file": "src/app/herregistratie/domain/herregistratie.machine.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Update one draft field while editing; ignored in any other state.</p>\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": "statusColor",
"file": "src/app/registratie/domain/registration.policy.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Brand colour token for a status. assertNever forces a colour for every new\nstatus variant at compile time.</p>\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": "<p>Domain logic for a registration — pure functions, NO Angular. This is where\n&quot;what the business rules say&quot; lives, separate from &quot;how it looks&quot; (UI) and\n&quot;where the data comes from&quot; (infrastructure). Keeping it framework-free means\nit is trivial to read and unit-test.</p>\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": "<p>Step 2 submit: parse everything; move to Submitting only with Valid data.</p>\n",
"args": [
{
"name": "s",
"type": "WizardState",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "WizardState",
"jsdoctags": [
{
"name": "s",
"type": "WizardState",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "submitHerregistratie",
"file": "src/app/herregistratie/application/submit-herregistratie.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>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&#39;s\nan API. The &quot;uren must be &gt; 0&quot; rule lets the demo show a failure path.</p>\n",
"args": [
{
"name": "data",
"type": "Valid",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "Promise<Result<string, void>>",
"jsdoctags": [
{
"name": "data",
"type": "Valid",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "validate",
"file": "src/app/herregistratie/domain/herregistratie.machine.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Parse every field; on success hand back a Valid, else the per-field errors.</p>\n",
"args": [
{
"name": "draft",
"type": "Draft",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "Result<Partial<Record<Draft, string>>, Valid>",
"jsdoctags": [
{
"name": "draft",
"type": "Draft",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
}
],
"typealiases": [
{
"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": "Brand<string | BigNummer>",
"file": "src/app/registratie/domain/value-objects/big-nummer.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Value object: a BIG registration number — 11 digits.</p>\n",
"kind": 184
},
{
"name": "Brand",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "unknown",
"file": "src/app/shared/kernel/fp.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Nominal typing: Brand&lt;string, &#39;Postcode&#39;&gt; is assignable from a plain string\nonly through an explicit cast — so a smart constructor is the only minter.</p>\n",
"kind": 194
},
{
"name": "Err",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "Error | undefined",
"file": "src/app/registratie/application/big-profile.store.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "",
"kind": 193
},
{
"name": "Postcode",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "Brand<string | Postcode>",
"file": "src/app/registratie/domain/value-objects/postcode.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Value object: a Dutch postcode. &quot;Parse, don&#39;t validate&quot; — a Postcode is a\ndistinct type from a raw string, mintable only via parsePostcode, so holding\none is proof it is well-formed.</p>\n",
"kind": 184
},
{
"name": "RegistrationStatus",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "literal type | literal type | literal type",
"file": "src/app/registratie/domain/registration.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Registration status as a discriminated union: each variant owns exactly the\ndata that makes sense for it. Only an active (Geregistreerd) registration has\na herregistratie date; a struck-off (Doorgehaald) one cannot carry one. The\nold flat interface allowed that impossible combination — this makes it\nunrepresentable.</p>\n",
"kind": 193
},
{
"name": "RemoteData",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "literal type | literal type | literal type | literal type",
"file": "src/app/shared/application/remote-data.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>The four mutually-exclusive states of an async fetch, as a tagged union.\nCrucially the data lives ON the state: only <code>Failure</code> has an <code>error</code>, only\n<code>Success</code> has a <code>value</code>. &quot;Loaded but no value&quot; or &quot;error with stale value&quot;\nare unrepresentable — Richard Feldman&#39;s RemoteData.</p>\n",
"kind": 193
},
{
"name": "Result",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "literal type | literal type",
"file": "src/app/shared/kernel/fp.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>A computation that either succeeded with a value or failed with an error.\nPlain objects (no classes) to match the signal/httpResource ergonomics.</p>\n",
"kind": 193
},
{
"name": "Scenario",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "\"default\" | \"slow\" | \"loading\" | \"empty\" | \"error\"",
"file": "src/app/shared/infrastructure/scenario.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "",
"kind": 193
},
{
"name": "StatusTag",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "RegistrationStatus",
"file": "src/app/registratie/domain/registration.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Just the discriminant — for atoms that only need the label/color.</p>\n",
"kind": 200
},
{
"name": "Uren",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "Brand<number | Uren>",
"file": "src/app/registratie/domain/value-objects/uren.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Value object: a non-negative whole number of hours.</p>\n",
"kind": 184
},
{
"name": "Variant",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "\"primary\" | \"secondary\" | \"subtle\" | \"danger\"",
"file": "src/app/shared/ui/button/button.component.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "",
"kind": 193
},
{
"name": "WizardMsg",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "literal type | literal type | literal type | literal type | literal type | literal type | literal type | literal type",
"file": "src/app/herregistratie/domain/herregistratie.machine.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Every event that can happen to the wizard, as one message type. The component\nsends a WizardMsg; <code>reduce</code> decides the next state. This is the Elm\nModel+Msg+update pattern: ONE pure function describes all state changes.</p>\n",
"kind": 193
},
{
"name": "WizardState",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "literal type | literal type | literal type | literal type",
"file": "src/app/herregistratie/domain/herregistratie.machine.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>The whole wizard as one tagged union. <code>step</code> and <code>errors</code> exist ONLY while\nEditing; Submitting/Submitted/Failed carry a <code>Valid</code> payload and nothing else.\nSo &quot;submitting while a field is invalid&quot; or &quot;showing the success screen with\nerrors set&quot; are unrepresentable — the bug class is gone by construction.</p>\n",
"kind": 193
}
],
"enumerations": [],
"groupedVariables": {
"src/app/app.config.ts": [
{
"name": "appConfig",
"ctype": "miscellaneous",
"subtype": "variable",
"file": "src/app/app.config.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "ApplicationConfig",
"defaultValue": "{\n providers: [\n provideBrowserGlobalErrorListeners(),\n provideRouter(routes, withViewTransitions()),\n provideHttpClient(withInterceptors([scenarioInterceptor])),\n { provide: LOCALE_ID, useValue: 'nl' },\n ]\n}"
}
],
"src/app/shared/ui/async/async.component.ts": [
{
"name": "ASYNC",
"ctype": "miscellaneous",
"subtype": "variable",
"file": "src/app/shared/ui/async/async.component.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"defaultValue": "[\n AsyncComponent, AsyncLoadedDirective, AsyncLoadingDirective,\n AsyncEmptyDirective, AsyncErrorDirective,\n] as const",
"rawdescription": "Convenience: import this array to get the wrapper + all slot directives.",
"description": "<p>Convenience: import this array to get the wrapper + all slot directives.</p>\n"
}
],
"src/app/auth/auth.guard.ts": [
{
"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": "<p>Route guard: only let authenticated users in; otherwise redirect to /login.</p>\n"
}
],
"src/app/shared/kernel/fp.ts": [
{
"name": "err",
"ctype": "miscellaneous",
"subtype": "variable",
"file": "src/app/shared/kernel/fp.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"defaultValue": "<E>(error: E): Result<E, never> => ({ ok: false, error })"
},
{
"name": "ok",
"ctype": "miscellaneous",
"subtype": "variable",
"file": "src/app/shared/kernel/fp.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"defaultValue": "<T>(value: T): Result<never, T> => ({ ok: true, value })"
}
],
"src/app/herregistratie/domain/herregistratie.machine.ts": [
{
"name": "initial",
"ctype": "miscellaneous",
"subtype": "variable",
"file": "src/app/herregistratie/domain/herregistratie.machine.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "WizardState",
"defaultValue": "{ tag: 'Editing', step: 1, draft: { uren: '', punten: '' }, errors: {} }"
}
],
"src/app/app.routes.ts": [
{
"name": "routes",
"ctype": "miscellaneous",
"subtype": "variable",
"file": "src/app/app.routes.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "Routes",
"defaultValue": "[\n {\n path: '',\n component: ShellComponent, // persistent header/footer; only children swap\n children: [\n { path: '', pathMatch: 'full', redirectTo: 'login' },\n { path: 'login', loadComponent: () => \"import('@auth/ui/login.page').then(m => m.LoginPage)\" },\n { path: 'dashboard', canActivate: [authGuard], loadComponent: () => \"import('@registratie/ui/dashboard.page').then(m => m.DashboardPage)\" },\n { path: 'registratie', canActivate: [authGuard], loadComponent: () => \"import('@registratie/ui/registration-detail.page').then(m => m.RegistrationDetailPage)\" },\n { path: 'herregistratie', canActivate: [authGuard], loadComponent: () => \"import('@herregistratie/ui/herregistratie.page').then(m => m.HerregistratiePage)\" },\n { path: 'concepts', loadComponent: () => \"import('./showcase/concepts.page').then(m => m.ConceptsPage)\" },\n { path: '**', redirectTo: 'login' },\n ],\n },\n]"
}
],
"src/app/shared/infrastructure/scenario.interceptor.ts": [
{
"name": "scenarioInterceptor",
"ctype": "miscellaneous",
"subtype": "variable",
"file": "src/app/shared/infrastructure/scenario.interceptor.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "HttpInterceptorFn",
"defaultValue": "(req, next) => {\n if (!req.url.includes('mock/')) return next(req);\n\n switch (currentScenario()) {\n case 'slow':\n return next(req).pipe(delay(2500));\n case 'loading':\n return next(req).pipe(delay(600_000)); // effectively never resolves\n case 'empty':\n return of(new HttpResponse({ status: 200, body: [] })).pipe(delay(400));\n case 'error':\n return timer(400).pipe(\n switchMap(() => throwError(() =>\n new HttpErrorResponse({ status: 500, statusText: 'Demo-fout', url: req.url }))),\n );\n default:\n return next(req);\n }\n}",
"rawdescription": "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.",
"description": "<p>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.</p>\n"
}
],
"src/app/shared/infrastructure/scenario.ts": [
{
"name": "VALID",
"ctype": "miscellaneous",
"subtype": "variable",
"file": "src/app/shared/infrastructure/scenario.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "Scenario[]",
"defaultValue": "['default', 'slow', 'loading', 'empty', 'error']"
}
]
},
"groupedFunctions": {
"src/app/shared/application/remote-data.ts": [
{
"name": "andThen",
"file": "src/app/shared/application/remote-data.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Chain a second source that depends on the first one&#39;s value.</p>\n",
"args": [
{
"name": "rd",
"type": "RemoteData",
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "f",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "RemoteData<E, B>",
"jsdoctags": [
{
"name": "rd",
"type": "RemoteData",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
},
{
"name": "f",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "foldRemote",
"file": "src/app/shared/application/remote-data.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Exhaustive fold: you must handle every case, checked at compile time.</p>\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": "<p>Project Angular&#39;s loosely-typed Resource into a RemoteData value.</p>\n",
"args": [
{
"name": "r",
"type": "Resource",
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "isEmpty",
"deprecated": false,
"deprecationMessage": "",
"defaultValue": "() => false"
}
],
"returnType": "RemoteData<Error | undefined, T>",
"jsdoctags": [
{
"name": "r",
"type": "Resource",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
},
{
"name": "isEmpty",
"deprecated": false,
"deprecationMessage": "",
"defaultValue": "() => false",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "map",
"file": "src/app/shared/application/remote-data.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Transform the value inside a Success; pass other states through unchanged.</p>\n",
"args": [
{
"name": "rd",
"type": "RemoteData",
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "f",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "RemoteData<E, B>",
"jsdoctags": [
{
"name": "rd",
"type": "RemoteData",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
},
{
"name": "f",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "map2",
"file": "src/app/shared/application/remote-data.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Combine 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.</p>\n",
"args": [
{
"name": "a",
"type": "RemoteData",
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "b",
"type": "RemoteData",
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "f",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "RemoteData<E, R>",
"jsdoctags": [
{
"name": "a",
"type": "RemoteData",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
},
{
"name": "b",
"type": "RemoteData",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
},
{
"name": "f",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "map3",
"file": "src/app/shared/application/remote-data.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Combine three sources (built on map2).</p>\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": "RemoteData<E, R>",
"jsdoctags": [
{
"name": "a",
"type": "RemoteData",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
},
{
"name": "b",
"type": "RemoteData",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
},
{
"name": "c",
"type": "RemoteData",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
},
{
"name": "f",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
}
],
"src/app/shared/kernel/fp.ts": [
{
"name": "assertNever",
"file": "src/app/shared/kernel/fp.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Tiny native-TS functional toolkit. No dependency — this is the whole &quot;library&quot;.\nReused by every &quot;impossible states&quot; concept in the POC.</p>\n",
"args": [
{
"name": "x",
"type": "never",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "never",
"jsdoctags": [
{
"name": "x",
"type": "never",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
}
],
"src/app/herregistratie/domain/herregistratie.machine.ts": [
{
"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": "next",
"file": "src/app/herregistratie/domain/herregistratie.machine.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Step 1 → 2: only advance if the uren field parses. Illegal elsewhere = no-op.</p>\n",
"args": [
{
"name": "s",
"type": "WizardState",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "WizardState",
"jsdoctags": [
{
"name": "s",
"type": "WizardState",
"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": "resolve",
"file": "src/app/herregistratie/domain/herregistratie.machine.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Resolve the async submit. Only meaningful while Submitting.</p>\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": "setField",
"file": "src/app/herregistratie/domain/herregistratie.machine.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Update one draft field while editing; ignored in any other state.</p>\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": "submit",
"file": "src/app/herregistratie/domain/herregistratie.machine.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Step 2 submit: parse everything; move to Submitting only with Valid data.</p>\n",
"args": [
{
"name": "s",
"type": "WizardState",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "WizardState",
"jsdoctags": [
{
"name": "s",
"type": "WizardState",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "validate",
"file": "src/app/herregistratie/domain/herregistratie.machine.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Parse every field; on success hand back a Valid, else the per-field errors.</p>\n",
"args": [
{
"name": "draft",
"type": "Draft",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "Result<Partial<Record<Draft, string>>, Valid>",
"jsdoctags": [
{
"name": "draft",
"type": "Draft",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
}
],
"src/app/shared/application/store.ts": [
{
"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": "Store<Model, Msg>",
"jsdoctags": [
{
"name": "init",
"type": "Model",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
},
{
"name": "update",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
}
],
"src/app/shared/infrastructure/scenario.ts": [
{
"name": "currentScenario",
"file": "src/app/shared/infrastructure/scenario.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Reads ?scenario= from the URL so a demo can force each async state.</p>\n",
"args": [],
"returnType": "Scenario"
}
],
"src/app/showcase/concepts.page.ts": [
{
"name": "fakeResource",
"file": "src/app/showcase/concepts.page.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Minimal fake Resource so <app-async> can be driven through every state without HTTP.</p>\n",
"args": [
{
"name": "status",
"type": "string",
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "value",
"type": "T",
"deprecated": false,
"deprecationMessage": "",
"optional": true
},
{
"name": "error",
"type": "Error",
"deprecated": false,
"deprecationMessage": "",
"optional": true
}
],
"returnType": "Resource<T>",
"jsdoctags": [
{
"name": "status",
"type": "string",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
},
{
"name": "value",
"type": "T",
"deprecated": false,
"deprecationMessage": "",
"optional": true,
"tagName": {
"text": "param"
}
},
{
"name": "error",
"type": "Error",
"deprecated": false,
"deprecationMessage": "",
"optional": true,
"tagName": {
"text": "param"
}
}
]
}
],
"src/app/registratie/domain/registration.policy.ts": [
{
"name": "herregistratieDeadline",
"file": "src/app/registratie/domain/registration.policy.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>The herregistratie deadline, if the status has one (only the active state does).</p>\n",
"args": [
{
"name": "reg",
"type": "Registration",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "Date | null",
"jsdoctags": [
{
"name": "reg",
"type": "Registration",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "isHerregistratieEligible",
"file": "src/app/registratie/domain/registration.policy.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>A registration may apply for herregistratie only while active and within the\nwindow before its deadline. A struck-off or suspended registration may not.</p>\n",
"args": [
{
"name": "reg",
"type": "Registration",
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "today",
"type": "Date",
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "windowMonths",
"type": "number",
"deprecated": false,
"deprecationMessage": "",
"defaultValue": "12"
}
],
"returnType": "boolean",
"jsdoctags": [
{
"name": "reg",
"type": "Registration",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
},
{
"name": "today",
"type": "Date",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
},
{
"name": "windowMonths",
"type": "number",
"deprecated": false,
"deprecationMessage": "",
"defaultValue": "12",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "isStatusConsistent",
"file": "src/app/registratie/domain/registration.policy.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>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.</p>\n",
"args": [
{
"name": "status",
"type": "RegistrationStatus",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "boolean",
"jsdoctags": [
{
"name": "status",
"type": "RegistrationStatus",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "statusColor",
"file": "src/app/registratie/domain/registration.policy.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Brand colour token for a status. assertNever forces a colour for every new\nstatus variant at compile time.</p>\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": "<p>Domain logic for a registration — pure functions, NO Angular. This is where\n&quot;what the business rules say&quot; lives, separate from &quot;how it looks&quot; (UI) and\n&quot;where the data comes from&quot; (infrastructure). Keeping it framework-free means\nit is trivial to read and unit-test.</p>\n",
"args": [
{
"name": "tag",
"type": "StatusTag",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "string",
"jsdoctags": [
{
"name": "tag",
"type": "StatusTag",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
}
],
"src/app/auth/domain/session.ts": [
{
"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"
}
}
]
}
],
"src/app/registratie/domain/value-objects/big-nummer.ts": [
{
"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": "Result<string, BigNummer>",
"jsdoctags": [
{
"name": "raw",
"type": "string",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
}
],
"src/app/registratie/domain/value-objects/postcode.ts": [
{
"name": "parsePostcode",
"file": "src/app/registratie/domain/value-objects/postcode.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "",
"args": [
{
"name": "raw",
"type": "string",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "Result<string, Postcode>",
"jsdoctags": [
{
"name": "raw",
"type": "string",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
}
],
"src/app/registratie/domain/value-objects/uren.ts": [
{
"name": "parseUren",
"file": "src/app/registratie/domain/value-objects/uren.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "",
"args": [
{
"name": "raw",
"type": "string",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "Result<string, Uren>",
"jsdoctags": [
{
"name": "raw",
"type": "string",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
}
],
"src/app/herregistratie/application/submit-herregistratie.ts": [
{
"name": "submitHerregistratie",
"file": "src/app/herregistratie/application/submit-herregistratie.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>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&#39;s\nan API. The &quot;uren must be &gt; 0&quot; rule lets the demo show a failure path.</p>\n",
"args": [
{
"name": "data",
"type": "Valid",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "Promise<Result<string, void>>",
"jsdoctags": [
{
"name": "data",
"type": "Valid",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
}
]
},
"groupedEnumerations": {},
"groupedTypeAliases": {
"src/app/shared/ui/alert/alert.component.ts": [
{
"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
}
],
"src/app/registratie/domain/value-objects/big-nummer.ts": [
{
"name": "BigNummer",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "Brand<string | BigNummer>",
"file": "src/app/registratie/domain/value-objects/big-nummer.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Value object: a BIG registration number — 11 digits.</p>\n",
"kind": 184
}
],
"src/app/shared/kernel/fp.ts": [
{
"name": "Brand",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "unknown",
"file": "src/app/shared/kernel/fp.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Nominal typing: Brand&lt;string, &#39;Postcode&#39;&gt; is assignable from a plain string\nonly through an explicit cast — so a smart constructor is the only minter.</p>\n",
"kind": 194
},
{
"name": "Result",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "literal type | literal type",
"file": "src/app/shared/kernel/fp.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>A computation that either succeeded with a value or failed with an error.\nPlain objects (no classes) to match the signal/httpResource ergonomics.</p>\n",
"kind": 193
}
],
"src/app/registratie/application/big-profile.store.ts": [
{
"name": "Err",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "Error | undefined",
"file": "src/app/registratie/application/big-profile.store.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "",
"kind": 193
}
],
"src/app/registratie/domain/value-objects/postcode.ts": [
{
"name": "Postcode",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "Brand<string | Postcode>",
"file": "src/app/registratie/domain/value-objects/postcode.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Value object: a Dutch postcode. &quot;Parse, don&#39;t validate&quot; — a Postcode is a\ndistinct type from a raw string, mintable only via parsePostcode, so holding\none is proof it is well-formed.</p>\n",
"kind": 184
}
],
"src/app/registratie/domain/registration.ts": [
{
"name": "RegistrationStatus",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "literal type | literal type | literal type",
"file": "src/app/registratie/domain/registration.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Registration status as a discriminated union: each variant owns exactly the\ndata that makes sense for it. Only an active (Geregistreerd) registration has\na herregistratie date; a struck-off (Doorgehaald) one cannot carry one. The\nold flat interface allowed that impossible combination — this makes it\nunrepresentable.</p>\n",
"kind": 193
},
{
"name": "StatusTag",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "RegistrationStatus",
"file": "src/app/registratie/domain/registration.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Just the discriminant — for atoms that only need the label/color.</p>\n",
"kind": 200
}
],
"src/app/shared/application/remote-data.ts": [
{
"name": "RemoteData",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "literal type | literal type | literal type | literal type",
"file": "src/app/shared/application/remote-data.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>The four mutually-exclusive states of an async fetch, as a tagged union.\nCrucially the data lives ON the state: only <code>Failure</code> has an <code>error</code>, only\n<code>Success</code> has a <code>value</code>. &quot;Loaded but no value&quot; or &quot;error with stale value&quot;\nare unrepresentable — Richard Feldman&#39;s RemoteData.</p>\n",
"kind": 193
}
],
"src/app/shared/infrastructure/scenario.ts": [
{
"name": "Scenario",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "\"default\" | \"slow\" | \"loading\" | \"empty\" | \"error\"",
"file": "src/app/shared/infrastructure/scenario.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "",
"kind": 193
}
],
"src/app/registratie/domain/value-objects/uren.ts": [
{
"name": "Uren",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "Brand<number | Uren>",
"file": "src/app/registratie/domain/value-objects/uren.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Value object: a non-negative whole number of hours.</p>\n",
"kind": 184
}
],
"src/app/shared/ui/button/button.component.ts": [
{
"name": "Variant",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "\"primary\" | \"secondary\" | \"subtle\" | \"danger\"",
"file": "src/app/shared/ui/button/button.component.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "",
"kind": 193
}
],
"src/app/herregistratie/domain/herregistratie.machine.ts": [
{
"name": "WizardMsg",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "literal type | literal type | literal type | literal type | literal type | literal type | literal type | literal type",
"file": "src/app/herregistratie/domain/herregistratie.machine.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Every event that can happen to the wizard, as one message type. The component\nsends a WizardMsg; <code>reduce</code> decides the next state. This is the Elm\nModel+Msg+update pattern: ONE pure function describes all state changes.</p>\n",
"kind": 193
},
{
"name": "WizardState",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "literal type | literal type | literal type | literal type",
"file": "src/app/herregistratie/domain/herregistratie.machine.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>The whole wizard as one tagged union. <code>step</code> and <code>errors</code> exist ONLY while\nEditing; Submitting/Submitted/Failed carry a <code>Valid</code> payload and nothing else.\nSo &quot;submitting while a field is invalid&quot; or &quot;showing the success screen with\nerrors set&quot; are unrepresentable — the bug class is gone by construction.</p>\n",
"kind": 193
}
]
}
},
"routes": {
"name": "<root>",
"kind": "module",
"children": [
{
"name": "ShellComponent",
"kind": "component",
"filename": "src/app/app.routes.ts"
},
{
"name": "login",
"kind": "route-path",
"filename": "src/app/app.routes.ts"
},
{
"name": "dashboard",
"kind": "route-path",
"filename": "src/app/app.routes.ts"
},
{
"name": "registratie",
"kind": "route-path",
"filename": "src/app/app.routes.ts"
},
{
"name": "herregistratie",
"kind": "route-path",
"filename": "src/app/app.routes.ts"
},
{
"name": "concepts",
"kind": "route-path",
"filename": "src/app/app.routes.ts"
},
{
"name": "**",
"kind": "route-path",
"filename": "src/app/app.routes.ts"
},
{
"name": "login",
"kind": "route-redirect",
"filename": "src/app/app.routes.ts"
},
{
"name": "login",
"kind": "route-redirect",
"filename": "src/app/app.routes.ts"
}
]
},
"coverage": {
"count": 47,
"status": "medium",
"files": [
{
"filePath": "src/app/app.config.ts",
"type": "variable",
"linktype": "miscellaneous",
"linksubtype": "variable",
"name": "appConfig",
"coveragePercent": 0,
"coverageCount": "0/1",
"status": "low"
},
{
"filePath": "src/app/app.routes.ts",
"type": "variable",
"linktype": "miscellaneous",
"linksubtype": "variable",
"name": "routes",
"coveragePercent": 0,
"coverageCount": "0/1",
"status": "low"
},
{
"filePath": "src/app/app.ts",
"type": "component",
"linktype": "component",
"name": "App",
"coveragePercent": 0,
"coverageCount": "0/1",
"status": "low"
},
{
"filePath": "src/app/auth/application/session.store.ts",
"type": "injectable",
"linktype": "injectable",
"name": "SessionStore",
"coveragePercent": 28,
"coverageCount": "2/7",
"status": "medium"
},
{
"filePath": "src/app/auth/auth.guard.ts",
"type": "variable",
"linktype": "miscellaneous",
"linksubtype": "variable",
"name": "authGuard",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/auth/domain/session.ts",
"type": "interface",
"linktype": "interface",
"name": "Session",
"coveragePercent": 33,
"coverageCount": "1/3",
"status": "medium"
},
{
"filePath": "src/app/auth/domain/session.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "isAuthenticated",
"coveragePercent": 0,
"coverageCount": "0/1",
"status": "low"
},
{
"filePath": "src/app/auth/infrastructure/digid.adapter.ts",
"type": "injectable",
"linktype": "injectable",
"name": "DigidAdapter",
"coveragePercent": 50,
"coverageCount": "1/2",
"status": "medium"
},
{
"filePath": "src/app/auth/ui/login-form/login-form.component.ts",
"type": "component",
"linktype": "component",
"name": "LoginFormComponent",
"coveragePercent": 25,
"coverageCount": "1/4",
"status": "low"
},
{
"filePath": "src/app/auth/ui/login.page.ts",
"type": "component",
"linktype": "component",
"name": "LoginPage",
"coveragePercent": 0,
"coverageCount": "0/5",
"status": "low"
},
{
"filePath": "src/app/herregistratie/application/submit-herregistratie.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "submitHerregistratie",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/herregistratie/domain/herregistratie.machine.ts",
"type": "interface",
"linktype": "interface",
"name": "Draft",
"coveragePercent": 33,
"coverageCount": "1/3",
"status": "medium"
},
{
"filePath": "src/app/herregistratie/domain/herregistratie.machine.ts",
"type": "interface",
"linktype": "interface",
"name": "Valid",
"coveragePercent": 33,
"coverageCount": "1/3",
"status": "medium"
},
{
"filePath": "src/app/herregistratie/domain/herregistratie.machine.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "back",
"coveragePercent": 0,
"coverageCount": "0/1",
"status": "low"
},
{
"filePath": "src/app/herregistratie/domain/herregistratie.machine.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "next",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/herregistratie/domain/herregistratie.machine.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "reduce",
"coveragePercent": 0,
"coverageCount": "0/1",
"status": "low"
},
{
"filePath": "src/app/herregistratie/domain/herregistratie.machine.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "resolve",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/herregistratie/domain/herregistratie.machine.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "setField",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/herregistratie/domain/herregistratie.machine.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "submit",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/herregistratie/domain/herregistratie.machine.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "validate",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/herregistratie/domain/herregistratie.machine.ts",
"type": "variable",
"linktype": "miscellaneous",
"linksubtype": "variable",
"name": "initial",
"coveragePercent": 0,
"coverageCount": "0/1",
"status": "low"
},
{
"filePath": "src/app/herregistratie/domain/herregistratie.machine.ts",
"type": "type alias",
"linktype": "miscellaneous",
"linksubtype": "typealias",
"name": "WizardMsg",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/herregistratie/domain/herregistratie.machine.ts",
"type": "type alias",
"linktype": "miscellaneous",
"linksubtype": "typealias",
"name": "WizardState",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/herregistratie/ui/herregistratie-wizard/herregistratie-wizard.component.ts",
"type": "component",
"linktype": "component",
"name": "HerregistratieWizardComponent",
"coveragePercent": 18,
"coverageCount": "3/16",
"status": "low"
},
{
"filePath": "src/app/herregistratie/ui/herregistratie.page.ts",
"type": "component",
"linktype": "component",
"name": "HerregistratiePage",
"coveragePercent": 33,
"coverageCount": "1/3",
"status": "medium"
},
{
"filePath": "src/app/registratie/application/big-profile.store.ts",
"type": "injectable",
"linktype": "injectable",
"name": "BigProfileStore",
"coveragePercent": 30,
"coverageCount": "4/13",
"status": "medium"
},
{
"filePath": "src/app/registratie/application/big-profile.store.ts",
"type": "type alias",
"linktype": "miscellaneous",
"linksubtype": "typealias",
"name": "Err",
"coveragePercent": 0,
"coverageCount": "0/1",
"status": "low"
},
{
"filePath": "src/app/registratie/domain/big-profile.ts",
"type": "interface",
"linktype": "interface",
"name": "BigProfile",
"coveragePercent": 33,
"coverageCount": "1/3",
"status": "medium"
},
{
"filePath": "src/app/registratie/domain/person.ts",
"type": "interface",
"linktype": "interface",
"name": "Adres",
"coveragePercent": 25,
"coverageCount": "1/4",
"status": "low"
},
{
"filePath": "src/app/registratie/domain/person.ts",
"type": "interface",
"linktype": "interface",
"name": "Person",
"coveragePercent": 0,
"coverageCount": "0/4",
"status": "low"
},
{
"filePath": "src/app/registratie/domain/registration.policy.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "herregistratieDeadline",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/registratie/domain/registration.policy.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "isHerregistratieEligible",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/registratie/domain/registration.policy.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "isStatusConsistent",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/registratie/domain/registration.policy.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "statusColor",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/registratie/domain/registration.policy.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "statusLabel",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/registratie/domain/registration.ts",
"type": "interface",
"linktype": "interface",
"name": "Aantekening",
"coveragePercent": 0,
"coverageCount": "0/4",
"status": "low"
},
{
"filePath": "src/app/registratie/domain/registration.ts",
"type": "interface",
"linktype": "interface",
"name": "Registration",
"coveragePercent": 0,
"coverageCount": "0/7",
"status": "low"
},
{
"filePath": "src/app/registratie/domain/registration.ts",
"type": "type alias",
"linktype": "miscellaneous",
"linksubtype": "typealias",
"name": "RegistrationStatus",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/registratie/domain/registration.ts",
"type": "type alias",
"linktype": "miscellaneous",
"linksubtype": "typealias",
"name": "StatusTag",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/registratie/domain/value-objects/big-nummer.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "parseBigNummer",
"coveragePercent": 0,
"coverageCount": "0/1",
"status": "low"
},
{
"filePath": "src/app/registratie/domain/value-objects/big-nummer.ts",
"type": "type alias",
"linktype": "miscellaneous",
"linksubtype": "typealias",
"name": "BigNummer",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/registratie/domain/value-objects/postcode.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "parsePostcode",
"coveragePercent": 0,
"coverageCount": "0/1",
"status": "low"
},
{
"filePath": "src/app/registratie/domain/value-objects/postcode.ts",
"type": "type alias",
"linktype": "miscellaneous",
"linksubtype": "typealias",
"name": "Postcode",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/registratie/domain/value-objects/uren.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "parseUren",
"coveragePercent": 0,
"coverageCount": "0/1",
"status": "low"
},
{
"filePath": "src/app/registratie/domain/value-objects/uren.ts",
"type": "type alias",
"linktype": "miscellaneous",
"linksubtype": "typealias",
"name": "Uren",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/registratie/infrastructure/big-register.adapter.ts",
"type": "injectable",
"linktype": "injectable",
"name": "BigRegisterAdapter",
"coveragePercent": 33,
"coverageCount": "1/3",
"status": "medium"
},
{
"filePath": "src/app/registratie/infrastructure/brp.adapter.ts",
"type": "injectable",
"linktype": "injectable",
"name": "BrpAdapter",
"coveragePercent": 50,
"coverageCount": "1/2",
"status": "medium"
},
{
"filePath": "src/app/registratie/ui/change-request-form/change-request-form.component.ts",
"type": "component",
"linktype": "component",
"name": "ChangeRequestFormComponent",
"coveragePercent": 12,
"coverageCount": "1/8",
"status": "low"
},
{
"filePath": "src/app/registratie/ui/change-request-form/change-request-form.component.ts",
"type": "interface",
"linktype": "interface",
"name": "ChangeRequest",
"coveragePercent": 25,
"coverageCount": "1/4",
"status": "low"
},
{
"filePath": "src/app/registratie/ui/dashboard.page.ts",
"type": "component",
"linktype": "component",
"name": "DashboardPage",
"coveragePercent": 0,
"coverageCount": "0/2",
"status": "low"
},
{
"filePath": "src/app/registratie/ui/registration-detail.page.ts",
"type": "component",
"linktype": "component",
"name": "RegistrationDetailPage",
"coveragePercent": 0,
"coverageCount": "0/3",
"status": "low"
},
{
"filePath": "src/app/registratie/ui/registration-summary/registration-summary.component.ts",
"type": "component",
"linktype": "component",
"name": "RegistrationSummaryComponent",
"coveragePercent": 25,
"coverageCount": "1/4",
"status": "low"
},
{
"filePath": "src/app/registratie/ui/registration-table/registration-table.component.ts",
"type": "component",
"linktype": "component",
"name": "RegistrationTableComponent",
"coveragePercent": 50,
"coverageCount": "1/2",
"status": "medium"
},
{
"filePath": "src/app/shared/application/remote-data.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "andThen",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/shared/application/remote-data.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "foldRemote",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/shared/application/remote-data.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "fromResource",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/shared/application/remote-data.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "map",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/shared/application/remote-data.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "map2",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/shared/application/remote-data.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "map3",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/shared/application/remote-data.ts",
"type": "type alias",
"linktype": "miscellaneous",
"linksubtype": "typealias",
"name": "RemoteData",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/shared/application/store.ts",
"type": "interface",
"linktype": "interface",
"name": "Store",
"coveragePercent": 100,
"coverageCount": "3/3",
"status": "very-good"
},
{
"filePath": "src/app/shared/application/store.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "createStore",
"coveragePercent": 0,
"coverageCount": "0/1",
"status": "low"
},
{
"filePath": "src/app/shared/infrastructure/scenario.interceptor.ts",
"type": "variable",
"linktype": "miscellaneous",
"linksubtype": "variable",
"name": "scenarioInterceptor",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/shared/infrastructure/scenario.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "currentScenario",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/shared/infrastructure/scenario.ts",
"type": "variable",
"linktype": "miscellaneous",
"linksubtype": "variable",
"name": "VALID",
"coveragePercent": 0,
"coverageCount": "0/1",
"status": "low"
},
{
"filePath": "src/app/shared/infrastructure/scenario.ts",
"type": "type alias",
"linktype": "miscellaneous",
"linksubtype": "typealias",
"name": "Scenario",
"coveragePercent": 0,
"coverageCount": "0/1",
"status": "low"
},
{
"filePath": "src/app/shared/kernel/fp.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "assertNever",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/shared/kernel/fp.ts",
"type": "variable",
"linktype": "miscellaneous",
"linksubtype": "variable",
"name": "err",
"coveragePercent": 0,
"coverageCount": "0/1",
"status": "low"
},
{
"filePath": "src/app/shared/kernel/fp.ts",
"type": "variable",
"linktype": "miscellaneous",
"linksubtype": "variable",
"name": "ok",
"coveragePercent": 0,
"coverageCount": "0/1",
"status": "low"
},
{
"filePath": "src/app/shared/kernel/fp.ts",
"type": "type alias",
"linktype": "miscellaneous",
"linksubtype": "typealias",
"name": "Brand",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/shared/kernel/fp.ts",
"type": "type alias",
"linktype": "miscellaneous",
"linksubtype": "typealias",
"name": "Result",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/shared/layout/page-shell/page-shell.component.ts",
"type": "component",
"linktype": "component",
"name": "PageShellComponent",
"coveragePercent": 16,
"coverageCount": "1/6",
"status": "low"
},
{
"filePath": "src/app/shared/layout/shell/shell.component.ts",
"type": "component",
"linktype": "component",
"name": "ShellComponent",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/shared/layout/site-footer/site-footer.component.ts",
"type": "component",
"linktype": "component",
"name": "SiteFooterComponent",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/shared/layout/site-header/site-header.component.ts",
"type": "component",
"linktype": "component",
"name": "SiteHeaderComponent",
"coveragePercent": 50,
"coverageCount": "1/2",
"status": "medium"
},
{
"filePath": "src/app/shared/ui/alert/alert.component.ts",
"type": "component",
"linktype": "component",
"name": "AlertComponent",
"coveragePercent": 50,
"coverageCount": "1/2",
"status": "medium"
},
{
"filePath": "src/app/shared/ui/alert/alert.component.ts",
"type": "type alias",
"linktype": "miscellaneous",
"linksubtype": "typealias",
"name": "AlertType",
"coveragePercent": 0,
"coverageCount": "0/1",
"status": "low"
},
{
"filePath": "src/app/shared/ui/async/async.component.ts",
"type": "component",
"linktype": "component",
"name": "AsyncComponent",
"coveragePercent": 8,
"coverageCount": "1/12",
"status": "low"
},
{
"filePath": "src/app/shared/ui/async/async.component.ts",
"type": "directive",
"linktype": "directive",
"name": "AsyncEmptyDirective",
"coveragePercent": 0,
"coverageCount": "0/3",
"status": "low"
},
{
"filePath": "src/app/shared/ui/async/async.component.ts",
"type": "directive",
"linktype": "directive",
"name": "AsyncErrorDirective",
"coveragePercent": 0,
"coverageCount": "0/3",
"status": "low"
},
{
"filePath": "src/app/shared/ui/async/async.component.ts",
"type": "directive",
"linktype": "directive",
"name": "AsyncLoadedDirective",
"coveragePercent": 0,
"coverageCount": "0/3",
"status": "low"
},
{
"filePath": "src/app/shared/ui/async/async.component.ts",
"type": "directive",
"linktype": "directive",
"name": "AsyncLoadingDirective",
"coveragePercent": 0,
"coverageCount": "0/3",
"status": "low"
},
{
"filePath": "src/app/shared/ui/async/async.component.ts",
"type": "variable",
"linktype": "miscellaneous",
"linksubtype": "variable",
"name": "ASYNC",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/shared/ui/button/button.component.ts",
"type": "component",
"linktype": "component",
"name": "ButtonComponent",
"coveragePercent": 25,
"coverageCount": "1/4",
"status": "low"
},
{
"filePath": "src/app/shared/ui/button/button.component.ts",
"type": "type alias",
"linktype": "miscellaneous",
"linksubtype": "typealias",
"name": "Variant",
"coveragePercent": 0,
"coverageCount": "0/1",
"status": "low"
},
{
"filePath": "src/app/shared/ui/data-row/data-row.component.ts",
"type": "component",
"linktype": "component",
"name": "DataRowComponent",
"coveragePercent": 33,
"coverageCount": "1/3",
"status": "medium"
},
{
"filePath": "src/app/shared/ui/form-field/form-field.component.ts",
"type": "component",
"linktype": "component",
"name": "FormFieldComponent",
"coveragePercent": 20,
"coverageCount": "1/5",
"status": "low"
},
{
"filePath": "src/app/shared/ui/heading/heading.component.ts",
"type": "component",
"linktype": "component",
"name": "HeadingComponent",
"coveragePercent": 50,
"coverageCount": "1/2",
"status": "medium"
},
{
"filePath": "src/app/shared/ui/link/link.component.ts",
"type": "component",
"linktype": "component",
"name": "LinkComponent",
"coveragePercent": 50,
"coverageCount": "1/2",
"status": "medium"
},
{
"filePath": "src/app/shared/ui/skeleton/skeleton.component.ts",
"type": "component",
"linktype": "component",
"name": "SkeletonComponent",
"coveragePercent": 10,
"coverageCount": "1/10",
"status": "low"
},
{
"filePath": "src/app/shared/ui/spinner/spinner.component.ts",
"type": "component",
"linktype": "component",
"name": "SpinnerComponent",
"coveragePercent": 16,
"coverageCount": "1/6",
"status": "low"
},
{
"filePath": "src/app/shared/ui/status-badge/status-badge.component.ts",
"type": "component",
"linktype": "component",
"name": "StatusBadgeComponent",
"coveragePercent": 33,
"coverageCount": "1/3",
"status": "medium"
},
{
"filePath": "src/app/shared/ui/text-input/text-input.component.ts",
"type": "component",
"linktype": "component",
"name": "TextInputComponent",
"coveragePercent": 7,
"coverageCount": "1/14",
"status": "low"
},
{
"filePath": "src/app/showcase/concepts.page.ts",
"type": "component",
"linktype": "component",
"name": "ConceptsPage",
"coveragePercent": 8,
"coverageCount": "1/12",
"status": "low"
},
{
"filePath": "src/app/showcase/concepts.page.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "fakeResource",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
}
]
}
}