Mijn aanvragen (E): two-flow submit through the aanvraag + all-wizard persistence

All three wizards now submit through the backend aanvraag lifecycle, so a
submitted Concept actually transitions (dashboard shows it correctly in F).

- blockActions(status) (domain + spec): the pure per-status action decision
  (Concept → resume/cancel; In behandeling → viewDocuments; resolved → none).
- createDraftSync.submit(): ensure the Concept exists, then
  POST /applications/{id}/submit; folded into a Result like the old commands.
- registratie: submit via draftSync (duo → auto, handmatig → manual pending — the
  old 422 path is gone from the wizard).
- intake + herregistratie: adopt createDraftSync (persistence + resume-by-link);
  intake retires sessionStorage `intake-v3`; herregistratie gains persistence.
  Both submit through the aanvraag too. hasProgress added to each machine (+spec).
- Delete now-dead submit-registratie/submit-intake/submit-herregistratie commands.

Deferred: the old /registrations, /intakes, /herregistraties backend endpoints +
RejectRegistratie are now unused by the FE but still present (+ tested) — retiring
them cascades into backend test rewrites, so it's a focused follow-up cleanup.
Gates green: vitest 128, lint, build; backend unchanged (dotnet 56).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-01 14:25:02 +02:00
parent 6db7f1e673
commit 9f217abe19
15 changed files with 136 additions and 144 deletions

View File

@@ -28,9 +28,7 @@ import {
hasProgress,
STEPS,
} from '@registratie/domain/registratie-wizard.machine';
import { submitRegistratie } from '@registratie/application/submit-registratie';
import { createDraftSync } from '@registratie/application/draft-sync';
import { ApiClient } from '@shared/infrastructure/api-client';
import { DocumentUploadComponent } from '@shared/ui/upload/document-upload/document-upload.component';
import { createUploadController } from '@shared/upload/upload-controller';
import { UploadState, initialUpload, deliveryRefs } from '@shared/upload/upload.machine';
@@ -185,7 +183,6 @@ const HANDMATIG = '__handmatig__'; // sentinel option: "my diploma isn't listed"
export class RegistratieWizardComponent {
private brp = inject(BrpAdapter);
private duo = inject(DuoAdapter);
private apiClient = inject(ApiClient);
private store = createStore<RegistratieState, RegistratieMsg>(initial, reduce);
protected adresRes = this.brp.adresResource();
@@ -375,13 +372,13 @@ export class RegistratieWizardComponent {
this.adresRes.reload();
}
/** The effect: when we enter Indienen, call the backend, then dispatch the
outcome (success carries the confirmation reference). */
/** The effect: when we enter Indienen, submit through the aanvraag lifecycle
(duo → auto-approve, handmatig → manual), then dispatch the outcome. */
private async runIfIndienen() {
const s = this.state();
if (s.tag !== 'Indienen') return;
const r = await submitRegistratie(this.apiClient, s.data);
if (r.ok) this.dispatch({ tag: 'SubmitConfirmed', referentie: r.value });
const r = await this.draftSync.submit({ diplomaHerkomst: s.data.diplomaHerkomst, documents: s.data.documents });
if (r.ok) this.dispatch({ tag: 'SubmitConfirmed', referentie: r.value.referentie ?? '' });
else this.dispatch({ tag: 'SubmitFailed', error: r.error });
}
}