feat: Erfolge (Achievements) – Unlock-Erkennung + Listing

- Tabelle user_achievements (Migration in db-migrate.js)
- src/lib/achievements.js: Definitionen + dedup-sichere Freischaltung
  (ON CONFLICT DO NOTHING … RETURNING → nur Neues), Listing mit Status
- /auth/progress liefert unlocked_achievements (defensiv gekapselt)
- neue Route GET /auth/achievements

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-17 21:53:49 +02:00
parent bb863640c0
commit 61b3bcb5ff
3 changed files with 99 additions and 0 deletions

View File

@@ -653,6 +653,16 @@ async function migrate() {
// Tagesziel (EP/Tag) auf dem App-Profil
await query(`ALTER TABLE users_public ADD COLUMN IF NOT EXISTS daily_goal_ep INTEGER NOT NULL DEFAULT 30`).catch(() => {});
// Freigeschaltete Erfolge je User (ein Eintrag pro Erfolg, dedup-sicher)
await query(`
CREATE TABLE IF NOT EXISTS user_achievements (
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
achievement_key VARCHAR(40) NOT NULL,
unlocked_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
PRIMARY KEY (user_id, achievement_key)
)
`);
// audios
await query(`
CREATE TABLE IF NOT EXISTS audios (