feat(ui): add useScope hook for tab+scope URL management
This commit is contained in:
68
ui/src/hooks/useScope.ts
Normal file
68
ui/src/hooks/useScope.ts
Normal file
@@ -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<TabKey>(['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 };
|
||||
}
|
||||
Reference in New Issue
Block a user