diff --git a/backend/routes/sessions.js b/backend/routes/sessions.js index 48a3608..9d31b36 100644 --- a/backend/routes/sessions.js +++ b/backend/routes/sessions.js @@ -315,6 +315,42 @@ router.delete('/:id/notes', authenticateToken, (req, res) => { } }); +// Archive a session (admin only) +router.post('/:id/archive', authenticateToken, (req, res) => { + try { + const session = db.prepare('SELECT id, is_active FROM sessions WHERE id = ?').get(req.params.id); + + if (!session) { + return res.status(404).json({ error: 'Session not found' }); + } + + if (session.is_active === 1) { + return res.status(400).json({ error: 'Cannot archive an active session. Please close it first.' }); + } + + db.prepare('UPDATE sessions SET archived = 1 WHERE id = ?').run(req.params.id); + res.json({ success: true }); + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); + +// Unarchive a session (admin only) +router.post('/:id/unarchive', authenticateToken, (req, res) => { + try { + const session = db.prepare('SELECT id FROM sessions WHERE id = ?').get(req.params.id); + + if (!session) { + return res.status(404).json({ error: 'Session not found' }); + } + + db.prepare('UPDATE sessions SET archived = 0 WHERE id = ?').run(req.params.id); + res.json({ success: true }); + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); + // Get games played in a session router.get('/:id/games', (req, res) => { try { diff --git a/tests/api/session-archive.test.js b/tests/api/session-archive.test.js index f1f205b..d6ae450 100644 --- a/tests/api/session-archive.test.js +++ b/tests/api/session-archive.test.js @@ -93,3 +93,81 @@ describe('GET /api/sessions — filter and limit', () => { expect(res.body).toHaveLength(8); }); }); + +describe('POST /api/sessions/:id/archive', () => { + beforeEach(() => { + cleanDb(); + }); + + test('archives a closed session', async () => { + const session = seedSession({ is_active: 0, notes: null }); + + const res = await request(app) + .post(`/api/sessions/${session.id}/archive`) + .set('Authorization', getAuthHeader()); + + expect(res.status).toBe(200); + expect(res.body.success).toBe(true); + + const check = await request(app).get(`/api/sessions/${session.id}`); + expect(check.body.archived).toBe(1); + }); + + test('returns 400 for active session', async () => { + const session = seedSession({ is_active: 1, notes: null }); + + const res = await request(app) + .post(`/api/sessions/${session.id}/archive`) + .set('Authorization', getAuthHeader()); + + expect(res.status).toBe(400); + }); + + test('returns 404 for non-existent session', async () => { + const res = await request(app) + .post('/api/sessions/9999/archive') + .set('Authorization', getAuthHeader()); + + expect(res.status).toBe(404); + }); + + test('returns 401 without auth', async () => { + const session = seedSession({ is_active: 0, notes: null }); + + const res = await request(app) + .post(`/api/sessions/${session.id}/archive`); + + expect(res.status).toBe(401); + }); +}); + +describe('POST /api/sessions/:id/unarchive', () => { + beforeEach(() => { + cleanDb(); + }); + + test('unarchives an archived session', async () => { + const session = seedSession({ is_active: 0, notes: null }); + require('../helpers/test-utils').db.prepare( + 'UPDATE sessions SET archived = 1 WHERE id = ?' + ).run(session.id); + + const res = await request(app) + .post(`/api/sessions/${session.id}/unarchive`) + .set('Authorization', getAuthHeader()); + + expect(res.status).toBe(200); + expect(res.body.success).toBe(true); + + const check = await request(app).get(`/api/sessions/${session.id}`); + expect(check.body.archived).toBe(0); + }); + + test('returns 404 for non-existent session', async () => { + const res = await request(app) + .post('/api/sessions/9999/unarchive') + .set('Authorization', getAuthHeader()); + + expect(res.status).toBe(404); + }); +});