feat: cockpit
This commit is contained in:
@@ -146,7 +146,15 @@ export const useAddWatchlistInstrument = () => {
|
||||
export const useInstrumentCatalogIds = () =>
|
||||
useQuery({
|
||||
queryKey: ['instrument-analysis-catalog'],
|
||||
queryFn: () => api.get('/instruments/').then(r => new Set((r.data ?? []).map((i: any) => String(i.id).toUpperCase()))),
|
||||
// No trailing slash: the backend route is registered at "/api/instruments" exactly
|
||||
// (router.get("")) — a trailing slash still resolves via FastAPI's redirect_slashes,
|
||||
// but calling the exact path avoids depending on that 307 round-trip surviving the
|
||||
// nginx proxy_pass unchanged.
|
||||
queryFn: () => api.get('/instruments').then(r => {
|
||||
const ids = new Set<string>((r.data ?? []).map((i: any) => String(i.id).toUpperCase()))
|
||||
console.debug('[useInstrumentCatalogIds] loaded', ids.size, 'catalog ids:', Array.from(ids))
|
||||
return ids
|
||||
}),
|
||||
staleTime: 10 * 60_000,
|
||||
})
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useMemo, useState, useRef, useLayoutEffect } from 'react'
|
||||
import { useMemo, useState, useRef, useLayoutEffect, useEffect } from 'react'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import {
|
||||
useGeoRiskScore, useAllQuotes,
|
||||
@@ -132,7 +132,7 @@ export default function Dashboard() {
|
||||
const { data: geoNews } = useGeoNews()
|
||||
const { data: watchlistItems } = useInstrumentsWatchlist()
|
||||
const { data: watchlistQuotesData } = useInstrumentsWatchlistQuotes()
|
||||
const { data: instrumentCatalogIds } = useInstrumentCatalogIds()
|
||||
const { data: instrumentCatalogIds, isError: instrumentCatalogError, error: instrumentCatalogErrorObj } = useInstrumentCatalogIds()
|
||||
const [ecoImpactFilter, setEcoImpactFilter] = useState<Set<string>>(new Set(['high', 'medium', 'low']))
|
||||
const [ecoCurrencyFilter, setEcoCurrencyFilter] = useState<Set<string>>(new Set(ECO_CURRENCY_FILTERS))
|
||||
const [ecoShowNextWeek, setEcoShowNextWeek] = useState(false)
|
||||
@@ -145,6 +145,24 @@ export default function Dashboard() {
|
||||
const { data: waveletSignalsData } = useWaveletWatchlistSignals()
|
||||
const { data: saxoIvWatchlistData } = useSaxoIvWatchlist()
|
||||
|
||||
// Diagnostic for the Watchlist card's "open in Instrument Analysis" arrow/double-click:
|
||||
// logs whether the catalog query succeeded and how each watchlist ticker resolves
|
||||
// against it, so a missing arrow can be traced to "catalog query failed" vs. "ticker
|
||||
// genuinely isn't registered in instruments.json" without needing a debugger.
|
||||
useEffect(() => {
|
||||
if (instrumentCatalogError) {
|
||||
console.error('[Watchlist] instrument catalog query failed:', instrumentCatalogErrorObj)
|
||||
return
|
||||
}
|
||||
if (!instrumentCatalogIds || !watchlistQuotesData) return
|
||||
const items: any[] = (watchlistQuotesData as any)?.items ?? []
|
||||
console.debug('[Watchlist] catalog ids:', Array.from(instrumentCatalogIds as Set<string>))
|
||||
console.debug('[Watchlist] ticker -> catalogId resolution:', items.map((it: any) => ({
|
||||
ticker: it.ticker,
|
||||
resolved: resolveCatalogId(it.ticker, instrumentCatalogIds as Set<string>) ?? null,
|
||||
})))
|
||||
}, [instrumentCatalogIds, instrumentCatalogError, instrumentCatalogErrorObj, watchlistQuotesData])
|
||||
|
||||
// Historical PnL curve (realized, from closed portfolio positions) + latest VaR snapshot
|
||||
const { data: pnlHistoryData } = usePnlHistory()
|
||||
const { data: latestVarData } = useQuery({
|
||||
|
||||
Reference in New Issue
Block a user