// ui/src/hooks/useScope.ts import { useParams, useNavigate, useLocation } from 'react-router'; import { useCallback } from 'react'; export type TabKey = 'exchanges' | 'dashboard' | 'runtime' | 'logs'; const VALID_TABS = new Set(['exchanges', 'dashboard', 'runtime', 'logs']); export interface Scope { tab: TabKey; appId?: string; routeId?: string; exchangeId?: string; } export function useScope() { const params = useParams<{ tab?: string; appId?: string; routeId?: string; exchangeId?: string }>(); const navigate = useNavigate(); const location = useLocation(); // Derive tab from first URL segment — fallback to 'exchanges' const rawTab = location.pathname.split('/').filter(Boolean)[0] ?? 'exchanges'; const tab: TabKey = VALID_TABS.has(rawTab as TabKey) ? (rawTab as TabKey) : 'exchanges'; const scope: Scope = { tab, appId: params.appId, routeId: params.routeId, exchangeId: params.exchangeId, }; const setTab = useCallback((newTab: TabKey) => { const parts = ['', newTab]; if (scope.appId) parts.push(scope.appId); if (scope.routeId) parts.push(scope.routeId); navigate(parts.join('/')); }, [navigate, scope.appId, scope.routeId]); const setApp = useCallback((appId: string | undefined) => { if (!appId) { navigate(`/${tab}`); } else { navigate(`/${tab}/${appId}`); } }, [navigate, tab]); const setRoute = useCallback((appId: string, routeId: string | undefined) => { if (!routeId) { navigate(`/${tab}/${appId}`); } else { navigate(`/${tab}/${appId}/${routeId}`); } }, [navigate, tab]); const setExchange = useCallback((appId: string, routeId: string, exchangeId: string | undefined) => { if (!exchangeId) { navigate(`/${tab}/${appId}/${routeId}`); } else { navigate(`/${tab}/${appId}/${routeId}/${exchangeId}`); } }, [navigate, tab]); const clearScope = useCallback(() => { navigate(`/${tab}`); }, [navigate, tab]); return { scope, setTab, setApp, setRoute, setExchange, clearScope }; }