Vite + React 18 + TypeScript project with: - Tailwind CSS for styling (dark theme, trading-focused color palette) - React Router with 6 dashboard routes (Trading, Risk, ML, Performance, Backtest, Config) and keyboard shortcuts (T/R/M/P/B/C) - TanStack Query for data fetching with auto-refetch - Shared lib layer: typed API client, WebSocket manager with auto-reconnect and topic subscriptions, auth (JWT in localStorage) - React hooks: useAuth, useApi (query/mutation wrappers), useWebSocket - DashboardLayout with nav tabs and StatusBar (WS connection, auth status) - Stub pages with placeholder component layouts matching design doc Vite proxy configured to forward /api/* to gateway at localhost:3000. TypeScript passes with zero errors, production build succeeds. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
35 lines
1.0 KiB
TypeScript
35 lines
1.0 KiB
TypeScript
import { useCallback, useSyncExternalStore } from 'react';
|
|
import { clearTokens, getToken, isAuthenticated, setTokens } from '../lib/auth';
|
|
import { wsManager } from '../lib/websocket';
|
|
|
|
/** Simple external store for auth state reactivity */
|
|
let authListeners: Set<() => void> = new Set();
|
|
function notifyAuthChange() {
|
|
authListeners.forEach((l) => l());
|
|
}
|
|
|
|
function subscribeAuth(listener: () => void) {
|
|
authListeners.add(listener);
|
|
return () => authListeners.delete(listener);
|
|
}
|
|
|
|
/** React hook for authentication state and actions */
|
|
export function useAuth() {
|
|
const authenticated = useSyncExternalStore(subscribeAuth, isAuthenticated);
|
|
const token = useSyncExternalStore(subscribeAuth, getToken);
|
|
|
|
const login = useCallback((accessToken: string, refreshToken?: string) => {
|
|
setTokens(accessToken, refreshToken);
|
|
wsManager.connect();
|
|
notifyAuthChange();
|
|
}, []);
|
|
|
|
const logout = useCallback(() => {
|
|
clearTokens();
|
|
wsManager.disconnect();
|
|
notifyAuthChange();
|
|
}, []);
|
|
|
|
return { authenticated, token, login, logout };
|
|
}
|