From 0e51fd884768f26e604f0b554b989b1d72d55999 Mon Sep 17 00:00:00 2001 From: admin Date: Wed, 17 Jun 2026 22:17:04 +0200 Subject: [PATCH] =?UTF-8?q?docs:=20CLAUDE.md=20=E2=80=93=20Fortschritts-/F?= =?UTF-8?q?eier-System=20+=20erweiterter=20API-Vertrag?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 --- CLAUDE.md | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index a5969b4..19eb928 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -33,15 +33,31 @@ React 19 + Vite SPA, **no router package**. There are no DB cards/feed entries f | Function | Endpoint | Notes | |---|---|---| | `login` / `registerUser` | `POST /auth/login`, `/auth/register` | return `{ token, userId, needsProfile }` | -| `getMe` | `GET /auth/me` | basis for auth check + progress (EP/streak/level); also `language_target_greeting` (Profil-Anrede „Hej, …") | +| `getMe` | `GET /auth/me` | auth check + progress: `total_ep`, `streak_days`, `level`, `ep_into_level`, `ep_to_next_level`, `last_practice_at`; also `language_target_greeting` (Profil-Anrede „Hej, …") | | `checkUsername` | `GET /auth/check-username` | | | `createProfile` | `POST /auth/profile` | username + native/target lang | | `getLanguageOptions` | `GET /auth/languages` | merged with local `LANG_META` (flag + Web Speech code) | -| `getFeedPairs` | `GET /auth/feed?lang=&limit=` | returns "pairs", the feed unit | -| `saveProgress` | `POST /auth/progress` | books EP/streak, returns updated `total_ep` | +| `getFeedPairs` | `GET /auth/feed?lang=&limit=&exclude=` | returns "pairs", the feed unit | +| `saveProgress` | `POST /auth/progress` | books EP/streak; returns the **milestone contract** (see below) | | `getStats` | `GET /auth/stats` | Profil-Daten: `daily`/`today`/`totals`/`skills` + `categories[]` (Punkte je Kategorie) | +| `getAchievements` | `GET /auth/achievements` | `[{ key, label, icon, unlocked, unlocked_at }]` für die Profil-Sektion | +| `setDailyGoal` | `PUT /auth/goal` | Tagesziel (EP/Tag) setzen; Backend klemmt auf 5–500 | -`src/pages/Profil.jsx` rendert daraus die Begrüßung (`language_target_greeting`), den Kategorie-Block (`stats.categories`), Wochen-/Aktivitäts-Graphen und Streak. +`saveProgress` returns `{ total_ep, level, prev_level, streak_days, streak_increased, daily_ep, daily_goal_ep, goal_just_reached, unlocked_achievements }` — `Feed.jsx` leitet daraus die Feier-Momente ab (Level-Up/Streak/Tagesziel/Achievement). Felder degradieren defensiv: fehlen sie (älteres Backend), greifen lokale Fallbacks. + +`src/pages/Profil.jsx` rendert die Begrüßung (`language_target_greeting`), **führt mit Momentum** (`% bis Level X` + Capability-Satz), zeigt Kategorie-Stufen (`stats.categories` + `categoryTier`), Wochenvergleich, Streak-Status, Erfolge-Grid (`getAchievements`) und einen Sound-Toggle. + +### Fortschritts-/Feier-System (Momente) + +Macht Fortschritt spürbar statt nur zählbar. Bausteine: + +- **`src/utils/leveling.js`** — spiegelt die Backend-Level-Kurve (`levelForEp`/`levelInfo`, Level 1 bei 20 EP). Backend ist Single Source of Truth; das ist Fallback + %-Anzeige. +- **`MilestoneOverlay`** (`components/`) — Vollbild-Feier, getriggert aus der `saveProgress`-Response. Typen: `level` / `streak` (Schwellen 3/7/14/30/50/100/200/365) / `goal` / `achievement`. Konfetti via `utils/confetti.js`. +- **`EpFloat`** — „+N EP" schwebt am Bestätigen-Button auf; EP-Badge zählt hoch (`hooks/useCountUp.js`). +- **`SessionSummary`** — ersetzt die End-Sackgasse mit Zahlen + Story-Zeilen. +- **Combo** + variables Lob/ermutigendes Fehler-Feedback (`utils/praise.js`, dort auch `categoryTier`/`capabilitySentence`). +- **`utils/sound.js`** — dezente WebAudio-Belohnung (Mute-Pref in localStorage). +- **`utils/streak.js`** + **`utils/streakReminder.js`** — Loss-Aversion-Nudge im Feed („Serie endet in X Std") und lokale Tages-Erinnerung via **`@capacitor/local-notifications`** (kein APNs nötig; nur nativ, web no-op — braucht `npx cap sync ios`). Several content functions (`getWords`, `getQuestions`, `getActiveLearningPair`, `assetUrl`, …) are **stubs** returning empty/null — content endpoints are not built yet. Don't assume they fetch anything.