diff --git a/frontend/components/dashboard/scan-terminal/LiveTemperatureThresholdChart.tsx b/frontend/components/dashboard/scan-terminal/LiveTemperatureThresholdChart.tsx index c7aa24de..27d1e643 100644 --- a/frontend/components/dashboard/scan-terminal/LiveTemperatureThresholdChart.tsx +++ b/frontend/components/dashboard/scan-terminal/LiveTemperatureThresholdChart.tsx @@ -1117,6 +1117,7 @@ export function LiveTemperatureThresholdChart({ const city = String(row?.city || "").toLowerCase().trim(); const [timeframe, setTimeframe] = useState<"1D" | "3D">("1D"); const [userToggledKeys, setUserToggledKeys] = useState>({}); + const [liveTemp, setLiveTemp] = useState(null); useEffect(() => { setUserToggledKeys({}); @@ -1167,6 +1168,24 @@ export function LiveTemperatureThresholdChart({ }; }, [city, row, isActive, slotIndex]); + // ── 60s lightweight live-temp poll ── + useEffect(() => { + if (!city) return; + const fetchLiveTemp = () => { + fetch(`/api/city/${encodeURIComponent(city)}/summary`) + .then((res) => (res.ok ? res.json() : null)) + .then((payload) => { + if (!payload) return; + const temp = validNumber(payload?.current?.temp); + if (temp !== null) setLiveTemp(temp); + }) + .catch(() => {}); + }; + fetchLiveTemp(); + const id = setInterval(fetchLiveTemp, 60_000); + return () => clearInterval(id); + }, [city]); + const { data, series } = useMemo(() => { if (timeframe === "3D") { return build3DayChartData(row, hourly); @@ -1247,6 +1266,7 @@ export function LiveTemperatureThresholdChart({ () => getObservationDisplayMetrics(row, hourly, settlementPlate), [row, hourly, settlementPlate], ); + const displayRunwayTemp = liveTemp ?? currentRunwayTemp; const wundergroundDailyHigh = validNumber(hourly?.airportCurrent?.max_so_far ?? hourly?.airportPrimary?.max_so_far) ?? null; const modelValues = Object.values(row?.model_cluster_sources || {}) @@ -1412,7 +1432,7 @@ export function LiveTemperatureThresholdChart({
{isEn ? "Runway" : runwayHeaderLabel}:{" "} - {temp(currentRunwayTemp)} + {temp(displayRunwayTemp)} | @@ -1454,7 +1474,7 @@ export function LiveTemperatureThresholdChart({ {isEn ? "Runway Live (1m)" : `${runwayHeaderLabel}`} - {temp(currentRunwayTemp)} + {temp(displayRunwayTemp)}
diff --git a/frontend/components/dashboard/scan-terminal/__tests__/refreshCadencePolicy.test.ts b/frontend/components/dashboard/scan-terminal/__tests__/refreshCadencePolicy.test.ts index c39f5fe4..861f0308 100644 --- a/frontend/components/dashboard/scan-terminal/__tests__/refreshCadencePolicy.test.ts +++ b/frontend/components/dashboard/scan-terminal/__tests__/refreshCadencePolicy.test.ts @@ -34,10 +34,13 @@ export function runTests() { ); assert( chartSource.includes("DASHBOARD_REFRESH_POLICY_MS.metar") && - !chartSource.includes("setInterval(") && !chartSource.includes("window.setInterval"), "selected city detail chart cache should align with 5-minute scan/metar cadence", ); + assert( + chartSource.includes("setInterval(fetchLiveTemp, 60_000)"), + "selected city chart should poll live temperature every 60 seconds via lightweight summary endpoint", + ); assert( chartSource.includes("_hourlyRequestCache") && chartSource.includes("seedHourlyForecastFromRow") &&