- Add X-Request-Id middleware with UUID v4 generation and header propagation - Convert 6 dashboard routes to React.lazy() with Suspense for code splitting - Add inline validation errors to OrderForm (symbol, quantity, price) - Add date range + symbol validation to BacktestingDashboard form - Fix !Send future issue: use .instrument(span) instead of span.entered() Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
95 lines
3.1 KiB
TypeScript
95 lines
3.1 KiB
TypeScript
import { lazy, Suspense } from 'react';
|
|
import { BrowserRouter, Navigate, Route, Routes } from 'react-router-dom';
|
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
import { ErrorBoundary } from './components/common/ErrorBoundary';
|
|
import { ProtectedRoute } from './components/common/ProtectedRoute';
|
|
import { DashboardLayout } from './components/common/DashboardLayout';
|
|
import { LoginPage } from './pages/LoginPage';
|
|
|
|
const TradingDashboard = lazy(() =>
|
|
import('./pages/TradingDashboard').then(m => ({ default: m.TradingDashboard }))
|
|
);
|
|
const RiskDashboard = lazy(() =>
|
|
import('./pages/RiskDashboard').then(m => ({ default: m.RiskDashboard }))
|
|
);
|
|
const MLDashboard = lazy(() =>
|
|
import('./pages/MLDashboard').then(m => ({ default: m.MLDashboard }))
|
|
);
|
|
const PerformanceDashboard = lazy(() =>
|
|
import('./pages/PerformanceDashboard').then(m => ({ default: m.PerformanceDashboard }))
|
|
);
|
|
const BacktestingDashboard = lazy(() =>
|
|
import('./pages/BacktestingDashboard').then(m => ({ default: m.BacktestingDashboard }))
|
|
);
|
|
const ConfigDashboard = lazy(() =>
|
|
import('./pages/ConfigDashboard').then(m => ({ default: m.ConfigDashboard }))
|
|
);
|
|
|
|
function LoadingFallback() {
|
|
return (
|
|
<div style={{
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
height: '100%',
|
|
minHeight: '200px',
|
|
}}>
|
|
<div style={{
|
|
width: '36px',
|
|
height: '36px',
|
|
borderRadius: '50%',
|
|
border: '3px solid var(--color-border, #333)',
|
|
borderTopColor: 'var(--color-accent, #3b82f6)',
|
|
animation: 'spin 0.8s linear infinite',
|
|
}} />
|
|
<style>{`@keyframes spin { to { transform: rotate(360deg); } }`}</style>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const queryClient = new QueryClient({
|
|
defaultOptions: {
|
|
queries: {
|
|
staleTime: 10_000,
|
|
refetchInterval: 15_000,
|
|
refetchOnWindowFocus: false,
|
|
},
|
|
},
|
|
});
|
|
|
|
function App() {
|
|
return (
|
|
<ErrorBoundary>
|
|
<QueryClientProvider client={queryClient}>
|
|
<BrowserRouter>
|
|
<Routes>
|
|
<Route path="/login" element={<LoginPage />} />
|
|
<Route
|
|
path="/*"
|
|
element={
|
|
<ProtectedRoute>
|
|
<DashboardLayout>
|
|
<Suspense fallback={<LoadingFallback />}>
|
|
<Routes>
|
|
<Route path="/trading" element={<TradingDashboard />} />
|
|
<Route path="/risk" element={<RiskDashboard />} />
|
|
<Route path="/ml" element={<MLDashboard />} />
|
|
<Route path="/performance" element={<PerformanceDashboard />} />
|
|
<Route path="/backtest" element={<BacktestingDashboard />} />
|
|
<Route path="/config" element={<ConfigDashboard />} />
|
|
<Route path="*" element={<Navigate to="/trading" replace />} />
|
|
</Routes>
|
|
</Suspense>
|
|
</DashboardLayout>
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
</Routes>
|
|
</BrowserRouter>
|
|
</QueryClientProvider>
|
|
</ErrorBoundary>
|
|
);
|
|
}
|
|
|
|
export default App;
|