CI / changes (pull_request) Successful in 15s
CI / lint (pull_request) Successful in 57s
CI / frontend (pull_request) Successful in 2m36s
CI / storybook-a11y (pull_request) Failing after 3m14s
CI / backend (pull_request) Successful in 2m1s
CI / semgrep (pull_request) Successful in 1m10s
CI / e2e (pull_request) Successful in 3m3s
CI / api-client-drift (pull_request) Successful in 2m1s
New GET /werkvoorraad endpoint lists aanvragen still open (Ingediend/InBehandeling), gated by the medewerker capability (CanBeoordelen) rather than the admin role — reuses the existing ApplicationSummaryDto, no new DTO. GET /me now surfaces aanvraag:beoordelen for a behandelaar so the FE can gate with the same AccessStore/capabilityGuard idiom every other page uses. FE: a behandeling domain type deliberately narrower than ssp's full AanvraagStatus union (only the two open tags — illegal states unrepresentable), composed into a werkvoorraad-list organism from existing shared/ui molecules. Replaces WP-61's scaffold placeholder as the app's real landing page. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
83 lines
3.4 KiB
TypeScript
83 lines
3.4 KiB
TypeScript
import { Component, computed, effect, inject } from '@angular/core';
|
|
import { PageShellComponent } from '@shared/layout/page-shell/page-shell.component';
|
|
import { AlertComponent } from '@shared/ui/alert/alert.component';
|
|
import { ButtonComponent } from '@shared/ui/button/button.component';
|
|
import { SkeletonComponent } from '@shared/ui/skeleton/skeleton.component';
|
|
import { ASYNC } from '@shared/ui/async/async.component';
|
|
import { AccessStore } from '@shared/application/access.store';
|
|
import { WerkvoorraadStore } from '@behandeling/application/werkvoorraad.store';
|
|
import { WerkvoorraadListComponent } from '@behandeling/ui/werkvoorraad-list/werkvoorraad-list.component';
|
|
|
|
/**
|
|
* Page: the behandelaar's werkvoorraad (WP-64) — the behandelportal's landing page.
|
|
* Deny-by-default capability gate (`aanvraag:beoordelen`), same idiom as ssp's
|
|
* AdminCasesPage: a denial alert for a non-behandelaar, the queue for one. Opening
|
|
* a case's detail is out of scope here (WP-65).
|
|
*/
|
|
@Component({
|
|
selector: 'app-werkvoorraad-page',
|
|
imports: [
|
|
PageShellComponent,
|
|
AlertComponent,
|
|
ButtonComponent,
|
|
SkeletonComponent,
|
|
WerkvoorraadListComponent,
|
|
...ASYNC,
|
|
],
|
|
template: `
|
|
<app-page-shell [heading]="heading" [intro]="intro">
|
|
@if (!access.ready()) {
|
|
<!-- wait for /me before deciding — avoids flashing the denial to a behandelaar -->
|
|
} @else if (!canBeoordelen()) {
|
|
<app-alert type="error">{{ deniedText }}</app-alert>
|
|
} @else {
|
|
<app-async [data]="store.items()" (retryClicked)="store.reload()">
|
|
<ng-template appAsyncLoading>
|
|
<app-skeleton height="2.5rem" [count]="4" />
|
|
</ng-template>
|
|
<ng-template appAsyncError>
|
|
<app-alert type="error">{{ failedText }}</app-alert>
|
|
<app-button variant="secondary" (click)="store.reload()">{{ retryText }}</app-button>
|
|
</ng-template>
|
|
<ng-template appAsyncLoaded>
|
|
@if (items().length === 0) {
|
|
<app-alert type="info">{{ emptyText }}</app-alert>
|
|
} @else {
|
|
<app-werkvoorraad-list [items]="items()" />
|
|
}
|
|
</ng-template>
|
|
</app-async>
|
|
}
|
|
</app-page-shell>
|
|
`,
|
|
})
|
|
export class WerkvoorraadPage {
|
|
protected store = inject(WerkvoorraadStore);
|
|
protected access = inject(AccessStore);
|
|
|
|
protected canBeoordelen = computed(() => this.access.can('aanvraag:beoordelen'));
|
|
protected items = computed(() => {
|
|
const rd = this.store.items();
|
|
return rd.tag === 'Success' ? rd.value : [];
|
|
});
|
|
|
|
protected heading = $localize`:@@werkvoorraad.heading:Werkvoorraad`;
|
|
protected intro = $localize`:@@werkvoorraad.intro:Aanvragen die op beoordeling wachten.`;
|
|
protected deniedText = $localize`:@@werkvoorraad.denied:U hebt geen rechten om de werkvoorraad te bekijken.`;
|
|
protected failedText = $localize`:@@werkvoorraad.failed:De werkvoorraad kon niet worden geladen.`;
|
|
protected emptyText = $localize`:@@werkvoorraad.empty:Er staan geen aanvragen open.`;
|
|
protected retryText = $localize`:@@werkvoorraad.retry:Opnieuw proberen`;
|
|
|
|
private loadRequested = false;
|
|
constructor() {
|
|
// Load once the capability resolves to allowed (a 403 GET would be wasted otherwise) —
|
|
// same guard-against-the-loop idiom as AdminCasesPage (WP-26 lesson).
|
|
effect(() => {
|
|
if (this.canBeoordelen() && !this.loadRequested) {
|
|
this.loadRequested = true;
|
|
void this.store.load();
|
|
}
|
|
});
|
|
}
|
|
}
|