From cc724870136fd629b09b0b338a19c8295a16ce29 Mon Sep 17 00:00:00 2001 From: Hermann_Kitio Date: Tue, 21 Apr 2026 00:59:18 +0300 Subject: [PATCH] feat(sujets): GET /sujets?mode=&tache= avec auth + filtre actif --- src/index.ts | 2 ++ src/routes/sujets.ts | 72 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 src/routes/sujets.ts diff --git a/src/index.ts b/src/index.ts index f93abb4..e55b339 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,6 +6,7 @@ import { createNodeWebSocket } from '@hono/node-ws' import authRoutes from './routes/auth.js' import plansRoutes from './routes/plans.js' import simulationsRoutes from './routes/simulations.js' +import sujetsRoutes from './routes/sujets.js' import correctionsRoutes from './routes/corrections.js' import stripeRoutes from './routes/stripe.js' import createT2LiveRoutes from './routes/t2live.js' @@ -33,6 +34,7 @@ app.get('/', (c) => { app.route('/auth', authRoutes) app.route('/plans', plansRoutes) app.route('/simulations', simulationsRoutes) +app.route('/sujets', sujetsRoutes) app.route('/corrections', correctionsRoutes) app.route('/stripe', stripeRoutes) app.route('/t2', createT2LiveRoutes(upgradeWebSocket)) diff --git a/src/routes/sujets.ts b/src/routes/sujets.ts new file mode 100644 index 0000000..c1903dc --- /dev/null +++ b/src/routes/sujets.ts @@ -0,0 +1,72 @@ +import { Hono } from 'hono' +import { authMiddleware } from '../middleware/auth.js' +import type { AppVariables } from '../middleware/auth.js' +import { supabase } from '../lib/supabase.js' + +/** + * Routes de la table `sujets` — catalogue des consignes d'examen. + * + * GET /sujets?mode=EE|EO&tache=1|2|3 + * Retourne la liste des sujets actifs pour la paire (mode, tache). + * Utilisé par l'écran de choix de sujet côté frontend (tâche G4). + */ + +const VALID_MODES = ['EE', 'EO'] as const +const VALID_TACHES = [1, 2, 3] as const + +type SujetMode = (typeof VALID_MODES)[number] + +const sujets = new Hono<{ Variables: AppVariables }>() + +sujets.get('/', authMiddleware, async (c) => { + const modeRaw = c.req.query('mode') + const tacheRaw = c.req.query('tache') + + if (!modeRaw || !VALID_MODES.includes(modeRaw as SujetMode)) { + return c.json( + { + error: true, + code: 'VALIDATION_ERROR', + message: `Mode invalide. Valeurs acceptées : ${VALID_MODES.join(', ')}`, + }, + 400 + ) + } + + const tacheNumber = Number(tacheRaw) + if (!tacheRaw || !Number.isInteger(tacheNumber) || !VALID_TACHES.includes(tacheNumber as 1 | 2 | 3)) { + return c.json( + { + error: true, + code: 'VALIDATION_ERROR', + message: `Tâche invalide. Valeurs acceptées : ${VALID_TACHES.join(', ')}`, + }, + 400 + ) + } + + const mode = modeRaw as SujetMode + + const { data, error } = await supabase + .from('sujets') + .select('id, consigne, role, contexte, doc1_titre, doc1_texte, doc2_titre, doc2_texte') + .eq('mode', mode) + .eq('tache', tacheNumber) + .eq('actif', true) + .order('id') + + if (error) { + return c.json( + { + error: true, + code: 'INTERNAL_ERROR', + message: 'Une erreur est survenue. Veuillez réessayer dans quelques instants.', + }, + 500 + ) + } + + return c.json({ sujets: data ?? [] }, 200) +}) + +export default sujets