// app.jsx — загрузка сессии и конфига, выбор экрана. // аноним → Главная = вход; База знаний открыта (публичное читается, закрытое — с замком) // вошёл, не участник / подписка истекла → Главная = «Доступ по подписке» // участник без анкеты → Главная = анкета (можно отложить до конца сессии браузера) // участник → Главная, База знаний, Профиль const VIEWS = ['home', 'kb', 'profile', 'onboarding']; const readRoute = () => { try { const q = new URLSearchParams(location.search); const v = q.get('view'); const params = {}; for (const k of ['m', 'c']) if (q.get(k)) params[k] = q.get(k); return { view: VIEWS.includes(v) ? v : 'home', params }; } catch (e) { return { view: 'home', params: {} }; } }; const routeUrl = (view, params = {}) => { if (view === 'home') return '/os/'; const q = new URLSearchParams({ view, ...params }); return '/os/?' + q.toString(); }; function App() { const [ready, setReady] = React.useState(false); const [route, setRoute] = React.useState(readRoute); const nav = (view, params = {}) => { const r = { view: VIEWS.includes(view) ? view : 'home', params }; setRoute(r); try { history.pushState(r, '', routeUrl(r.view, params)); } catch (e) {} window.scrollTo(0, 0); }; React.useEffect(() => { const onPop = () => setRoute(readRoute()); window.addEventListener('popstate', onPop); Promise.all([ fetch('/api/auth/me', { credentials:'same-origin' }).then(r => r.json()).catch(() => null), fetch('/api/config', { credentials:'same-origin' }).then(r => r.json()).catch(() => null), ]).then(([me, cfg]) => { if (me && me.ok) window.__ME = me; if (cfg && cfg.ok) window.__CFG = cfg; setReady(true); }); return () => window.removeEventListener('popstate', onPop); }, []); React.useEffect(() => { if (ready) track(route.view); }, [route.view, ready]); if (!ready) return null; const { view, params } = route; const anon = isAnon(); const member = isMember(); let screen; if (view === 'kb') screen = ; else if (anon) screen = ; else if (view === 'profile') screen = ; else if (!member) screen = ; else if (view === 'onboarding') screen = ; else { let skipped = false; try { skipped = sessionStorage.getItem('cm_onboarding_skip') === '1'; } catch (e) {} screen = !ME().profile && !skipped ? : ; } return
{screen}
; } ReactDOM.createRoot(document.getElementById('root')).render();