/* ============================================================ Клиентский кабинет — #/c/cabinet Доступен только роли client. ============================================================ */ const CabinetScreen = (function () { function escHtml(s) { return String(s == null ? "" : s) .replace(/&/g, "&").replace(//g, ">").replace(/"/g, """); } function fmtDate(iso) { if (!iso) return "—"; try { return new Date(iso).toLocaleDateString("ru-RU", { day: "numeric", month: "short" }); } catch { return iso.slice(0, 10); } } async function _api(path, body = {}) { const ctrl = new AbortController(); const t = setTimeout(() => ctrl.abort(), 15000); try { const res = await fetch(`${BACKEND_URL}/api/${path}`, { method: "POST", signal: ctrl.signal, headers: { "Content-Type": "application/json" }, body: JSON.stringify({ initData: tg?.initData || "", initDataUnsafe: tg?.initDataUnsafe || null, ...body }), }); return await res.json(); } catch (e) { if (e.name === "AbortError") throw new Error("Сервер не отвечает"); throw e; } finally { clearTimeout(t); } } const STATUS_LABELS = { draft: "📝 Черновик", sent: "📨 Отправлен", reviewed: "✅ Просмотрен", approved: "🎉 Принят", rejected: "❌ Отклонён", created: "🆕 Создана", scheduled: "📅 Запланирована", in_progress: "🔨 В работе", done: "✅ Завершена", cancelled: "❌ Отменена", }; function statusChip(status) { const label = STATUS_LABELS[status] || status || "—"; return `${escHtml(label)}`; } // ── Блок «Менеджер» ────────────────────────────────────────────────────── function renderManagerBlock(mgr) { if (!mgr?.full_name) return ""; const tgLink = mgr.tg_id ? `📩 Написать` : ""; return `
Мой менеджер
${escHtml(mgr.full_name)}
${mgr.salon ? `
${escHtml(mgr.salon)}
` : ""}
${tgLink}
`; } // ── Блок «Подборы» ─────────────────────────────────────────────────────── function renderProposalsBlock(proposals) { if (!proposals?.length) { return `
Мои подборы
Подборов пока нет
`; } const items = proposals.slice(0, 3).map(p => `
Подбор от ${escHtml(fmtDate(p.created_at))}
${p.n_categories || 0} категор. · ${p.n_variants || 0} вар.
${statusChip(p.status)}
`).join(""); return `
Мои подборы ${proposals.length > 3 ? `Все ${proposals.length}` : ""}
${items}
`; } // ── Блок «Сборки» ──────────────────────────────────────────────────────── function renderAssembliesBlock(assemblies) { if (!assemblies?.length) { return `
Мои сборки
Сборок пока нет
`; } const items = assemblies.slice(0, 3).map(a => `
${escHtml(a.address || "Адрес не указан")}
${escHtml(fmtDate(a.scheduled_at || a.ts))}
${statusChip(a.status)}
`).join(""); return `
Мои сборки
${items}
${assemblies.length > 3 ? `
+${assemblies.length - 3} ещё
` : ""}
`; } async function mount(container) { container.innerHTML = ""; document.body.classList.remove("has-bottom-nav"); const oldNav = document.getElementById("bottom-nav"); if (oldNav) oldNav.remove(); // Header 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); const screen = document.createElement("div"); screen.className = "podbor-screen"; screen.innerHTML = `
`; container.appendChild(screen); try { // Параллельно грузим профиль + подборы + сборки const [me, proposalsData, assembliesData] = await Promise.all([ _api("me"), _api("proposal_list").catch(() => ({ proposals: [] })), _api("assembly_list").catch(() => ({ assemblies: [] })), ]); screen.innerHTML = ""; if (me.error) { screen.innerHTML = `
${escHtml(me.error)}
`; return; } const u = me.user || {}; const initial = u.avatar_initial || (u.full_name || "К")[0].toUpperCase(); // Аватар + имя screen.innerHTML = `
${escHtml(initial)}
${escHtml(u.full_name || "Клиент")}
Личный кабинет
${renderManagerBlock(me.manager)} ${renderProposalsBlock(proposalsData.proposals || [])} ${renderAssembliesBlock(assembliesData.assemblies || [])}
`; // Навигация по data-href screen.querySelectorAll("[data-href]").forEach(el => { el.addEventListener("click", () => { haptic && haptic("impact"); location.hash = el.dataset.href; }); }); } catch (e) { screen.innerHTML = `
Ошибка: ${escHtml(e.message)}
`; } } return { mount }; })();