{ "pipes": [], "interfaces": [ { "name": "Aantekening", "id": "interface-Aantekening-2ecca36e413e22c1c5967d07b811fa4171ff578eb6b47a7275723bcca44e93a2db27d77a765b82e5f6182492464cc8b9268c9724e13b400718d30da7bc4ba50c", "file": "src/app/core/models.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": "ChangeRequest", "id": "interface-ChangeRequest-e366867f9f2a82d4c6cafc6fbdce9749e7775f651192c4de62cefc40a237a6e2c6772537e64a4aeeb6667ffa33d9a69ee6114c69160674807408090b1cbc283a", "file": "src/app/organisms/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 '../../molecules/form-field/form-field.component';\nimport { TextInputComponent } from '../../atoms/text-input/text-input.component';\nimport { ButtonComponent } from '../../atoms/button/button.component';\nimport { HeadingComponent } from '../../atoms/heading/heading.component';\nimport { Postcode, parsePostcode } from '../../core/parse';\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 Adreswijziging doorgeven\n
\n \n \n \n \n \n \n \n \n \n
\n Wijziging indienen\n
\n
\n `,\n})\nexport class ChangeRequestFormComponent {\n street = '';\n zip = '';\n city = '';\n streetError = signal('');\n zipError = signal('');\n submitted = output();\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": "

A submitted change request carries a parsed postcode (branded Postcode),\nnot a raw string — downstream code can't receive an unvalidated one.

\n", "rawdescription": "\nA submitted change request carries a *parsed* postcode (branded Postcode),\nnot a raw string — downstream code can't receive an unvalidated one.", "methods": [], "extends": [] }, { "name": "Draft", "id": "interface-Draft-6fcaabe58c126a645622a7a77942a847877e8d80e60ddd45cb9ba4c247cede3ee197def542b645ef02b0ce5dd0deab6c644edddf2f37dec67a129b27ba53bb23", "file": "src/app/organisms/herregistratie-wizard/wizard.machine.ts", "deprecated": false, "deprecationMessage": "", "type": "interface", "sourceCode": "import { Result } from '../../core/fp';\nimport { Uren, parseUren } from '../../core/parse';\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> }\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>, Valid> {\n const uren = parseUren(draft.uren);\n const punten = parseUren(draft.punten);\n const errors: Partial> = {};\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): 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", "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": "

What the user is typing (raw, possibly invalid).

\n", "rawdescription": "\nWhat the user is typing (raw, possibly invalid).", "methods": [], "extends": [] }, { "name": "Registration", "id": "interface-Registration-2ecca36e413e22c1c5967d07b811fa4171ff578eb6b47a7275723bcca44e93a2db27d77a765b82e5f6182492464cc8b9268c9724e13b400718d30da7bc4ba50c", "file": "src/app/core/models.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": "Valid", "id": "interface-Valid-6fcaabe58c126a645622a7a77942a847877e8d80e60ddd45cb9ba4c247cede3ee197def542b645ef02b0ce5dd0deab6c644edddf2f37dec67a129b27ba53bb23", "file": "src/app/organisms/herregistratie-wizard/wizard.machine.ts", "deprecated": false, "deprecationMessage": "", "type": "interface", "sourceCode": "import { Result } from '../../core/fp';\nimport { Uren, parseUren } from '../../core/parse';\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> }\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>, Valid> {\n const uren = parseUren(draft.uren);\n const punten = parseUren(draft.punten);\n const errors: Partial> = {};\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): 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", "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": "

What we have AFTER parsing — branded/typed, guaranteed valid.

\n", "rawdescription": "\nWhat we have AFTER parsing — branded/typed, guaranteed valid.", "methods": [], "extends": [] } ], "injectables": [ { "name": "RegistrationService", "id": "injectable-RegistrationService-03230b1d6b08769d82b6b7d378749dd92ae4e2487883f5e23a741e40a04d5d54b22e38f1301b13de7a23c8d0e57015e3f77dfb741fb51883d9c30d7bdabd0291", "file": "src/app/core/registration.service.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": "

Exposes signal-based resources (Angular's httpResource). Each returns a\nResource with status()/value()/error()/reload() — consumed by ,\nwhich turns those signals into the loading/empty/error/loaded UI.\nCall these from a component field initializer (injection context required).

\n", "rawdescription": "\n\nExposes signal-based resources (Angular's httpResource). Each returns a\nResource with status()/value()/error()/reload() — consumed by ,\nwhich turns those signals into the loading/empty/error/loaded UI.\nCall these from a component field initializer (injection context required).\n", "sourceCode": "import { Injectable } from '@angular/core';\nimport { httpResource } from '@angular/common/http';\nimport { Registration, Aantekening } from './models';\n\n/**\n * Exposes signal-based resources (Angular's httpResource). Each returns a\n * Resource with status()/value()/error()/reload() — consumed by ,\n * which turns those signals into the loading/empty/error/loaded UI.\n * Call these from a component field initializer (injection context required).\n */\n@Injectable({ providedIn: 'root' })\nexport class RegistrationService {\n registrationResource() {\n return httpResource(() => 'mock/registration.json');\n }\n\n aantekeningenResource() {\n return httpResource(() => 'mock/notes.json', { defaultValue: [] });\n }\n}\n", "extends": [], "type": "injectable" } ], "guards": [], "interceptors": [], "classes": [], "directives": [ { "name": "AsyncEmptyDirective", "id": "directive-AsyncEmptyDirective-2c3bb2a3fee90c1c02ec41aacfd672fcdf754eccc5e8761a7590b96d19724dc55523a26a1eff26c0caeaf28a297042b8fdf7e78d70272079bd5465f72e58dbc9", "file": "src/app/molecules/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 '../../atoms/spinner/spinner.component';\nimport { AlertComponent } from '../../atoms/alert/alert.component';\nimport { ButtonComponent } from '../../atoms/button/button.component';\nimport { fromResource, foldRemote } from '../../core/remote-data';\n\n/* Slot markers. Put on children of . */\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) {}\n}\n@Directive({ selector: '[appAsyncEmpty]' })\nexport class AsyncEmptyDirective {\n constructor(public tpl: TemplateRef) {}\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()) { }\n @else { }\n }\n @case ('Failure') {\n @if (errorTpl()) {\n \n } @else {\n Er ging iets mis bij het laden van de gegevens.\n
\n Opnieuw proberen\n
\n }\n }\n @case ('Empty') {\n @if (emptyTpl()) { }\n @else {

Geen gegevens gevonden.

}\n }\n @case ('Success') {\n \n }\n }\n `,\n})\nexport class AsyncComponent {\n resource = input.required>();\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 resource projected into a RemoteData union.\n protected rd = computed(() => fromResource(this.resource(), this.isEmpty()));\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 ('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", "indexKey": "", "optional": false, "description": "", "line": 20, "modifierKind": [ 125 ] } ], "methodsClass": [], "extends": [], "constructorObj": { "name": "constructor", "description": "", "deprecated": false, "deprecationMessage": "", "args": [ { "name": "tpl", "type": "TemplateRef", "optional": false, "dotDotDotToken": false, "deprecated": false, "deprecationMessage": "" } ], "line": 19, "jsdoctags": [ { "name": "tpl", "type": "TemplateRef", "optional": false, "dotDotDotToken": false, "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] } }, { "name": "AsyncErrorDirective", "id": "directive-AsyncErrorDirective-2c3bb2a3fee90c1c02ec41aacfd672fcdf754eccc5e8761a7590b96d19724dc55523a26a1eff26c0caeaf28a297042b8fdf7e78d70272079bd5465f72e58dbc9", "file": "src/app/molecules/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 '../../atoms/spinner/spinner.component';\nimport { AlertComponent } from '../../atoms/alert/alert.component';\nimport { ButtonComponent } from '../../atoms/button/button.component';\nimport { fromResource, foldRemote } from '../../core/remote-data';\n\n/* Slot markers. Put on children of . */\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) {}\n}\n@Directive({ selector: '[appAsyncEmpty]' })\nexport class AsyncEmptyDirective {\n constructor(public tpl: TemplateRef) {}\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()) { }\n @else { }\n }\n @case ('Failure') {\n @if (errorTpl()) {\n \n } @else {\n Er ging iets mis bij het laden van de gegevens.\n
\n Opnieuw proberen\n
\n }\n }\n @case ('Empty') {\n @if (emptyTpl()) { }\n @else {

Geen gegevens gevonden.

}\n }\n @case ('Success') {\n \n }\n }\n `,\n})\nexport class AsyncComponent {\n resource = input.required>();\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 resource projected into a RemoteData union.\n protected rd = computed(() => fromResource(this.resource(), this.isEmpty()));\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 ('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", "indexKey": "", "optional": false, "description": "", "line": 24, "modifierKind": [ 125 ] } ], "methodsClass": [], "extends": [], "constructorObj": { "name": "constructor", "description": "", "deprecated": false, "deprecationMessage": "", "args": [ { "name": "tpl", "type": "TemplateRef", "optional": false, "dotDotDotToken": false, "deprecated": false, "deprecationMessage": "" } ], "line": 23, "jsdoctags": [ { "name": "tpl", "type": "TemplateRef", "optional": false, "dotDotDotToken": false, "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] } }, { "name": "AsyncLoadedDirective", "id": "directive-AsyncLoadedDirective-2c3bb2a3fee90c1c02ec41aacfd672fcdf754eccc5e8761a7590b96d19724dc55523a26a1eff26c0caeaf28a297042b8fdf7e78d70272079bd5465f72e58dbc9", "file": "src/app/molecules/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 '../../atoms/spinner/spinner.component';\nimport { AlertComponent } from '../../atoms/alert/alert.component';\nimport { ButtonComponent } from '../../atoms/button/button.component';\nimport { fromResource, foldRemote } from '../../core/remote-data';\n\n/* Slot markers. Put on children of . */\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) {}\n}\n@Directive({ selector: '[appAsyncEmpty]' })\nexport class AsyncEmptyDirective {\n constructor(public tpl: TemplateRef) {}\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()) { }\n @else { }\n }\n @case ('Failure') {\n @if (errorTpl()) {\n \n } @else {\n Er ging iets mis bij het laden van de gegevens.\n
\n Opnieuw proberen\n
\n }\n }\n @case ('Empty') {\n @if (emptyTpl()) { }\n @else {

Geen gegevens gevonden.

}\n }\n @case ('Success') {\n \n }\n }\n `,\n})\nexport class AsyncComponent {\n resource = input.required>();\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 resource projected into a RemoteData union.\n protected rd = computed(() => fromResource(this.resource(), this.isEmpty()));\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 ('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", "indexKey": "", "optional": false, "description": "", "line": 12, "modifierKind": [ 125 ] } ], "methodsClass": [], "extends": [], "constructorObj": { "name": "constructor", "description": "", "deprecated": false, "deprecationMessage": "", "args": [ { "name": "tpl", "type": "TemplateRef", "optional": false, "dotDotDotToken": false, "deprecated": false, "deprecationMessage": "" } ], "line": 11, "jsdoctags": [ { "name": "tpl", "type": "TemplateRef", "optional": false, "dotDotDotToken": false, "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] } }, { "name": "AsyncLoadingDirective", "id": "directive-AsyncLoadingDirective-2c3bb2a3fee90c1c02ec41aacfd672fcdf754eccc5e8761a7590b96d19724dc55523a26a1eff26c0caeaf28a297042b8fdf7e78d70272079bd5465f72e58dbc9", "file": "src/app/molecules/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 '../../atoms/spinner/spinner.component';\nimport { AlertComponent } from '../../atoms/alert/alert.component';\nimport { ButtonComponent } from '../../atoms/button/button.component';\nimport { fromResource, foldRemote } from '../../core/remote-data';\n\n/* Slot markers. Put on children of . */\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) {}\n}\n@Directive({ selector: '[appAsyncEmpty]' })\nexport class AsyncEmptyDirective {\n constructor(public tpl: TemplateRef) {}\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()) { }\n @else { }\n }\n @case ('Failure') {\n @if (errorTpl()) {\n \n } @else {\n Er ging iets mis bij het laden van de gegevens.\n
\n Opnieuw proberen\n
\n }\n }\n @case ('Empty') {\n @if (emptyTpl()) { }\n @else {

Geen gegevens gevonden.

}\n }\n @case ('Success') {\n \n }\n }\n `,\n})\nexport class AsyncComponent {\n resource = input.required>();\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 resource projected into a RemoteData union.\n protected rd = computed(() => fromResource(this.resource(), this.isEmpty()));\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 ('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", "indexKey": "", "optional": false, "description": "", "line": 16, "modifierKind": [ 125 ] } ], "methodsClass": [], "extends": [], "constructorObj": { "name": "constructor", "description": "", "deprecated": false, "deprecationMessage": "", "args": [ { "name": "tpl", "type": "TemplateRef", "optional": false, "dotDotDotToken": false, "deprecated": false, "deprecationMessage": "" } ], "line": 15, "jsdoctags": [ { "name": "tpl", "type": "TemplateRef", "optional": false, "dotDotDotToken": false, "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] } } ], "components": [ { "name": "AlertComponent", "id": "component-AlertComponent-7d03ee2c0179c2f8d44795112c823951406810027571b5471bc765873f1aeaee550dcb89c6ebd8514ee36f2d96c8c6ba118293bf44a4a1316f61e91fa3c06f4e", "file": "src/app/atoms/alert/alert.component.ts", "encapsulation": [], "entryComponents": [], "inputs": [], "outputs": [], "providers": [], "selector": "app-alert", "styleUrls": [], "styles": [], "template": "\n \n\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": "

Atom: alert/message banner.

\n", "rawdescription": "\nAtom: alert/message banner.", "type": "component", "sourceCode": "import { Component, input } from '@angular/core';\n\ntype AlertType = 'info' | 'ok' | 'warning' | 'error';\n\n/** Atom: alert/message banner. */\n@Component({\n selector: 'app-alert',\n template: `\n \n \n \n `,\n})\nexport class AlertComponent {\n type = input('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": "", "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: '',\n})\nexport class App {}\n", "assetsDirs": [], "styleUrlsData": "", "stylesData": "", "extends": [] }, { "name": "AsyncComponent", "id": "component-AsyncComponent-2c3bb2a3fee90c1c02ec41aacfd672fcdf754eccc5e8761a7590b96d19724dc55523a26a1eff26c0caeaf28a297042b8fdf7e78d70272079bd5465f72e58dbc9", "file": "src/app/molecules/async/async.component.ts", "encapsulation": [], "entryComponents": [], "inputs": [], "outputs": [], "providers": [], "selector": "app-async", "styleUrls": [], "styles": [], "template": "@switch (rd().tag) {\n @case ('Loading') {\n @if (loadingTpl()) { }\n @else { }\n }\n @case ('Failure') {\n @if (errorTpl()) {\n \n } @else {\n Er ging iets mis bij het laden van de gegevens.\n
\n Opnieuw proberen\n
\n }\n }\n @case ('Empty') {\n @if (emptyTpl()) { }\n @else {

Geen gegevens gevonden.

}\n }\n @case ('Success') {\n \n }\n}\n", "templateUrl": [], "viewProviders": [], "hostDirectives": [], "inputsClass": [ { "name": "isEmpty", "defaultValue": "() => false", "deprecated": false, "deprecationMessage": "", "type": "(v: T) => boolean", "indexKey": "", "optional": false, "description": "", "line": 67, "required": false }, { "name": "resource", "deprecated": false, "deprecationMessage": "", "type": "Resource", "indexKey": "", "optional": false, "description": "", "line": 66, "required": true } ], "outputsClass": [], "propertiesClass": [ { "name": "emptyTpl", "defaultValue": "contentChild(AsyncEmptyDirective)", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 71 }, { "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": 82, "modifierKind": [ 124 ] }, { "name": "errorTpl", "defaultValue": "contentChild(AsyncErrorDirective)", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 72 }, { "name": "loadedTpl", "defaultValue": "contentChild.required(AsyncLoadedDirective)", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 69 }, { "name": "loadingTpl", "defaultValue": "contentChild(AsyncLoadingDirective)", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 70 }, { "name": "rd", "defaultValue": "computed(() => fromResource(this.resource(), this.isEmpty()))", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 75, "modifierKind": [ 124 ] }, { "name": "retry", "defaultValue": "() => {...}", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 86 }, { "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": 79, "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": "

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 ("impossible states"). Unprovided slots\nfall back to sensible defaults.

\n", "rawdescription": "\n\nRenders exactly ONE of loading / empty / error / loaded for a signal-based\nresource (e.g. httpResource). Built on a RemoteData tagged union (see\ncore/remote-data.ts), so the states are mutually exclusive by construction —\nthe UI can never show two at once (\"impossible states\"). Unprovided slots\nfall back to sensible defaults.\n", "type": "component", "sourceCode": "import { Component, Directive, TemplateRef, computed, contentChild, input } from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport type { Resource } from '@angular/core';\nimport { SpinnerComponent } from '../../atoms/spinner/spinner.component';\nimport { AlertComponent } from '../../atoms/alert/alert.component';\nimport { ButtonComponent } from '../../atoms/button/button.component';\nimport { fromResource, foldRemote } from '../../core/remote-data';\n\n/* Slot markers. Put on children of . */\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) {}\n}\n@Directive({ selector: '[appAsyncEmpty]' })\nexport class AsyncEmptyDirective {\n constructor(public tpl: TemplateRef) {}\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()) { }\n @else { }\n }\n @case ('Failure') {\n @if (errorTpl()) {\n \n } @else {\n Er ging iets mis bij het laden van de gegevens.\n
\n Opnieuw proberen\n
\n }\n }\n @case ('Empty') {\n @if (emptyTpl()) { }\n @else {

Geen gegevens gevonden.

}\n }\n @case ('Success') {\n \n }\n }\n `,\n})\nexport class AsyncComponent {\n resource = input.required>();\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 resource projected into a RemoteData union.\n protected rd = computed(() => fromResource(this.resource(), this.isEmpty()));\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 ('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/atoms/button/button.component.ts", "encapsulation": [], "entryComponents": [], "inputs": [], "outputs": [], "providers": [], "selector": "app-button", "styleUrls": [], "styles": [], "template": "\n \n\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": "

Atom: button. Thin wrapper over the Utrecht/RHC button CSS.

\n", "rawdescription": "\nAtom: button. Thin wrapper over the Utrecht/RHC button CSS.", "type": "component", "sourceCode": "import { Component, input } from '@angular/core';\n\ntype Variant = 'primary' | 'secondary' | 'subtle' | 'danger';\n\n/** Atom: button. Thin wrapper over the Utrecht/RHC button CSS. */\n@Component({\n selector: 'app-button',\n template: `\n \n \n \n `,\n})\nexport class ButtonComponent {\n variant = input('primary');\n type = input<'button' | 'submit'>('button');\n disabled = input(false);\n}\n", "assetsDirs": [], "styleUrlsData": "", "stylesData": "", "extends": [] }, { "name": "ChangeRequestFormComponent", "id": "component-ChangeRequestFormComponent-e366867f9f2a82d4c6cafc6fbdce9749e7775f651192c4de62cefc40a237a6e2c6772537e64a4aeeb6667ffa33d9a69ee6114c69160674807408090b1cbc283a", "file": "src/app/organisms/change-request-form/change-request-form.component.ts", "encapsulation": [], "entryComponents": [], "inputs": [], "outputs": [], "providers": [], "selector": "app-change-request-form", "styleUrls": [], "styles": [], "template": "Adreswijziging doorgeven\n
\n \n \n \n \n \n \n \n \n \n
\n Wijziging indienen\n
\n
\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": "

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's Result — no parallel "is it valid" flag to drift.

\n", "rawdescription": "\nOrganism: change-request (adreswijziging) form. Reuses the same form-field\nmolecule + text-input/button atoms as the login form. Field errors come\nstraight from the parser's Result — no parallel \"is it valid\" flag to drift.", "type": "component", "sourceCode": "import { Component, output, signal } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FormFieldComponent } from '../../molecules/form-field/form-field.component';\nimport { TextInputComponent } from '../../atoms/text-input/text-input.component';\nimport { ButtonComponent } from '../../atoms/button/button.component';\nimport { HeadingComponent } from '../../atoms/heading/heading.component';\nimport { Postcode, parsePostcode } from '../../core/parse';\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 Adreswijziging doorgeven\n
\n \n \n \n \n \n \n \n \n \n
\n Wijziging indienen\n
\n
\n `,\n})\nexport class ChangeRequestFormComponent {\n street = '';\n zip = '';\n city = '';\n streetError = signal('');\n zipError = signal('');\n submitted = output();\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-6ebc285de6e31b814c5a5499d296626fc51bce08971ae012bfa0176580e767b207f13bbc91e38ad1d616cb28e386208e7686eef9bdf8f5e0ddf89b7ee67362cb", "file": "src/app/pages/concepts/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": "\n \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 \n\n \n 1 · Discriminated unions\n
\n
\n

Fout — vlakke interface

\n
{{ unionBad }}
\n

Een doorgehaalde registratie houdt tóch een herregistratiedatum: onmogelijke toestand.

\n
\n
\n

Goed — sum type

\n \n

De variant Doorgehaald kent geen herregistratiedatum, dus de rij bestaat simpelweg niet.

\n
\n
\n\n \n 2 · RemoteData fold\n
\n
\n

Eén molecuul, vier elkaar uitsluitende toestanden

\n

Loading

\n {{ v }}\n

Empty

\n {{ v }}\n

Failure

\n {{ v }}\n

Success

\n
    @for (i of v; track i) {
  • {{ i }}
  • }
\n
\n
\n

De exhaustieve fold

\n
{{ foldCode }}
\n

Een nieuwe variant toevoegen breekt de compile via assertNever tot je hem afhandelt.

\n
\n
\n\n \n 3 · Parse, don't validate\n
\n
\n

Smart constructor → Result

\n \n
\n
\n @if (parsed().ok) {\n

ok

\n
Postcode = \"{{ parsed().ok ? $any(parsed()).value : '' }}\"
\n

Een gevalideerde Postcode is een ander type dan een ruwe string.

\n } @else {\n

err

\n
{{ $any(parsed()).error }}
\n }\n
\n
\n\n \n 4 · Form als state machine\n
\n
\n

Fout — losse booleans

\n
{{ machineBad }}
\n

Niets verhindert \"submitting\" mét validatiefouten of een successcherm met errors.

\n
\n
\n

Goed — één tagged union stuurt de UI

\n \n
\n
\n
\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('resolved', [])", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 124 }, { "name": "errorRes", "defaultValue": "fakeResource('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('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('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": "

Teaching showcase: each section pairs the impossible-state-permitting "before"\nwith the "after" where the type system rules it out. Composition-only.

\n", "rawdescription": "\nTeaching showcase: each section pairs the impossible-state-permitting \"before\"\nwith the \"after\" where the type system rules it out. Composition-only.", "type": "component", "sourceCode": "import { Component, computed, signal } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport type { Resource } from '@angular/core';\nimport { PageShellComponent } from '../../templates/page-shell/page-shell.component';\nimport { HeadingComponent } from '../../atoms/heading/heading.component';\nimport { AlertComponent } from '../../atoms/alert/alert.component';\nimport { TextInputComponent } from '../../atoms/text-input/text-input.component';\nimport { ASYNC } from '../../molecules/async/async.component';\nimport { SkeletonComponent } from '../../atoms/skeleton/skeleton.component';\nimport { RegistrationSummaryComponent } from '../../organisms/registration-summary/registration-summary.component';\nimport { HerregistratieWizardComponent } from '../../organisms/herregistratie-wizard/herregistratie-wizard.component';\nimport { Registration } from '../../core/models';\nimport { parsePostcode } from '../../core/parse';\n\n/** Minimal fake Resource so can be driven through every state without HTTP. */\nfunction fakeResource(status: string, value?: T, error?: Error): Resource {\n return { value: () => value as T, status: () => status, error: () => error, hasValue: () => value !== undefined, reload: () => {} } as unknown as Resource;\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 \n \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 \n\n \n 1 · Discriminated unions\n
\n
\n

Fout — vlakke interface

\n
{{ unionBad }}
\n

Een doorgehaalde registratie houdt tóch een herregistratiedatum: onmogelijke toestand.

\n
\n
\n

Goed — sum type

\n \n

De variant Doorgehaald kent geen herregistratiedatum, dus de rij bestaat simpelweg niet.

\n
\n
\n\n \n 2 · RemoteData fold\n
\n
\n

Eén molecuul, vier elkaar uitsluitende toestanden

\n

Loading

\n {{ v }}\n

Empty

\n {{ v }}\n

Failure

\n {{ v }}\n

Success

\n
    @for (i of v; track i) {
  • {{ i }}
  • }
\n
\n
\n

De exhaustieve fold

\n
{{ foldCode }}
\n

Een nieuwe variant toevoegen breekt de compile via assertNever tot je hem afhandelt.

\n
\n
\n\n \n 3 · Parse, don't validate\n
\n
\n

Smart constructor → Result

\n \n
\n
\n @if (parsed().ok) {\n

ok

\n
Postcode = \"{{ parsed().ok ? $any(parsed()).value : '' }}\"
\n

Een gevalideerde Postcode is een ander type dan een ruwe string.

\n } @else {\n

err

\n
{{ $any(parsed()).error }}
\n }\n
\n
\n\n \n 4 · Form als state machine\n
\n
\n

Fout — losse booleans

\n
{{ machineBad }}
\n

Niets verhindert \"submitting\" mét validatiefouten of een successcherm met errors.

\n
\n
\n

Goed — één tagged union stuurt de UI

\n \n
\n
\n
\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('loading');\n emptyRes = fakeResource('resolved', []);\n errorRes = fakeResource('error', undefined, new Error('Demo'));\n successRes = fakeResource('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-f363992c5154b037dc0dc2a461da66f9a297af7bc7ba9dd9f19a1bef213af9b9fb15a92e6d5e1922040acbf5aa3f7ec27db8035944e496c8f97bb519b4652cb3", "file": "src/app/pages/dashboard/dashboard.page.ts", "encapsulation": [], "entryComponents": [], "inputs": [], "outputs": [], "providers": [], "selector": "app-dashboard-page", "styleUrls": [], "styles": [], "template": "\n \n \n \n \n \n \n \n \n \n\n
\n Specialismen en aantekeningen\n \n \n \n \n \n \n \n \n

U heeft nog geen specialismen of aantekeningen.

\n
\n
\n
\n\n

\n Gegevens bekijken of een wijziging doorgeven →\n

\n

\n Herregistratie aanvragen →\n

\n

\n Functionele patronen (impossible states) →\n

\n
\n", "templateUrl": [], "viewProviders": [], "hostDirectives": [], "inputsClass": [], "outputsClass": [], "propertiesClass": [ { "name": "notes", "defaultValue": "this.svc.aantekeningenResource()", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 60 }, { "name": "notesEmpty", "defaultValue": "() => {...}", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 61 }, { "name": "reg", "defaultValue": "this.svc.registrationResource()", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 59 }, { "name": "regEmpty", "defaultValue": "() => {...}", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 62 }, { "name": "svc", "defaultValue": "inject(RegistrationService)", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 58, "modifierKind": [ 123 ] } ], "methodsClass": [], "deprecated": false, "deprecationMessage": "", "hostBindings": [], "hostListeners": [], "standalone": false, "imports": [ { "name": "PageShellComponent", "type": "component" }, { "name": "HeadingComponent", "type": "component" }, { "name": "LinkComponent", "type": "component" }, { "name": "SkeletonComponent", "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 '../../templates/page-shell/page-shell.component';\nimport { HeadingComponent } from '../../atoms/heading/heading.component';\nimport { LinkComponent } from '../../atoms/link/link.component';\nimport { SkeletonComponent } from '../../atoms/skeleton/skeleton.component';\nimport { ASYNC } from '../../molecules/async/async.component';\nimport { RegistrationSummaryComponent } from '../../organisms/registration-summary/registration-summary.component';\nimport { RegistrationTableComponent } from '../../organisms/registration-table/registration-table.component';\nimport { RegistrationService } from '../../core/registration.service';\nimport { Aantekening } from '../../core/models';\n\n@Component({\n selector: 'app-dashboard-page',\n imports: [\n PageShellComponent, HeadingComponent, LinkComponent, SkeletonComponent, ...ASYNC,\n RegistrationSummaryComponent, RegistrationTableComponent,\n ],\n template: `\n \n \n \n \n \n \n \n \n \n \n\n
\n Specialismen en aantekeningen\n \n \n \n \n \n \n \n \n

U heeft nog geen specialismen of aantekeningen.

\n
\n
\n
\n\n

\n Gegevens bekijken of een wijziging doorgeven →\n

\n

\n Herregistratie aanvragen →\n

\n

\n Functionele patronen (impossible states) →\n

\n
\n `,\n})\nexport class DashboardPage {\n private svc = inject(RegistrationService);\n reg = this.svc.registrationResource();\n notes = this.svc.aantekeningenResource();\n notesEmpty = (v: Aantekening[]) => v.length === 0;\n regEmpty = (v: unknown) => !v || Object.keys(v).length === 0;\n}\n", "assetsDirs": [], "styleUrlsData": "", "stylesData": "", "extends": [] }, { "name": "DataRowComponent", "id": "component-DataRowComponent-bf012e0b5e277c5c6d53311a7649373316677ab4f6d5ba0b313f5eaeb5a061ea55cb08b0af237c487dcc3be5b15014d5c2b21b6f6903ff7689881fc8607eb1b2", "file": "src/app/molecules/data-row/data-row.component.ts", "encapsulation": [], "entryComponents": [], "inputs": [], "outputs": [], "providers": [], "selector": "app-data-row", "styleUrls": [], "styles": [], "template": "
\n
{{ key() }}
\n
{{ value() }}
\n
\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": "

Molecule: one key/value row inside an RHC data-summary.\nWrap several of these in .rhc-data-summary (see registration-summary).

\n", "rawdescription": "\nMolecule: one key/value row inside an RHC data-summary.\nWrap several of these in .rhc-data-summary (see registration-summary).", "type": "component", "sourceCode": "import { Component, input } from '@angular/core';\n\n/** Molecule: one key/value row inside an RHC data-summary.\n Wrap several of these in .rhc-data-summary (see registration-summary). */\n@Component({\n selector: 'app-data-row',\n template: `\n
\n
{{ key() }}
\n
{{ value() }}
\n
\n `,\n})\nexport class DataRowComponent {\n key = input.required();\n value = input('');\n}\n", "assetsDirs": [], "styleUrlsData": "", "stylesData": "", "extends": [] }, { "name": "FormFieldComponent", "id": "component-FormFieldComponent-9f7fb7fac967056161f8440bccbd87825bc2897463f63a612a12ac6154cfaa4e17a2a6469fbe936deba74319ac6029c6aa024abfc07095b226f5980e654cb12c", "file": "src/app/molecules/form-field/form-field.component.ts", "encapsulation": [], "entryComponents": [], "inputs": [], "outputs": [], "providers": [], "selector": "app-form-field", "styleUrls": [], "styles": [], "template": "
\n \n @if (description()) {\n
{{ description() }}
\n }\n \n @if (error()) {\n
{{ error() }}
\n }\n
\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": "

Molecule: form field = label + projected control + optional error/description.\nReused by both the login form and the change-request form.

\n", "rawdescription": "\nMolecule: form field = label + projected control + optional error/description.\nReused by both the login form and the change-request form.", "type": "component", "sourceCode": "import { Component, input } from '@angular/core';\n\n/** Molecule: form field = label + projected control + optional error/description.\n Reused by both the login form and the change-request form. */\n@Component({\n selector: 'app-form-field',\n template: `\n
\n \n @if (description()) {\n
{{ description() }}
\n }\n \n @if (error()) {\n
{{ error() }}
\n }\n
\n `,\n})\nexport class FormFieldComponent {\n label = input.required();\n fieldId = input.required();\n description = input();\n error = input();\n}\n", "assetsDirs": [], "styleUrlsData": "", "stylesData": "", "extends": [] }, { "name": "HeadingComponent", "id": "component-HeadingComponent-0f0b442fc9ccbfde8481137b728000bb093868ddc931f507bbd4a86ee528820cf4c6dab36a9a82b4a940bb96c2355f42bc34a94700acc7df3e7dfeea627be67c", "file": "src/app/atoms/heading/heading.component.ts", "encapsulation": [], "entryComponents": [], "inputs": [], "outputs": [], "providers": [], "selector": "app-heading", "styleUrls": [], "styles": [], "template": "\n@switch (level()) {\n @case (1) {

}\n @case (2) {

}\n @case (3) {

}\n @case (4) {

}\n @default {
}\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": "

Atom: heading. Renders the right h1..h5 with RHC heading styling.\nSingle captured in a template — multiple ng-content across

\n", "rawdescription": "\nAtom: heading. Renders the right h1..h5 with RHC heading styling.\nSingle 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 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 \n @switch (level()) {\n @case (1) {

}\n @case (2) {

}\n @case (3) {

}\n @case (4) {

}\n @default {
}\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-e6eeb0932b0d6c7f4073bda82d95601ef7d31f17ac310061dcf3347c8f30d1444f50e124bfedda286285ebfda9932bb075fdaf20683413b524570e51fa350c3f", "file": "src/app/pages/herregistratie/herregistratie.page.ts", "encapsulation": [], "entryComponents": [], "inputs": [], "outputs": [], "providers": [], "selector": "app-herregistratie-page", "styleUrls": [], "styles": [], "template": "\n \n Uw huidige registratie verloopt op 1 september 2027. Vraag tijdig herregistratie aan.\n \n
\n \n
\n
\n", "templateUrl": [], "viewProviders": [], "hostDirectives": [], "inputsClass": [], "outputsClass": [], "propertiesClass": [], "methodsClass": [], "deprecated": false, "deprecationMessage": "", "hostBindings": [], "hostListeners": [], "standalone": false, "imports": [ { "name": "PageShellComponent", "type": "component" }, { "name": "AlertComponent", "type": "component" }, { "name": "HerregistratieWizardComponent", "type": "component" } ], "description": "

A whole new page built from existing building blocks — no new components.\nThis is the atomic-design payoff: a new flow is just composition.

\n", "rawdescription": "\nA whole new page built from existing building blocks — no new components.\nThis is the atomic-design payoff: a new flow is just composition.", "type": "component", "sourceCode": "import { Component } from '@angular/core';\nimport { PageShellComponent } from '../../templates/page-shell/page-shell.component';\nimport { AlertComponent } from '../../atoms/alert/alert.component';\nimport { HerregistratieWizardComponent } from '../../organisms/herregistratie-wizard/herregistratie-wizard.component';\n\n/** A whole new page built from existing building blocks — no new components.\n This is the atomic-design payoff: a new flow is just composition. */\n@Component({\n selector: 'app-herregistratie-page',\n imports: [PageShellComponent, AlertComponent, HerregistratieWizardComponent],\n template: `\n \n \n Uw huidige registratie verloopt op 1 september 2027. Vraag tijdig herregistratie aan.\n \n
\n \n
\n
\n `,\n})\nexport class HerregistratiePage {}\n", "assetsDirs": [], "styleUrlsData": "", "stylesData": "", "extends": [] }, { "name": "HerregistratieWizardComponent", "id": "component-HerregistratieWizardComponent-ad587121f38c0c6e6bb4c8525e7b626054b7790ec708c99a0f6e66b3b7703b935b47c6b141072f7f8c9e567974dd162961ef5e17b983e373d6d7a3a7814aaf80", "file": "src/app/organisms/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

Stap {{ step() }} van 2

\n
\n @if (step() === 1) {\n \n \n \n Volgende\n } @else {\n \n \n \n
\n Vorige\n Herregistratie aanvragen\n
\n }\n
\n }\n @case ('Submitting') {\n Aanvraag wordt verwerkt…\n }\n @case ('Submitted') {\n Uw aanvraag tot herregistratie is ontvangen.\n }\n @case ('Failed') {\n Indienen mislukt. Probeer het opnieuw.\n
\n Opnieuw proberen\n
\n }\n}\n", "templateUrl": [], "viewProviders": [], "hostDirectives": [], "inputsClass": [ { "name": "seed", "defaultValue": "initial", "deprecated": false, "deprecationMessage": "", "type": "WizardState", "indexKey": "", "optional": false, "description": "

Optional seed so Storybook / the showcase can mount any state directly.

\n", "line": 58, "rawdescription": "\nOptional seed so Storybook / the showcase can mount any state directly.", "required": false } ], "outputsClass": [], "propertiesClass": [ { "name": "back", "defaultValue": "back", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 61 }, { "name": "draft", "defaultValue": "computed(() => this.editing()?.draft ?? { uren: '', punten: '' })", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 65, "modifierKind": [ 124 ] }, { "name": "editing", "defaultValue": "computed(() => (this.state().tag === 'Editing' ? (this.state() as Extract) : null))", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 63, "modifierKind": [ 123 ] }, { "name": "errPunten", "defaultValue": "computed(() => this.editing()?.errors.punten ?? '')", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 67, "modifierKind": [ 124 ] }, { "name": "errUren", "defaultValue": "computed(() => this.editing()?.errors.uren ?? '')", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 66, "modifierKind": [ 124 ] }, { "name": "state", "defaultValue": "signal(initial)", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 59 }, { "name": "step", "defaultValue": "computed(() => this.editing()?.step ?? 1)", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 64, "modifierKind": [ 124 ] } ], "methodsClass": [ { "name": "onPrimary", "args": [], "optional": false, "returnType": "void", "typeParameters": [], "line": 79, "deprecated": false, "deprecationMessage": "" }, { "name": "onRetry", "args": [], "optional": false, "returnType": "void", "typeParameters": [], "line": 86, "deprecated": false, "deprecationMessage": "" }, { "name": "runIfSubmitting", "args": [], "optional": false, "returnType": "void", "typeParameters": [], "line": 94, "deprecated": false, "deprecationMessage": "", "modifierKind": [ 123 ] }, { "name": "set", "args": [ { "name": "key", "type": "unknown", "optional": false, "dotDotDotToken": false, "deprecated": false, "deprecationMessage": "" }, { "name": "value", "type": "string", "optional": false, "dotDotDotToken": false, "deprecated": false, "deprecationMessage": "" } ], "optional": false, "returnType": "void", "typeParameters": [], "line": 73, "deprecated": false, "deprecationMessage": "", "jsdoctags": [ { "name": "key", "type": "unknown", "optional": false, "dotDotDotToken": false, "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } }, { "name": "value", "type": "string", "optional": false, "dotDotDotToken": false, "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] } ], "deprecated": false, "deprecationMessage": "", "hostBindings": [], "hostListeners": [], "standalone": false, "imports": [ { "name": "FormsModule", "type": "module" }, { "name": "FormFieldComponent", "type": "component" }, { "name": "TextInputComponent", "type": "component" }, { "name": "ButtonComponent", "type": "component" }, { "name": "AlertComponent", "type": "component" }, { "name": "SpinnerComponent", "type": "component" } ], "description": "

Organism: multi-step herregistratie wizard driven entirely by a state\nmachine (wizard.machine.ts). The signal IS the union, so the UI just folds\nover its tag — no booleans like submitting/submitted that could contradict\neach other. Composition-only: reuses existing form-field/input/button/alert.

\n", "rawdescription": "\nOrganism: multi-step herregistratie wizard driven entirely by a state\nmachine (wizard.machine.ts). The signal IS the union, so the UI just folds\nover its tag — no booleans like `submitting`/`submitted` that could contradict\neach other. Composition-only: reuses existing form-field/input/button/alert.", "type": "component", "sourceCode": "import { Component, computed, input, signal } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FormFieldComponent } from '../../molecules/form-field/form-field.component';\nimport { TextInputComponent } from '../../atoms/text-input/text-input.component';\nimport { ButtonComponent } from '../../atoms/button/button.component';\nimport { AlertComponent } from '../../atoms/alert/alert.component';\nimport { SpinnerComponent } from '../../atoms/spinner/spinner.component';\nimport { ok } from '../../core/fp';\nimport { WizardState, Draft, initial, next, back, submit, resolve } from './wizard.machine';\n\n/** Organism: multi-step herregistratie wizard driven entirely by a state\n machine (wizard.machine.ts). The signal IS the union, so the UI just folds\n over its tag — no booleans like `submitting`/`submitted` that could contradict\n each other. Composition-only: reuses existing form-field/input/button/alert. */\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

Stap {{ step() }} van 2

\n
\n @if (step() === 1) {\n \n \n \n Volgende\n } @else {\n \n \n \n
\n Vorige\n Herregistratie aanvragen\n
\n }\n
\n }\n @case ('Submitting') {\n Aanvraag wordt verwerkt…\n }\n @case ('Submitted') {\n Uw aanvraag tot herregistratie is ontvangen.\n }\n @case ('Failed') {\n Indienen mislukt. Probeer het opnieuw.\n
\n Opnieuw proberen\n
\n }\n }\n `,\n})\nexport class HerregistratieWizardComponent {\n /** Optional seed so Storybook / the showcase can mount any state directly. */\n seed = input(initial);\n state = signal(initial);\n\n back = back;\n\n private editing = computed(() => (this.state().tag === 'Editing' ? (this.state() as Extract) : null));\n protected step = computed(() => this.editing()?.step ?? 1);\n protected draft = computed(() => this.editing()?.draft ?? { uren: '', punten: '' });\n protected errUren = computed(() => this.editing()?.errors.uren ?? '');\n protected errPunten = computed(() => this.editing()?.errors.punten ?? '');\n\n constructor() {\n queueMicrotask(() => this.state.set(this.seed()));\n }\n\n set(key: keyof Draft, value: string) {\n const s = this.state();\n if (s.tag !== 'Editing') return;\n this.state.set({ ...s, draft: { ...s.draft, [key]: value } });\n }\n\n onPrimary() {\n const s = this.state();\n if (s.tag !== 'Editing') return;\n this.state.set(s.step === 1 ? next(s) : submit(s));\n this.runIfSubmitting();\n }\n\n onRetry() {\n const s = this.state();\n if (s.tag !== 'Failed') return;\n this.state.set({ tag: 'Submitting', data: s.data });\n this.runIfSubmitting();\n }\n\n // ponytail: fake the backend with a timer; swap for a real httpResource call later.\n private runIfSubmitting() {\n if (this.state().tag !== 'Submitting') return;\n setTimeout(() => this.state.set(resolve(this.state(), ok(undefined))), 800);\n }\n}\n", "assetsDirs": [], "styleUrlsData": "", "stylesData": "", "constructorObj": { "name": "constructor", "description": "", "deprecated": false, "deprecationMessage": "", "args": [], "line": 67 }, "extends": [] }, { "name": "LinkComponent", "id": "component-LinkComponent-81d97782386b884f56c43d583cbf6d1005dda96974f169366a9af853aeb8b8f4e99f9cce2f9a7ef0fdafce32f51e6049483a44ab35614c486f82535b65ce2818", "file": "src/app/atoms/link/link.component.ts", "encapsulation": [], "entryComponents": [], "inputs": [], "outputs": [], "providers": [], "selector": "app-link", "styleUrls": [], "styles": [], "template": "", "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": "

Atom: link. Internal router link styled as an RHC/Utrecht link.

\n", "rawdescription": "\nAtom: link. Internal router link styled as an RHC/Utrecht link.", "type": "component", "sourceCode": "import { Component, input } from '@angular/core';\nimport { RouterLink } from '@angular/router';\n\n/** Atom: link. Internal router link styled as an RHC/Utrecht link. */\n@Component({\n selector: 'app-link',\n imports: [RouterLink],\n template: ``,\n})\nexport class LinkComponent {\n to = input.required();\n}\n", "assetsDirs": [], "styleUrlsData": "", "stylesData": "", "extends": [] }, { "name": "LoginFormComponent", "id": "component-LoginFormComponent-09b4fa4e3820031285372fc93c6a18697b3099647bf79b1869c466189d5041da442eaac2e437ae8efa5cd2546d72bbdbd9c001c24e8b1d26f363e763d0382e3d", "file": "src/app/organisms/login-form/login-form.component.ts", "encapsulation": [], "entryComponents": [], "inputs": [], "outputs": [], "providers": [], "selector": "app-login-form", "styleUrls": [], "styles": [], "template": "
\n \n \n \n\n \n \n \n\n
\n Inloggen met DigiD\n
\n
\n", "templateUrl": [], "viewProviders": [], "hostDirectives": [], "inputsClass": [], "outputsClass": [ { "name": "submit", "deprecated": false, "deprecationMessage": "", "type": "void", "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": "

Organism: DigiD-style mock login. No real auth — just composes atoms/molecules.

\n", "rawdescription": "\nOrganism: DigiD-style mock login. No real auth — just composes atoms/molecules.", "type": "component", "sourceCode": "import { Component, output } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FormFieldComponent } from '../../molecules/form-field/form-field.component';\nimport { TextInputComponent } from '../../atoms/text-input/text-input.component';\nimport { ButtonComponent } from '../../atoms/button/button.component';\n\n/** Organism: DigiD-style mock login. No real auth — just composes atoms/molecules. */\n@Component({\n selector: 'app-login-form',\n imports: [FormsModule, FormFieldComponent, TextInputComponent, ButtonComponent],\n template: `\n
\n \n \n \n\n \n \n \n\n
\n Inloggen met DigiD\n
\n
\n `,\n})\nexport class LoginFormComponent {\n bsn = '';\n password = '';\n submit = output();\n}\n", "assetsDirs": [], "styleUrlsData": "", "stylesData": "", "extends": [] }, { "name": "LoginPage", "id": "component-LoginPage-e8a9fcb0309464188c46b54292e1b26314533e424703d8d6d84a1cffe31832e80d7ae8fe256da4b42d053ec775301d70502a9022e092ee0b2d10c7777baf1913", "file": "src/app/pages/login/login.page.ts", "encapsulation": [], "entryComponents": [], "inputs": [], "outputs": [], "providers": [], "selector": "app-login-page", "styleUrls": [], "styles": [], "template": "\n \n\n", "templateUrl": [], "viewProviders": [], "hostDirectives": [], "inputsClass": [], "outputsClass": [], "propertiesClass": [ { "name": "router", "defaultValue": "inject(Router)", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 17, "modifierKind": [ 123 ] } ], "methodsClass": [ { "name": "login", "args": [], "optional": false, "returnType": "void", "typeParameters": [], "line": 18, "deprecated": false, "deprecationMessage": "" } ], "deprecated": false, "deprecationMessage": "", "hostBindings": [], "hostListeners": [], "standalone": false, "imports": [ { "name": "PageShellComponent", "type": "component" }, { "name": "LoginFormComponent", "type": "component" } ], "description": "", "rawdescription": "\n", "type": "component", "sourceCode": "import { Component, inject } from '@angular/core';\nimport { Router } from '@angular/router';\nimport { PageShellComponent } from '../../templates/page-shell/page-shell.component';\nimport { LoginFormComponent } from '../../organisms/login-form/login-form.component';\n\n@Component({\n selector: 'app-login-page',\n imports: [PageShellComponent, LoginFormComponent],\n template: `\n \n \n \n `,\n})\nexport class LoginPage {\n private router = inject(Router);\n login() { this.router.navigate(['/dashboard']); }\n}\n", "assetsDirs": [], "styleUrlsData": "", "stylesData": "", "extends": [] }, { "name": "PageShellComponent", "id": "component-PageShellComponent-f2d3224d1fdc66ba96a373ea16cc259b086450cd1700c9f2b59b9f3193d96b4cd69bc9218497aa73519a3545157d691f273fb410f78d9f7fe9373e5921be9c1b", "file": "src/app/templates/page-shell/page-shell.component.ts", "encapsulation": [], "entryComponents": [], "inputs": [], "outputs": [], "providers": [], "selector": "app-page-shell", "styleUrls": [], "styles": [ ":host{display:block}" ], "template": "
\n @if (backLink()) {\n

← {{ backLabel() }}

\n }\n {{ heading() }}\n @if (intro()) {\n

{{ intro() }}

\n }\n \n
\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": "

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).

\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 '../../atoms/heading/heading.component';\nimport { LinkComponent } from '../../atoms/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
\n @if (backLink()) {\n

← {{ backLabel() }}

\n }\n {{ heading() }}\n @if (intro()) {\n

{{ intro() }}

\n }\n \n
\n `,\n})\nexport class PageShellComponent {\n heading = input.required();\n intro = input();\n backLink = input();\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-efb92f879b64c25c80211fcc675636fad2b1709613792834a68cec3b82982d290d7f04e97dd3186900b77a5922cd219f565fbf9a9957ec78e2321ad7e2eb30dc", "file": "src/app/pages/registration-detail/registration-detail.page.ts", "encapsulation": [], "entryComponents": [], "inputs": [], "outputs": [], "providers": [], "selector": "app-registration-detail-page", "styleUrls": [], "styles": [], "template": "\n \n \n \n \n \n \n \n \n\n
\n @if (submitted()) {\n Uw adreswijziging is ontvangen. U ontvangt binnen 5 werkdagen bericht.\n } @else {\n \n }\n
\n
\n", "templateUrl": [], "viewProviders": [], "hostDirectives": [], "inputsClass": [], "outputsClass": [], "propertiesClass": [ { "name": "reg", "defaultValue": "this.svc.registrationResource()", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 39 }, { "name": "regEmpty", "defaultValue": "() => {...}", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 40 }, { "name": "submitted", "defaultValue": "signal(false)", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 41 }, { "name": "svc", "defaultValue": "inject(RegistrationService)", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 38, "modifierKind": [ 123 ] } ], "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 '../../templates/page-shell/page-shell.component';\nimport { AlertComponent } from '../../atoms/alert/alert.component';\nimport { SkeletonComponent } from '../../atoms/skeleton/skeleton.component';\nimport { ASYNC } from '../../molecules/async/async.component';\nimport { RegistrationSummaryComponent } from '../../organisms/registration-summary/registration-summary.component';\nimport { ChangeRequestFormComponent } from '../../organisms/change-request-form/change-request-form.component';\nimport { RegistrationService } from '../../core/registration.service';\n\n@Component({\n selector: 'app-registration-detail-page',\n imports: [\n PageShellComponent, AlertComponent, SkeletonComponent, ...ASYNC,\n RegistrationSummaryComponent, ChangeRequestFormComponent,\n ],\n template: `\n \n \n \n \n \n \n \n \n \n\n
\n @if (submitted()) {\n Uw adreswijziging is ontvangen. U ontvangt binnen 5 werkdagen bericht.\n } @else {\n \n }\n
\n
\n `,\n})\nexport class RegistrationDetailPage {\n private svc = inject(RegistrationService);\n reg = this.svc.registrationResource();\n regEmpty = (v: unknown) => !v || Object.keys(v).length === 0;\n submitted = signal(false);\n}\n", "assetsDirs": [], "styleUrlsData": "", "stylesData": "", "extends": [] }, { "name": "RegistrationSummaryComponent", "id": "component-RegistrationSummaryComponent-cad630ad4fd52e8743ba17ebf8f1cf8362c4f8677937ac6e41fadc055438d0c35c6756d7f2d39b67239ceb2af09e0a11c141fa9cd398f80e5d18a8e6960d90ee", "file": "src/app/organisms/registration-summary/registration-summary.component.ts", "encapsulation": [], "entryComponents": [], "inputs": [], "outputs": [], "providers": [], "selector": "app-registration-summary", "styleUrls": [], "styles": [], "template": "
\n
\n \n \n \n \n \n \n \n \n @switch (reg().status.tag) {\n @case ('Geregistreerd') {\n \n }\n @case ('Geschorst') {\n \n \n }\n @case ('Doorgehaald') {\n \n \n }\n }\n
\n
\n", "templateUrl": [], "viewProviders": [], "hostDirectives": [], "inputsClass": [ { "name": "reg", "deprecated": false, "deprecationMessage": "", "type": "Registration", "indexKey": "", "optional": false, "description": "", "line": 40, "required": true } ], "outputsClass": [], "propertiesClass": [], "methodsClass": [], "deprecated": false, "deprecationMessage": "", "hostBindings": [], "hostListeners": [], "standalone": false, "imports": [ { "name": "DatePipe", "type": "pipe" }, { "name": "DataRowComponent", "type": "component" }, { "name": "StatusBadgeComponent", "type": "component" } ], "description": "

Organism: registration summary card. Composes data-row molecules + status-badge atom.

\n", "rawdescription": "\nOrganism: registration summary card. Composes data-row molecules + status-badge atom.", "type": "component", "sourceCode": "import { Component, input } from '@angular/core';\nimport { DatePipe } from '@angular/common';\nimport { Registration } from '../../core/models';\nimport { DataRowComponent } from '../../molecules/data-row/data-row.component';\nimport { StatusBadgeComponent } from '../../atoms/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
\n
\n \n \n \n \n \n \n \n \n @switch (reg().status.tag) {\n @case ('Geregistreerd') {\n \n }\n @case ('Geschorst') {\n \n \n }\n @case ('Doorgehaald') {\n \n \n }\n }\n
\n
\n `,\n})\nexport class RegistrationSummaryComponent {\n reg = input.required();\n}\n", "assetsDirs": [], "styleUrlsData": "", "stylesData": "", "extends": [] }, { "name": "RegistrationTableComponent", "id": "component-RegistrationTableComponent-53e1c5109b067c2b72ccd183e6350c59ea4bbd34a8f40a0f4e50c59d6165f5f8040177f74a592be42b8e571c4530ad2bf60c4a3a712689c82460997cb91ed770", "file": "src/app/organisms/registration-table/registration-table.component.ts", "encapsulation": [], "entryComponents": [], "inputs": [], "outputs": [], "providers": [], "selector": "app-registration-table", "styleUrls": [], "styles": [], "template": "
\n \n \n \n \n \n \n \n \n \n @for (row of rows(); track row.omschrijving) {\n \n \n \n \n \n }\n \n
TypeOmschrijvingDatum
{{ row.type }}{{ row.omschrijving }}{{ row.datum | date:'mediumDate' }}
\n
\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": "

Organism: table of specialismen/aantekeningen.

\n", "rawdescription": "\nOrganism: table of specialismen/aantekeningen.", "type": "component", "sourceCode": "import { Component, input } from '@angular/core';\nimport { DatePipe } from '@angular/common';\nimport { Aantekening } from '../../core/models';\n\n/** Organism: table of specialismen/aantekeningen. */\n@Component({\n selector: 'app-registration-table',\n imports: [DatePipe],\n template: `\n
\n \n \n \n \n \n \n \n \n \n @for (row of rows(); track row.omschrijving) {\n \n \n \n \n \n }\n \n
TypeOmschrijvingDatum
{{ row.type }}{{ row.omschrijving }}{{ row.datum | date:'mediumDate' }}
\n
\n `,\n})\nexport class RegistrationTableComponent {\n rows = input.required();\n}\n", "assetsDirs": [], "styleUrlsData": "", "stylesData": "", "extends": [] }, { "name": "ShellComponent", "id": "component-ShellComponent-a435ec99fc0234f16b0f1ab3b0860d9ec513acbf7cb2cefcaec3d7e36fd4c943f9b5e91c76481402563c62d8a63dd1363b29ac130c4d9a731839eccc4bbd12c2", "file": "src/app/templates/shell/shell.component.ts", "encapsulation": [], "entryComponents": [], "inputs": [], "outputs": [], "providers": [], "selector": "app-shell", "styleUrls": [], "styles": [ ":host{display:block}" ], "template": "Naar de inhoud\n
\n \n
\n
\n \n
\n
\n \n
\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": "

Template: persistent app chrome. Header + footer mount once; only the routed\ncontent inside changes (and cross-fades — see styles.scss).

\n", "rawdescription": "\nTemplate: persistent app chrome. Header + footer mount once; only the routed\ncontent inside changes (and cross-fades — see styles.scss).", "type": "component", "sourceCode": "import { Component } from '@angular/core';\nimport { RouterOutlet } from '@angular/router';\nimport { SiteHeaderComponent } from '../../organisms/site-header/site-header.component';\nimport { SiteFooterComponent } from '../../organisms/site-footer/site-footer.component';\n\n/** Template: persistent app chrome. Header + footer mount once; only the routed\n content inside 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 Naar de inhoud\n
\n \n
\n
\n \n
\n
\n \n
\n `,\n})\nexport class ShellComponent {}\n", "assetsDirs": [], "styleUrlsData": "", "stylesData": ":host{display:block}\n", "extends": [] }, { "name": "SiteFooterComponent", "id": "component-SiteFooterComponent-90391287c6e8f3ad80c034a7a6fdabdd0514fd9c0dcf549a8e4a2d3bc3d885fcd5a45a2eeeb24fa8a4bbcf2cfe865093d712765d9d1ed11b4bfca26d1fb35153", "file": "src/app/organisms/site-footer/site-footer.component.ts", "encapsulation": [], "entryComponents": [], "inputs": [], "outputs": [], "providers": [], "selector": "app-site-footer", "styleUrls": [], "styles": [ ":host{display:block}" ], "template": "
\n
\n BIG-register\n CIBG — Ministerie van Volksgezondheid, Welzijn en Sport\n Demo / POC — geen echte gegevens\n
\n
\n", "templateUrl": [], "viewProviders": [], "hostDirectives": [], "inputsClass": [], "outputsClass": [], "propertiesClass": [], "methodsClass": [], "deprecated": false, "deprecationMessage": "", "hostBindings": [], "hostListeners": [], "standalone": false, "imports": [], "description": "

Organism: site footer.

\n", "rawdescription": "\nOrganism: site footer.", "type": "component", "sourceCode": "import { Component } from '@angular/core';\n\n/** Organism: site footer. */\n@Component({\n selector: 'app-site-footer',\n styles: [':host{display:block}'],\n template: `\n
\n
\n BIG-register\n CIBG — Ministerie van Volksgezondheid, Welzijn en Sport\n Demo / POC — geen echte gegevens\n
\n
\n `,\n})\nexport class SiteFooterComponent {}\n", "assetsDirs": [], "styleUrlsData": "", "stylesData": ":host{display:block}\n", "extends": [] }, { "name": "SiteHeaderComponent", "id": "component-SiteHeaderComponent-710f1c109f26ae5f1888aa77ac682c58c9534fbba74aeae04b903e169f674c1ce04b8ae9e379a936c8ddef16e53c500e93d132021bcdd4ef743a601e05808f66", "file": "src/app/organisms/site-header/site-header.component.ts", "encapsulation": [], "entryComponents": [], "inputs": [], "outputs": [], "providers": [], "selector": "app-site-header", "styleUrls": [], "styles": [ ":host{display:block}" ], "template": "
\n \n
\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": "

Organism: site header with Rijksoverheid-style wordmark + title.\nponytail: text wordmark instead of the licensed Rijksoverheid logo.

\n", "rawdescription": "\nOrganism: site header with Rijksoverheid-style wordmark + title.\nponytail: text wordmark instead of the licensed Rijksoverheid logo.", "type": "component", "sourceCode": "import { Component, input } from '@angular/core';\nimport { RouterLink } from '@angular/router';\n\n/** Organism: site header with Rijksoverheid-style wordmark + title.\n ponytail: text wordmark instead of the licensed Rijksoverheid logo. */\n@Component({\n selector: 'app-site-header',\n imports: [RouterLink],\n // :host display:block so the full-bleed bar fills the flex column (custom\n // elements default to display:inline, which collapsed the bar to its content).\n styles: [':host{display:block}'],\n template: `\n
\n \n
\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/atoms/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
\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", "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": "

Atom: skeleton placeholder (grey shimmer). Delay-gated so it never flashes\non fast responses. Render count lines shaped roughly like the content.

\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
\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;\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/atoms/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
\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", "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": "

Atom: spinner that only appears after delay ms — fast responses never\nflash a spinner, slow ones get feedback.

\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
\n }\n `,\n})\nexport class SpinnerComponent implements OnInit, OnDestroy {\n delay = input(250);\n protected visible = signal(false);\n private timer?: ReturnType;\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-5cb9f831687f564e86bbc72b1276fd5b10bc1bc877bf15a2dfff580724e2795f7abdc861ad6ccce41846084a022c11d4c570924d3f7ec1388a1cd5e31b9fd8a2", "file": "src/app/atoms/status-badge/status-badge.component.ts", "encapsulation": [], "entryComponents": [], "inputs": [], "outputs": [], "providers": [], "selector": "app-status-badge", "styleUrls": [], "styles": [], "template": "\n \n {{ status() }}\n\n", "templateUrl": [], "viewProviders": [], "hostDirectives": [], "inputsClass": [ { "name": "status", "deprecated": false, "deprecationMessage": "", "type": "StatusTag", "indexKey": "", "optional": false, "description": "", "line": 18, "required": true } ], "outputsClass": [], "propertiesClass": [ { "name": "color", "defaultValue": "computed(() => {\n const tag = this.status();\n switch (tag) {\n case 'Geregistreerd':\n return 'var(--rhc-color-groen-500)';\n case 'Doorgehaald':\n return 'var(--rhc-color-rood-500)';\n case 'Geschorst':\n return 'var(--rhc-color-oranje-500)';\n default:\n return assertNever(tag);\n }\n })", "deprecated": false, "deprecationMessage": "", "type": "unknown", "indexKey": "", "optional": false, "description": "", "line": 19 } ], "methodsClass": [], "deprecated": false, "deprecationMessage": "", "hostBindings": [], "hostListeners": [], "standalone": false, "imports": [], "description": "

Atom: status badge = colored RHC dot-badge + label. The color is a total\nfunction of the status tag — assertNever makes a new status fail to compile\nuntil a color is chosen for it.

\n", "rawdescription": "\nAtom: status badge = colored RHC dot-badge + label. The color is a total\nfunction of the status tag — assertNever makes a new status fail to compile\nuntil a color is chosen for it.", "type": "component", "sourceCode": "import { Component, computed, input } from '@angular/core';\nimport { StatusTag } from '../../core/models';\nimport { assertNever } from '../../core/fp';\n\n/** Atom: status badge = colored RHC dot-badge + label. The color is a total\n function of the status tag — assertNever makes a new status fail to compile\n until a color is chosen for it. */\n@Component({\n selector: 'app-status-badge',\n template: `\n \n \n {{ status() }}\n \n `,\n})\nexport class StatusBadgeComponent {\n status = input.required();\n color = computed(() => {\n const tag = this.status();\n switch (tag) {\n case 'Geregistreerd':\n return 'var(--rhc-color-groen-500)';\n case 'Doorgehaald':\n return 'var(--rhc-color-rood-500)';\n case 'Geschorst':\n return 'var(--rhc-color-oranje-500)';\n default:\n return assertNever(tag);\n }\n });\n}\n", "assetsDirs": [], "styleUrlsData": "", "stylesData": "", "extends": [] }, { "name": "TextInputComponent", "id": "component-TextInputComponent-9d0cd6c2d7892958e9a016b570670f0186d410ea16a22925126f9eeea1aa178f081a4e5647af633f8a0bc1c458422a9f30169f159f930e9048702995fbb827e6", "file": "src/app/atoms/text-input/text-input.component.ts", "encapsulation": [], "entryComponents": [], "inputs": [], "outputs": [], "providers": [ { "name": ")" } ], "selector": "app-text-input", "styleUrls": [], "styles": [], "template": "\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": "

Atom: text input. Utrecht textbox wired up as a form control (ngModel/reactive).

\n", "rawdescription": "\nAtom: text input. Utrecht textbox wired up as a form control (ngModel/reactive).", "type": "component", "sourceCode": "import { Component, forwardRef, input } from '@angular/core';\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\n\n/** Atom: text input. Utrecht textbox wired up as a form control (ngModel/reactive). */\n@Component({\n selector: 'app-text-input',\n template: `\n \n `,\n providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => TextInputComponent), multi: true }],\n})\nexport class TextInputComponent implements ControlValueAccessor {\n type = input<'text' | 'password' | 'email'>('text');\n placeholder = input('');\n invalid = input(false);\n inputId = input();\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/molecules/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": "

Convenience: import this array to get the wrapper + all slot directives.

\n" }, { "name": "err", "ctype": "miscellaneous", "subtype": "variable", "file": "src/app/core/fp.ts", "deprecated": false, "deprecationMessage": "", "type": "unknown", "defaultValue": "(error: E): Result => ({ ok: false, error })" }, { "name": "initial", "ctype": "miscellaneous", "subtype": "variable", "file": "src/app/organisms/herregistratie-wizard/wizard.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/core/fp.ts", "deprecated": false, "deprecationMessage": "", "type": "unknown", "defaultValue": "(value: T): Result => ({ 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('./pages/login/login.page').then(m => m.LoginPage)\" },\n { path: 'dashboard', loadComponent: () => \"import('./pages/dashboard/dashboard.page').then(m => m.DashboardPage)\" },\n { path: 'registratie', loadComponent: () => \"import('./pages/registration-detail/registration-detail.page').then(m => m.RegistrationDetailPage)\" },\n { path: 'herregistratie', loadComponent: () => \"import('./pages/herregistratie/herregistratie.page').then(m => m.HerregistratiePage)\" },\n { path: 'concepts', loadComponent: () => \"import('./pages/concepts/concepts.page').then(m => m.ConceptsPage)\" },\n { path: '**', redirectTo: 'login' },\n ],\n },\n]" }, { "name": "scenarioInterceptor", "ctype": "miscellaneous", "subtype": "variable", "file": "src/app/core/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": "

Demo-only: rewrites the timing/outcome of mock data requests based on\n?scenario= so loading / empty / error states can be shown on demand.\nReal requests are untouched.

\n" }, { "name": "VALID", "ctype": "miscellaneous", "subtype": "variable", "file": "src/app/core/scenario.ts", "deprecated": false, "deprecationMessage": "", "type": "Scenario[]", "defaultValue": "['default', 'slow', 'loading', 'empty', 'error']" } ], "functions": [ { "name": "assertNever", "file": "src/app/core/fp.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "

Tiny native-TS functional toolkit. No dependency — this is the whole "library".\nReused by every "impossible states" concept in the POC.

\n", "args": [ { "name": "x", "type": "never", "deprecated": false, "deprecationMessage": "" } ], "returnType": "never", "jsdoctags": [ { "name": "x", "type": "never", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "back", "file": "src/app/organisms/herregistratie-wizard/wizard.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": "currentScenario", "file": "src/app/core/scenario.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "

Reads ?scenario= from the URL so a demo can force each async state.

\n", "args": [], "returnType": "Scenario" }, { "name": "fakeResource", "file": "src/app/pages/concepts/concepts.page.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "

Minimal fake Resource so can be driven through every state without HTTP.

\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", "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/core/remote-data.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "

Exhaustive fold: you must handle every case, checked at compile time.

\n", "args": [ { "name": "rd", "type": "RemoteData", "deprecated": false, "deprecationMessage": "" }, { "name": "h", "deprecated": false, "deprecationMessage": "" } ], "returnType": "R", "jsdoctags": [ { "name": "rd", "type": "RemoteData", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } }, { "name": "h", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "fromResource", "file": "src/app/core/remote-data.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "

Project Angular's loosely-typed Resource into a RemoteData value.

\n", "args": [ { "name": "r", "type": "Resource", "deprecated": false, "deprecationMessage": "" }, { "name": "isEmpty", "deprecated": false, "deprecationMessage": "", "defaultValue": "() => false" } ], "returnType": "RemoteData", "jsdoctags": [ { "name": "r", "type": "Resource", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } }, { "name": "isEmpty", "deprecated": false, "deprecationMessage": "", "defaultValue": "() => false", "tagName": { "text": "param" } } ] }, { "name": "next", "file": "src/app/organisms/herregistratie-wizard/wizard.machine.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "

Step 1 → 2: only advance if the uren field parses. Illegal elsewhere = no-op.

\n", "args": [ { "name": "s", "type": "WizardState", "deprecated": false, "deprecationMessage": "" } ], "returnType": "WizardState", "jsdoctags": [ { "name": "s", "type": "WizardState", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "parsePostcode", "file": "src/app/core/parse.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "", "args": [ { "name": "raw", "type": "string", "deprecated": false, "deprecationMessage": "" } ], "returnType": "Result", "jsdoctags": [ { "name": "raw", "type": "string", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "parseUren", "file": "src/app/core/parse.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "", "args": [ { "name": "raw", "type": "string", "deprecated": false, "deprecationMessage": "" } ], "returnType": "Result", "jsdoctags": [ { "name": "raw", "type": "string", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "resolve", "file": "src/app/organisms/herregistratie-wizard/wizard.machine.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "

Resolve the async submit. Only meaningful while Submitting.

\n", "args": [ { "name": "s", "type": "WizardState", "deprecated": false, "deprecationMessage": "" }, { "name": "r", "type": "Result", "deprecated": false, "deprecationMessage": "" } ], "returnType": "WizardState", "jsdoctags": [ { "name": "s", "type": "WizardState", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } }, { "name": "r", "type": "Result", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "submit", "file": "src/app/organisms/herregistratie-wizard/wizard.machine.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "

Step 2 submit: parse everything; move to Submitting only with Valid data.

\n", "args": [ { "name": "s", "type": "WizardState", "deprecated": false, "deprecationMessage": "" } ], "returnType": "WizardState", "jsdoctags": [ { "name": "s", "type": "WizardState", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "validate", "file": "src/app/organisms/herregistratie-wizard/wizard.machine.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "

Parse every field; on success hand back a Valid, else the per-field errors.

\n", "args": [ { "name": "draft", "type": "Draft", "deprecated": false, "deprecationMessage": "" } ], "returnType": "Result>, 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/atoms/alert/alert.component.ts", "deprecated": false, "deprecationMessage": "", "description": "", "kind": 193 }, { "name": "Brand", "ctype": "miscellaneous", "subtype": "typealias", "rawtype": "unknown", "file": "src/app/core/fp.ts", "deprecated": false, "deprecationMessage": "", "description": "

Nominal typing: Brand<string, 'Postcode'> is assignable from a plain string\nonly through an explicit cast — so a smart constructor is the only minter.

\n", "kind": 194 }, { "name": "Postcode", "ctype": "miscellaneous", "subtype": "typealias", "rawtype": "Brand", "file": "src/app/core/parse.ts", "deprecated": false, "deprecationMessage": "", "description": "

"Parse, don't validate." A validated value gets its own branded type, and the\nsmart constructor is the ONLY way to mint one. So once you hold a Postcode you\nknow it's well-formed — validity is carried in the type, not re-checked\neverywhere or tracked in a parallel error flag.

\n", "kind": 184 }, { "name": "RegistrationStatus", "ctype": "miscellaneous", "subtype": "typealias", "rawtype": "literal type | literal type | literal type", "file": "src/app/core/models.ts", "deprecated": false, "deprecationMessage": "", "description": "

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.

\n", "kind": 193 }, { "name": "RemoteData", "ctype": "miscellaneous", "subtype": "typealias", "rawtype": "literal type | literal type | literal type | literal type", "file": "src/app/core/remote-data.ts", "deprecated": false, "deprecationMessage": "", "description": "

The four mutually-exclusive states of an async fetch, as a tagged union.\nCrucially the data lives ON the state: only Failure has an error, only\nSuccess has a value. "Loaded but no value" or "error with stale value"\nare unrepresentable — Richard Feldman's RemoteData.

\n", "kind": 193 }, { "name": "Result", "ctype": "miscellaneous", "subtype": "typealias", "rawtype": "literal type | literal type", "file": "src/app/core/fp.ts", "deprecated": false, "deprecationMessage": "", "description": "

A computation that either succeeded with a value or failed with an error.\nPlain objects (no classes) to match the signal/httpResource ergonomics.

\n", "kind": 193 }, { "name": "Scenario", "ctype": "miscellaneous", "subtype": "typealias", "rawtype": "\"default\" | \"slow\" | \"loading\" | \"empty\" | \"error\"", "file": "src/app/core/scenario.ts", "deprecated": false, "deprecationMessage": "", "description": "", "kind": 193 }, { "name": "StatusTag", "ctype": "miscellaneous", "subtype": "typealias", "rawtype": "RegistrationStatus", "file": "src/app/core/models.ts", "deprecated": false, "deprecationMessage": "", "description": "

Just the discriminant — for atoms that only need the label/color.

\n", "kind": 200 }, { "name": "Uren", "ctype": "miscellaneous", "subtype": "typealias", "rawtype": "Brand", "file": "src/app/core/parse.ts", "deprecated": false, "deprecationMessage": "", "description": "", "kind": 184 }, { "name": "Variant", "ctype": "miscellaneous", "subtype": "typealias", "rawtype": "\"primary\" | \"secondary\" | \"subtle\" | \"danger\"", "file": "src/app/atoms/button/button.component.ts", "deprecated": false, "deprecationMessage": "", "description": "", "kind": 193 }, { "name": "WizardState", "ctype": "miscellaneous", "subtype": "typealias", "rawtype": "literal type | literal type | literal type | literal type", "file": "src/app/organisms/herregistratie-wizard/wizard.machine.ts", "deprecated": false, "deprecationMessage": "", "description": "

The whole wizard as one tagged union. step and errors exist ONLY while\nEditing; Submitting/Submitted/Failed carry a Valid payload and nothing else.\nSo "submitting while a field is invalid" or "showing the success screen with\nerrors set" are unrepresentable — the bug class is gone by construction.

\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/molecules/async/async.component.ts": [ { "name": "ASYNC", "ctype": "miscellaneous", "subtype": "variable", "file": "src/app/molecules/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": "

Convenience: import this array to get the wrapper + all slot directives.

\n" } ], "src/app/core/fp.ts": [ { "name": "err", "ctype": "miscellaneous", "subtype": "variable", "file": "src/app/core/fp.ts", "deprecated": false, "deprecationMessage": "", "type": "unknown", "defaultValue": "(error: E): Result => ({ ok: false, error })" }, { "name": "ok", "ctype": "miscellaneous", "subtype": "variable", "file": "src/app/core/fp.ts", "deprecated": false, "deprecationMessage": "", "type": "unknown", "defaultValue": "(value: T): Result => ({ ok: true, value })" } ], "src/app/organisms/herregistratie-wizard/wizard.machine.ts": [ { "name": "initial", "ctype": "miscellaneous", "subtype": "variable", "file": "src/app/organisms/herregistratie-wizard/wizard.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('./pages/login/login.page').then(m => m.LoginPage)\" },\n { path: 'dashboard', loadComponent: () => \"import('./pages/dashboard/dashboard.page').then(m => m.DashboardPage)\" },\n { path: 'registratie', loadComponent: () => \"import('./pages/registration-detail/registration-detail.page').then(m => m.RegistrationDetailPage)\" },\n { path: 'herregistratie', loadComponent: () => \"import('./pages/herregistratie/herregistratie.page').then(m => m.HerregistratiePage)\" },\n { path: 'concepts', loadComponent: () => \"import('./pages/concepts/concepts.page').then(m => m.ConceptsPage)\" },\n { path: '**', redirectTo: 'login' },\n ],\n },\n]" } ], "src/app/core/scenario.interceptor.ts": [ { "name": "scenarioInterceptor", "ctype": "miscellaneous", "subtype": "variable", "file": "src/app/core/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": "

Demo-only: rewrites the timing/outcome of mock data requests based on\n?scenario= so loading / empty / error states can be shown on demand.\nReal requests are untouched.

\n" } ], "src/app/core/scenario.ts": [ { "name": "VALID", "ctype": "miscellaneous", "subtype": "variable", "file": "src/app/core/scenario.ts", "deprecated": false, "deprecationMessage": "", "type": "Scenario[]", "defaultValue": "['default', 'slow', 'loading', 'empty', 'error']" } ] }, "groupedFunctions": { "src/app/core/fp.ts": [ { "name": "assertNever", "file": "src/app/core/fp.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "

Tiny native-TS functional toolkit. No dependency — this is the whole "library".\nReused by every "impossible states" concept in the POC.

\n", "args": [ { "name": "x", "type": "never", "deprecated": false, "deprecationMessage": "" } ], "returnType": "never", "jsdoctags": [ { "name": "x", "type": "never", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] } ], "src/app/organisms/herregistratie-wizard/wizard.machine.ts": [ { "name": "back", "file": "src/app/organisms/herregistratie-wizard/wizard.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/organisms/herregistratie-wizard/wizard.machine.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "

Step 1 → 2: only advance if the uren field parses. Illegal elsewhere = no-op.

\n", "args": [ { "name": "s", "type": "WizardState", "deprecated": false, "deprecationMessage": "" } ], "returnType": "WizardState", "jsdoctags": [ { "name": "s", "type": "WizardState", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "resolve", "file": "src/app/organisms/herregistratie-wizard/wizard.machine.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "

Resolve the async submit. Only meaningful while Submitting.

\n", "args": [ { "name": "s", "type": "WizardState", "deprecated": false, "deprecationMessage": "" }, { "name": "r", "type": "Result", "deprecated": false, "deprecationMessage": "" } ], "returnType": "WizardState", "jsdoctags": [ { "name": "s", "type": "WizardState", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } }, { "name": "r", "type": "Result", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "submit", "file": "src/app/organisms/herregistratie-wizard/wizard.machine.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "

Step 2 submit: parse everything; move to Submitting only with Valid data.

\n", "args": [ { "name": "s", "type": "WizardState", "deprecated": false, "deprecationMessage": "" } ], "returnType": "WizardState", "jsdoctags": [ { "name": "s", "type": "WizardState", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "validate", "file": "src/app/organisms/herregistratie-wizard/wizard.machine.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "

Parse every field; on success hand back a Valid, else the per-field errors.

\n", "args": [ { "name": "draft", "type": "Draft", "deprecated": false, "deprecationMessage": "" } ], "returnType": "Result>, Valid>", "jsdoctags": [ { "name": "draft", "type": "Draft", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] } ], "src/app/core/scenario.ts": [ { "name": "currentScenario", "file": "src/app/core/scenario.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "

Reads ?scenario= from the URL so a demo can force each async state.

\n", "args": [], "returnType": "Scenario" } ], "src/app/pages/concepts/concepts.page.ts": [ { "name": "fakeResource", "file": "src/app/pages/concepts/concepts.page.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "

Minimal fake Resource so can be driven through every state without HTTP.

\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", "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/core/remote-data.ts": [ { "name": "foldRemote", "file": "src/app/core/remote-data.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "

Exhaustive fold: you must handle every case, checked at compile time.

\n", "args": [ { "name": "rd", "type": "RemoteData", "deprecated": false, "deprecationMessage": "" }, { "name": "h", "deprecated": false, "deprecationMessage": "" } ], "returnType": "R", "jsdoctags": [ { "name": "rd", "type": "RemoteData", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } }, { "name": "h", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "fromResource", "file": "src/app/core/remote-data.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "

Project Angular's loosely-typed Resource into a RemoteData value.

\n", "args": [ { "name": "r", "type": "Resource", "deprecated": false, "deprecationMessage": "" }, { "name": "isEmpty", "deprecated": false, "deprecationMessage": "", "defaultValue": "() => false" } ], "returnType": "RemoteData", "jsdoctags": [ { "name": "r", "type": "Resource", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } }, { "name": "isEmpty", "deprecated": false, "deprecationMessage": "", "defaultValue": "() => false", "tagName": { "text": "param" } } ] } ], "src/app/core/parse.ts": [ { "name": "parsePostcode", "file": "src/app/core/parse.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "", "args": [ { "name": "raw", "type": "string", "deprecated": false, "deprecationMessage": "" } ], "returnType": "Result", "jsdoctags": [ { "name": "raw", "type": "string", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] }, { "name": "parseUren", "file": "src/app/core/parse.ts", "ctype": "miscellaneous", "subtype": "function", "deprecated": false, "deprecationMessage": "", "description": "", "args": [ { "name": "raw", "type": "string", "deprecated": false, "deprecationMessage": "" } ], "returnType": "Result", "jsdoctags": [ { "name": "raw", "type": "string", "deprecated": false, "deprecationMessage": "", "tagName": { "text": "param" } } ] } ] }, "groupedEnumerations": {}, "groupedTypeAliases": { "src/app/atoms/alert/alert.component.ts": [ { "name": "AlertType", "ctype": "miscellaneous", "subtype": "typealias", "rawtype": "\"info\" | \"ok\" | \"warning\" | \"error\"", "file": "src/app/atoms/alert/alert.component.ts", "deprecated": false, "deprecationMessage": "", "description": "", "kind": 193 } ], "src/app/core/fp.ts": [ { "name": "Brand", "ctype": "miscellaneous", "subtype": "typealias", "rawtype": "unknown", "file": "src/app/core/fp.ts", "deprecated": false, "deprecationMessage": "", "description": "

Nominal typing: Brand<string, 'Postcode'> is assignable from a plain string\nonly through an explicit cast — so a smart constructor is the only minter.

\n", "kind": 194 }, { "name": "Result", "ctype": "miscellaneous", "subtype": "typealias", "rawtype": "literal type | literal type", "file": "src/app/core/fp.ts", "deprecated": false, "deprecationMessage": "", "description": "

A computation that either succeeded with a value or failed with an error.\nPlain objects (no classes) to match the signal/httpResource ergonomics.

\n", "kind": 193 } ], "src/app/core/parse.ts": [ { "name": "Postcode", "ctype": "miscellaneous", "subtype": "typealias", "rawtype": "Brand", "file": "src/app/core/parse.ts", "deprecated": false, "deprecationMessage": "", "description": "

"Parse, don't validate." A validated value gets its own branded type, and the\nsmart constructor is the ONLY way to mint one. So once you hold a Postcode you\nknow it's well-formed — validity is carried in the type, not re-checked\neverywhere or tracked in a parallel error flag.

\n", "kind": 184 }, { "name": "Uren", "ctype": "miscellaneous", "subtype": "typealias", "rawtype": "Brand", "file": "src/app/core/parse.ts", "deprecated": false, "deprecationMessage": "", "description": "", "kind": 184 } ], "src/app/core/models.ts": [ { "name": "RegistrationStatus", "ctype": "miscellaneous", "subtype": "typealias", "rawtype": "literal type | literal type | literal type", "file": "src/app/core/models.ts", "deprecated": false, "deprecationMessage": "", "description": "

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.

\n", "kind": 193 }, { "name": "StatusTag", "ctype": "miscellaneous", "subtype": "typealias", "rawtype": "RegistrationStatus", "file": "src/app/core/models.ts", "deprecated": false, "deprecationMessage": "", "description": "

Just the discriminant — for atoms that only need the label/color.

\n", "kind": 200 } ], "src/app/core/remote-data.ts": [ { "name": "RemoteData", "ctype": "miscellaneous", "subtype": "typealias", "rawtype": "literal type | literal type | literal type | literal type", "file": "src/app/core/remote-data.ts", "deprecated": false, "deprecationMessage": "", "description": "

The four mutually-exclusive states of an async fetch, as a tagged union.\nCrucially the data lives ON the state: only Failure has an error, only\nSuccess has a value. "Loaded but no value" or "error with stale value"\nare unrepresentable — Richard Feldman's RemoteData.

\n", "kind": 193 } ], "src/app/core/scenario.ts": [ { "name": "Scenario", "ctype": "miscellaneous", "subtype": "typealias", "rawtype": "\"default\" | \"slow\" | \"loading\" | \"empty\" | \"error\"", "file": "src/app/core/scenario.ts", "deprecated": false, "deprecationMessage": "", "description": "", "kind": 193 } ], "src/app/atoms/button/button.component.ts": [ { "name": "Variant", "ctype": "miscellaneous", "subtype": "typealias", "rawtype": "\"primary\" | \"secondary\" | \"subtle\" | \"danger\"", "file": "src/app/atoms/button/button.component.ts", "deprecated": false, "deprecationMessage": "", "description": "", "kind": 193 } ], "src/app/organisms/herregistratie-wizard/wizard.machine.ts": [ { "name": "WizardState", "ctype": "miscellaneous", "subtype": "typealias", "rawtype": "literal type | literal type | literal type | literal type", "file": "src/app/organisms/herregistratie-wizard/wizard.machine.ts", "deprecated": false, "deprecationMessage": "", "description": "

The whole wizard as one tagged union. step and errors exist ONLY while\nEditing; Submitting/Submitted/Failed carry a Valid payload and nothing else.\nSo "submitting while a field is invalid" or "showing the success screen with\nerrors set" are unrepresentable — the bug class is gone by construction.

\n", "kind": 193 } ] } }, "routes": { "name": "", "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": 41, "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/atoms/alert/alert.component.ts", "type": "component", "linktype": "component", "name": "AlertComponent", "coveragePercent": 50, "coverageCount": "1/2", "status": "medium" }, { "filePath": "src/app/atoms/alert/alert.component.ts", "type": "type alias", "linktype": "miscellaneous", "linksubtype": "typealias", "name": "AlertType", "coveragePercent": 0, "coverageCount": "0/1", "status": "low" }, { "filePath": "src/app/atoms/button/button.component.ts", "type": "component", "linktype": "component", "name": "ButtonComponent", "coveragePercent": 25, "coverageCount": "1/4", "status": "low" }, { "filePath": "src/app/atoms/button/button.component.ts", "type": "type alias", "linktype": "miscellaneous", "linksubtype": "typealias", "name": "Variant", "coveragePercent": 0, "coverageCount": "0/1", "status": "low" }, { "filePath": "src/app/atoms/heading/heading.component.ts", "type": "component", "linktype": "component", "name": "HeadingComponent", "coveragePercent": 50, "coverageCount": "1/2", "status": "medium" }, { "filePath": "src/app/atoms/link/link.component.ts", "type": "component", "linktype": "component", "name": "LinkComponent", "coveragePercent": 50, "coverageCount": "1/2", "status": "medium" }, { "filePath": "src/app/atoms/skeleton/skeleton.component.ts", "type": "component", "linktype": "component", "name": "SkeletonComponent", "coveragePercent": 10, "coverageCount": "1/10", "status": "low" }, { "filePath": "src/app/atoms/spinner/spinner.component.ts", "type": "component", "linktype": "component", "name": "SpinnerComponent", "coveragePercent": 16, "coverageCount": "1/6", "status": "low" }, { "filePath": "src/app/atoms/status-badge/status-badge.component.ts", "type": "component", "linktype": "component", "name": "StatusBadgeComponent", "coveragePercent": 33, "coverageCount": "1/3", "status": "medium" }, { "filePath": "src/app/atoms/text-input/text-input.component.ts", "type": "component", "linktype": "component", "name": "TextInputComponent", "coveragePercent": 7, "coverageCount": "1/14", "status": "low" }, { "filePath": "src/app/core/fp.ts", "type": "function", "linktype": "miscellaneous", "linksubtype": "function", "name": "assertNever", "coveragePercent": 100, "coverageCount": "1/1", "status": "very-good" }, { "filePath": "src/app/core/fp.ts", "type": "variable", "linktype": "miscellaneous", "linksubtype": "variable", "name": "err", "coveragePercent": 0, "coverageCount": "0/1", "status": "low" }, { "filePath": "src/app/core/fp.ts", "type": "variable", "linktype": "miscellaneous", "linksubtype": "variable", "name": "ok", "coveragePercent": 0, "coverageCount": "0/1", "status": "low" }, { "filePath": "src/app/core/fp.ts", "type": "type alias", "linktype": "miscellaneous", "linksubtype": "typealias", "name": "Brand", "coveragePercent": 100, "coverageCount": "1/1", "status": "very-good" }, { "filePath": "src/app/core/fp.ts", "type": "type alias", "linktype": "miscellaneous", "linksubtype": "typealias", "name": "Result", "coveragePercent": 100, "coverageCount": "1/1", "status": "very-good" }, { "filePath": "src/app/core/models.ts", "type": "interface", "linktype": "interface", "name": "Aantekening", "coveragePercent": 0, "coverageCount": "0/4", "status": "low" }, { "filePath": "src/app/core/models.ts", "type": "interface", "linktype": "interface", "name": "Registration", "coveragePercent": 0, "coverageCount": "0/7", "status": "low" }, { "filePath": "src/app/core/models.ts", "type": "type alias", "linktype": "miscellaneous", "linksubtype": "typealias", "name": "RegistrationStatus", "coveragePercent": 100, "coverageCount": "1/1", "status": "very-good" }, { "filePath": "src/app/core/models.ts", "type": "type alias", "linktype": "miscellaneous", "linksubtype": "typealias", "name": "StatusTag", "coveragePercent": 100, "coverageCount": "1/1", "status": "very-good" }, { "filePath": "src/app/core/parse.ts", "type": "function", "linktype": "miscellaneous", "linksubtype": "function", "name": "parsePostcode", "coveragePercent": 0, "coverageCount": "0/1", "status": "low" }, { "filePath": "src/app/core/parse.ts", "type": "function", "linktype": "miscellaneous", "linksubtype": "function", "name": "parseUren", "coveragePercent": 0, "coverageCount": "0/1", "status": "low" }, { "filePath": "src/app/core/parse.ts", "type": "type alias", "linktype": "miscellaneous", "linksubtype": "typealias", "name": "Postcode", "coveragePercent": 100, "coverageCount": "1/1", "status": "very-good" }, { "filePath": "src/app/core/parse.ts", "type": "type alias", "linktype": "miscellaneous", "linksubtype": "typealias", "name": "Uren", "coveragePercent": 0, "coverageCount": "0/1", "status": "low" }, { "filePath": "src/app/core/registration.service.ts", "type": "injectable", "linktype": "injectable", "name": "RegistrationService", "coveragePercent": 33, "coverageCount": "1/3", "status": "medium" }, { "filePath": "src/app/core/remote-data.ts", "type": "function", "linktype": "miscellaneous", "linksubtype": "function", "name": "foldRemote", "coveragePercent": 100, "coverageCount": "1/1", "status": "very-good" }, { "filePath": "src/app/core/remote-data.ts", "type": "function", "linktype": "miscellaneous", "linksubtype": "function", "name": "fromResource", "coveragePercent": 100, "coverageCount": "1/1", "status": "very-good" }, { "filePath": "src/app/core/remote-data.ts", "type": "type alias", "linktype": "miscellaneous", "linksubtype": "typealias", "name": "RemoteData", "coveragePercent": 100, "coverageCount": "1/1", "status": "very-good" }, { "filePath": "src/app/core/scenario.interceptor.ts", "type": "variable", "linktype": "miscellaneous", "linksubtype": "variable", "name": "scenarioInterceptor", "coveragePercent": 100, "coverageCount": "1/1", "status": "very-good" }, { "filePath": "src/app/core/scenario.ts", "type": "function", "linktype": "miscellaneous", "linksubtype": "function", "name": "currentScenario", "coveragePercent": 100, "coverageCount": "1/1", "status": "very-good" }, { "filePath": "src/app/core/scenario.ts", "type": "variable", "linktype": "miscellaneous", "linksubtype": "variable", "name": "VALID", "coveragePercent": 0, "coverageCount": "0/1", "status": "low" }, { "filePath": "src/app/core/scenario.ts", "type": "type alias", "linktype": "miscellaneous", "linksubtype": "typealias", "name": "Scenario", "coveragePercent": 0, "coverageCount": "0/1", "status": "low" }, { "filePath": "src/app/molecules/async/async.component.ts", "type": "component", "linktype": "component", "name": "AsyncComponent", "coveragePercent": 9, "coverageCount": "1/11", "status": "low" }, { "filePath": "src/app/molecules/async/async.component.ts", "type": "directive", "linktype": "directive", "name": "AsyncEmptyDirective", "coveragePercent": 0, "coverageCount": "0/3", "status": "low" }, { "filePath": "src/app/molecules/async/async.component.ts", "type": "directive", "linktype": "directive", "name": "AsyncErrorDirective", "coveragePercent": 0, "coverageCount": "0/3", "status": "low" }, { "filePath": "src/app/molecules/async/async.component.ts", "type": "directive", "linktype": "directive", "name": "AsyncLoadedDirective", "coveragePercent": 0, "coverageCount": "0/3", "status": "low" }, { "filePath": "src/app/molecules/async/async.component.ts", "type": "directive", "linktype": "directive", "name": "AsyncLoadingDirective", "coveragePercent": 0, "coverageCount": "0/3", "status": "low" }, { "filePath": "src/app/molecules/async/async.component.ts", "type": "variable", "linktype": "miscellaneous", "linksubtype": "variable", "name": "ASYNC", "coveragePercent": 100, "coverageCount": "1/1", "status": "very-good" }, { "filePath": "src/app/molecules/data-row/data-row.component.ts", "type": "component", "linktype": "component", "name": "DataRowComponent", "coveragePercent": 33, "coverageCount": "1/3", "status": "medium" }, { "filePath": "src/app/molecules/form-field/form-field.component.ts", "type": "component", "linktype": "component", "name": "FormFieldComponent", "coveragePercent": 20, "coverageCount": "1/5", "status": "low" }, { "filePath": "src/app/organisms/change-request-form/change-request-form.component.ts", "type": "component", "linktype": "component", "name": "ChangeRequestFormComponent", "coveragePercent": 12, "coverageCount": "1/8", "status": "low" }, { "filePath": "src/app/organisms/change-request-form/change-request-form.component.ts", "type": "interface", "linktype": "interface", "name": "ChangeRequest", "coveragePercent": 25, "coverageCount": "1/4", "status": "low" }, { "filePath": "src/app/organisms/herregistratie-wizard/herregistratie-wizard.component.ts", "type": "component", "linktype": "component", "name": "HerregistratieWizardComponent", "coveragePercent": 14, "coverageCount": "2/14", "status": "low" }, { "filePath": "src/app/organisms/herregistratie-wizard/wizard.machine.ts", "type": "interface", "linktype": "interface", "name": "Draft", "coveragePercent": 33, "coverageCount": "1/3", "status": "medium" }, { "filePath": "src/app/organisms/herregistratie-wizard/wizard.machine.ts", "type": "interface", "linktype": "interface", "name": "Valid", "coveragePercent": 33, "coverageCount": "1/3", "status": "medium" }, { "filePath": "src/app/organisms/herregistratie-wizard/wizard.machine.ts", "type": "function", "linktype": "miscellaneous", "linksubtype": "function", "name": "back", "coveragePercent": 0, "coverageCount": "0/1", "status": "low" }, { "filePath": "src/app/organisms/herregistratie-wizard/wizard.machine.ts", "type": "function", "linktype": "miscellaneous", "linksubtype": "function", "name": "next", "coveragePercent": 100, "coverageCount": "1/1", "status": "very-good" }, { "filePath": "src/app/organisms/herregistratie-wizard/wizard.machine.ts", "type": "function", "linktype": "miscellaneous", "linksubtype": "function", "name": "resolve", "coveragePercent": 100, "coverageCount": "1/1", "status": "very-good" }, { "filePath": "src/app/organisms/herregistratie-wizard/wizard.machine.ts", "type": "function", "linktype": "miscellaneous", "linksubtype": "function", "name": "submit", "coveragePercent": 100, "coverageCount": "1/1", "status": "very-good" }, { "filePath": "src/app/organisms/herregistratie-wizard/wizard.machine.ts", "type": "function", "linktype": "miscellaneous", "linksubtype": "function", "name": "validate", "coveragePercent": 100, "coverageCount": "1/1", "status": "very-good" }, { "filePath": "src/app/organisms/herregistratie-wizard/wizard.machine.ts", "type": "variable", "linktype": "miscellaneous", "linksubtype": "variable", "name": "initial", "coveragePercent": 0, "coverageCount": "0/1", "status": "low" }, { "filePath": "src/app/organisms/herregistratie-wizard/wizard.machine.ts", "type": "type alias", "linktype": "miscellaneous", "linksubtype": "typealias", "name": "WizardState", "coveragePercent": 100, "coverageCount": "1/1", "status": "very-good" }, { "filePath": "src/app/organisms/login-form/login-form.component.ts", "type": "component", "linktype": "component", "name": "LoginFormComponent", "coveragePercent": 25, "coverageCount": "1/4", "status": "low" }, { "filePath": "src/app/organisms/registration-summary/registration-summary.component.ts", "type": "component", "linktype": "component", "name": "RegistrationSummaryComponent", "coveragePercent": 50, "coverageCount": "1/2", "status": "medium" }, { "filePath": "src/app/organisms/registration-table/registration-table.component.ts", "type": "component", "linktype": "component", "name": "RegistrationTableComponent", "coveragePercent": 50, "coverageCount": "1/2", "status": "medium" }, { "filePath": "src/app/organisms/site-footer/site-footer.component.ts", "type": "component", "linktype": "component", "name": "SiteFooterComponent", "coveragePercent": 100, "coverageCount": "1/1", "status": "very-good" }, { "filePath": "src/app/organisms/site-header/site-header.component.ts", "type": "component", "linktype": "component", "name": "SiteHeaderComponent", "coveragePercent": 50, "coverageCount": "1/2", "status": "medium" }, { "filePath": "src/app/pages/concepts/concepts.page.ts", "type": "component", "linktype": "component", "name": "ConceptsPage", "coveragePercent": 8, "coverageCount": "1/12", "status": "low" }, { "filePath": "src/app/pages/concepts/concepts.page.ts", "type": "function", "linktype": "miscellaneous", "linksubtype": "function", "name": "fakeResource", "coveragePercent": 100, "coverageCount": "1/1", "status": "very-good" }, { "filePath": "src/app/pages/dashboard/dashboard.page.ts", "type": "component", "linktype": "component", "name": "DashboardPage", "coveragePercent": 0, "coverageCount": "0/6", "status": "low" }, { "filePath": "src/app/pages/herregistratie/herregistratie.page.ts", "type": "component", "linktype": "component", "name": "HerregistratiePage", "coveragePercent": 100, "coverageCount": "1/1", "status": "very-good" }, { "filePath": "src/app/pages/login/login.page.ts", "type": "component", "linktype": "component", "name": "LoginPage", "coveragePercent": 0, "coverageCount": "0/3", "status": "low" }, { "filePath": "src/app/pages/registration-detail/registration-detail.page.ts", "type": "component", "linktype": "component", "name": "RegistrationDetailPage", "coveragePercent": 0, "coverageCount": "0/5", "status": "low" }, { "filePath": "src/app/templates/page-shell/page-shell.component.ts", "type": "component", "linktype": "component", "name": "PageShellComponent", "coveragePercent": 16, "coverageCount": "1/6", "status": "low" }, { "filePath": "src/app/templates/shell/shell.component.ts", "type": "component", "linktype": "component", "name": "ShellComponent", "coveragePercent": 100, "coverageCount": "1/1", "status": "very-good" } ] } }