- React+Vite Frontend mit Routing, eigenem fetch-Client (kein axios) - Express Backend: Auth (JWT), Topics, Tasks, Leaderboard - PostgreSQL Schema + Seed: 7 Kategorien, 21 Topics, ~25 Aufgaben - Gamification: XP, Level (100×n^1.5), tägliche Streaks - docker-compose auf Port 3100 für DS1621 - Alltagsaufgaben: Finanzen, Geometrie, Physik, Informatik, Verkehr, Shopping
60 lines
1.8 KiB
JavaScript
60 lines
1.8 KiB
JavaScript
import { Router } from 'express';
|
|
import { requireAuth } from '../middleware/auth.js';
|
|
import pool from '../db/index.js';
|
|
|
|
const router = Router();
|
|
|
|
// GET /api/topics — alle Kategorien mit Topics
|
|
router.get('/', requireAuth, async (req, res) => {
|
|
try {
|
|
const cats = await pool.query(
|
|
'SELECT id, slug, title, icon FROM categories ORDER BY sort_order'
|
|
);
|
|
const topics = await pool.query(
|
|
`SELECT t.id, t.category_id, t.slug, t.title, t.description, t.difficulty, t.is_premium,
|
|
COUNT(tk.id) AS task_count
|
|
FROM topics t
|
|
LEFT JOIN tasks tk ON tk.topic_id = t.id
|
|
GROUP BY t.id
|
|
ORDER BY t.sort_order`
|
|
);
|
|
|
|
const result = cats.rows.map(cat => ({
|
|
...cat,
|
|
topics: topics.rows.filter(t => t.category_id === cat.id),
|
|
}));
|
|
|
|
res.json(result);
|
|
} catch (err) {
|
|
console.error(err);
|
|
res.status(500).json({ message: 'Serverfehler' });
|
|
}
|
|
});
|
|
|
|
// GET /api/topics/:slug/tasks — Aufgaben eines Topics (mit Fortschritt)
|
|
router.get('/:slug/tasks', requireAuth, async (req, res) => {
|
|
try {
|
|
const topic = await pool.query(
|
|
'SELECT * FROM topics WHERE slug = $1', [req.params.slug]
|
|
);
|
|
if (!topic.rows[0]) return res.status(404).json({ message: 'Topic nicht gefunden' });
|
|
|
|
const tasks = await pool.query(
|
|
`SELECT tk.id, tk.title, tk.question, tk.answer_type, tk.choices,
|
|
tk.unit, tk.xp_reward, tk.difficulty,
|
|
up.correct AS solved, up.solved_at
|
|
FROM tasks tk
|
|
LEFT JOIN user_progress up ON up.task_id = tk.id AND up.user_id = $1
|
|
WHERE tk.topic_id = $2
|
|
ORDER BY tk.difficulty, tk.id`,
|
|
[req.user.id, topic.rows[0].id]
|
|
);
|
|
|
|
res.json({ topic: topic.rows[0], tasks: tasks.rows });
|
|
} catch (err) {
|
|
console.error(err);
|
|
res.status(500).json({ message: 'Serverfehler' });
|
|
}
|
|
});
|
|
|
|
export default router;
|