// DataLoop Cabinet — shell + routing const { useState: useStateCab, useEffect: useEffectCab } = React; // Curated accent palettes (mirror the landing page) const ACCENT_INK_CAB = { "#ff5b2e": "#1a0a04", "#c9f24a": "#0e1602", "#38e8d6": "#022119", "#ff4dc2": "#1f0414", }; const ACCENT_NAMES_CAB = { "#ff5b2e": "коралл", "#c9f24a": "лайм", "#38e8d6": "циан", "#ff4dc2": "маджента", }; const ACCENT_HEXES_CAB = Object.keys(ACCENT_INK_CAB); const DEFAULTS_CAB = /*EDITMODE-BEGIN*/{ "direction": "a", "accent": "#ff5b2e", "section": "overview", "env": "live" }/*EDITMODE-END*/; const NAV = [ { id: "overview", label: "Обзор", icon: "home" }, { id: "keys", label: "API ключи", icon: "key", badge: "4" }, { id: "logs", label: "Логи запросов", icon: "logs" }, { id: "billing", label: "Биллинг", icon: "billing" }, { id: "team", label: "Команда", icon: "team" }, { id: "settings", label: "Настройки", icon: "settings" }, ]; const CRUMBS = { overview: "Обзор", keys: "API ключи", logs: "Логи запросов", billing: "Биллинг", team: "Команда", settings: "Настройки", }; function CabinetApp() { const [t, setTweak] = useTweaks(DEFAULTS_CAB); const [section, setSection] = useStateCab(t.section || "overview"); const [env, setEnv] = useStateCab(t.env || "live"); const [navOpen, setNavOpen] = useStateCab(false); useEffectCab(() => { const ink = ACCENT_INK_CAB[t.accent] || "#1a0a04"; document.documentElement.style.setProperty("--accent", t.accent); document.documentElement.style.setProperty("--accent-ink", ink); }, [t.accent]); useEffectCab(() => { document.body.className = t.direction === "b" ? "dir-b" : "dir-a"; }, [t.direction]); // lock body scroll while mobile drawer open useEffectCab(() => { document.body.style.overflow = navOpen ? "hidden" : ""; return () => { document.body.style.overflow = ""; }; }, [navOpen]); // auto-close drawer when section changes on mobile function gotoSection(id) { setSection(id); setNavOpen(false); } const D = window.__CAB; function renderView() { switch (section) { case "overview": return ; case "keys": return ; case "logs": return ; case "billing": return ; case "team": return ; case "settings": return ; default: return ; } } return (
{/* SIDEBAR */} {/* MAIN */}
Кабинет / {CRUMBS[section] || section}
⌘K
API · 27 мс
{renderView()}
{/* Mobile scrim */}
setNavOpen(false)} /> {/* Tweaks panel */} setTweak("direction", v)} options={[ { value: "a", label: "Светлое" }, { value: "b", label: "Тёмное" }, ]} /> setTweak("accent", v)} options={ACCENT_HEXES_CAB} />
{ACCENT_NAMES_CAB[t.accent] || ""}
gotoSection(v)} options={NAV.map((n) => ({ value: n.id, label: n.label }))} />
); } const rootCab = ReactDOM.createRoot(document.getElementById("root")); rootCab.render();