Mijn aanvragen (F2): document preview/download on completed uploads

Re-opening a Concept wizard now lets the user preview/download what they already
uploaded (PRD 0001 goal 2).

- document-chip: optional previewUrl input → a "Voorbeeld / Download" link (opens
  the stored bytes; server serves inline for pdf/image, attachment otherwise).
- previewUrlFor callback threaded document-upload → document-category → single-upload
  (which builds the URL from a completed upload's documentId). Keeps URL-building out
  of the presentational atoms.
- registratie + herregistratie wizards supply previewUrlFor via UploadAdapter.contentUrl,
  returning undefined for dev-simulation `demo-*` ids (no stored bytes → no link).
- Story: DocumentChip/WithPreview.

Gates green: vitest 128, lint, ng build, check:tokens; backend dotnet 56.
(build-storybook has a pre-existing Compodoc/$localize issue in untouched files.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-01 14:50:40 +02:00
parent 0bef08e5b3
commit 168cf9786c
8 changed files with 15157 additions and 1665 deletions

View File

@@ -31,6 +31,7 @@ import {
import { createDraftSync } from '@registratie/application/draft-sync';
import { DocumentUploadComponent } from '@shared/ui/upload/document-upload/document-upload.component';
import { createUploadController } from '@shared/upload/upload-controller';
import { UploadAdapter } from '@shared/upload/upload.adapter';
import { UploadState, initialUpload, deliveryRefs } from '@shared/upload/upload.machine';
const KANALEN = [
@@ -140,6 +141,7 @@ const HANDMATIG = '__handmatig__'; // sentinel option: "my diploma isn't listed"
<app-document-upload
class="app-section"
[state]="upload()"
[previewUrlFor]="previewUrlFor"
(fileSelected)="uploadCtl.onFileSelected($event.categoryId, $event.files)"
(removeUpload)="uploadCtl.onRemove($event)"
(retryUpload)="uploadCtl.onRetry($event)"
@@ -183,8 +185,14 @@ const HANDMATIG = '__handmatig__'; // sentinel option: "my diploma isn't listed"
export class RegistratieWizardComponent {
private brp = inject(BrpAdapter);
private duo = inject(DuoAdapter);
private uploadAdapter = inject(UploadAdapter);
private store = createStore<RegistratieState, RegistratieMsg>(initial, reduce);
/** Preview/download link for a completed upload; the dev-simulation `demo-*` ids
have no stored bytes, so they get no link. */
protected previewUrlFor = (documentId: string): string | undefined =>
documentId.startsWith('demo-') ? undefined : this.uploadAdapter.contentUrl(documentId);
protected adresRes = this.brp.adresResource();
private diplomasRes = this.duo.diplomasResource();