Each dashboard section (Mijn aanvragen, Wat moet ik regelen, Mijn registratie, Specialismen, Wat wilt u doen, Beheer) now owns its own store access, async state, and template. DashboardPage becomes pure composition. Extract the repeated RemoteData Success-narrowing pattern into successOf() and the dashboard sort/split logic into sortForDashboard/concepten/ingediend, both with tests. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
64 lines
2.5 KiB
TypeScript
64 lines
2.5 KiB
TypeScript
import { Component, computed, inject } from '@angular/core';
|
|
import { successOf } from '@shared/application/remote-data';
|
|
import { HeadingComponent } from '@shared/ui/heading/heading.component';
|
|
import { AlertComponent } from '@shared/ui/alert/alert.component';
|
|
import { SkeletonComponent } from '@shared/ui/skeleton/skeleton.component';
|
|
import { TaskListComponent } from '@shared/ui/task-list/task-list.component';
|
|
import { ASYNC } from '@shared/ui/async/async.component';
|
|
import { BigProfileStore } from '@registratie/application/big-profile.store';
|
|
import { tasksFromProfile } from '@registratie/domain/tasks';
|
|
|
|
/** Section: "Wat moet ik regelen" — the open tasks derived from the registration
|
|
+ the server-computed herregistratie eligibility (rendered, never recomputed;
|
|
ADR-0001). Empty task list → a plain "niets openstaan" message, not an empty
|
|
async state (the registration itself did load). */
|
|
@Component({
|
|
selector: 'app-wat-moet-ik-regelen-section',
|
|
imports: [HeadingComponent, AlertComponent, SkeletonComponent, TaskListComponent, ...ASYNC],
|
|
template: `
|
|
@if (store.pendingHerregistratie()) {
|
|
<app-alert type="info" i18n="@@dashboard.pendingHerregistratie"
|
|
>Uw herregistratie-aanvraag is in behandeling.</app-alert
|
|
>
|
|
}
|
|
<app-async [data]="store.profile()" (retryClicked)="store.reloadProfile()">
|
|
<ng-template appAsyncLoaded>
|
|
@if (tasks(); as t) {
|
|
<section>
|
|
@if (t.length) {
|
|
<app-task-list
|
|
i18n-listHeading="@@dashboard.watMoetIkRegelen"
|
|
listHeading="Wat moet ik regelen"
|
|
[tasks]="t"
|
|
/>
|
|
} @else {
|
|
<app-heading [level]="2" i18n="@@dashboard.watMoetIkRegelen"
|
|
>Wat moet ik regelen</app-heading
|
|
>
|
|
<p class="app-text-subtle" i18n="@@dashboard.nietsOpenstaan">
|
|
U heeft op dit moment niets openstaan.
|
|
</p>
|
|
}
|
|
</section>
|
|
}
|
|
</ng-template>
|
|
<ng-template appAsyncLoading>
|
|
<app-skeleton height="2.5rem" [count]="2" />
|
|
</ng-template>
|
|
</app-async>
|
|
`,
|
|
})
|
|
export class WatMoetIkRegelenSection {
|
|
protected store = inject(BigProfileStore);
|
|
|
|
private eligible = computed(() => {
|
|
const d = successOf(this.store.decisions());
|
|
return d?.eligibleForHerregistratie ?? false;
|
|
});
|
|
|
|
protected tasks = computed(() => {
|
|
const p = successOf(this.store.profile());
|
|
return p ? tasksFromProfile(p.registration, this.eligible()) : undefined;
|
|
});
|
|
}
|