import { Injectable, inject, signal } from '@angular/core'; import { RemoteData } from '@shared/application/remote-data'; import { runSubmit, SUBMIT_FAILED } from '@shared/application/submit'; import { Aanvraag } from '@registratie/domain/aanvraag'; import { ApplicationsAdapter, parseApplications, } from '@registratie/infrastructure/applications.adapter'; type Err = Error | undefined; /** * Admin view of ALL cases across owners (WP-36; `cases:manage`) — the back-office * counterpart of the user-facing `ApplicationsStore`. Same shape: one root singleton * owns the list as a writable RemoteData signal, delete removes the row synchronously * (optimistic), goes through `runSubmit`, and rolls back plus surfaces `lastError` on * failure (RB-20). Admin delete removes any case (any owner, submitted or not — the * server enforces the capability). */ @Injectable({ providedIn: 'root' }) export class AdminCasesStore { private adapter = inject(ApplicationsAdapter); private state = signal>({ tag: 'Loading' }); readonly cases = this.state.asReadonly(); /** Set on a failed delete (RB-20): the optimistic removal already rolled back by then, this is only the message for the alert the page renders above the list. */ private error = signal(null); readonly lastError = this.error.asReadonly(); /** Fetch + parse at the trust boundary, then publish as RemoteData. Keeps the last-good value on a resync (only shows Loading on the first load). */ async load() { if (this.state().tag !== 'Success') this.state.set({ tag: 'Loading' }); try { const parsed = parseApplications(await this.adapter.listAll()); this.state.set( parsed.ok ? { tag: 'Success', value: parsed.value } : { tag: 'Failure', error: new Error(parsed.error) }, ); } catch (e) { this.state.set({ tag: 'Failure', error: e as Error }); } } reload() { void this.load(); } /** Delete a case: drop it now (synchronous), then confirm the DELETE; roll back on error AND surface it (RB-20) — a silent reappearance leaves the admin guessing why. */ async delete(id: string) { const before = this.state(); if (before.tag === 'Success') { this.state.set({ tag: 'Success', value: before.value.filter((a) => a.id !== id) }); } this.error.set(null); const r = await runSubmit(() => this.adapter.deleteAny(id), SUBMIT_FAILED); if (!r.ok) { this.state.set(before); // roll back: the row reappears this.error.set(r.error); } } }