Commit graph

6 commits

Author SHA1 Message Date
Till JS
f2f752e9ee feat(web): apiErrorMessage-Utility + MultipleChoice-Fallback
- Neue Utility `apiErrorMessage()` in `$lib/api/error.ts`: liest `body.detail`
  / `body.error` aus ApiError-Responses statt generischer "(err as Error).message"
  — 22 Dateien auf die Utility umgestellt, keine rohen Type-Casts mehr
- MultipleChoiceView: Fallback-UI wenn < 1 Distractor verfügbar — zeigt
  Antwort direkt + Nochmal/Gewusst-Buttons statt kaputter 1-Option-Auswahl

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 16:27:19 +02:00
Till JS
f3a148171a refactor(account): Profil-Karte, Meta-Grid, Action-Karten
- Avatar mit Initialen, Name, E-Mail, Tier-Badge, Logout-Button
- Meta-Grid: User-ID (gekürzt, full on hover) + Tier
- Export- und Danger-Zone als saubere Action-Karten mit Icon
- Einheitliche Btn-Styles (outline, primary, danger)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 16:18:57 +02:00
Till JS
19a0036b82 feat(theming): forest variant from @mana/themes (sprint 9m)
Cards is the first app on the new 12-token mana-vereinsweite
theming system (mana/docs/THEMING.md). Forest-Variant aus
@mana/themes/variants/forest.css konsumiert via app.css-Import,
data-theme="forest" in app.html.

Token-Welt umgestellt — 158 renames + 304 hsl-wraps in 17 Files
(Python-Refactor, BSD-sed war zu unzuverlässig):
- --color-bg          → --color-background
- --color-fg          → --color-foreground
- --color-muted       → --color-muted-foreground
- --color-primary-fg  → --color-primary-foreground
- --color-danger      → --color-error
- bare var(--color-X) → hsl(var(--color-X)) durchgängig

Bridge-Aliase in app.css mappen die shared-ui@0.1.x-Erwartungen
(card, accent, surface-elevated-*, …) auf das 12er-Set. Mit
shared-ui@2.0-Refactor entfällt diese Sektion. --brand-cards-forest
als App-Identitäts-Hex separiert von Theme-Tokens.

Header konsumiert PillTabGroup aus @mana/shared-ui@0.1.1 für die
Routen-Navigation (Decks/Lernen/Library/Import/Stats) und den
DE/EN-Sprach-Switcher — visuell konsistent mit Vereins-Standard.

Cards' primary-Grün wurde dabei von 142 76% 36% (alter Live-Stand)
auf 142 76% 28% verdunkelt, damit primary-foreground/primary-
Kontrast WCAG-AA-konform (≥4.5) ist. Der alte Live-Stand hatte
Ratio 3.35.

i18n: deck_stack.aria_label, deck_detail.fan_aria, deck_detail.
card_open, decks.card_count_more, study_session.manage_link.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 18:01:37 +02:00
Till JS
7119756ce6 Phase 10c: Cards-Web SSO-Login gegen mana-auth
Some checks are pending
CI / validate (push) Waiting to run
Echte Anmeldung gegen auth.mana.how/api/v1/auth/login statt
Dev-Stub-User-ID. accessToken (EdDSA-JWT, 15 min TTL) + Profil
(email, name, tier) leben in localStorage; jeder API-Call schickt
`Authorization: Bearer <jwt>`. Bei 401 wird die Session lokal
geleert — User landet beim nächsten Render auf der Login-Page.

`devUser.id` bleibt eine Vereinfachte UI-Sentinel (gibt id wenn
JWT ODER Dev-Stub aktiv) — alle existierenden Importer
funktionieren unverändert. Dev-Stub-Pfad bleibt als Fallback für
Tests + Anki-Importer-Migration. Filename `dev-stub.svelte.ts`
behalten, Inhalt komplett umgebaut (Sprint 10d wäre der Rename).

Account-Page zeigt Email + Name + Tier statt nur UUID. Header
zeigt Email statt UUID. Login-Form auf Landing-Page mit Email +
Passwort, error-Anzeige, autocomplete-Hints für Browser-Manager.

uploadMedia (multipart) angepasst: Bearer first, X-User-Id-Stub
als Fallback.

svelte-check 384 files 0 errors, 7 Web-Tests grün, prod-Build
sauber.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 21:08:06 +02:00
Till JS
c25c1d0dc4 Phase 9g: i18n DE/EN über alle Routes
Schmale Eigen-Lösung statt svelte-i18n: $lib/i18n mit de.ts + en.ts
(je ~150 Strings, flat-with-nesting), index.svelte.ts liefert reaktiven
i18n-Store als Svelte-5-Rune plus t()/tn()-Helper. Locale wird in
localStorage persistiert, Default = navigator.language (DE/EN-Erkennung),
Fallback = de.

Header bekommt einen DE/EN-Toggle-Switcher (role=group, aria-pressed).
Alle Routes (decks, decks/[id], decks/new, cards/new, cards/[id]/edit,
study, study/[deckId], import, account, stats, +page) und alle
Komponenten (Header, AnkiImport, InboxBanner) ziehen jetzt durch t().

tn(key, n) wählt zwischen `<key>_one` (n=1) und `<key>` — minimaler
Plural-Helper, reicht für DE/EN-MVP. Komplexere Pluralregeln (FR/IT)
bräuchten Intl.PluralRules, kommen wenn die Locales dazukommen.

Begleitend ein paar A11y-Vorbereitungen mitgenommen: aria-label am
Locale-Switcher, role=group für Grade-Buttons, role=button +
keyboard-handler für die Anki-Dropzone, role=progressbar mit
aria-valuemin/max/now, role=alert für Error-States,
aria-live=polite für Lade-Meldungen, sr-only-Heading im
Study-Card-Render, aria-hidden für rein dekorative Elemente.

svelte-check 379 files 0 errors, 94 Tests grün (41 Domain + 48 API
+ 5 Web).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 18:22:00 +02:00
Till JS
03117d5869 Phase 9e: Account-Page mit DSGVO-Self-Service
Neuer User-JWT-Pfad GET/POST /api/v1/me/{export,delete} — gespiegelte
DSGVO-Logik aus dem Service-Key-Pfad, aber gegen die eigene User-ID
gated. buildUserExport extrahiert in dsgvo.ts und wird von beiden
Routern geteilt.

/account-Page zeigt User-ID, Logout, JSON-Daten-Export (Download als
Blob), und einen rot-markierten Account-Delete-Knopf mit "LÖSCHEN"-
Confirmation. Logout im Header verlinkt jetzt auf /account statt
direkt clear() — der User sieht zuerst, was an seinem Account hängt.

Andere mana-Apps werden nicht mit gelöscht — der UI-Hinweistext zeigt
auf die spätere Verein-DSGVO-Sammelanfrage über mana-admin.

48 API-Tests grün (+2 neue auth-gate-Tests für /me), web type-check
374 files 0 errors.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 18:03:41 +02:00