/* ============================================================ Экран «Мой профиль» — #/me Работает для всех ролей: manager, staff, client ============================================================ */ const MeScreen = (function () { function escHtml(s) { return String(s == null ? "" : s) .replace(/&/g, "&").replace(//g, ">").replace(/"/g, """); } async function _fetchWithTimeout(url, body, ms = 15000) { const ctrl = new AbortController(); const t = setTimeout(() => ctrl.abort(), ms); try { const res = await fetch(url, { method: "POST", signal: ctrl.signal, headers: { "Content-Type": "application/json" }, body: JSON.stringify(body) }); return await res.json(); } catch (e) { if (e.name === "AbortError") throw new Error("Сервер не отвечает"); throw e; } finally { clearTimeout(t); } } function header(container) { const h = document.createElement("header"); h.className = "podbor-header"; h.innerHTML = `
Мой профиль
`; h.querySelector(".podbor-back").addEventListener("click", () => { haptic && haptic("impact"); history.back(); }); container.appendChild(h); } function avatarBlock(initial, name, subtitle) { return `
${escHtml(initial)}
${escHtml(name)}
${subtitle ? `
${escHtml(subtitle)}
` : ""}
`; } function roleChip(label, color) { const colors = { gold: "#C5A55E", blue: "#3D7AB5", green: "#4A9E6A", muted: "var(--muted)" }; const c = colors[color] || colors.gold; return ` ${escHtml(label)} `; } function renderManager(container, me) { const u = me.user || {}; const statusLabel = me.status === "active" ? "✅ Активен" : me.status === "trial" ? "🟡 Пробный" : "🔴 Неактивен"; const statusColor = me.status === "active" ? "green" : me.status === "trial" ? "gold" : "muted"; const screen = document.createElement("div"); screen.className = "podbor-screen"; screen.innerHTML = ` ${avatarBlock(u.avatar_initial || "?", u.full_name || "Менеджер", u.salon || "")}
Статус доступа
Статус ${roleChip(statusLabel, statusColor)}
${me.status_until ? `
Активен до${escHtml(me.status_until)}
` : ""} ${u.salon ? `
Салон${escHtml(u.salon)}
` : ""}
Быстрый переход
`; screen.querySelectorAll("[data-href]").forEach(btn => { btn.addEventListener("click", () => { haptic && haptic("impact"); location.hash = btn.dataset.href; }); }); container.appendChild(screen); } const EQUIPMENT_ITEMS = [ { key: "tablet", label: "Планшет с ПО для замеров", icon: "📱" }, { key: "laser_tape", label: "Лазерная рулетка (интеграция с ПО)", icon: "📡" }, { key: "angle_meter", label: "Угломер", icon: "📐" }, { key: "tape", label: "Обычная рулетка", icon: "📏" }, { key: "laser_level", label: "Лазерный уровень", icon: "🔴" }, ]; function renderStaffMe(container, me) { const u = me.user || {}; const caps = me.capabilities || {}; const eqList = me.equipment || []; const eqOk = me.equipment_ok !== false; const chips = [ caps.measurer && roleChip("замерщик", "blue"), caps.assembler && roleChip("сборщик", "green"), ].filter(Boolean).join(""); // Бейдж укомплектованности const eqBadge = caps.measurer ? `
${eqOk ? "✅ Укомплектован — допуск к замерам открыт" : "⚠️ Не укомплектован — допуск ограничен"}
${!eqOk ? `
Заполните список оборудования ниже
` : ""}
` : ""; const screen = document.createElement("div"); screen.className = "podbor-screen"; screen.innerHTML = ` ${avatarBlock(u.avatar_initial || "?", u.full_name || "Сотрудник", "")}
${chips}
${eqBadge}
Мои задачи
${caps.measurer ? `` : ""} ${caps.measurer ? `` : ""} ${caps.assembler ? `` : ""}
${caps.measurer ? `
Оборудование
Все 5 пунктов обязательны для допуска к замерам
` : ""} `; screen.querySelectorAll("[data-href]").forEach(btn => { btn.addEventListener("click", () => { haptic && haptic("impact"); location.hash = btn.dataset.href; }); }); container.appendChild(screen); // Чеклист оборудования if (caps.measurer) { const checklist = screen.querySelector("#eq-checklist"); EQUIPMENT_ITEMS.forEach(item => { const checked = eqList.includes(item.key); const row = document.createElement("label"); row.style.cssText = `display:flex;align-items:center;gap:10px;padding:10px 0; border-bottom:1px solid var(--border);cursor:pointer;`; row.innerHTML = ` ${item.icon} ${escHtml(item.label)} `; checklist.appendChild(row); }); // Кнопка сохранить const saveBtn = screen.querySelector("#eq-save-btn"); const statusEl = screen.querySelector("#eq-status"); saveBtn.addEventListener("click", async () => { haptic && haptic("impact"); saveBtn.disabled = true; saveBtn.textContent = "Сохраняем…"; const selected = Array.from(checklist.querySelectorAll("input[data-key]:checked")) .map(cb => cb.dataset.key); try { const res = await _fetchWithTimeout(`${BACKEND_URL}/api/equipment_save`, { initData: typeof Platform !== "undefined" ? Platform.initData : (window.tg?.initData || ""), initDataUnsafe: typeof Platform !== "undefined" ? Platform.initDataUnsafe : null, equipment: selected, }); if (res.ok) { statusEl.style.color = res.equipment_ok ? "#27AE60" : "#E74C3C"; statusEl.textContent = res.equipment_ok ? "✅ Сохранено. Допуск открыт." : "⚠️ Сохранено. Заполните все пункты для допуска."; // Обновить бейдж const badge = container.querySelector("#equipment-block")?.closest(".podbor-screen")?.querySelector("[style*='Укомплектован']") || container.querySelector("[style*='допуск']"); } else { statusEl.style.color = "#E74C3C"; statusEl.textContent = "Ошибка: " + (res.error || "неизвестно"); } } catch (e) { statusEl.style.color = "#E74C3C"; statusEl.textContent = "Ошибка: " + e.message; } finally { saveBtn.disabled = false; saveBtn.textContent = "Сохранить оборудование"; } }); } } function renderClientMe(container, me) { const u = me.user || {}; const mgr = me.manager || {}; const screen = document.createElement("div"); screen.className = "podbor-screen"; screen.innerHTML = ` ${avatarBlock(u.avatar_initial || "?", u.full_name || "Клиент", "Личный кабинет")} ${mgr.full_name ? `
Мой менеджер
Имя${escHtml(mgr.full_name)}
${mgr.salon ? `
Салон${escHtml(mgr.salon)}
` : ""}
` : ""}
`; screen.querySelectorAll("[data-href]").forEach(btn => { btn.addEventListener("click", () => { haptic && haptic("impact"); location.hash = btn.dataset.href; }); }); container.appendChild(screen); } async function mount(container) { container.innerHTML = ""; document.body.classList.remove("has-bottom-nav"); const oldNav = document.getElementById("bottom-nav"); if (oldNav) oldNav.remove(); header(container); const loading = document.createElement("div"); loading.className = "loader-inline"; loading.innerHTML = `
`; container.appendChild(loading); try { const me = await _fetchWithTimeout(`${BACKEND_URL}/api/me`, { initData: tg?.initData || "", initDataUnsafe: tg?.initDataUnsafe || null, }); loading.remove(); if (me.error) { container.appendChild(el(`
${escHtml(me.error)}
`)); return; } const role = me.role; if (role === "manager" || me.roles?.includes("manager")) { renderManager(container, me); } else if (role === "staff") { renderStaffMe(container, me); } else { renderClientMe(container, me); } } catch (e) { loading.remove(); container.appendChild(el(`
Ошибка: ${escHtml(e.message)}
`)); } } return { mount }; })();