feat: add live temperature threshold chart logic and components for runway monitoring
This commit is contained in:
@@ -444,7 +444,17 @@ export function LiveTemperatureThresholdChart({
|
||||
}, [row, chartHourly, tzOffset, chartLocalDate]);
|
||||
|
||||
const runwayPlates = useMemo(() => buildRunwayPlates(chartHourly?.amos, row, settlementObs), [chartHourly?.amos, row, settlementObs]);
|
||||
const hasRunwayData = runwayPlates.length > 0;
|
||||
const hasRunwaySeries = useMemo(
|
||||
() =>
|
||||
series.some(
|
||||
(item) =>
|
||||
item.key.startsWith("runway_") &&
|
||||
item.key !== "runway_max" &&
|
||||
item.values.some((value) => validNumber(value) !== null),
|
||||
),
|
||||
[series],
|
||||
);
|
||||
const hasRunwayData = runwayPlates.length > 0 || hasRunwaySeries;
|
||||
const settlementPlate = useMemo(() => runwayPlates.find((p) => p.isSettlement), [runwayPlates]);
|
||||
|
||||
const chartSeries = useMemo(() => {
|
||||
|
||||
+48
@@ -10,6 +10,7 @@ import {
|
||||
__mergePatchIntoHourlyForTest,
|
||||
__selectDisplayRunwayTempForTest,
|
||||
} from "@/components/dashboard/scan-terminal/LiveTemperatureThresholdChart";
|
||||
import { __buildTemperatureTooltipRowsForTest } from "@/components/dashboard/scan-terminal/TemperatureTooltipContent";
|
||||
|
||||
function assert(condition: unknown, message: string): asserts condition {
|
||||
if (!condition) throw new Error(message);
|
||||
@@ -369,6 +370,23 @@ export function runTests() {
|
||||
!englishSettlement?.label.includes("结算跑道"),
|
||||
`${city} English settlement runway label should not leak Chinese`,
|
||||
);
|
||||
const englishRunwayPoint = englishChart.data.find(
|
||||
(point: any) => point[runwayKey(settlementRwy)] !== null && point[runwayKey(settlementRwy)] !== undefined,
|
||||
);
|
||||
const tooltipRows = __buildTemperatureTooltipRowsForTest(
|
||||
englishRunwayPoint as any,
|
||||
englishChart.data,
|
||||
englishChart.series,
|
||||
);
|
||||
const tooltipRunway = tooltipRows.find((item) => item.key === runwayKey(settlementRwy));
|
||||
assert(
|
||||
tooltipRunway?.label.includes("Settlement Runway"),
|
||||
`${city} English tooltip runway label should be translated`,
|
||||
);
|
||||
assert(
|
||||
!tooltipRunway?.label.includes("结算跑道"),
|
||||
`${city} English tooltip runway label should not leak Chinese`,
|
||||
);
|
||||
});
|
||||
|
||||
const shenzhen = __buildTemperatureChartDataForTest(
|
||||
@@ -785,6 +803,36 @@ export function runTests() {
|
||||
"live aggregate temp should not override runway-history current temp when runway data is rendered",
|
||||
);
|
||||
|
||||
const wuhanRunwayMetrics = __getObservationDisplayMetricsForTest(
|
||||
{
|
||||
city: "wuhan",
|
||||
local_date: "2026-05-27",
|
||||
local_time: "13:54",
|
||||
tz_offset_seconds: 8 * 60 * 60,
|
||||
current_temp: 25.0,
|
||||
temp_symbol: "°C",
|
||||
} as any,
|
||||
{
|
||||
localTime: "13:54",
|
||||
times: ["00:00", "12:00", "18:00", "23:00"],
|
||||
temps: [22.0, 30.0, 29.0, 25.0],
|
||||
runwayPlateHistory: {
|
||||
"04/22": [
|
||||
{ time: "13:52", temp: 28.6 },
|
||||
{ time: "13:54", temp: 28.8 },
|
||||
],
|
||||
},
|
||||
} as any,
|
||||
);
|
||||
assert(
|
||||
wuhanRunwayMetrics.currentRunwayTemp === 28.8,
|
||||
"runway header metrics should use the latest settlement runway history point",
|
||||
);
|
||||
assert(
|
||||
__selectDisplayRunwayTempForTest(25.0, wuhanRunwayMetrics.currentRunwayTemp, false) === 28.8,
|
||||
"runway header should prefer runway-history current temp even when the latest detail payload lacks runway_obs snapshot",
|
||||
);
|
||||
|
||||
const newYorkMetrics = __getObservationDisplayMetricsForTest(
|
||||
{
|
||||
city: "new york",
|
||||
|
||||
@@ -713,12 +713,10 @@ function getObservationDisplayMetrics(
|
||||
function selectDisplayRunwayTemp(
|
||||
liveTemp: number | null,
|
||||
currentRunwayTemp: number | null,
|
||||
hasRunwayData: boolean,
|
||||
_hasRunwayData: boolean,
|
||||
) {
|
||||
if (hasRunwayData && currentRunwayTemp !== null) {
|
||||
return currentRunwayTemp;
|
||||
}
|
||||
return liveTemp ?? currentRunwayTemp;
|
||||
if (currentRunwayTemp !== null) return currentRunwayTemp;
|
||||
return liveTemp;
|
||||
}
|
||||
|
||||
function isSettlementRunway(row: ScanOpportunityRow | null, rwy: string) {
|
||||
|
||||
Reference in New Issue
Block a user