wordeck/apps/web/src/lib/api/me.ts
Till JS 6db6dc3e42 Phase 9f: Statistik-Dashboard
Neuer Endpoint GET /api/v1/me/stats liefert in einem Aufruf alle
Aggregate für die Stats-UI:
- total_decks / total_cards / total_reviews / due_now
- state_counts pro FSRS-Zustand (new/learning/review/relearning)
- reviewed_per_day für die letzten 7 Tage (Quelle: reviews.last_review,
  via to_char(day, 'YYYY-MM-DD') auf Postgres-Seite gruppiert)
- streak_days (rückwärts ab heute bis zum ersten Tag ohne Review)

study_sessions wird aktuell NICHT befüllt — der Schema-Slot existiert
seit Phase 3, aber der Session-Tracker kommt erst, wenn das Lern-
Flow-Layer ausgebaut wird. last_review reicht für jetzt.

/stats-Page rendert vier KPI-Cards, einen 7-Tage-Säulen-Chart per
CSS-Heights, plus eine FSRS-State-Distribution. Header-Nav um
"Statistik" ergänzt.

E2E-Smoke gegen lokale Postgres bestätigt: bestehender Cloze-User
zeigt 1 Deck, 1 Karte, 2 Reviews, 2 due, alle "new"-State, 0
Streak — passt zum gestern eingespielten Smoke-User.

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

46 lines
1.1 KiB
TypeScript

import { api } from './client.ts';
export interface UserExport {
user_id: string;
exported_at: string;
app: string;
app_version: string;
data: {
decks: unknown[];
cards: unknown[];
reviews: unknown[];
study_sessions: unknown[];
tags: unknown[];
media_refs: unknown[];
import_jobs: unknown[];
};
}
/** Lädt den vollständigen DSGVO-Export der eigenen Daten (User-JWT). */
export function exportMe() {
return api<UserExport>('/api/v1/me/export');
}
/** Löscht alle Cards-Daten des eingeloggten Users (User-JWT). */
export function deleteMe() {
return api<{ deleted: true; user_id: string; counts: { decks: number; import_jobs: number } }>(
'/api/v1/me/delete',
{ method: 'POST' }
);
}
export interface UserStats {
user_id: string;
generated_at: string;
total_decks: number;
total_cards: number;
total_reviews: number;
due_now: number;
state_counts: { new: number; learning: number; review: number; relearning: number };
reviewed_per_day: { day: string; n: number }[];
streak_days: number;
}
export function loadStats() {
return api<UserStats>('/api/v1/me/stats');
}