fix(tests): режимы доступных тестов только exam/practice + скрытие пустых предметов

Рассогласование: админ-настройка допускала режимы topic/random, но POST /api/sessions
принимает только exam/practice → клик по такому предмету падал с 400. Убрал topic/random
из валидатора subjects.js и из админ-дропдауна (SC_MODES). Дашборд: старые значения
topic/random коэрсятся в practice; предметы без вопросов в банке И без фикс-теста больше
не показываются (раньше давали 404 «No questions found» при запуске).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maxim Dolgolyov
2026-06-23 10:53:43 +03:00
parent 1aa95a6776
commit c5d440a7a9
3 changed files with 12 additions and 5 deletions
+3 -1
View File
@@ -11,7 +11,9 @@ router.get('/', (_req, res) => {
router.patch('/:slug', authMiddleware, requireRole('admin'), (req, res) => { router.patch('/:slug', authMiddleware, requireRole('admin'), (req, res) => {
const { default_mode, default_count, default_test_id } = req.body; const { default_mode, default_count, default_test_id } = req.body;
const valid_modes = ['exam', 'practice', 'topic', 'random']; // Старт сессии (POST /api/sessions) поддерживает только exam/practice — раньше тут
// допускались topic/random, но клик по такому предмету на дашборде падал с 400.
const valid_modes = ['exam', 'practice'];
if (default_mode && !valid_modes.includes(default_mode)) if (default_mode && !valid_modes.includes(default_mode))
return res.status(400).json({ error: 'Invalid mode' }); return res.status(400).json({ error: 'Invalid mode' });
+7 -3
View File
@@ -2222,10 +2222,14 @@
async function loadSubjects() { async function loadSubjects() {
const list = document.getElementById('subjects-list'); const list = document.getElementById('subjects-list');
try { try {
const SUBJ_MODE_LABELS = { exam:'Экзамен', practice:'Пробный тест', topic:'По теме', random:'Случайный' }; const SUBJ_MODE_LABELS = { exam:'Экзамен', practice:'Пробный тест' };
const subjects = await LS.getSubjects(); // Прячем предметы, по которым нечего запустить (нет вопросов в банке и нет фикс-теста).
const subjects = (await LS.getSubjects())
.filter(s => (s.question_count || 0) > 0 || s.default_test_id);
if (!subjects.length) { list.innerHTML = '<div class="empty">Тесты пока недоступны</div>'; return; }
list.innerHTML = subjects.map((s, si) => { list.innerHTML = subjects.map((s, si) => {
const mode = s.default_mode || 'exam'; let mode = s.default_mode || 'exam';
if (mode !== 'exam' && mode !== 'practice') mode = 'practice'; // старые topic/random → practice (старт сессии их не принимает)
const count = s.default_count || 25; const count = s.default_count || 25;
const testId = s.default_test_id || null; const testId = s.default_test_id || null;
const modeLabel = SUBJ_MODE_LABELS[mode] || mode; const modeLabel = SUBJ_MODE_LABELS[mode] || mode;
+2 -1
View File
@@ -4,7 +4,8 @@
'use strict'; 'use strict';
let inited = false; let inited = false;
const SC_MODES = { exam: 'Экзамен', practice: 'Пробный тест', topic: 'По теме', random: 'Случайный' }; // Старт сессии поддерживает только exam/practice (topic/random убраны — давали 400 на дашборде).
const SC_MODES = { exam: 'Экзамен', practice: 'Пробный тест' };
const SC_ICONS = { bio:'dna', chem:'flask-conical', math:'calculator', phys:'zap' }; const SC_ICONS = { bio:'dna', chem:'flask-conical', math:'calculator', phys:'zap' };
const SC_COLORS = { bio:'#9B5DE5', chem:'#06D6A0', math:'#06B6D4', phys:'#F59E0B' }; const SC_COLORS = { bio:'#9B5DE5', chem:'#06D6A0', math:'#06B6D4', phys:'#F59E0B' };