refactor: ещё 6 модалок → LS.modal (dashboard, theory, course)

dashboard.html: 2 → 0 
  - join-modal — вступить в класс
  - qs-modal — быстрый тест с выбором предмета + режим + кол-во

theory.html: 1 → 0 
  - new-course-modal — создание нового курса учителем

course.html: 4 → 0 
  - add-section-modal — новый раздел курса
  - edit-course-modal — редактирование курса
  - add-lesson-modal — новый урок
  - save-course-tpl-modal — сохранить курс как шаблон

Везде:
  - Inline <div class=\"modal-overlay\">...</div> → удалён
  - openX(): создаёт modal через LS.modal({content, actions})
  - closeX() удалена — _xModal.close()
  - Глобальный selectQsSubject() inline'нут как listener на body модалки
  - Enter-handler на главных inputs сохранён

Не трогаю:
  - biochem.html#lib-modal — кастомная тёмная тема, не подходит под
    светлый LS.modal без редизайна
  - library.html — 3 сложные модалки (folder-access, assign, upload)
    с tabs и dynamic state — отдельный заход
  - classes.html — modal-assign (128 строк, complex) + review-modal
  - flashcards.html — fc-modal (не modal-overlay, своя CSS)

Прогресс миграции: 12 простых модалок → LS.modal за серию (4 ранее
+ 2 ранее + 6 сейчас). 4 страницы полностью очищены от
modal-overlay. Унифицированы:
  - ESC/backdrop/focus поведение
  - z-index (9000)
  - Анимация (scale .22s)
  - Адаптив на мобилке
This commit is contained in:
Maxim Dolgolyov
2026-05-16 19:33:39 +03:00
parent d3b16f55c8
commit 5c66105fc2
3 changed files with 183 additions and 241 deletions
+35 -44
View File
@@ -340,37 +340,6 @@
</div><!-- /app-layout -->
<!-- New course modal -->
<div class="modal-overlay" id="new-course-modal" onclick="if(event.target===this)closeNewCourseModal()">
<div class="modal">
<div class="modal-title">Новый курс</div>
<div class="form-group">
<label class="form-label">Предмет</label>
<select class="form-input" id="nc-subject">
<option value="bio">Биология</option>
<option value="chem">Химия</option>
<option value="math">Математика</option>
<option value="phys">Физика</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Название</label>
<input class="form-input" id="nc-title" placeholder="Например: Молекулярная биология" />
</div>
<div class="form-group">
<label class="form-label">Описание (необязательно)</label>
<textarea class="form-input" id="nc-desc" rows="2" placeholder="Кратко о курсе…" style="resize:vertical"></textarea>
</div>
<div class="form-group">
<label class="form-label">Эмодзи обложки</label>
<input class="form-input" id="nc-emoji" placeholder="" maxlength="4" style="max-width:90px" />
</div>
<div class="modal-footer">
<button class="btn-cancel" onclick="closeNewCourseModal()">Отмена</button>
<button class="btn-primary" id="btn-do-create" onclick="doCreateCourse()">Создать</button>
</div>
</div>
</div>
<script src="/js/api.js"></script>
<script src="/js/sidebar.js"></script>
<script src="/js/notifications.js"></script>
@@ -559,15 +528,39 @@
loadContinue();
/* ── modal ── */
let _newCourseModal = null;
function openNewCourseModal() {
document.getElementById('nc-title').value = '';
document.getElementById('nc-desc').value = '';
document.getElementById('nc-emoji').value = '';
document.getElementById('new-course-modal').classList.add('open');
setTimeout(() => document.getElementById('nc-title').focus(), 50);
}
function closeNewCourseModal() {
document.getElementById('new-course-modal').classList.remove('open');
const body = `
<div class="form-group">
<label class="form-label">Предмет</label>
<select class="form-input" id="nc-subject">
<option value="bio">Биология</option>
<option value="chem">Химия</option>
<option value="math">Математика</option>
<option value="phys">Физика</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Название</label>
<input class="form-input" id="nc-title" placeholder="Например: Молекулярная биология" />
</div>
<div class="form-group">
<label class="form-label">Описание (необязательно)</label>
<textarea class="form-input" id="nc-desc" rows="2" placeholder="Кратко о курсе…" style="resize:vertical"></textarea>
</div>
<div class="form-group">
<label class="form-label">Эмодзи обложки</label>
<input class="form-input" id="nc-emoji" placeholder="" maxlength="4" style="max-width:90px" />
</div>`;
_newCourseModal = LS.modal({
title: 'Новый курс', content: body, size: 'sm',
actions: [
{ label: 'Отмена', onClick: () => _newCourseModal.close() },
{ label: 'Создать', primary: true, id: 'btn-do-create', onClick: doCreateCourse },
],
});
const titleEl = _newCourseModal.body.querySelector('#nc-title');
titleEl.addEventListener('keydown', e => { if (e.key === 'Enter') doCreateCourse(); });
}
async function doCreateCourse() {
const title = document.getElementById('nc-title').value.trim();
@@ -585,15 +578,13 @@
coverEmoji: document.getElementById('nc-emoji').value.trim() || '',
}),
});
closeNewCourseModal();
_newCourseModal?.close();
location.href = '/course?id=' + res.id;
} catch (e) {
LS.toast(e.message || 'Ошибка', 'error');
} finally { btn.disabled = false; }
btn.disabled = false;
}
}
document.getElementById('nc-title').addEventListener('keydown', e => {
if (e.key === 'Enter') doCreateCourse();
});
/* ══════════════════════════════════════════════════════════════════
TEMPLATE BROWSER