Make AsyncLoadedDirective generic with a static ngTemplateContextGuard for AsyncComponent's own internal typing. That can't propagate to consumer `<ng-template appAsyncLoaded let-p>` sites though -- Angular only infers a structural directive's type parameter from an input bound on that same node, not from a sibling input on the parent component -- so the ~9 root-cause consumers (dashboard, registration-detail, aanvraag-detail, registratie-wizard) instead unwrap the RemoteData Success value via a typed computed() and narrow it locally with `@if (x(); as p)`. The remaining union-narrowing casts (registration-summary, showcase concepts page) are replaced with a stable @let binding and a direct resource read, respectively. Documented as a deviation in WP-06's backlog file.
75 lines
2.9 KiB
TypeScript
75 lines
2.9 KiB
TypeScript
import { Component, computed, inject } from '@angular/core';
|
|
import { ActivatedRoute } from '@angular/router';
|
|
import { PageShellComponent } from '@shared/layout/page-shell/page-shell.component';
|
|
import { SkeletonComponent } from '@shared/ui/skeleton/skeleton.component';
|
|
import { AlertComponent } from '@shared/ui/alert/alert.component';
|
|
import { DataBlockComponent } from '@shared/ui/data-block/data-block.component';
|
|
import { DataRowComponent } from '@shared/ui/data-row/data-row.component';
|
|
import { ASYNC } from '@shared/ui/async/async.component';
|
|
import { ApplicationsStore } from '@registratie/application/applications.store';
|
|
import { Aanvraag } from '@registratie/domain/aanvraag';
|
|
import { detailRows } from '@registratie/domain/aanvraag-view';
|
|
|
|
/** Page: a single aanvraag ("case"). Stub — it renders the aanvraag's known fields
|
|
(soort, waarvoor, status, referentie, ingediend) in a CIBG Datablock; full case
|
|
handling is future work. The dashboard "Mijn aanvragen" rows link here. */
|
|
@Component({
|
|
selector: 'app-aanvraag-detail-page',
|
|
imports: [
|
|
PageShellComponent,
|
|
SkeletonComponent,
|
|
AlertComponent,
|
|
DataBlockComponent,
|
|
DataRowComponent,
|
|
...ASYNC,
|
|
],
|
|
template: `
|
|
<app-page-shell
|
|
i18n-heading="@@aanvraagDetail.heading"
|
|
heading="Aanvraag"
|
|
backLink="/dashboard"
|
|
>
|
|
<app-async [data]="store.applications()">
|
|
<ng-template appAsyncLoaded>
|
|
@if (applications(); as list) {
|
|
@let a = find(list);
|
|
@if (a) {
|
|
<app-data-block
|
|
i18n-ariaLabel="@@aanvraagDetail.ariaLabel"
|
|
ariaLabel="Aanvraaggegevens"
|
|
>
|
|
@for (row of rows(a); track row.key) {
|
|
<div app-data-row [key]="row.key" [value]="row.value"></div>
|
|
}
|
|
</app-data-block>
|
|
<app-alert class="app-section" type="info" i18n="@@aanvraagDetail.stub">
|
|
De volledige afhandeling van deze aanvraag is nog niet beschikbaar in deze POC.
|
|
</app-alert>
|
|
} @else {
|
|
<app-alert type="warning" i18n="@@aanvraagDetail.nietGevonden"
|
|
>Deze aanvraag is niet gevonden.</app-alert
|
|
>
|
|
}
|
|
}
|
|
</ng-template>
|
|
<ng-template appAsyncLoading>
|
|
<app-skeleton height="2.5rem" [count]="5" />
|
|
</ng-template>
|
|
</app-async>
|
|
</app-page-shell>
|
|
`,
|
|
})
|
|
export class AanvraagDetailPage {
|
|
protected store = inject(ApplicationsStore);
|
|
private id = inject(ActivatedRoute).snapshot.paramMap.get('id') ?? '';
|
|
|
|
protected find = (list: Aanvraag[]): Aanvraag | undefined => list.find((a) => a.id === this.id);
|
|
protected rows = detailRows;
|
|
|
|
/** See DashboardPage's `profile` for why this narrows via a computed instead of `let-`. */
|
|
protected readonly applications = computed(() => {
|
|
const rd = this.store.applications();
|
|
return rd.tag === 'Success' ? rd.value : undefined;
|
|
});
|
|
}
|