ecbba9160d
The intraday chart data builder lived inside dashboard-utils with observation-source and TAF helpers, so chart consumers had to depend on the large dashboard utility surface. This moves chart data preparation, observation-source helpers, and TAF marker labels into focused modules while keeping dashboard-utils re-export compatibility. Constraint: Preserve existing chart data shape, observation labels, TAF labels, and legacy dashboard-utils exports. Rejected: Rewrite chart data generation while moving it | this pass is a boundary move only so visual behavior remains stable. Confidence: high Scope-risk: moderate Reversibility: clean Tested: TypeScript diagnostics for chart-utils, dashboard-utils, observation-source-utils, and taf-utils Tested: npm run build Not-tested: Browser visual regression across every chart city.
75 lines
2.1 KiB
TypeScript
75 lines
2.1 KiB
TypeScript
import type { CityDetail } from "@/lib/dashboard-types";
|
|
import { normalizeObservationSourceLabel } from "@/lib/source-labels";
|
|
|
|
export function isTurkishMgmCity(detail: CityDetail) {
|
|
const city = String(detail.name || detail.display_name || "")
|
|
.trim()
|
|
.toLowerCase();
|
|
return city === "ankara" || city === "istanbul";
|
|
}
|
|
|
|
export function getObservationSourceCode(detail: CityDetail): string {
|
|
const source = String(detail.current?.settlement_source || "")
|
|
.trim()
|
|
.toLowerCase();
|
|
if (source) return source;
|
|
|
|
const city = String(detail.name || detail.display_name || "")
|
|
.trim()
|
|
.toLowerCase();
|
|
if (
|
|
city === "hong kong" ||
|
|
city === "shek kong" ||
|
|
city === "lau fau shan"
|
|
) {
|
|
return "hko";
|
|
}
|
|
if (city === "taipei") return "noaa";
|
|
return "metar";
|
|
}
|
|
|
|
export function getObservationSourceTag(detail: CityDetail): string {
|
|
const label = normalizeObservationSourceLabel(
|
|
detail.current?.settlement_source_label,
|
|
"",
|
|
)
|
|
.trim()
|
|
.toUpperCase();
|
|
if (label) return label;
|
|
const code = getObservationSourceCode(detail);
|
|
if (code === "hko") return "HKO";
|
|
if (code === "cwa") return "CWA";
|
|
if (code === "noaa") return "NOAA";
|
|
if (code === "wunderground") {
|
|
const icao = String(detail.risk?.icao || detail.current?.station_code || "")
|
|
.trim()
|
|
.toUpperCase();
|
|
return icao ? `${icao} METAR` : "METAR";
|
|
}
|
|
if (code === "mgm") return "MGM";
|
|
return "METAR";
|
|
}
|
|
|
|
export function getRealtimeObservationTag(detail: CityDetail): string {
|
|
const code = getObservationSourceCode(detail);
|
|
if (code === "wunderground") {
|
|
const icao = String(detail.risk?.icao || "").trim().toUpperCase();
|
|
return icao ? `${icao} METAR` : "METAR";
|
|
}
|
|
return getObservationSourceTag(detail);
|
|
}
|
|
|
|
export function getNoaaStationCode(detail: CityDetail): string {
|
|
return String(detail.current?.station_code || detail.risk?.icao || "NOAA")
|
|
.trim()
|
|
.toUpperCase();
|
|
}
|
|
|
|
export function getNoaaStationName(detail: CityDetail): string {
|
|
return (
|
|
String(detail.current?.station_name || "").trim() ||
|
|
String(detail.risk?.airport || "").trim() ||
|
|
getNoaaStationCode(detail)
|
|
);
|
|
}
|