// App shell: sidebar, org switcher dropdown, topbar, mobile bottom nav. // Export to window.Screens.Shell. const { useState: useStateSh, useRef: useRefSh, useEffect: useEffectSh } = React; const NAV = [ { id: 'dashboard', label: 'Дашборд', icon: 'Dashboard', tint: 'lavender' }, { id: 'sources', label: 'Источники', icon: 'Plug', tint: 'mint' }, { id: 'ideas', label: 'Идеи', icon: 'Lightbulb', tint: 'lemon' }, { id: 'generate', label: 'Генерация', icon: 'Sparkles', tint: 'violet' }, { id: 'posts', label: 'Посты', icon: 'Grid', tint: 'sky' }, { id: 'analytics', label: 'Аналитика', icon: 'BarChart', tint: 'peach' }, { id: 'brand', label: 'Брендбук', icon: 'Palette', tint: 'rose' }, { id: 'settings', label: 'Настройки', icon: 'Settings', tint: 'ink' }, ]; const NAV_TINT_BG = { lavender: 'bg-lavender-soft text-lavender-ink', mint: 'bg-mint-soft text-mint-ink', lemon: 'bg-lemon-soft text-lemon-ink', violet: 'bg-violet-soft text-violet-ink', sky: 'bg-sky-soft text-sky-ink', peach: 'bg-peach-soft text-peach-ink', rose: 'bg-rose-soft text-rose-ink', ink: 'bg-ink-100 text-ink-700', }; function Shell({ user, orgs, currentOrgId, route, onRouteChange, onSwitchOrg, onCreateOrg, onLogout, children, topbar }) { const I = window.Icons; const { Avatar, IconButton } = window.UI; const currentOrg = orgs.find(o => o.id === currentOrgId) || orgs[0]; const [orgOpen, setOrgOpen] = useStateSh(false); const [mobileMenu, setMobileMenu] = useStateSh(false); const orgRef = useRefSh(null); useEffectSh(() => { const onDoc = (e) => { if (orgRef.current && !orgRef.current.contains(e.target)) setOrgOpen(false); }; document.addEventListener('mousedown', onDoc); return () => document.removeEventListener('mousedown', onDoc); }, []); return (
{/* Sidebar */} {/* Main column */}
{/* Top bar */}
{/* mobile menu trigger */}
{currentOrg.name} {NAV.find(n => n.id === route)?.label || ''}
{NAV.find(n => n.id === route)?.label || ''}
{topbar}
{/* Page content */}
{children}
{/* Mobile drawer */} {mobileMenu && (
setMobileMenu(false)}>
e.stopPropagation()}>
{currentOrg.name}
{currentOrg.role}
setMobileMenu(false)}>
Орг-ции
{orgs.map((o) => ( ))}
Навигация
)} {/* Mobile bottom nav */}
); } function ThemeSwitcher() { const I = window.Icons; const [theme, setTheme] = useStateSh(() => { try { return localStorage.getItem('omneee.theme') || 'light'; } catch (e) { return 'light'; } }); const [hover, setHover] = useStateSh(null); useEffectSh(() => { const html = document.documentElement; if (theme === 'light') html.removeAttribute('data-theme'); else html.setAttribute('data-theme', theme); try { localStorage.setItem('omneee.theme', theme); } catch (e) {} }, [theme]); const opts = [ { v: 'light', Icon: I.Sun, label: 'Светлая' }, { v: 'dark', Icon: I.Moon, label: 'Тёмная' }, { v: 'mono', Icon: I.Contrast, label: 'Минимал' }, ]; return (
{opts.map((o) => { const Icon = o.Icon; const active = theme === o.v; return ( ); })}
); } window.Screens = window.Screens || {}; window.Screens.Shell = Shell; window.ThemeSwitcher = ThemeSwitcher;