93 lines
3.6 KiB
JavaScript
93 lines
3.6 KiB
JavaScript
'use strict';
|
|
/* ──────────────────────────────────────────────────────────────────
|
|
Exam Preparation Module — common helpers
|
|
Loaded by every exam-prep*.html page before its view-specific JS.
|
|
|
|
Responsibilities:
|
|
- Parse examKey from URL path: /exam-prep/<key>[/...]
|
|
- Determine current view (dashboard | variants | practice | topics | mock)
|
|
- Render the tabs bar with the active tab highlighted
|
|
- Expose helpers on window.EP
|
|
────────────────────────────────────────────────────────────────── */
|
|
|
|
(function () {
|
|
const VIEWS = [
|
|
{ id: 'dashboard', label: 'Дашборд', icon: 'gauge', path: '' },
|
|
{ id: 'variants', label: 'Варианты', icon: 'layout-grid', path: '/variants' },
|
|
{ id: 'practice', label: 'Тренажёр', icon: 'dumbbell', path: '/practice' },
|
|
{ id: 'topics', label: 'Темы', icon: 'tag', path: '/topics' },
|
|
{ id: 'mock', label: 'Пробник', icon: 'timer', path: '/mock' },
|
|
];
|
|
|
|
/* Parse examKey and view from `/exam-prep/<key>[/<view>[/...]]` */
|
|
function parseUrl() {
|
|
const parts = location.pathname.replace(/\/+$/, '').split('/').filter(Boolean);
|
|
// parts[0] === 'exam-prep'; parts[1] === examKey; parts[2] === optional view
|
|
const examKey = parts[1] || 'math9';
|
|
const view = (parts[2] && VIEWS.find(v => v.id === parts[2]))
|
|
? parts[2]
|
|
: 'dashboard';
|
|
return { examKey, view };
|
|
}
|
|
|
|
function renderTabs(containerSel, { examKey, view }) {
|
|
const el = document.querySelector(containerSel);
|
|
if (!el) return;
|
|
el.innerHTML = VIEWS.map(v => {
|
|
const href = `/exam-prep/${examKey}${v.path}`;
|
|
const active = v.id === view ? ' active' : '';
|
|
return `<a class="ep-tab${active}" href="${href}">
|
|
<i data-lucide="${v.icon}"></i><span>${v.label}</span>
|
|
</a>`;
|
|
}).join('');
|
|
if (window.lucide && typeof lucide.createIcons === 'function') lucide.createIcons();
|
|
}
|
|
|
|
/* Bootstrap shared for every exam-prep page.
|
|
- Reads {examKey, view}
|
|
- Initializes LS auth/page chrome
|
|
- Renders the tabs bar (if a #ep-tabs slot exists)
|
|
- Loads track info and writes it into #ep-title / #ep-sub if present
|
|
- Returns the {track, counts, progress} payload to the caller (Promise) */
|
|
async function boot(opts = {}) {
|
|
const { examKey, view } = parseUrl();
|
|
|
|
if (typeof LS !== 'undefined') {
|
|
LS.initPage?.();
|
|
LS.showBoardIfAllowed?.();
|
|
LS.hideDisabledFeatures?.();
|
|
}
|
|
|
|
renderTabs(opts.tabsSelector || '#ep-tabs', { examKey, view });
|
|
|
|
let info = null;
|
|
try {
|
|
info = await LS.api(`/api/exam-prep/${examKey}/info`);
|
|
} catch (e) {
|
|
console.warn('[exam-prep] info failed', e);
|
|
}
|
|
|
|
if (info?.track) {
|
|
const titleEl = document.getElementById('ep-title');
|
|
const subEl = document.getElementById('ep-sub');
|
|
if (titleEl) titleEl.textContent = info.track.title;
|
|
if (subEl) {
|
|
const c = info.counts || {};
|
|
subEl.textContent =
|
|
`${info.track.variants_count} вариантов · ${c.total ?? '—'} задач · ` +
|
|
`${info.track.duration_min} мин`;
|
|
}
|
|
}
|
|
|
|
window.EP = window.EP || {};
|
|
window.EP.examKey = examKey;
|
|
window.EP.view = view;
|
|
window.EP.info = info;
|
|
return { examKey, view, info };
|
|
}
|
|
|
|
window.EP = {
|
|
boot, parseUrl, renderTabs, VIEWS,
|
|
};
|
|
})();
|