Commit Graph

336 Commits

Author SHA1 Message Date
Marcel
d8dcba1a71 fix(ocr): unblock event loop during OCR and show errors in UI
OCR engines are CPU-bound and were blocking Uvicorn's single async
event loop, making /health unresponsive during processing. This caused
new OCR requests to fail silently (health check failure → no DB record
→ UI shows NONE). Wrap engine calls in asyncio.to_thread() to keep the
event loop free. Also surface OCR trigger errors in the frontend
instead of silently resetting the spinner.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 23:50:39 +02:00
Marcel
ef11e4af09 fix(ocr): disable manual annotation drawing while OCR is running
Some checks failed
CI / Unit & Component Tests (push) Failing after 1s
CI / Backend Unit Tests (push) Failing after 1s
CI / Unit & Component Tests (pull_request) Failing after 1s
CI / Backend Unit Tests (pull_request) Failing after 1s
Prevents users from drawing annotations that would be cleared when
the OCR job finishes. transcribeMode is set to false for the PDF
viewer while ocrRunning is true.

Refs #226

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 23:32:55 +02:00
Marcel
971527a50e feat(ocr): show translated progress messages during OCR processing
Some checks failed
CI / Unit & Component Tests (push) Failing after 2s
CI / Backend Unit Tests (push) Failing after 1s
CI / Unit & Component Tests (pull_request) Failing after 2s
CI / Backend Unit Tests (pull_request) Failing after 1s
Backend sends progress codes (PREPARING, LOADING, ANALYZING,
CREATING_BLOCKS:N, DONE:N, ERROR) via OcrJob.progressMessage.
Frontend translates them via Paraglide (de/en/es) and displays
below the spinner.

- V27 migration: adds progress_message column to ocr_jobs
- OcrAsyncRunner updates progress at each phase
- Poll interval reduced to 2s for snappier updates

Refs #226

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 23:31:23 +02:00
Marcel
c1befd3fa3 fix(ocr): resume polling on page reload + track single-doc job status
Some checks failed
CI / Unit & Component Tests (push) Failing after 1s
CI / Backend Unit Tests (push) Failing after 1s
CI / Unit & Component Tests (pull_request) Failing after 0s
CI / Backend Unit Tests (pull_request) Failing after 1s
Single-document OCR now creates an OcrJobDocument row so
GET /api/documents/{id}/ocr-status can find running jobs.
OcrAsyncRunner updates the job document status (RUNNING → DONE/FAILED).

Frontend checks OCR status when entering transcription mode —
if a job is running, resumes polling and shows the spinner.

Refs #226

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 23:16:59 +02:00
Marcel
dd175d09e2 refactor(ocr): make single-document OCR async, fix circular dependency
Some checks failed
CI / Unit & Component Tests (push) Failing after 1s
CI / Backend Unit Tests (push) Failing after 1s
CI / Unit & Component Tests (pull_request) Failing after 1s
CI / Backend Unit Tests (pull_request) Failing after 1s
OcrService → OcrAsyncRunner was circular. Fixed by moving all OCR
processing logic (processDocument, clearExistingBlocks, createBlocks)
into OcrAsyncRunner. OcrService is now a thin entry point that
validates, creates the job, and dispatches to OcrAsyncRunner.

Architecture:
- OcrService: validates document, checks health, creates OcrJob, delegates
- OcrAsyncRunner: @Async processDocument + runSingleDocument + runBatch
- OcrBatchService: creates job + job documents, delegates to OcrAsyncRunner
- No circular dependencies

Single-document OCR is now async (returns jobId immediately).
Frontend polls GET /api/ocr/jobs/{jobId} every 3s until DONE/FAILED.

816 backend tests pass, 687 frontend tests pass.

Refs #226

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 22:55:52 +02:00
Marcel
f6667e0e15 feat(frontend): show OcrProgress during OCR job + check status on load
Some checks failed
CI / Unit & Component Tests (push) Failing after 1s
CI / Backend Unit Tests (push) Failing after 2s
CI / Unit & Component Tests (pull_request) Failing after 1s
CI / Backend Unit Tests (pull_request) Failing after 1s
- triggerOcr captures jobId from POST response and shows OcrProgress
- OcrProgress rendered in the transcription panel when ocrJobId is set
- handleOcrDone reloads blocks and annotations when OCR completes
- checkOcrStatus called when entering transcription mode — resumes
  progress display if a job is already running for this document

Refs #226

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 22:09:24 +02:00
Marcel
8dc9243add feat(frontend): wire OCR trigger + review toggle into transcription panel
Some checks failed
CI / Unit & Component Tests (push) Failing after 1s
CI / Backend Unit Tests (push) Failing after 1s
CI / Unit & Component Tests (pull_request) Failing after 1s
CI / Backend Unit Tests (pull_request) Failing after 1s
- OcrTrigger component rendered in the transcription empty state when
  the document has a file and user has write permission
- Review checkmark toggle on each TranscriptionBlock (turquoise when
  reviewed, muted outline when not). Calls PUT .../review to toggle.
- TranscriptionBlockData type: added source + reviewed fields
- +page.svelte: triggerOcr() and reviewToggle() functions wired up
- Paraglide translations (de/en/es) for review toggle + reviewed count

All 687 frontend tests pass.

Refs #226, #230

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 22:02:56 +02:00
Marcel
11a35f2952 fix(tests): resolve all 4 pre-existing test failures
Some checks failed
CI / Unit & Component Tests (push) Failing after 1s
CI / Backend Unit Tests (push) Failing after 1s
- CommentThread: add missing empty-state paragraph using comment_empty_hint
  i18n key (key existed but was never rendered in the template)
- TranscriptionBlock: add selectedQuote hint using transcription_block_quote_hint
  i18n key (key existed but was never rendered); fix test to use native DOM
  el.focus()/setSelectionRange()/dispatchEvent instead of locator.selectText()
  which is not available in this vitest-browser version
- TranscriptionEditView: fix test to use native el.dispatchEvent(FocusEvent)
  instead of locator.blur() which is not available
- Conversations: fix test expected text from stale "Korrespondenz durchsuchen"
  to match current conv_empty_heading() = "Wessen Briefe möchten Sie lesen?"

All 687 tests now pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 14:55:34 +02:00
Marcel
a2d078b8f9 refactor(persons): replace non-null assertion with null guard on removeFormEl
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 14:36:47 +02:00
Marcel
1a519eedd6 refactor(persons): replace inline delete modal with ConfirmService in NameHistoryEditCard
Some checks failed
CI / Unit & Component Tests (push) Failing after 4s
CI / Backend Unit Tests (push) Failing after 1s
CI / Unit & Component Tests (pull_request) Failing after 3s
CI / Backend Unit Tests (pull_request) Failing after 2s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 14:19:33 +02:00
Marcel
498679234a refactor(docs): replace inline confirmDelete toggle with ConfirmService in SaveBar
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 14:12:01 +02:00
Marcel
14fc5cbc54 refactor(admin): replace window.confirm with ConfirmService in admin group delete
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 14:06:54 +02:00
Marcel
0d1401ce4f refactor(admin): replace window.confirm with ConfirmService in admin user delete
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 14:04:09 +02:00
Marcel
08bd27b5cd feat(layout): mount ConfirmDialog in root layout and provide confirm service
provideConfirmService() sets up context for the entire component tree.
ConfirmDialog is mounted once at the bottom of the layout shell.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 13:21:34 +02:00
Marcel
fb00de6690 feat(design-system): add --c-danger/--c-danger-fg token pair for destructive actions
Light: #c0392b (5.1:1 on white — WCAG AA), dark: #e55347 (4.7:1 on surface).
Exposed as bg-danger/text-danger-fg Tailwind utilities via @theme inline.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 13:07:46 +02:00
Marcel
166f60f7d3 feat(ui): show type icon in avatar for non-person entities
Person list and detail page avatars now display a type-specific
icon (building, people group, question mark) instead of meaningless
initials for INSTITUTION, GROUP, and UNKNOWN person types.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 18:36:34 +02:00
Marcel
a1b21d6989 refactor(ui): use CSS custom properties for PersonTypeBadge colors
Replace hardcoded Tailwind utility colors with project CSS variables
(--c-badge-institution-*, --c-badge-group-*, --c-badge-unknown-*).
Dark mode variants defined in both @media and manual toggle blocks.
Extract shared badge classes and use $derived config object.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 18:35:05 +02:00
Marcel
6ee1ef73c3 feat(ui): add PersonTypeBadge to person list and detail pages
Show colored badge for non-PERSON types per design spec:
- INSTITUTION: blue with building icon
- GROUP: purple with people icon
- UNKNOWN: amber with question mark icon
- PERSON: no badge (unmarked default)

Badge appears on person cards in list and on detail page.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 13:09:16 +02:00
Marcel
1aabd9826c test(frontend): update mock data for displayName and nullable firstName
Add displayName and personType to all Person mock objects in
component and page tests. Update assertions from reversed
"lastName, firstName" format to forward-order displayName.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 12:47:15 +02:00
Marcel
f11d8a38ed feat(frontend): replace all name concatenation with displayName
- Add displayName default method to PersonSummaryDTO
- Update native SQL queries to include title, person_type columns
- Add getInitials() utility to personFormat.ts
- Update abbreviateName/abbreviateCompact for nullable firstName
- Replace firstName+lastName concatenation with displayName in all
  person-displaying components and server load files
- Regenerate API types with displayName on Person and PersonSummaryDTO

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 12:22:30 +02:00
Marcel
e204ed89b6 fix(ui): switch alias operations from client fetch to form actions
Some checks failed
CI / Unit & Component Tests (push) Failing after 1s
CI / Backend Unit Tests (push) Failing after 2s
CI / Unit & Component Tests (pull_request) Failing after 1s
CI / Backend Unit Tests (pull_request) Failing after 1s
Replaces raw client-side fetch with SvelteKit form actions
(addAlias, removeAlias) using the server-side API client for
proper auth handling. 10 new component tests for NameHistoryEditCard.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 16:05:56 +02:00
Marcel
036843bf8f fix(ui): use mt-6 on save bar to match card spacing
Some checks failed
CI / Unit & Component Tests (push) Failing after 3s
CI / Backend Unit Tests (push) Failing after 2s
CI / Unit & Component Tests (pull_request) Failing after 2s
CI / Backend Unit Tests (pull_request) Failing after 1s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 16:01:43 +02:00
Marcel
9027f60760 fix(ui): use card-style save bar with mt-4 instead of full-bleed
Some checks failed
CI / Unit & Component Tests (push) Failing after 3s
CI / Backend Unit Tests (push) Failing after 1s
CI / Unit & Component Tests (pull_request) Failing after 1s
CI / Backend Unit Tests (pull_request) Failing after 1s
Removes -mx-4 negative margin and switches to the card pattern
(rounded border, shadow-sm, mt-4) so the save bar matches the
width of the other cards on the edit page.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 15:59:55 +02:00
Marcel
0f5eebec29 fix(ui): move save bar to end of edit page after alias and danger zone
Some checks failed
CI / Unit & Component Tests (push) Failing after 2s
CI / Backend Unit Tests (push) Failing after 1s
CI / Unit & Component Tests (pull_request) Failing after 1s
CI / Backend Unit Tests (pull_request) Failing after 1s
Uses HTML form attribute to associate the submit button with the
person-edit-form from outside the form tag. Page now reads:
Personendaten -> Namensverlauf -> Danger zone -> Save bar.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 15:59:05 +02:00
Marcel
f0eb3a76be test(ui): add component tests for NameHistoryCard
Some checks failed
CI / Unit & Component Tests (push) Failing after 3s
CI / Backend Unit Tests (push) Failing after 1s
CI / Unit & Component Tests (pull_request) Failing after 2s
CI / Backend Unit Tests (pull_request) Failing after 2s
Verifies alias rendering, empty state, firstName fallback,
and type label display. 5 browser-based Svelte tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 13:43:09 +02:00
Marcel
6d837c518c fix(a11y): include alias name in delete button aria-label
Screen readers now announce which alias is being deleted, e.g.
"Entfernen de Gruyter" instead of just "Entfernen".

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 13:42:08 +02:00
Marcel
97646a31df fix(ui): always show Namensverlauf card on detail page
Removes the {#if} guard so the card with empty state message is
always visible for feature discoverability.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 13:41:19 +02:00
Marcel
59f593280b fix(test): update person detail loader tests for 4th aliases API call
Some checks failed
CI / Unit & Component Tests (push) Failing after 2s
CI / Backend Unit Tests (push) Failing after 1s
CI / Unit & Component Tests (pull_request) Failing after 1s
CI / Backend Unit Tests (pull_request) Failing after 2s
Adds mock for the new GET /api/persons/{id}/aliases call added
in the parallel Promise.all.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 13:35:19 +02:00
Marcel
b910517690 feat(ui): add alias management to person edit page
NameHistoryEditCard with add form (type dropdown + name fields),
delete with confirmation modal, and IDOR-safe client-side fetch
calls. Placed between Personendaten and DangerZone cards.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 13:31:41 +02:00
Marcel
002ee1010a feat(ui): add Namensverlauf read-only card to person detail page
Shows historical name aliases in the left column with type labels
and firstName fallback. Fetches aliases in parallel with other data.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 13:31:07 +02:00
Marcel
b5ec4ebc0c refactor(ui): rename shadowed m parameter to newMode
Some checks failed
CI / Unit & Component Tests (pull_request) Failing after 1s
CI / Backend Unit Tests (pull_request) Failing after 3s
CI / Unit & Component Tests (push) Failing after 3s
CI / Backend Unit Tests (push) Failing after 2s
Avoids shadowing the Paraglide m import in the onModeChange callback.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 11:58:54 +02:00
Marcel
4d5b8b4ead feat(ui): add collapsible PDF strip and abbreviated labels on mobile
Some checks failed
CI / Unit & Component Tests (push) Failing after 2s
CI / Backend Unit Tests (push) Failing after 2s
CI / Unit & Component Tests (pull_request) Failing after 3s
CI / Backend Unit Tests (pull_request) Failing after 1s
PDF viewer collapses to 70px on mobile in read mode, expandable to
50vh. Toggle button with chevron. Paragraph tap auto-expands strip.
Mode toggle abbreviates to "Bearb." on small screens.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 11:30:36 +02:00
Marcel
10cecb01f5 feat(a11y): respect prefers-reduced-motion for scroll-sync
Uses scrollIntoView behavior 'instant' instead of 'smooth', skips
CSS animations (static highlight instead), and extends timeout to
2s for reduced-motion users.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 11:27:01 +02:00
Marcel
81b14e5026 feat(ui): add bidirectional scroll-sync with flash animations
Paragraph click flashes the PDF annotation outline (1.5s fade).
Annotation click highlights the paragraph with a background flash.
Both directions scroll the target into view.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 11:25:23 +02:00
Marcel
e089192d7a feat(ui): wire panelMode state with read/edit view switching
Adds TranscriptionPanelHeader and TranscriptionReadView to the
document detail page. Default mode is 'read' when blocks exist,
'edit' otherwise. Annotations dimmed in read mode.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 11:21:15 +02:00
Marcel
53b318f7ad fix(ui): add py-8 to results state matching document search page
Some checks failed
CI / Unit & Component Tests (pull_request) Failing after 2s
CI / Backend Unit Tests (pull_request) Failing after 1s
CI / Unit & Component Tests (push) Failing after 3s
CI / Backend Unit Tests (push) Failing after 2s
Aligns the top/bottom padding of the Briefwechsel results view with
the document search page wrapper (both py-8).

Refs: #179

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 08:52:44 +02:00
Marcel
001e875f31 fix(ui): use De Gruyter long arrows for swap button and timeline entries
Some checks failed
CI / Unit & Component Tests (push) Failing after 2s
CI / Backend Unit Tests (push) Failing after 1s
CI / Unit & Component Tests (pull_request) Failing after 1s
CI / Backend Unit Tests (pull_request) Failing after 1s
Swap button: stack right/left arrows vertically at h-3.5 for a
compact look. Timeline: replace → ← text with Long-Arrow icons on
each letter entry and the distribution bar summary.

Refs: #179

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 08:50:58 +02:00
Marcel
06709e7458 fix(ui): remove disabled look from receiver typeahead when empty
Some checks failed
CI / Unit & Component Tests (push) Failing after 3s
CI / Backend Unit Tests (push) Failing after 1s
CI / Unit & Component Tests (pull_request) Failing after 1s
CI / Backend Unit Tests (pull_request) Failing after 2s
Remove border-dashed and bg-canvas conditional styles so the
receiver input matches the sender input styling. The placeholder
"Alle Korrespondenten" already communicates the optional state.

Refs: #179

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 08:46:36 +02:00
Marcel
7fed057e59 fix(ui): prevent hero flicker when clearing sender input
Some checks failed
CI / Unit & Component Tests (pull_request) Failing after 2s
CI / Backend Unit Tests (pull_request) Failing after 2s
CI / Unit & Component Tests (push) Failing after 5s
CI / Backend Unit Tests (push) Failing after 5s
Only navigate (applyFilters) when a person is actually selected, not
when the sender input is cleared. Combined with showHero checking
data.filters.senderId, the user stays in the search bar view after
clearing — no jump back to the hero.

Refs: #179

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 22:56:44 +02:00
Marcel
a3edf9d7b4 fix(ui): date input placeholders show format TT.MM.JJJJ instead of label
Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Failing after 1m20s
CI / Backend Unit Tests (pull_request) Failing after 1m49s
Remove custom placeholder props so DateInput falls back to its default
format hint (TT.MM.JJJJ / DD.MM.YYYY / DD.MM.AAAA) instead of
repeating the label text above.

Refs: #179

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 22:47:28 +02:00
Marcel
708d02a1f7 fix(ui): unify date inputs — use DateInput component on both pages
Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Failing after 1m16s
CI / Backend Unit Tests (pull_request) Failing after 2m23s
Replace native <input type="date"> on the document search page with
the custom DateInput component (German dd.mm.yyyy format with auto-dot
insertion). Align both pages' date input styling: add rounded-md,
border, bg-surface, px-3, text-ink, placeholder color, and focus ring
to match all other inputs in the card.

Refs: #179

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 22:46:29 +02:00
Marcel
2e943b7f91 fix(ui): De Gruyter long arrows on both sort buttons, rotate swap icon 90°
Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Failing after 1m21s
CI / Backend Unit Tests (pull_request) Failing after 2m30s
Replace ↑↓ text with Long-Arrow-Up/Down-MD.svg on the document search
SortDropdown and the Briefwechsel sort button. Rotate the swap button
SVG 90° so arrows point left/right matching the horizontal person
field layout.

Refs: #179

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 22:43:45 +02:00
Marcel
b4a9e678c6 fix(ui): use De Gruyter long arrow icons for sort direction
Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Failing after 1m24s
CI / Backend Unit Tests (pull_request) Failing after 2m28s
Replace tiny ↑↓ text with Long-Arrow-Up/Down-MD.svg icons from the
brand icon set for better visibility and consistency.

Refs: #179

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 22:37:50 +02:00
Marcel
fe51936d17 fix(ui): use sort arrows ↑↓ instead of chevrons on sort button
Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Failing after 1m17s
CI / Backend Unit Tests (pull_request) Failing after 2m23s
Chevrons indicate collapsible elements, not sort direction. Match
the document search SortDropdown pattern using ↑/↓ text arrows.

Refs: #179

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 22:36:05 +02:00
Marcel
c8b4bce003 feat(ui): collapsible date filter with sort + filter toggle on person row
Some checks failed
CI / Unit & Component Tests (push) Failing after 1m13s
CI / Backend Unit Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Failing after 1m10s
CI / Backend Unit Tests (pull_request) Failing after 2m33s
Move sort button and filter toggle to the person row, matching the
document search page pattern (sort + filter + count inline). Date
range inputs are now a collapsible section behind the filter toggle,
using slide transition and the same grid layout as the document
search advanced filters. Fix date input padding (add px-3).

Refs: #179

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 22:34:14 +02:00
Marcel
c4715f1637 fix(ui): unify Briefwechsel search bar with document search card style
Some checks failed
CI / Unit & Component Tests (push) Failing after 1m26s
CI / Backend Unit Tests (push) Failing after 2m25s
CI / Unit & Component Tests (pull_request) Failing after 1m15s
CI / Backend Unit Tests (pull_request) Failing after 2m20s
Wrap person bar + filter controls in a card matching the document
search page (rounded-sm border p-6 shadow-sm). Switch PersonTypeahead
to default mode with matching label/input overrides. Bump date inputs
and sort button to text-sm py-2.5. Filter row uses border-t separator
like the document search advanced section.

Refs: #179

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 22:20:32 +02:00
Marcel
93be64878e fix(ui): guard selectPerson against empty id
Some checks failed
CI / Unit & Component Tests (push) Failing after 1m16s
CI / Backend Unit Tests (push) Failing after 2m30s
CI / Unit & Component Tests (pull_request) Failing after 1m11s
CI / Backend Unit Tests (pull_request) Failing after 2m39s
Restores early return when id is empty, preventing a wasteful
navigation to /briefwechsel with no senderId param.

Refs: #179

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 20:30:30 +02:00
Marcel
e2af9f924b fix(i18n): replace hardcoded "oder" with conv_hero_divider message key
Adds conv_hero_divider to de/en/es messages and uses it in the
CorrespondenzHero divider. Fixes i18n blocker from review.

Refs: #179

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 20:29:31 +02:00
Marcel
822a2fac3a fix(ui): add inner padding to strip components
Some checks failed
CI / Unit & Component Tests (push) Failing after 1m59s
CI / Backend Unit Tests (push) Failing after 3m2s
CI / Unit & Component Tests (pull_request) Failing after 1m18s
CI / Backend Unit Tests (pull_request) Failing after 2m29s
Add px-3 to person bar, filter controls, and hint bar so inputs
don't sit flush against the container edge.

Refs: #179

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 19:53:03 +02:00
Marcel
fbf5e9f178 refactor(ui): remove CorrespondenzEmptyState, replaced by CorrespondenzHero
Refs: #179

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 19:50:07 +02:00