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:
+52
-57
@@ -1526,45 +1526,8 @@
|
||||
</div>
|
||||
|
||||
<!-- Join modal -->
|
||||
<div class="modal-overlay" id="join-modal" onclick="if(event.target===this)closeJoinModal()">
|
||||
<div class="modal">
|
||||
<div class="modal-title">Вступить в класс</div>
|
||||
<input class="form-input" id="join-code" placeholder="Код приглашения" />
|
||||
<div style="font-size:0.78rem;color:var(--text-3);margin-top:8px">Попросите учителя поделиться кодом или ссылкой</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn-cancel" onclick="closeJoinModal()">Отмена</button>
|
||||
<button class="btn-join" id="btn-do-join" onclick="doJoin()">Вступить</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Quick-start test modal -->
|
||||
<div class="modal-overlay" id="qs-modal" onclick="if(event.target===this)closeQuickStart()">
|
||||
<div class="modal" style="max-width:480px">
|
||||
<div class="modal-title">Быстрый тест</div>
|
||||
<div class="qs-subjects" id="qs-subjects"></div>
|
||||
<div class="qs-options">
|
||||
<div class="qs-row">
|
||||
<span class="qs-label">Режим</span>
|
||||
<select class="qs-select" id="qs-mode">
|
||||
<option value="exam">Экзамен</option>
|
||||
<option value="practice">Тренировка</option>
|
||||
<option value="random">Случайный</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="qs-row">
|
||||
<span class="qs-label">Вопросов</span>
|
||||
<input class="qs-input" id="qs-count" type="number" min="5" max="50" value="25">
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn-cancel" onclick="closeQuickStart()">Отмена</button>
|
||||
<button class="btn-join" onclick="doQuickStart()">Начать</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/js/api.js"></script>
|
||||
<!-- Quick-start test modal -->
|
||||
<script src="/js/api.js"></script>
|
||||
<script src="/js/sound.js"></script>
|
||||
<script src="/js/sidebar.js"></script>
|
||||
<script src="/js/notifications.js"></script>
|
||||
@@ -2801,12 +2764,19 @@
|
||||
/* ══ УВЕДОМЛЕНИЯ — handled by notifications.js ══ */
|
||||
|
||||
/* ══ JOIN MODAL ════════════════════════════════════════════════════════ */
|
||||
let _joinModal = null;
|
||||
function openJoinModal(code) {
|
||||
document.getElementById('join-code').value = code || '';
|
||||
document.getElementById('join-modal').classList.add('open');
|
||||
setTimeout(() => document.getElementById('join-code').focus(), 50);
|
||||
const body = `
|
||||
<input class="form-input" id="join-code" placeholder="Код приглашения" value="${LS.esc(code || '')}" />
|
||||
<div style="font-size:0.78rem;color:var(--text-3);margin-top:8px">Попросите учителя поделиться кодом или ссылкой</div>`;
|
||||
_joinModal = LS.modal({
|
||||
title: 'Вступить в класс', content: body, size: 'sm',
|
||||
actions: [
|
||||
{ label: 'Отмена', onClick: () => _joinModal.close() },
|
||||
{ label: 'Вступить', primary: true, id: 'btn-do-join', onClick: doJoin },
|
||||
],
|
||||
});
|
||||
}
|
||||
function closeJoinModal() { document.getElementById('join-modal').classList.remove('open'); }
|
||||
async function doJoin() {
|
||||
const code = document.getElementById('join-code').value.trim();
|
||||
if (!code) return;
|
||||
@@ -2814,11 +2784,10 @@
|
||||
btn.disabled = true;
|
||||
try {
|
||||
const r = await LS.joinClass(code);
|
||||
closeJoinModal();
|
||||
_joinModal?.close();
|
||||
LS.toast(`Вы вступили в класс «${r.class_name}»!`, 'success');
|
||||
loadAssignments();
|
||||
} catch (e) { LS.toast('Ошибка: ' + e.message, 'error'); }
|
||||
finally { btn.disabled = false; }
|
||||
} catch (e) { LS.toast('Ошибка: ' + e.message, 'error'); btn.disabled = false; }
|
||||
}
|
||||
|
||||
/* ══ SUBMISSIONS (student) ════════════════════════════════════════════ */
|
||||
@@ -3439,33 +3408,59 @@
|
||||
|
||||
/* ══ B1: QUICK-START MODAL ═════════════════════════════════════════ */
|
||||
let _qsSlug = null;
|
||||
let _qsModal = null;
|
||||
async function openQuickStart(slug) {
|
||||
_qsSlug = slug || null;
|
||||
let subjectsHtml = '';
|
||||
try {
|
||||
const subjects = await LS.getSubjects();
|
||||
document.getElementById('qs-subjects').innerHTML = subjects.map(s => {
|
||||
subjectsHtml = subjects.map(s => {
|
||||
const color = SUBJ_COLORS[s.slug] || '#9B5DE5';
|
||||
const active = s.slug === _qsSlug ? ' active' : '';
|
||||
return `<button class="qs-subj-btn${active}" onclick="selectQsSubject('${s.slug}',this)">
|
||||
return `<button class="qs-subj-btn${active}" data-slug="${s.slug}">
|
||||
<div class="qs-subj-icon" style="background:${color}">${lci(ICONS[s.slug]||'book-open')}</div>
|
||||
${esc(s.name)}
|
||||
</button>`;
|
||||
}).join('');
|
||||
reIcons();
|
||||
} catch {}
|
||||
document.getElementById('qs-modal').classList.add('open');
|
||||
const body = `
|
||||
<div class="qs-subjects" id="qs-subjects">${subjectsHtml}</div>
|
||||
<div class="qs-options">
|
||||
<div class="qs-row">
|
||||
<span class="qs-label">Режим</span>
|
||||
<select class="qs-select" id="qs-mode">
|
||||
<option value="exam">Экзамен</option>
|
||||
<option value="practice">Тренировка</option>
|
||||
<option value="random">Случайный</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="qs-row">
|
||||
<span class="qs-label">Вопросов</span>
|
||||
<input class="qs-input" id="qs-count" type="number" min="5" max="50" value="25">
|
||||
</div>
|
||||
</div>`;
|
||||
_qsModal = LS.modal({
|
||||
title: 'Быстрый тест', content: body, size: 'sm',
|
||||
actions: [
|
||||
{ label: 'Отмена', onClick: () => _qsModal.close() },
|
||||
{ label: 'Начать', primary: true, onClick: doQuickStart },
|
||||
],
|
||||
});
|
||||
reIcons();
|
||||
// Wire subject selection within modal
|
||||
_qsModal.body.querySelectorAll('.qs-subj-btn').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
_qsSlug = btn.dataset.slug;
|
||||
_qsModal.body.querySelectorAll('.qs-subj-btn').forEach(b => b.classList.remove('active'));
|
||||
btn.classList.add('active');
|
||||
});
|
||||
});
|
||||
}
|
||||
function selectQsSubject(slug, btn) {
|
||||
_qsSlug = slug;
|
||||
document.querySelectorAll('.qs-subj-btn').forEach(b => b.classList.remove('active'));
|
||||
btn.classList.add('active');
|
||||
}
|
||||
function closeQuickStart() { document.getElementById('qs-modal').classList.remove('open'); }
|
||||
function doQuickStart() {
|
||||
if (!_qsSlug) { LS.toast('Выберите предмет', 'warn'); return; }
|
||||
const mode = document.getElementById('qs-mode').value;
|
||||
const count = parseInt(document.getElementById('qs-count').value) || 25;
|
||||
closeQuickStart();
|
||||
_qsModal?.close();
|
||||
window.location.href = `/test-run?subject=${_qsSlug}&mode=${mode}&count=${count}`;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user