From 5af04878691c26967db9f04a7171c1612fec61e2 Mon Sep 17 00:00:00 2001 From: kalugin66 Date: Mon, 13 Apr 2026 18:06:41 +0500 Subject: [PATCH] =?UTF-8?q?c=D0=BE=D0=B3=D0=BB=D0=B0=D1=81=D0=BD=D0=BE=20?= =?UTF-8?q?=D1=80=D0=B0=D1=81=D0=BF=D0=B8=D1=81=D0=B0=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/admin.js | 75 +++++++++++++++++++++++++++++++++++-------------- public/main.js | 20 ++++++------- server.js | 7 +++-- 3 files changed, 68 insertions(+), 34 deletions(-) diff --git a/public/admin.js b/public/admin.js index 00173e4..67fba50 100644 --- a/public/admin.js +++ b/public/admin.js @@ -174,6 +174,7 @@ function openLessonModal(id = null) { document.getElementById('lessonId').value = ''; document.getElementById('modalTitle').innerText = id ? 'Редактирование урока' : 'Новый урок'; if (id) { + // Загружаем все уроки и находим нужный (можно было бы сделать отдельный запрос, но так проще) fetch(`/api/admin/lessons`).then(res => res.json()).then(lessons => { const lesson = lessons.find(l => l.id == id); if (lesson) { @@ -184,6 +185,7 @@ function openLessonModal(id = null) { document.getElementById('teacher').value = lesson.teacher; document.getElementById('topic').value = lesson.topic || ''; document.getElementById('maxSlots').value = lesson.max_slots; + // Заполняем дату и время, если они есть, иначе пустые строки document.getElementById('date').value = lesson.date || ''; document.getElementById('time').value = lesson.time || ''; } @@ -196,24 +198,51 @@ function openLessonModal(id = null) { document.getElementById('lessonForm')?.addEventListener('submit', async (e) => { e.preventDefault(); const id = document.getElementById('lessonId').value; + const class_name = document.getElementById('className').value.trim(); + const parallel = parseInt(document.getElementById('parallel').value); + const subject = document.getElementById('subject').value.trim(); + const teacher = document.getElementById('teacher').value.trim(); + const topic = document.getElementById('topic').value; + const max_slots = parseInt(document.getElementById('maxSlots').value); + const date = document.getElementById('date').value; + const time = document.getElementById('time').value; + + // Проверяем обязательные поля (дата и время теперь обязательны) + if (!class_name || isNaN(parallel) || !subject || !teacher || isNaN(max_slots) || !date || !time) { + alert('Пожалуйста, заполните все поля: класс, параллель, предмет, учитель, макс. мест, дата и время.'); + return; + } + const payload = { id: id || undefined, - class_name: document.getElementById('className').value, - parallel: parseInt(document.getElementById('parallel').value), - subject: document.getElementById('subject').value, - teacher: document.getElementById('teacher').value, - topic: document.getElementById('topic').value, - max_slots: parseInt(document.getElementById('maxSlots').value), - date: document.getElementById('date').value, - time: document.getElementById('time').value + class_name, + parallel, + subject, + teacher, + topic, + max_slots, + date, + time }; - await fetch('/api/admin/lessons', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(payload) - }); - document.getElementById('lessonModal').style.display = 'none'; - loadLessons(getCurrentFilters()); + + try { + const response = await fetch('/api/admin/lessons', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload) + }); + const data = await response.json(); + if (!response.ok) { + alert('Ошибка сохранения: ' + (data.error || 'Неизвестная ошибка')); + return; + } + document.getElementById('lessonModal').style.display = 'none'; + // Сбрасываем фильтры, чтобы обновлённый урок точно отобразился + resetFilters(); + loadLessons(getCurrentFilters()); + } catch (err) { + alert('Ошибка соединения: ' + err.message); + } }); function getCurrentFilters() { @@ -225,6 +254,14 @@ function getCurrentFilters() { }; } +function resetFilters() { + document.getElementById('filterClass').value = ''; + document.getElementById('filterParallel').value = ''; + document.getElementById('filterTeacher').value = ''; + document.getElementById('filterTopic').value = ''; + updateDependentFilters(); +} + function setupEventListeners() { const classSelect = document.getElementById('filterClass'); const teacherSelect = document.getElementById('filterTeacher'); @@ -244,11 +281,7 @@ function setupEventListeners() { }); document.getElementById('resetFilters')?.addEventListener('click', () => { - document.getElementById('filterClass').value = ''; - document.getElementById('filterParallel').value = ''; - document.getElementById('filterTeacher').value = ''; - document.getElementById('filterTopic').value = ''; - updateDependentFilters(); + resetFilters(); loadLessons({}); }); @@ -276,7 +309,7 @@ function setupEventListeners() { } }); - // Импорт (теперь XLSX всегда глобально доступен) + // Импорт (XLSX) function parseExcelToRecords(file) { return new Promise((resolve, reject) => { const reader = new FileReader(); diff --git a/public/main.js b/public/main.js index 0999012..bbe7551 100644 --- a/public/main.js +++ b/public/main.js @@ -118,11 +118,11 @@ function renderLessons(lessons) { container.innerHTML = lessons.map(lesson => { // Определяем, что показывать в строке времени let timeHtml = ''; - if (lesson.topic === 'Консультация' && lesson.date && lesson.time) { - timeHtml = `

Дата/время: ${escapeHtml(lesson.date)} ${escapeHtml(lesson.time)}

`; - } else { - timeHtml = `

Время: Согласно расписания

`; - } +if (lesson.topic && lesson.topic.includes('Консультация') && lesson.date && lesson.time) { + timeHtml = `

Дата/время: ${escapeHtml(lesson.date)} ${escapeHtml(lesson.time)}

`; +} else { + timeHtml = `

Время: Согласно расписания

`; +} return `
@@ -192,11 +192,11 @@ function openModal(lessonId) { if (!lesson) return; let timeInfo = ''; - if (lesson.topic === 'Консультация' && lesson.date && lesson.time) { - timeInfo = `${lesson.date} ${lesson.time}`; - } else { - timeInfo = 'Согласно расписания'; - } +if (lesson.topic && lesson.topic.includes('Консультация') && lesson.date && lesson.time) { + timeInfo = `${lesson.date} ${lesson.time}`; +} else { + timeInfo = 'Согласно расписания'; +} document.getElementById('lessonId').value = lessonId; document.getElementById('modalLessonInfo').innerHTML = ` diff --git a/server.js b/server.js index 39cc3f9..d330ba5 100644 --- a/server.js +++ b/server.js @@ -165,8 +165,9 @@ app.get('/api/admin/lessons', isAuthenticated, isAdmin, async (req, res) => { app.post('/api/admin/lessons', isAuthenticated, isAdmin, async (req, res) => { const { id, class_name, parallel, subject, teacher, topic, max_slots, date, time } = req.body; - if (!class_name || !parallel || !subject || !teacher || !max_slots || !date || !time) { - return res.status(400).json({ error: 'Все поля обязательны' }); + // Проверяем все обязательные поля, включая дату и время + if (!class_name || parallel === undefined || parallel === null || !subject || !teacher || !max_slots || !date || !time) { + return res.status(400).json({ error: 'Все поля, включая дату и время, обязательны' }); } try { @@ -181,7 +182,7 @@ app.post('/api/admin/lessons', isAuthenticated, isAdmin, async (req, res) => { } } catch (err) { console.error(err); - res.status(500).json({ error: 'Ошибка сохранения урока' }); + res.status(500).json({ error: 'Ошибка сохранения урока: ' + err.message }); } });