feat(portal-self-service): tell the citizen why a diploma upload was refused (refs #192)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -14,10 +14,8 @@
|
||||
@if (documentsProvided()) {
|
||||
<p utrecht-paragraph role="status">Uw documenten zijn aangeleverd.</p>
|
||||
} @else {
|
||||
@if (provideDocumentsFailed()) {
|
||||
<p utrecht-paragraph role="alert">
|
||||
Het aanleveren van uw documenten is niet gelukt. Probeer het opnieuw.
|
||||
</p>
|
||||
@if (provideDocumentsError(); as error) {
|
||||
<p utrecht-paragraph role="alert">{{ error }}</p>
|
||||
}
|
||||
<p utrecht-paragraph>Lever uw diploma aan (PDF).</p>
|
||||
<label utrecht-form-label for="diploma">Diploma</label>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Component, inject, type OnInit, signal } from '@angular/core';
|
||||
import { BffApiV1Service, type CurrentRegistration, type SubmitAccepted } from 'api-client';
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
import { BffApiV1Service, type CurrentRegistration, type Refusal, type SubmitAccepted } from 'api-client';
|
||||
import { AuthService } from 'auth';
|
||||
import { UtrechtComponentsModule } from 'ui';
|
||||
|
||||
@@ -31,7 +32,8 @@ export class RegistrationPage implements OnInit {
|
||||
protected readonly withdrawFailed = signal(false);
|
||||
protected readonly providingDocuments = signal(false);
|
||||
protected readonly documentsProvided = signal(false);
|
||||
protected readonly provideDocumentsFailed = signal(false);
|
||||
/** Why the last upload failed, worded for the citizen; undefined while there is nothing to report. */
|
||||
protected readonly provideDocumentsError = signal<string | undefined>(undefined);
|
||||
protected readonly selectedFile = signal<File | undefined>(undefined);
|
||||
|
||||
/** Resume an existing in-flight registration after a refresh (S-26): the BFF returns the caller's
|
||||
@@ -80,12 +82,12 @@ export class RegistrationPage implements OnInit {
|
||||
return;
|
||||
}
|
||||
this.providingDocuments.set(true);
|
||||
this.provideDocumentsFailed.set(false);
|
||||
this.provideDocumentsError.set(undefined);
|
||||
let contentBase64: string;
|
||||
try {
|
||||
contentBase64 = await readAsBase64(file);
|
||||
} catch {
|
||||
this.provideDocumentsFailed.set(true);
|
||||
this.provideDocumentsError.set(uploadFailure());
|
||||
this.providingDocuments.set(false);
|
||||
return;
|
||||
}
|
||||
@@ -101,8 +103,8 @@ export class RegistrationPage implements OnInit {
|
||||
this.providingDocuments.set(false);
|
||||
},
|
||||
// Surface the failure instead of swallowing it: keep the action so the user can retry.
|
||||
error: () => {
|
||||
this.provideDocumentsFailed.set(true);
|
||||
error: (err: unknown) => {
|
||||
this.provideDocumentsError.set(uploadFailure(err));
|
||||
this.providingDocuments.set(false);
|
||||
},
|
||||
});
|
||||
@@ -129,6 +131,20 @@ export class RegistrationPage implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
/** Word a failed upload for the citizen: the BFF says why a file was refused (422 + reason) or that
|
||||
* the virus scanner was unreachable (503, S-29); anything else is a generic retry. */
|
||||
function uploadFailure(err?: unknown): string {
|
||||
if (err instanceof HttpErrorResponse && err.status === 422) {
|
||||
return (err.error as Refusal | null)?.reason === 'infected'
|
||||
? 'Er is een virus gevonden in dit bestand. Het is niet opgeslagen; lever een ander bestand aan.'
|
||||
: 'Dit bestand is geen PDF. Lever uw diploma aan als PDF-bestand.';
|
||||
}
|
||||
if (err instanceof HttpErrorResponse && err.status === 503) {
|
||||
return 'Uw bestand kan tijdelijk niet worden gecontroleerd. Probeer het later opnieuw.';
|
||||
}
|
||||
return 'Het aanleveren van uw documenten is niet gelukt. Probeer het opnieuw.';
|
||||
}
|
||||
|
||||
/** Read a file's bytes as a base64 string (without the `data:...;base64,` prefix). */
|
||||
function readAsBase64(file: File): Promise<string> {
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
|
||||
Reference in New Issue
Block a user