diff --git a/apps/dashboard/src/App.tsx b/apps/dashboard/src/App.tsx index 7fd51b0..6d96882 100644 --- a/apps/dashboard/src/App.tsx +++ b/apps/dashboard/src/App.tsx @@ -27,9 +27,28 @@ interface DashboardState { type UsageRow = DashboardOverview['usage']['rows'][number]; type RiskLevel = 'ok' | 'warn' | 'critical'; type UsageGroup = 'primary' | 'codex'; +type DashboardView = 'usage' | 'health' | 'rooms' | 'scheduled'; const REFRESH_INTERVAL_MS = 15_000; const LOCALE_STORAGE_KEY = 'ejclaw.dashboard.locale'; +const DEFAULT_VIEW: DashboardView = 'usage'; + +function isDashboardView( + value: string | null | undefined, +): value is DashboardView { + return ( + value === 'usage' || + value === 'health' || + value === 'rooms' || + value === 'scheduled' + ); +} + +function readViewFromHash(): DashboardView { + if (typeof window === 'undefined') return DEFAULT_VIEW; + const raw = window.location.hash.replace(/^#\/?/, ''); + return isDashboardView(raw) ? raw : DEFAULT_VIEW; +} function readInitialLocale(): Locale { const stored = @@ -110,10 +129,10 @@ function queueLabel( function navItems(t: Messages) { return [ - { href: '#overview', label: t.nav.health }, - { href: '#usage', label: t.nav.usage }, - { href: '#rooms', label: t.nav.rooms }, - { href: '#work', label: t.nav.scheduled }, + { href: '#/usage', label: t.nav.usage, view: 'usage' as const }, + { href: '#/health', label: t.nav.health, view: 'health' as const }, + { href: '#/rooms', label: t.nav.rooms, view: 'rooms' as const }, + { href: '#/scheduled', label: t.nav.scheduled, view: 'scheduled' as const }, ]; } @@ -170,15 +189,19 @@ function LoadingSkeleton({ t }: { t: Messages }) { } function SideRail({ + activeView, lastRefreshed, locale, + onNavigate, onLocaleChange, onRefresh, refreshing, t, }: { + activeView: DashboardView; lastRefreshed: string | null; locale: Locale; + onNavigate: (view: DashboardView) => void; onLocaleChange: (locale: Locale) => void; onRefresh: () => void; refreshing: boolean; @@ -192,7 +215,13 @@ function SideRail({