feat(enrich): field reordering, required-fields progress bar, and no-PDF upload state #267

Merged
marcel merged 20 commits from feat/issue-261-enrich-field-reorder-progress-bar-upload into main 2026-04-18 23:36:33 +02:00

20 Commits

Author SHA1 Message Date
Marcel
0cdd7d9695 fix(forms): correct required/optional field markers and divider placement
Some checks failed
CI / Unit & Component Tests (push) Failing after 3m13s
CI / OCR Service Tests (push) Successful in 39s
CI / Backend Unit Tests (push) Failing after 2m49s
CI / Unit & Component Tests (pull_request) Failing after 2m23s
CI / OCR Service Tests (pull_request) Successful in 30s
CI / Backend Unit Tests (pull_request) Failing after 2m39s
- Add * to Datum and Absender labels (both are required fields)
- Add required prop to PersonTypeahead to show * in its label
- Move "Optional" divider in DescriptionSection to after Titel (the only
  required field), so Tags and Inhalt appear below the divider where they belong

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 20:12:41 +02:00
Marcel
921c7dcd7f test(edit): add tests for handleDelete on the edit page
Some checks failed
CI / Unit & Component Tests (push) Failing after 2m43s
CI / OCR Service Tests (push) Successful in 44s
CI / Backend Unit Tests (push) Failing after 2m58s
CI / Unit & Component Tests (pull_request) Failing after 2m46s
CI / OCR Service Tests (pull_request) Successful in 42s
CI / Backend Unit Tests (pull_request) Failing after 3m8s
Covers: button present, confirm dialog opens, form submitted on confirm,
form not submitted on cancel.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 16:30:10 +02:00
Marcel
3f07c4fe58 refactor(types): use generated Document type for doc prop in DocumentEditLayout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 16:18:24 +02:00
Marcel
aff485400d feat(upload): validate MIME type and size on file replace in DocumentEditLayout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 16:15:22 +02:00
Marcel
ddbd6ef92f feat(i18n): extract hardcoded strings in DocumentEditLayout to i18n keys
Adds label_required_fields to all three locales. Fixes "Datei ersetzen"
toolbar colors to use semantic ink tokens (readable in both light and dark
pdf-bg themes).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 16:12:01 +02:00
Marcel
9daf43834b feat(upload): replace Unicode arrow with SVG icon in UploadZone
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 16:08:59 +02:00
Marcel
8149949de8 feat(edit): unify edit page with enrich split-panel layout
Some checks failed
CI / OCR Service Tests (push) Successful in 41s
CI / Backend Unit Tests (push) Failing after 2m51s
CI / Backend Unit Tests (pull_request) Failing after 2m47s
CI / Unit & Component Tests (push) Failing after 2m33s
CI / Unit & Component Tests (pull_request) Failing after 2m36s
CI / OCR Service Tests (pull_request) Successful in 31s
Extract DocumentEditLayout shared component for the PDF+form split-panel
UI, replacing the old scrolling layout on /documents/[id]/edit with the
same fixed-panel structure used by /enrich/[id]. Removes TranscriptionSection
and FileSectionEdit from the edit page; file upload/replace is now handled
by the shared layout. Delete SaveBar and FileSectionEdit as dead code.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 15:50:21 +02:00
Marcel
a8c8c3fbcf fix(i18n): replace hardcoded strings with Paraglide message keys
Some checks failed
CI / Unit & Component Tests (push) Failing after 2m34s
CI / OCR Service Tests (push) Successful in 35s
CI / Backend Unit Tests (push) Failing after 2m49s
CI / Unit & Component Tests (pull_request) Failing after 2m40s
CI / OCR Service Tests (pull_request) Successful in 38s
CI / Backend Unit Tests (pull_request) Failing after 2m46s
- error_file_upload_failed key used in enrich upload handler
- label_optional key added (de/en/es) and used in DescriptionSection divider

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 14:54:06 +02:00
Marcel
02cc08dfc6 fix(a11y): bump Optional divider label to text-xs minimum (WCAG 1.4.4)
Some checks failed
CI / Unit & Component Tests (push) Failing after 2m37s
CI / OCR Service Tests (push) Successful in 38s
CI / Backend Unit Tests (push) Failing after 2m43s
CI / Unit & Component Tests (pull_request) Failing after 2m35s
CI / Backend Unit Tests (pull_request) Failing after 2m48s
CI / OCR Service Tests (pull_request) Successful in 37s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 14:38:29 +02:00
Marcel
0e1f076727 fix(a11y): bump progress bar text to text-xs minimum, add motion-safe to upload animation
Some checks failed
CI / Unit & Component Tests (push) Failing after 2m39s
CI / OCR Service Tests (push) Successful in 35s
CI / Backend Unit Tests (push) Failing after 2m46s
CI / Unit & Component Tests (pull_request) Failing after 2m37s
CI / OCR Service Tests (pull_request) Successful in 36s
CI / Backend Unit Tests (pull_request) Failing after 2m50s
- text-[9px]/text-[10px] in required-fields bar raised to text-xs (12px),
  meeting the project minimum for the 60+ audience (WCAG 1.4.4)
- Upload animation now uses motion-safe: prefix so it stops for users
  with prefers-reduced-motion set (WCAG 2.1 SC 2.3.3)
- Strengthened UploadZone tests: onCancel uses [role=status] button
  selector instead of first-button heuristic; added positive file
  selection test (valid PDF calls onFile), file-too-large test, and
  MIME rejection now also asserts the error message is visible

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 14:31:05 +02:00
Marcel
270005e0da fix(backend): move IOException into service, add content-type whitelist to attachFile
- DocumentService.attachFile() now catches IOException internally and
  re-throws as DomainException.internal — the IOException no longer leaks
  through the service boundary
- DocumentController.attachFile() is now a plain delegate (no try/catch)
- ALLOWED_CONTENT_TYPES whitelist (PDF/JPEG/PNG/TIFF) is now enforced on
  the attachFile endpoint, matching the existing quick-upload validation
- Added 5 DocumentService unit tests for attachFile (notFound, status
  transition PLACEHOLDER→UPLOADED, no-change when already UPLOADED,
  field assignment from upload result, IOException→DomainException)
- Added controller tests: 400 on disallowed content type, 404 on missing doc

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 14:27:22 +02:00
Marcel
836d30e262 feat(frontend): wire progress bar, upload zone, and file replace into enrich page
Some checks failed
CI / Unit & Component Tests (push) Failing after 2m35s
CI / OCR Service Tests (push) Successful in 37s
CI / Backend Unit Tests (push) Failing after 2m54s
CI / Unit & Component Tests (pull_request) Failing after 2m31s
CI / OCR Service Tests (pull_request) Successful in 32s
CI / Backend Unit Tests (pull_request) Failing after 2m43s
- Required-fields progress bar (Pflichtfelder) with role="progressbar" ARIA tracks
  Titel, Datum, and Absender live via bound props from child components
- Left panel shows UploadZone for PLACEHOLDER documents (no filePath); after upload
  invalidates 'app:document' to transition to PDF viewer without page reload
- AbortController powers the cancel button during upload
- "Datei ersetzen" ghost button lives in a thin toolbar above the PDF viewer
- dateIso and currentTitle are now bound from WhoWhenSection/DescriptionSection

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 14:07:23 +02:00
Marcel
93fc8696fd feat(frontend): add countRequiredFilled utility with all 8 field-combination tests
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 14:05:09 +02:00
Marcel
14cfe8cae6 feat(frontend): add UploadZone component for PLACEHOLDER document file upload
Presentational component with idle/uploading/error states, drag-and-drop,
client-side MIME type + 50 MB size validation, accessible touch targets (44px),
aria-live region, and indeterminate progress animation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 14:03:28 +02:00
Marcel
3893a104d3 feat(frontend): add @keyframes slide for indeterminate upload progress animation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 13:57:44 +02:00
Marcel
44c7adbc24 feat(frontend): add depends('app:document') to enrich load for targeted invalidation after file upload
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 13:56:32 +02:00
Marcel
765d282923 feat(frontend): reorder DescriptionSection fields, expose currentTitle bindable, add Optional divider
Field order: Titel → Schlagworte → Kurzinhalt → [Optional divider] → Aufbewahrungsort.
currentTitle is now bindable so the enrich page can derive the required-fields progress bar.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 13:55:38 +02:00
Marcel
77db791d0a feat(frontend): reorder WhoWhenSection grid, expose dateIso bindable, add autofocus
Required fields (Datum, Absender) move to row 1; optional fields (Empfänger, Ort)
to row 2. dateIso is now bindable for the progress bar. Autofocus lands on the
first empty required field on page load.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 13:54:26 +02:00
Marcel
255eeb660b feat(frontend): add autofocus prop to PersonTypeahead forwarded to text input
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 13:53:10 +02:00
Marcel
57ed9379a2 feat(backend): add POST /api/documents/{id}/file endpoint to attach file to existing document
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 13:46:25 +02:00