Upload feature (c): atomic UI components (atoms/molecules/organisms) + stories
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
import { Component, input, output } from '@angular/core';
|
||||
import type { DeliveryChannel, UploadState } from '@shared/upload/upload.machine';
|
||||
import { DocumentCategoryComponent } from '../document-category/document-category.component';
|
||||
import { UploadStatusBannerComponent } from '../upload-status-banner/upload-status-banner.component';
|
||||
|
||||
/** Organism: the full document-upload step — the category list, or a load-error
|
||||
banner. Pure UI: re-exposes the category events, tagging each with its category
|
||||
where the parent needs it. The container wires these to the upload reducer. */
|
||||
@Component({
|
||||
selector: 'app-document-upload',
|
||||
imports: [DocumentCategoryComponent, UploadStatusBannerComponent],
|
||||
styles: [`
|
||||
:host { display: flex; flex-direction: column; gap: var(--rhc-space-max-xl); }
|
||||
`],
|
||||
template: `
|
||||
@if (state().categoriesError) {
|
||||
<app-upload-status-banner type="error" [message]="state().categoriesError!" />
|
||||
} @else {
|
||||
@if (state().backgroundSyncAvailable === false) {
|
||||
<app-upload-status-banner type="info" [message]="foregroundOnlyMessage" />
|
||||
}
|
||||
@for (c of state().categories; track c.categoryId) {
|
||||
<app-document-category
|
||||
[category]="c"
|
||||
[uploads]="uploadsFor(c.categoryId)"
|
||||
[channel]="channelFor(c.categoryId)"
|
||||
[rejection]="state().rejections[c.categoryId]"
|
||||
(fileSelected)="fileSelected.emit({ categoryId: c.categoryId, files: $event })"
|
||||
(removeUpload)="removeUpload.emit($event)"
|
||||
(retryUpload)="retryUpload.emit($event)"
|
||||
(deleteUpload)="deleteUpload.emit($event)"
|
||||
(channelChange)="channelChange.emit({ categoryId: c.categoryId, channel: $event })" />
|
||||
}
|
||||
}
|
||||
`,
|
||||
})
|
||||
export class DocumentUploadComponent {
|
||||
state = input.required<UploadState>();
|
||||
|
||||
fileSelected = output<{ categoryId: string; files: File[] }>();
|
||||
removeUpload = output<string>();
|
||||
retryUpload = output<string>();
|
||||
deleteUpload = output<{ localId: string; documentId: string }>();
|
||||
channelChange = output<{ categoryId: string; channel: DeliveryChannel }>();
|
||||
|
||||
protected readonly foregroundOnlyMessage = $localize`:@@upload.foregroundOnly:Uploads gaan alleen door zolang deze pagina open blijft.`;
|
||||
|
||||
protected uploadsFor(categoryId: string) {
|
||||
return this.state().uploads.filter((u) => u.categoryId === categoryId);
|
||||
}
|
||||
protected channelFor(categoryId: string): DeliveryChannel {
|
||||
return this.state().deliveryChannel[categoryId] ?? 'digital';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user