Commit Graph

875 Commits

Author SHA1 Message Date
Marcel
7cb20dec50 test: add e2e tests 2026-03-17 13:34:05 +00:00
Marcel
4417fc9828 refactor: migrate all Svelte components from Svelte 4 to Svelte 5 runes
- Replace `export let` with `$props()` and `$bindable()` across all components
- Replace `$:` reactive statements with `$derived()` and `$effect()`
- Replace `createEventDispatcher` with callback props (e.g. `onchange`)
- Replace `on:event` directives with inline event handlers (`onclick`, `oninput`, etc.)
- Replace `<slot />` with `{@render children()}` in layout
- Use `untrack()` for SSR-safe $state initialization from reactive props
- Replace `blur` + `setTimeout` anti-pattern in TagInput with `clickOutside` action
- Fix `page` store usage in layout to use `$app/state` directly
- 0 errors, 0 warnings after svelte-check

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 11:43:26 +01:00
Marcel
6b5c78f789 fix: align save bar width with form card on new person page
Replaced sticky full-bleed bar with a regular card-style row,
matching the form card width and adding mt-4 top margin.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 16:25:44 +01:00
Marcel
0123dffdc4 feat: add create person feature via web interface
- Backend: new POST /api/persons endpoint in PersonController
- Frontend: new /persons/new route with Vorname/Nachname/Alias form,
  redirects to the new person's detail page on success
- Persons list: subtle '+ Neue Person' link below the page title

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 16:23:05 +01:00
Marcel
b583c8489d fix: disable overscroll bounce to keep header stationary
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 16:13:24 +01:00
Marcel
29c5f1ff81 fix: improve visibility of person search input
Added white background, explicit border, and rounded corners to make
the search field clearly visible against the sand-colored page background.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 16:08:45 +01:00
Marcel
6fcff3355d feat: add create document feature via web interface
- Backend: new POST /api/documents endpoint with DocumentService.createDocument()
  reusing DocumentUpdateDTO; handles file upload, tags, sender, receivers
- Frontend: new /documents/new route with same four-section form as edit page
  (Wer & Wann, Beschreibung, Transkription, Datei) but with empty fields
- Home page: subtle '+ Neues Dokument' link above the document list

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 16:04:56 +01:00
Marcel
c4806474df fix: format person document list dates with Intl API (20. Dezember 2026)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 15:48:06 +01:00
Marcel
d5d882fe88 fix: format home page document dates with Intl API (20. Dezember 2026)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 12:25:19 +01:00
Marcel
775e185e0f fix: format conversation date with Intl API (20. Dezember 2026)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 12:15:23 +01:00
Marcel
8a9e7bd9eb fix: resolve all 47 svelte-check errors and 10 a11y warnings
Root cause 1 — OpenAPI types: add @Schema(requiredMode=REQUIRED) to
non-nullable fields on Person, Tag, Document, AppUser, UserGroup;
regenerate api.ts so required fields are no longer optional.

Root cause 2 — Stale types: api.ts regenerated, picking up the Tag
endpoint fix from commit 62189d8 (List<Tag> instead of List<String>).

Root cause 3 — openapi-fetch error pattern: replace `if (apiError)`
(broken when error type is never/undefined) with `if (!result.response.ok)`
across all +page.server.ts files. Cast error via `unknown` to satisfy TS.

Root cause 4 — FormData casts: add `as string` / `as string[]` to
FormData.get() / FormData.getAll() calls in admin/+page.server.ts.

Standalone fixes:
- +page.server.ts: return error field so home page template compiles
- documents/[id]/+page.svelte: type loadFile param, remove invalid iframe `type`
- conversations: type documents as Document[] instead of unknown[]
- persons/[id]: non-null assert person data after ok-check

a11y: aria-label on all icon-only buttons in TagInput and admin page,
replace invalid <label> with <p> for compound controls, remove autofocus.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 12:08:25 +01:00
Marcel
5921a10d2e fix: format document date with Intl API (20. Dezember 2026)
Use Intl.DateTimeFormat with de-DE locale to show full German month
name. Appending T12:00:00 to the ISO string avoids UTC-midnight
timezone shifts misrendering the day.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 11:06:41 +01:00
Marcel
1c708d41ad fix: display document date in German format (dd.mm.yyyy)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 11:04:26 +01:00
Marcel
1c6ea5ec30 feat: add inline validation hint for German date input
Show a red border and format hint ("TT.MM.JJJJ") only when the user
has typed something but the date is not yet complete. Focuses-only
or empty fields show no error.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 11:02:08 +01:00
Marcel
eae9fba170 feat: use German date format (dd.mm.yyyy) with auto-dot insertion
Replace native date picker (mm/dd/yyyy) with a plain text input that
auto-inserts dots as the user types (20122026 → 20.12.2026). A hidden
field transforms the display value back to ISO (yyyy-mm-dd) before
the form is submitted to the backend.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 10:56:39 +01:00
Marcel
9c4a7acde8 feat: redesign document edit form for accessibility and usability
Full UX overhaul of the edit page targeting non-technical users:
- Grouped fields into four labelled sections (Wer & Wann, Beschreibung, Transkription, Datei)
- Replaced date text field with native <input type="date">
- Replaced sender <select> with PersonTypeahead component
- Replaced receiver multi-select with new PersonMultiSelect (chip-based)
- Sticky save bar at bottom with cancel/save actions
- Aligned all colours to brand palette (no more blue-*)
- Fixed a11y: replaced invalid <label> on compound components with <p>

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 10:50:03 +01:00
Marcel
8d66a50652 feat: add PersonMultiSelect component for chip-based multi-person selection
Replaces the native multi-select pattern with a typeahead + dismissible
chips UI. Uses fixed dropdown positioning (same getBoundingClientRect
trick as PersonTypeahead) to escape overflow:hidden parents.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 10:23:21 +01:00
Marcel
62189d8bb3 fix: show names in admin tag panel 2026-03-15 21:08:06 +00:00
Marcel
c2625657e2 fix: reset merge form after redirect 2026-03-15 21:00:01 +00:00
Marcel
ee279a29e5 feat: edit persons 2026-03-15 20:47:01 +00:00
Marcel
1819829d6e chore: regenerate api.ts after removing spring-boot-starter-data-rest
Now contains only the 16 intentional /api/* endpoints. TypeScript will
enforce path and parameter correctness for all typed client calls.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 14:31:07 +01:00
Marcel
d76248cffd refactor: migrate all page.server.ts files to typed API client
All server-side fetch calls now go through createApiClient() from
$lib/api.server.ts, which wraps openapi-fetch with the generated OpenAPI
types. This means backend changes are reflected in the frontend after
running npm run generate:api.

- Add stub src/lib/generated/api.ts (replaced by generate:api output)
- Fix GroupController: missing /api prefix and ResponseStatusException
- Root, conversations, persons, documents pages all use typed client
- Error handling uses apiError.code directly (no parseBackendError needed)
- Edit page load uses typed client; PUT action keeps raw fetch (multipart)
- Login keeps raw fetch (explicit Authorization header, not cookie auth)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 13:39:15 +01:00
Marcel
5d356cd694 feat: add OpenAPI spec (dev only) with typed frontend client
- Add springdoc-openapi 3.0.2 (supports Spring Boot 4) to backend
- Disable api-docs/swagger-ui in application.yaml (prod default)
- Enable both in application-dev.yaml; Swagger UI at /swagger-ui.html
- Add openapi-fetch (runtime) and openapi-typescript (dev) to frontend
- Add generate:api npm script — run with backend up to regenerate types
- Add src/lib/api.server.ts typed client factory (uses SvelteKit fetch)
- Gitignore src/lib/generated/api.ts (generated artifact)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 13:30:57 +01:00
Marcel
4cc86de143 feat: replace raw error messages with structured error codes
Backend now returns { code: ErrorCode, message: string } for all errors,
making it language-agnostic. Frontend maps codes to localised strings via
Paraglide (en/de/es), so translations live in messages/*.json.

- Add ErrorCode enum and DomainException with static factory methods
- Update GlobalExceptionHandler to return ErrorResponse(code, message)
- Replace ResponseStatusException throughout controllers/services/aspects
- Add frontend errors.ts with parseBackendError() and getErrorMessage()
- getErrorMessage() delegates to Paraglide m.error_*() functions
- Add error_* keys to messages/en.json, de.json, es.json
- Update all page.server.ts files to use the new error utilities
- Fix hardcoded localhost URLs in admin and login pages
- Fix missing baseUrl in deleteTag action

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 13:15:28 +01:00
Marcel
e63adb964d restructure: flatten workspace nesting, move devcontainer to root
- backend/workspaces/backend/ → backend/
- backend/workspaces/frontend/ → frontend/
- backend/.devcontainer/ + .vscode/ → repo root (where VS Code expects them)
- loose scripts/SQL files → scripts/
- replace nested git repo with single repo at project root
- update docker-compose.yml build context and devcontainer.json path
- add root .gitignore

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 11:47:58 +01:00