"use strict"; // ---------- Демонстрационный режим (персональный) ---------- function setSession(t) { token = t.access_token; localStorage.setItem("token", token); localStorage.setItem("refresh", t.refresh_token); me = null; } function demoBanner() { const back = sessionStorage.getItem("admin_tokens"); return h("div", { class: "demobar" }, h("span", {}, "🎭 ДЕМО-РЕЖИМ (только у вас) — данные тестовые. Остальные пользователи работают с рабочими данными."), back ? h("button", { class: "sm", onclick: backToAdmin }, "↩ Вернуться в админа") : h("button", { class: "sm", onclick: guard(async () => { if (!confirm("Выйти из демо-режима и вернуться к рабочим данным?")) return; const t = await api("POST", "/demo/leave"); setSession(t); location.hash = "#/"; route(); }) }, "Выйти из демо"), me.is_admin ? h("a", { href: "#/demo" }, "Управление") : null); } function backToAdmin() { const t = JSON.parse(sessionStorage.getItem("admin_tokens") || "null"); sessionStorage.removeItem("admin_tokens"); if (t) { setSession(t); location.hash = "#/demo"; route(); } } async function demoPage() { if (!me.is_admin) throw new Error("Только для администратора"); const info = await api("GET", "/demo"); const reload = () => demoPage(); const switchTo = guard(async (path, body, hash = "#/demo") => { const t = await api("POST", path, body); sessionStorage.removeItem("admin_tokens"); setSession(t); location.hash = hash; route(); }); const q = h("input", { type: "search", placeholder: "🔍 Найти пользователя", style: "max-width:320px" }); const tbody = h("tbody"); const drawUsers = () => { const s = q.value.trim().toLowerCase(); tbody.replaceChildren(...info.users.filter(u => !s || (u.full_name + " " + u.username).toLowerCase().includes(s)).map(u => h("tr", {}, h("td", {}, u.full_name || u.username, h("div", { class: "small muted" }, u.username, u.is_admin ? " · админ" : "")), h("td", {}, u.in_demo ? h("span", { class: "badge b-in_progress" }, "в демо") : h("span", { class: "muted" }, "рабочие данные")), h("td", { class: "row end" }, u.id === me.id && info.in_demo ? h("span", { class: "small muted" }, "это вы") : h("button", { class: "sec sm", onclick: guard(async () => { if (!u.in_demo && !confirm(`Перевести «${u.full_name || u.username}» в демо-режим? Он увидит тестовые данные до выхода из демо.`)) return; await api("POST", `/demo/users/${u.id}`, { on: !u.in_demo }); toast(u.in_demo ? "Выведен из демо" : "Переведён в демо"); reload(); }) }, u.in_demo ? "Выключить демо" : "Включить демо"))))); }; q.oninput = drawUsers; drawUsers(); const usersCard = h("div", { class: "card tablewrap" }, h("h2", { style: "margin-top:0" }, "Кто в демо-режиме"), h("p", { class: "small muted" }, "Демо включается каждому отдельно. Если кто-то включил его случайно и не может выйти — выключите здесь: со следующего действия он вернётся к рабочим данным."), q, h("table", { style: "margin-top:8px" }, tbody)); const head = [h("a", { href: "#/admin" }, "← Администрирование"), h("h1", {}, "Демонстрационный режим")]; const intro = h("ul", { class: "small" }, h("li", {}, h("b", {}, "Демо — персональное."), " Его видит только тот, кто в него вошёл; остальные в это время работают с рабочими данными как обычно."), h("li", {}, "Тестовая база отдельная: рабочие данные не изменяются. Всё, что сделано в демо, исчезнет при удалении демо-данных."), h("li", {}, "Выйти из демо можно кнопкой в жёлтой полосе вверху экрана.")); if (!info.active) { $app.replaceChildren(...head, h("div", { class: "card" }, h("p", {}, "Тестовый набор: сотрудники, графики, оборудование, чек-листы, наряды и задания за 14 дней, карта завода, склады, инциденты."), intro, h("button", { onclick: () => confirm("Войти в демонстрационный режим?\nДругие пользователи его не увидят.") && switchTo("/demo/enable", { confirm: true }, "#/") }, "Войти в демо-режим")), usersCard); return; } const control = h("div", { class: "card" }, h("p", {}, `Демо-данные созданы: ${fmtFull(info.since)}. Сейчас в демо: ${info.users.filter(u => u.in_demo).length} чел.`), intro, h("div", { class: "row" }, info.in_demo ? h("button", { onclick: () => confirm("Выйти из демо и вернуться к рабочим данным?") && switchTo("/demo/leave", undefined, "#/") }, "Выйти из демо") : h("button", { onclick: () => switchTo("/demo/enable", { confirm: true }, "#/") }, "Войти в демо"), h("button", { class: "sec", onclick: guard(async () => { if (confirm("Пересоздать тестовые данные? Все правки в демо будут потеряны.")) { await api("POST", "/demo/reset"); toast("Демо-данные пересозданы"); location.reload(); } }) }, "Пересоздать демо-данные"), h("button", { class: "bad", onclick: guard(async () => { if (confirm("Удалить демо-данные? Все, кто в демо, вернутся к рабочим данным.")) { await api("POST", "/demo/destroy"); toast("Демо-данные удалены"); location.reload(); } }) }, "Удалить демо-данные"))); const accounts = info.accounts && info.in_demo ? h("div", { class: "card tablewrap" }, h("h2", { style: "margin-top:0" }, "Тестовые учётные записи"), h("p", { class: "small muted" }, "Пароль у всех: ", h("b", {}, info.password), ". «Войти как» открывает систему под этим пользователем без пароля — удобно показывать роли. Вернуться можно кнопкой в жёлтой полосе вверху."), h("table", {}, h("thead", {}, h("tr", {}, ...["Логин", "ФИО", "Роль", "Должность", "Смена", ""].map(t => h("th", {}, t)))), h("tbody", {}, ...info.accounts.map(a => h("tr", {}, h("td", {}, a.username), h("td", {}, a.full_name), h("td", {}, a.role), h("td", {}, a.position || "—"), h("td", {}, a.position ? (a.on_shift ? "на смене" : "не на смене") : "—"), h("td", {}, h("button", { class: "sec sm", onclick: guard(async () => { const keep = { access_token: token, refresh_token: localStorage.getItem("refresh") }; const t = await api("POST", "/demo/impersonate", { user_id: a.id }); sessionStorage.setItem("admin_tokens", JSON.stringify(keep)); setSession(t); location.hash = "#/"; route(); }) }, "Войти как"))))))) : h("p", { class: "small muted" }, `Тестовые учётные записи (пароль ${info.password}) видны, когда вы сами в демо.`); $app.replaceChildren(...head, control, usersCard, accounts); }