65 lines
2.3 KiB
JavaScript
65 lines
2.3 KiB
JavaScript
import { Router } from 'express';
|
|
import db from '../db/index.js';
|
|
import { requireAuth } from '../auth/middleware.js';
|
|
import { getGame } from '../games/registry.js';
|
|
|
|
const router = Router();
|
|
|
|
// GET /api/puzzles/:slug/progress
|
|
// Returns the highest contiguous level the signed-in user has cleared.
|
|
router.get('/:slug/progress', requireAuth, (req, res) => {
|
|
const { slug } = req.params;
|
|
if (!getGame(slug)) return res.status(400).json({ error: 'Unknown game slug.' });
|
|
|
|
const row = db
|
|
.prepare('SELECT levels_completed FROM puzzle_progress WHERE user_id = ? AND slug = ?')
|
|
.get(req.user.id, slug);
|
|
|
|
res.json({ levelsCompleted: row?.levels_completed ?? 0 });
|
|
});
|
|
|
|
// POST /api/puzzles/:slug/complete body: { level }
|
|
// Records completion of `level`. Levels must be cleared in order, so this only
|
|
// advances progress when level === current + 1; replaying an earlier level is a
|
|
// no-op that still returns the current high-water mark.
|
|
router.post('/:slug/complete', requireAuth, (req, res) => {
|
|
const { slug } = req.params;
|
|
const { level } = req.body ?? {};
|
|
|
|
if (!getGame(slug)) return res.status(400).json({ error: 'Unknown game slug.' });
|
|
if (!Number.isInteger(level) || level < 1) {
|
|
return res.status(400).json({ error: 'Invalid level.' });
|
|
}
|
|
|
|
const row = db
|
|
.prepare('SELECT levels_completed FROM puzzle_progress WHERE user_id = ? AND slug = ?')
|
|
.get(req.user.id, slug);
|
|
const current = row?.levels_completed ?? 0;
|
|
|
|
if (level !== current + 1) {
|
|
return res.json({ levelsCompleted: current });
|
|
}
|
|
|
|
db.prepare(
|
|
`INSERT INTO puzzle_progress (user_id, slug, levels_completed, updated_at)
|
|
VALUES (?, ?, ?, datetime('now'))
|
|
ON CONFLICT(user_id, slug)
|
|
DO UPDATE SET levels_completed = excluded.levels_completed,
|
|
updated_at = excluded.updated_at`,
|
|
).run(req.user.id, slug, level);
|
|
|
|
res.json({ levelsCompleted: level });
|
|
});
|
|
|
|
// POST /api/puzzles/:slug/reset
|
|
// Clears the signed-in user's progress for this puzzle (back to level 0).
|
|
router.post('/:slug/reset', requireAuth, (req, res) => {
|
|
const { slug } = req.params;
|
|
if (!getGame(slug)) return res.status(400).json({ error: 'Unknown game slug.' });
|
|
|
|
db.prepare('DELETE FROM puzzle_progress WHERE user_id = ? AND slug = ?').run(req.user.id, slug);
|
|
res.json({ levelsCompleted: 0 });
|
|
});
|
|
|
|
export default router;
|