feat: add weather unit preferences
Some checks failed
CI / Lint, test, typecheck and build (push) Has been cancelled
Some checks failed
CI / Lint, test, typecheck and build (push) Has been cancelled
This commit is contained in:
@@ -11,13 +11,19 @@ import type {
|
||||
import { translate, type Language } from "@/lib/i18n";
|
||||
import { getProvinceFromTeryt, normalizeProvinceName } from "@/lib/provinces";
|
||||
import type { CurrentWeatherCondition } from "@/types/imgw-current";
|
||||
import type { TemperatureUnit, WindSpeedUnit } from "@/types/units";
|
||||
import type { DistanceUnit, PrecipitationUnit, PressureUnit, TemperatureUnit, WindSpeedUnit } from "@/types/units";
|
||||
|
||||
const locales: Record<Language, string> = { pl: "pl-PL", en: "en-GB" };
|
||||
export const DEFAULT_TEMPERATURE_UNIT: TemperatureUnit = "c";
|
||||
export const TEMPERATURE_UNITS: TemperatureUnit[] = ["c", "f"];
|
||||
export const DEFAULT_WIND_SPEED_UNIT: WindSpeedUnit = "kmh";
|
||||
export const WIND_SPEED_UNITS: WindSpeedUnit[] = ["ms", "kmh", "mph"];
|
||||
export const WIND_SPEED_UNITS: WindSpeedUnit[] = ["ms", "kmh", "mph", "kt", "bft"];
|
||||
export const DEFAULT_PRECIPITATION_UNIT: PrecipitationUnit = "mm";
|
||||
export const PRECIPITATION_UNITS: PrecipitationUnit[] = ["mm", "cm", "in"];
|
||||
export const DEFAULT_PRESSURE_UNIT: PressureUnit = "hpa";
|
||||
export const PRESSURE_UNITS: PressureUnit[] = ["hpa", "kpa", "inhg", "mmhg"];
|
||||
export const DEFAULT_DISTANCE_UNIT: DistanceUnit = "km";
|
||||
export const DISTANCE_UNITS: DistanceUnit[] = ["km", "mi"];
|
||||
|
||||
const temperatureUnitLabels: Record<TemperatureUnit, string> = {
|
||||
c: "°C",
|
||||
@@ -28,6 +34,26 @@ const windSpeedUnitLabels: Record<WindSpeedUnit, string> = {
|
||||
ms: "m/s",
|
||||
kmh: "km/h",
|
||||
mph: "mph",
|
||||
kt: "kt",
|
||||
bft: "Bft",
|
||||
};
|
||||
|
||||
const precipitationUnitLabels: Record<PrecipitationUnit, string> = {
|
||||
mm: "mm",
|
||||
cm: "cm",
|
||||
in: "in",
|
||||
};
|
||||
|
||||
const pressureUnitLabels: Record<PressureUnit, string> = {
|
||||
hpa: "hPa",
|
||||
kpa: "kPa",
|
||||
inhg: "inHg",
|
||||
mmhg: "mm Hg",
|
||||
};
|
||||
|
||||
const distanceUnitLabels: Record<DistanceUnit, string> = {
|
||||
km: "km",
|
||||
mi: "mi",
|
||||
};
|
||||
|
||||
export function toNumber(value: unknown): number | null {
|
||||
@@ -152,10 +178,6 @@ export function formatTemperature(
|
||||
: formatTemperatureValue(convertTemperature(value, unit), language, unit);
|
||||
}
|
||||
|
||||
export function formatPressure(value: number | null, language: Language = "pl") {
|
||||
return value === null ? translate(language, "common.noData") : `${value.toFixed(1)} hPa`;
|
||||
}
|
||||
|
||||
export function formatHumidity(value: number | null, language: Language = "pl") {
|
||||
return value === null ? translate(language, "common.noData") : `${Math.round(value)}%`;
|
||||
}
|
||||
@@ -168,18 +190,60 @@ export function getWindSpeedUnitLabel(unit: WindSpeedUnit) {
|
||||
return windSpeedUnitLabels[unit];
|
||||
}
|
||||
|
||||
export function isPrecipitationUnit(value: unknown): value is PrecipitationUnit {
|
||||
return typeof value === "string" && PRECIPITATION_UNITS.includes(value as PrecipitationUnit);
|
||||
}
|
||||
|
||||
export function getPrecipitationUnitLabel(unit: PrecipitationUnit) {
|
||||
return precipitationUnitLabels[unit];
|
||||
}
|
||||
|
||||
export function isPressureUnit(value: unknown): value is PressureUnit {
|
||||
return typeof value === "string" && PRESSURE_UNITS.includes(value as PressureUnit);
|
||||
}
|
||||
|
||||
export function getPressureUnitLabel(unit: PressureUnit) {
|
||||
return pressureUnitLabels[unit];
|
||||
}
|
||||
|
||||
export function isDistanceUnit(value: unknown): value is DistanceUnit {
|
||||
return typeof value === "string" && DISTANCE_UNITS.includes(value as DistanceUnit);
|
||||
}
|
||||
|
||||
export function getDistanceUnitLabel(unit: DistanceUnit) {
|
||||
return distanceUnitLabels[unit];
|
||||
}
|
||||
|
||||
export function convertWindSpeed(speed: number, unit: WindSpeedUnit) {
|
||||
if (unit === "kmh") return speed * 3.6;
|
||||
if (unit === "mph") return speed * 2.2369362921;
|
||||
if (unit === "kt") return speed * 1.9438444924;
|
||||
return speed;
|
||||
}
|
||||
|
||||
export function convertWindSpeedToBeaufort(speed: number) {
|
||||
if (speed < 0.3) return 0;
|
||||
if (speed < 1.6) return 1;
|
||||
if (speed < 3.4) return 2;
|
||||
if (speed < 5.5) return 3;
|
||||
if (speed < 8) return 4;
|
||||
if (speed < 10.8) return 5;
|
||||
if (speed < 13.9) return 6;
|
||||
if (speed < 17.2) return 7;
|
||||
if (speed < 20.8) return 8;
|
||||
if (speed < 24.5) return 9;
|
||||
if (speed < 28.5) return 10;
|
||||
if (speed < 32.7) return 11;
|
||||
return 12;
|
||||
}
|
||||
|
||||
export function formatWindSpeed(
|
||||
speed: number | null,
|
||||
language: Language = "pl",
|
||||
unit: WindSpeedUnit = DEFAULT_WIND_SPEED_UNIT,
|
||||
) {
|
||||
if (speed === null) return translate(language, "common.noData");
|
||||
if (unit === "bft") return `${convertWindSpeedToBeaufort(speed)} ${getWindSpeedUnitLabel(unit)}`;
|
||||
const convertedSpeed = convertWindSpeed(speed, unit);
|
||||
const digits = unit === "ms" ? 1 : 0;
|
||||
const formattedSpeed = new Intl.NumberFormat(locales[language], {
|
||||
@@ -200,8 +264,73 @@ export function formatWind(
|
||||
return `${formatWindSpeed(speed, language, unit)}${directionLabel}`;
|
||||
}
|
||||
|
||||
export function formatRainfall(value: number | null, language: Language = "pl") {
|
||||
return value === null ? translate(language, "common.noData") : `${value.toFixed(value < 1 ? 2 : 1)} mm`;
|
||||
export function formatRainfall(
|
||||
value: number | null,
|
||||
language: Language = "pl",
|
||||
unit: PrecipitationUnit = DEFAULT_PRECIPITATION_UNIT,
|
||||
) {
|
||||
return formatPrecipitation(value, language, unit);
|
||||
}
|
||||
|
||||
export function convertPrecipitation(value: number, unit: PrecipitationUnit) {
|
||||
if (unit === "cm") return value / 10;
|
||||
if (unit === "in") return value / 25.4;
|
||||
return value;
|
||||
}
|
||||
|
||||
export function formatPrecipitation(
|
||||
value: number | null,
|
||||
language: Language = "pl",
|
||||
unit: PrecipitationUnit = DEFAULT_PRECIPITATION_UNIT,
|
||||
) {
|
||||
if (value === null) return translate(language, "common.noData");
|
||||
const convertedValue = convertPrecipitation(value, unit);
|
||||
const digits = unit === "mm" ? (convertedValue < 1 ? 2 : 1) : unit === "cm" ? 2 : 2;
|
||||
const formattedValue = new Intl.NumberFormat(locales[language], {
|
||||
minimumFractionDigits: unit === "in" ? 2 : 0,
|
||||
maximumFractionDigits: digits,
|
||||
}).format(convertedValue);
|
||||
return `${formattedValue} ${getPrecipitationUnitLabel(unit)}`;
|
||||
}
|
||||
|
||||
export function convertPressure(value: number, unit: PressureUnit) {
|
||||
if (unit === "kpa") return value / 10;
|
||||
if (unit === "inhg") return value * 0.0295299830714;
|
||||
if (unit === "mmhg") return value * 0.750061683;
|
||||
return value;
|
||||
}
|
||||
|
||||
export function formatPressure(
|
||||
value: number | null,
|
||||
language: Language = "pl",
|
||||
unit: PressureUnit = DEFAULT_PRESSURE_UNIT,
|
||||
) {
|
||||
if (value === null) return translate(language, "common.noData");
|
||||
const convertedValue = convertPressure(value, unit);
|
||||
const digits = unit === "inhg" ? 2 : unit === "kpa" ? 1 : unit === "mmhg" ? 0 : 1;
|
||||
const formattedValue = new Intl.NumberFormat(locales[language], {
|
||||
minimumFractionDigits: unit === "inhg" ? 2 : 0,
|
||||
maximumFractionDigits: digits,
|
||||
}).format(convertedValue);
|
||||
return `${formattedValue} ${getPressureUnitLabel(unit)}`;
|
||||
}
|
||||
|
||||
export function convertDistance(value: number, unit: DistanceUnit) {
|
||||
if (unit === "mi") return value * 0.621371;
|
||||
return value;
|
||||
}
|
||||
|
||||
export function formatDistance(
|
||||
value: number | null,
|
||||
language: Language = "pl",
|
||||
unit: DistanceUnit = DEFAULT_DISTANCE_UNIT,
|
||||
) {
|
||||
if (value === null) return translate(language, "common.noData");
|
||||
const convertedValue = convertDistance(value, unit);
|
||||
const formattedValue = new Intl.NumberFormat(locales[language], {
|
||||
maximumFractionDigits: convertedValue < 10 ? 1 : 0,
|
||||
}).format(convertedValue);
|
||||
return `${formattedValue} ${getDistanceUnitLabel(unit)}`;
|
||||
}
|
||||
|
||||
export function formatWaterLevel(value: number | null, language: Language = "pl") {
|
||||
|
||||
Reference in New Issue
Block a user