diff --git a/ui/src/hooks/useScope.ts b/ui/src/hooks/useScope.ts new file mode 100644 index 00000000..a466fb3a --- /dev/null +++ b/ui/src/hooks/useScope.ts @@ -0,0 +1,68 @@ +// ui/src/hooks/useScope.ts +import { useParams, useNavigate, useLocation } from 'react-router'; +import { useCallback } from 'react'; + +export type TabKey = 'exchanges' | 'dashboard' | 'runtime'; + +const VALID_TABS = new Set(['exchanges', 'dashboard', 'runtime']); + +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 }; +}