feat: add temperature unit preference

This commit is contained in:
zv
2026-06-13 21:05:01 +02:00
parent 66ead03f49
commit cb113714f9
24 changed files with 150 additions and 51 deletions

View File

@@ -5,8 +5,8 @@ import type { HourlyForecast, WeatherForecast } from "@/types/forecast";
import type { WeatherWarning } from "@/types/imgw";
import type { Province } from "@/types/province";
import { warningMatchesCounty } from "@/lib/warning-regions";
import { DEFAULT_WIND_SPEED_UNIT, formatWindSpeed } from "@/lib/weather-utils";
import type { WindSpeedUnit } from "@/types/units";
import { DEFAULT_TEMPERATURE_UNIT, DEFAULT_WIND_SPEED_UNIT, formatTemperature as formatDisplayTemperature, formatWindSpeed } from "@/lib/weather-utils";
import type { TemperatureUnit, WindSpeedUnit } from "@/types/units";
export type WeatherBriefSeverity = "normal" | "attention" | "warning";
@@ -26,6 +26,7 @@ interface BuildWeatherBriefInput {
countyTeryt?: string | null;
locationName: string;
language: Language;
temperatureUnit?: TemperatureUnit;
windSpeedUnit?: WindSpeedUnit;
now?: Date;
}
@@ -36,10 +37,6 @@ function formatNumber(value: number, language: Language, digits = 0) {
}).format(value);
}
function formatTemperature(value: number, language: Language) {
return `${formatNumber(value, language)}°C`;
}
function formatRainfall(value: number, language: Language) {
return `${formatNumber(value, language, 1)} mm`;
}
@@ -202,7 +199,7 @@ function getTomorrowCondition(hours: HourlyForecast[], rainfallTotal: number | n
return language === "pl" ? "bez istotnych opadów" : "no significant precipitation";
}
export function buildWeatherBrief({ forecast, warnings, province, countyTeryt, locationName, language, windSpeedUnit = DEFAULT_WIND_SPEED_UNIT, now = new Date() }: BuildWeatherBriefInput): WeatherBrief | null {
export function buildWeatherBrief({ forecast, warnings, province, countyTeryt, locationName, language, temperatureUnit = DEFAULT_TEMPERATURE_UNIT, windSpeedUnit = DEFAULT_WIND_SPEED_UNIT, now = new Date() }: BuildWeatherBriefInput): WeatherBrief | null {
const hours = getUpcomingHours(forecast.hourly, now, 24);
if (!hours.length) return null;
@@ -218,7 +215,7 @@ export function buildWeatherBrief({ forecast, warnings, province, countyTeryt, l
const rainPeakHour = getPeakHour(hours, (hour) => hour.precipitationProbability);
const conditionPeakHour = hours.find((hour) => hour.weatherCode !== null) ?? null;
const temperatureRange = minimumTemperature !== null && maximumTemperature !== null
? `${formatTemperature(minimumTemperature, language)}-${formatTemperature(maximumTemperature, language)}`
? `${formatDisplayTemperature(minimumTemperature, language, temperatureUnit)}-${formatDisplayTemperature(maximumTemperature, language, temperatureUnit)}`
: null;
const hasRainSignal = (maximumProbability ?? 0) >= 35 || (rainfallTotal ?? 0) >= 0.5;
const hasWindSignal = (maximumWind ?? 0) >= 8;
@@ -295,7 +292,7 @@ export function buildWeatherBrief({ forecast, warnings, province, countyTeryt, l
};
}
export function buildTomorrowWeatherBrief({ forecast, warnings, province, countyTeryt, locationName, language, windSpeedUnit = DEFAULT_WIND_SPEED_UNIT, now = new Date() }: BuildWeatherBriefInput): WeatherBrief | null {
export function buildTomorrowWeatherBrief({ forecast, warnings, province, countyTeryt, locationName, language, temperatureUnit = DEFAULT_TEMPERATURE_UNIT, windSpeedUnit = DEFAULT_WIND_SPEED_UNIT, now = new Date() }: BuildWeatherBriefInput): WeatherBrief | null {
const targetDateKey = getWarsawDateKey(now, 1);
const hours = getForecastHoursForDate(forecast.hourly, targetDateKey);
if (!hours.length) return null;
@@ -318,7 +315,7 @@ export function buildTomorrowWeatherBrief({ forecast, warnings, province, county
const hasWindSignal = (maximumWind ?? 0) >= 8;
const condition = getTomorrowCondition(hours, rainfallTotal, maximumProbability, language);
const temperatureRange = minimumTemperature !== null && maximumTemperature !== null
? `${formatTemperature(minimumTemperature, language)} / ${formatTemperature(maximumTemperature, language)}`
? `${formatDisplayTemperature(minimumTemperature, language, temperatureUnit)} / ${formatDisplayTemperature(maximumTemperature, language, temperatureUnit)}`
: null;
const severity: WeatherBriefSeverity = topWarning || hasThunderstorm ? "warning" : hasRainSignal || hasWindSignal ? "attention" : "normal";
const provinceLabel = province ? formatProvinceName(province, language) : null;