feat: instrument analysis
This commit is contained in:
@@ -100,7 +100,7 @@ function KeepAlivePage({ path, component: Component }: { path: string; component
|
||||
|
||||
// Registers the instrument tab on navigation (renders nothing itself)
|
||||
function InstrumentRoute() {
|
||||
const { id = 'EURUSD' } = useParams<{ id: string }>()
|
||||
const { id = localStorage.getItem('last_instrument') || 'EURUSD' } = useParams<{ id: string }>()
|
||||
const { openInstrument } = useTabs()
|
||||
useEffect(() => { openInstrument(id.toUpperCase()) }, [id, openInstrument])
|
||||
return null
|
||||
@@ -112,7 +112,7 @@ function InstrumentKeepAlive({ id }: { id: string }) {
|
||||
const isActive = location.pathname.toLowerCase() === `/instruments/${id.toLowerCase()}`
|
||||
return (
|
||||
<div className={isActive ? 'flex-1 min-h-0 overflow-y-auto' : 'hidden'}>
|
||||
<InstrumentDashboard instrumentIdProp={id} />
|
||||
<InstrumentDashboard instrumentIdProp={id} isVisible={isActive} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -129,7 +129,7 @@ function NormalRoutes() {
|
||||
return (
|
||||
<div className={isInstrument ? 'hidden' : 'flex-1 overflow-auto'}>
|
||||
<Routes>
|
||||
<Route path="/instruments" element={<Navigate to="/instruments/EURUSD" replace />} />
|
||||
<Route path="/instruments" element={<Navigate to={`/instruments/${localStorage.getItem('last_instrument') || 'EURUSD'}`} replace />} />
|
||||
<Route path="/instruments/:id" element={<InstrumentRoute />} />
|
||||
{/* Legacy redirects */}
|
||||
<Route path="/impact" element={<Navigate to="/market-events" replace />} />
|
||||
|
||||
@@ -28,8 +28,10 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
||||
const forgetRoute = useCallback((r: string) =>
|
||||
setKept(p => { const n = new Set(p); n.delete(r); return n }), [])
|
||||
|
||||
const openInstrument = useCallback((id: string) =>
|
||||
setInstrumentIds(p => p.includes(id) ? p : [...p, id]), [])
|
||||
const openInstrument = useCallback((id: string) => {
|
||||
localStorage.setItem('last_instrument', id)
|
||||
setInstrumentIds(p => p.includes(id) ? p : [...p, id])
|
||||
}, [])
|
||||
|
||||
const closeInstrument = useCallback((id: string) =>
|
||||
setInstrumentIds(p => p.filter(x => x !== id)), [])
|
||||
|
||||
@@ -1205,8 +1205,8 @@ const PERIODS = [
|
||||
{ key: '5y', label: '5Y' },
|
||||
]
|
||||
|
||||
export default function InstrumentDashboard({ instrumentIdProp }: { instrumentIdProp?: string } = {}) {
|
||||
const { id: paramId = 'EURUSD' } = useParams<{ id: string }>()
|
||||
export default function InstrumentDashboard({ instrumentIdProp, isVisible }: { instrumentIdProp?: string; isVisible?: boolean } = {}) {
|
||||
const { id: paramId = localStorage.getItem('last_instrument') || 'EURUSD' } = useParams<{ id: string }>()
|
||||
const navigate = useNavigate()
|
||||
const [period, setPeriod] = useState('1y')
|
||||
const [chartStyle, setChartStyle] = useState<'candles' | 'line'>('candles')
|
||||
@@ -1237,6 +1237,14 @@ export default function InstrumentDashboard({ instrumentIdProp }: { instrumentId
|
||||
api.get('/causal-lab/templates').then(r => setTemplates(r.data)).catch(() => {})
|
||||
}, [])
|
||||
|
||||
// Silent refresh when the tab becomes visible again (e.g. after analysis updated from MarketEvents)
|
||||
const mountedRef = useRef(false)
|
||||
useEffect(() => {
|
||||
if (!mountedRef.current) { mountedRef.current = true; return }
|
||||
if (isVisible) fetchSnapshotSilent()
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isVisible])
|
||||
|
||||
const fetchSnapshot = useCallback(() => {
|
||||
setLoading(true)
|
||||
api.get(`/instruments/${instrumentId}/snapshot?period=${period}`)
|
||||
|
||||
Reference in New Issue
Block a user