feat: dashboard + tutorials modules - stats tiles, tutorial list, reader, completion
Dieser Commit ist enthalten in:
Ursprung
2c34aea901
Commit
03778e4bed
4 geänderte Dateien mit 197 neuen und 0 gelöschten Zeilen
40
edu/api/dashboard.php
Normale Datei
40
edu/api/dashboard.php
Normale Datei
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
$user_id = require_auth();
|
||||
if (get_method() !== 'GET') json_error('Methode nicht erlaubt', 405);
|
||||
|
||||
$stmt = $pdo->prepare("SELECT COUNT(*) FROM card_progress WHERE user_id = :uid AND last_reviewed_at IS NOT NULL");
|
||||
$stmt->execute([':uid' => $user_id]);
|
||||
$cards_learned = (int) $stmt->fetchColumn();
|
||||
|
||||
$stmt = $pdo->prepare("SELECT COUNT(*) FROM card_progress WHERE user_id = :uid AND next_review <= CURRENT_DATE");
|
||||
$stmt->execute([':uid' => $user_id]);
|
||||
$cards_due = (int) $stmt->fetchColumn();
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT COUNT(*) FILTER (WHERE last_rating IN ('easy','medium')) AS correct, COUNT(*) AS total
|
||||
FROM card_progress WHERE user_id = :uid AND last_reviewed_at IS NOT NULL
|
||||
");
|
||||
$stmt->execute([':uid' => $user_id]);
|
||||
$acc = $stmt->fetch();
|
||||
$correct_pct = ($acc['total'] > 0) ? round(($acc['correct'] / $acc['total']) * 100) : 0;
|
||||
|
||||
$total_cards = (int) $pdo->query("SELECT COUNT(*) FROM cards")->fetchColumn();
|
||||
|
||||
$stmt = $pdo->prepare("SELECT COUNT(*) FROM tutorial_progress WHERE user_id = :uid AND completed = true");
|
||||
$stmt->execute([':uid' => $user_id]);
|
||||
$tutorials_done = (int) $stmt->fetchColumn();
|
||||
$tutorials_total = (int) $pdo->query("SELECT COUNT(*) FROM tutorials")->fetchColumn();
|
||||
|
||||
$deck_count = (int) $pdo->query("SELECT COUNT(*) FROM decks")->fetchColumn();
|
||||
$cheatsheet_count = (int) $pdo->query("SELECT COUNT(*) FROM cheatsheets")->fetchColumn();
|
||||
|
||||
$stmt = $pdo->prepare("SELECT score_percent FROM quiz_results WHERE user_id = :uid ORDER BY created_at DESC LIMIT 1");
|
||||
$stmt->execute([':uid' => $user_id]);
|
||||
$last_quiz = $stmt->fetchColumn();
|
||||
|
||||
json_ok([
|
||||
'cards_learned' => $cards_learned, 'cards_due' => $cards_due, 'cards_total' => $total_cards,
|
||||
'correct_pct' => $correct_pct, 'tutorials_done' => $tutorials_done, 'tutorials_total' => $tutorials_total,
|
||||
'deck_count' => $deck_count, 'cheatsheet_count' => $cheatsheet_count,
|
||||
'last_quiz_score' => $last_quiz !== false ? (int) $last_quiz : null
|
||||
]);
|
||||
47
edu/api/tutorials.php
Normale Datei
47
edu/api/tutorials.php
Normale Datei
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
$user_id = require_auth();
|
||||
|
||||
// GET /api/tutorials
|
||||
if (get_method() === 'GET' && empty($segments[1])) {
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT t.id, t.slug, t.title, t.description, t.duration_min, t.sort_order,
|
||||
COALESCE(tp.completed, false) AS completed, tp.completed_at
|
||||
FROM tutorials t
|
||||
LEFT JOIN tutorial_progress tp ON tp.tutorial_id = t.id AND tp.user_id = :uid
|
||||
ORDER BY t.sort_order
|
||||
");
|
||||
$stmt->execute([':uid' => $user_id]);
|
||||
json_ok(['tutorials' => $stmt->fetchAll()]);
|
||||
}
|
||||
|
||||
// GET /api/tutorials/{slug}
|
||||
if (get_method() === 'GET' && !empty($segments[1]) && ($segments[2] ?? '') !== 'complete') {
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT t.*, COALESCE(tp.completed, false) AS completed
|
||||
FROM tutorials t
|
||||
LEFT JOIN tutorial_progress tp ON tp.tutorial_id = t.id AND tp.user_id = :uid
|
||||
WHERE t.slug = :slug
|
||||
");
|
||||
$stmt->execute([':slug' => $segments[1], ':uid' => $user_id]);
|
||||
$tutorial = $stmt->fetch();
|
||||
if (!$tutorial) json_error('Tutorial nicht gefunden', 404);
|
||||
json_ok(['tutorial' => $tutorial]);
|
||||
}
|
||||
|
||||
// POST /api/tutorials/{slug}/complete
|
||||
if (get_method() === 'POST' && !empty($segments[1]) && ($segments[2] ?? '') === 'complete') {
|
||||
$stmt = $pdo->prepare("SELECT id FROM tutorials WHERE slug = :slug");
|
||||
$stmt->execute([':slug' => $segments[1]]);
|
||||
$tutorial = $stmt->fetch();
|
||||
if (!$tutorial) json_error('Tutorial nicht gefunden', 404);
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
INSERT INTO tutorial_progress (user_id, tutorial_id, completed, completed_at)
|
||||
VALUES (:uid, :tid, true, NOW())
|
||||
ON CONFLICT (user_id, tutorial_id) DO UPDATE SET completed = true, completed_at = NOW()
|
||||
");
|
||||
$stmt->execute([':uid' => $user_id, ':tid' => $tutorial['id']]);
|
||||
json_ok(['ok' => true]);
|
||||
}
|
||||
|
||||
json_error('Unbekannter Tutorials-Endpunkt', 404);
|
||||
Laden …
Tabelle hinzufügen
Einen Link hinzufügen
In neuem Issue referenzieren