Files
familienarchiv/frontend/src/lib/shared
Marcel 6150fc7be5
Some checks failed
CI / Unit & Component Tests (pull_request) Failing after 4m17s
CI / OCR Service Tests (pull_request) Successful in 24s
CI / Backend Unit Tests (pull_request) Successful in 5m23s
CI / fail2ban Regex (pull_request) Successful in 47s
CI / Semgrep Security Scan (pull_request) Successful in 26s
CI / Compose Bucket Idempotency (pull_request) Successful in 1m8s
SDD Gate / RTM Check (pull_request) Successful in 16s
SDD Gate / Contract Validate (pull_request) Successful in 25s
SDD Gate / Constitution Impact (pull_request) Successful in 17s
fix(timeline): track form dirtiness via change callbacks, not an $effect
The round-2 dirty-guard used an $effect that both read and wrote its `dirtyArmed`
$state, so the self-write re-triggered the effect and `dirty` flipped true on
mount — the beforeNavigate confirm then fired on every navigation away from an
untouched form (caught by the round-3 clean-agent review + the Svelte autofixer,
which flags assigning state inside $effect).

Replace it with the component's existing idiomatic pattern: DatePrecisionField,
PersonMultiSelect, and DocumentMultiSelect each gain an optional `onchange`
callback fired on a real user edit, and EventForm passes `markDirty` to all
three. Now date/precision/end-date and picker add/remove mark the form dirty
exactly like title/type/description already did — no effect, no mount-timing
trap. The new props are optional, so the other consumers (WhoWhenSection, the
document forms) are unaffected. Svelte autofixer: clean.

Addresses PR #832 review (round-3 clean-agent concern).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 00:55:34 +02:00
..

shared (frontend)

Cross-domain utilities and UI primitives. Any file here is consumed by two or more domain folders and has no domain identity of its own.

Admission criteria (what belongs here)

A file belongs in shared/ if it meets all three conditions:

  1. No domain identity — it does not represent a Document, Person, Tag, etc.
  2. Consumed by ≥ 2 domain folders — or is framework infrastructure that every domain depends on.
  3. Generic — could work in a different SvelteKit project with zero business-logic changes.

If any condition fails, the file belongs in the domain folder of its primary consumer.

What this folder owns

Sub-folder / file Purpose
api.server.ts Typed openapi-fetch client factory — the standard entry point for all backend API calls in server-side load functions and actions
errors.ts Mirror of the backend ErrorCode enum + getErrorMessage() → Paraglide i18n key mapping
types.ts Cross-domain TypeScript interfaces
utils.ts Pure utility functions (date formatting, sorting, debounce)
utils/monthBuckets.ts Pure month-bucket math (boundaries, sequences, gap-fill, year aggregation, axis ticks) shared by the document/ density chart and the timeline/ density strip — moved up from document/timeline.ts so timeline/ need not import document/
primitives/Sparkline.svelte Fixed-series bar sparkline (one bar per value) — used by the timeline density strip
relativeTime.ts Human-relative time formatting ("2 days ago")
primitives/ Generic UI components: BackButton.svelte, form inputs, pagination, layout shells
discussion/ Comment/mention editor shared by document/ and geschichte/
dashboard/ Family Pulse widget and recent-activity components assembled in the / route
hooks/ Svelte 5 reactive hooks: useTypeahead, useUnsavedWarning
services/ Generic client-side service helpers
actions/ Shared SvelteKit form action utilities
server/ Server-only shared utilities (load function helpers)
help/ Coach marks and empty-state components used across multiple domains

What does NOT belong here

  • Components owned by one domain — move to that domain's folder.
  • Domain-specific business logic — even if shared, it belongs in the owning domain's public surface.

Adding to shared/

If you need to add a file here, confirm it meets all three admission criteria. If it's domain-adjacent, check whether the owning domain should export it as part of its public surface instead.