// Shell: topbar + navbar + sidebar + page header. // Translations via window.t() (see i18n.js). const { useState, useEffect, useRef, useMemo } = React; const Topbar = ({ theme, setTheme, searchValue, onSearchChange, userBadge }) => { const t = window.t; return (
LLM Gate
acme-prod
onSearchChange(e.target.value)} onKeyDown={(e) => { if (e.key === 'Escape') onSearchChange(''); }} style={{background:'transparent', border:0, color:'var(--text-1)', outline:'none', flex:1, minWidth:0, fontSize:12, padding:0, marginLeft:2}} /> {searchValue ? ( ) : ⌘K}
{(userBadge || 'NR').slice(0, 2).toUpperCase()}
); }; const Navbar = ({ activeTab, setActiveTab }) => { const t = window.t; const tabs = [ { id: 'Overview', label: t('nav.overview') }, { id: 'Providers', label: t('nav.providers') }, { id: 'Models', label: t('nav.models') }, { id: 'Policies', label: t('nav.policies') }, { id: 'API keys', label: t('nav.apiKeys') }, { id: 'Playground', label: t('nav.playground') }, { id: 'Analytics', label: t('nav.analytics') }, { id: 'Logs', label: t('nav.logs') }, ]; return (
{tabs.map(tab => ( ))}
openai-compat · v2.3.1
); }; const Sidebar = ({ activeTab, setActiveTab, providers }) => { const t = window.t; const modelsCount = providers.reduce((a, p) => a + (p.models || 0), 0); const enabled = providers.filter(p => p.enabled).length; const groups = [ { group: t('side.workspace'), items: [ { id: 'Overview', icon: 'overview', label: t('nav.overview') }, { id: 'Providers', icon: 'providers', label: t('nav.providers'), count: enabled }, { id: 'Models', icon: 'models', label: t('nav.models'), count: modelsCount }, { id: '__deploy', icon: 'cube', label: t('side.deployments'), count: 4 }, ]}, { group: t('side.routing'), items: [ { id: 'Policies', icon: 'policies', label: t('nav.policies'), count: 5 }, { id: '__rate', icon: 'filter', label: t('side.rateLimits') }, { id: '__exp', icon: 'flask', label: t('side.experiments'), count: 2 }, ]}, { group: t('side.developer'), items: [ { id: 'API keys', icon: 'keys', label: t('nav.apiKeys'), count: 12 }, { id: 'Playground', icon: 'playground', label: t('nav.playground') }, { id: 'Logs', icon: 'logs', label: t('nav.logs') }, ]}, { group: t('side.observability'), items: [ { id: 'Analytics', icon: 'analytics', label: t('nav.analytics') }, { id: '__spend', icon: 'dollar', label: t('side.spend') }, { id: '__alerts', icon: 'bell', label: t('topbar.alerts'), count: 2 }, ]}, ]; return ( ); }; const PageHeader = ({ title, timeRange, setTimeRange, onAddProvider, onDeploy, onExport }) => { const t = window.t; const ranges = ['1h', '24h', '7d', '30d']; return (

{title || t('page.overview')}

{t('page.liveSync')} · acme-prod / openai-compat · {t('page.region')}: us-east-1
{ranges.map(r => ( ))}
); }; Object.assign(window, { Topbar, Navbar, Sidebar, PageHeader });