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>
46 lines
1.1 KiB
TypeScript
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');
|
|
}
|