feat: add temperature unit preference
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { Bell, BellRing, Clock3, Languages, MapPinned, Palette, Settings, Smartphone, Wind } from "lucide-react";
|
||||
import { Bell, BellRing, Clock3, Languages, MapPinned, Palette, Settings, Smartphone, Thermometer, Wind } from "lucide-react";
|
||||
import type { LucideIcon } from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card } from "@/components/ui/card";
|
||||
@@ -15,9 +15,9 @@ import { locateSynopStations } from "@/lib/location-utils";
|
||||
import { decodeBase64UrlKey, deletePushSubscription, fetchVapidPublicKey, savePushSubscription, sendTestPushNotification } from "@/lib/notification-api";
|
||||
import { formatProvinceName, getProvinceForSelection, PROVINCES } from "@/lib/provinces";
|
||||
import { useWeatherStore } from "@/lib/store";
|
||||
import { WIND_SPEED_UNITS } from "@/lib/weather-utils";
|
||||
import { TEMPERATURE_UNITS, WIND_SPEED_UNITS } from "@/lib/weather-utils";
|
||||
import type { Province } from "@/types/province";
|
||||
import type { WindSpeedUnit } from "@/types/units";
|
||||
import type { TemperatureUnit, WindSpeedUnit } from "@/types/units";
|
||||
|
||||
type NotificationSupportStatus = "checking" | "unconfigured" | "unsupported" | "needs-install" | "default" | "denied" | "granted";
|
||||
|
||||
@@ -108,6 +108,11 @@ const windSpeedUnitKeys: Record<WindSpeedUnit, "settings.units.wind.ms" | "setti
|
||||
mph: "settings.units.wind.mph",
|
||||
};
|
||||
|
||||
const temperatureUnitKeys: Record<TemperatureUnit, "settings.units.temperature.c" | "settings.units.temperature.f"> = {
|
||||
c: "settings.units.temperature.c",
|
||||
f: "settings.units.temperature.f",
|
||||
};
|
||||
|
||||
export function SettingsPage() {
|
||||
const { language, t } = useI18n();
|
||||
const [notificationStatus, setNotificationStatus] = useState<NotificationSupportStatus>("checking");
|
||||
@@ -124,12 +129,14 @@ export function SettingsPage() {
|
||||
const tomorrowBriefEnabled = useWeatherStore((state) => state.tomorrowBriefNotificationsEnabled);
|
||||
const provinceMode = useWeatherStore((state) => state.warningNotificationProvinceMode);
|
||||
const manualProvince = useWeatherStore((state) => state.warningNotificationProvince);
|
||||
const temperatureUnit = useWeatherStore((state) => state.temperatureUnit);
|
||||
const windSpeedUnit = useWeatherStore((state) => state.windSpeedUnit);
|
||||
const setNotificationsEnabled = useWeatherStore((state) => state.setWarningNotificationsEnabled);
|
||||
const setMorningBriefEnabled = useWeatherStore((state) => state.setMorningBriefNotificationsEnabled);
|
||||
const setTomorrowBriefEnabled = useWeatherStore((state) => state.setTomorrowBriefNotificationsEnabled);
|
||||
const setProvinceMode = useWeatherStore((state) => state.setWarningNotificationProvinceMode);
|
||||
const setManualProvince = useWeatherStore((state) => state.setWarningNotificationProvince);
|
||||
const setTemperatureUnit = useWeatherStore((state) => state.setTemperatureUnit);
|
||||
const setWindSpeedUnit = useWeatherStore((state) => state.setWindSpeedUnit);
|
||||
|
||||
const selectedStation = stations?.find((station) => station.id === selectedStationId)
|
||||
@@ -180,6 +187,7 @@ export function SettingsPage() {
|
||||
longitude: notificationLongitude,
|
||||
locationName: notificationLocationName,
|
||||
countyTeryt: notificationCountyTeryt,
|
||||
temperatureUnit,
|
||||
windSpeedUnit,
|
||||
}).catch(() => undefined);
|
||||
}
|
||||
@@ -188,7 +196,7 @@ export function SettingsPage() {
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [effectiveProvince, language, morningBriefEnabled, notificationCountyTeryt, notificationLatitude, notificationLocationName, notificationLongitude, notificationStatus, notificationsEnabled, tomorrowBriefEnabled, vapidPublicKey, windSpeedUnit]);
|
||||
}, [effectiveProvince, language, morningBriefEnabled, notificationCountyTeryt, notificationLatitude, notificationLocationName, notificationLongitude, notificationStatus, notificationsEnabled, temperatureUnit, tomorrowBriefEnabled, vapidPublicKey, windSpeedUnit]);
|
||||
|
||||
const notificationStatusLabel = useMemo(() => {
|
||||
switch (notificationStatus) {
|
||||
@@ -247,6 +255,7 @@ export function SettingsPage() {
|
||||
longitude: notificationLongitude,
|
||||
locationName: notificationLocationName,
|
||||
countyTeryt: notificationCountyTeryt,
|
||||
temperatureUnit,
|
||||
windSpeedUnit,
|
||||
});
|
||||
setNotificationsEnabled(true);
|
||||
@@ -310,6 +319,7 @@ export function SettingsPage() {
|
||||
longitude: notificationLongitude,
|
||||
locationName: notificationLocationName,
|
||||
countyTeryt: notificationCountyTeryt,
|
||||
temperatureUnit,
|
||||
windSpeedUnit,
|
||||
});
|
||||
} catch {
|
||||
@@ -331,6 +341,7 @@ export function SettingsPage() {
|
||||
longitude: notificationLongitude,
|
||||
locationName: notificationLocationName,
|
||||
countyTeryt: notificationCountyTeryt,
|
||||
temperatureUnit,
|
||||
windSpeedUnit,
|
||||
});
|
||||
} catch {
|
||||
@@ -353,6 +364,26 @@ export function SettingsPage() {
|
||||
<SettingsRow icon={Palette} title={t("settings.theme.title")} description={t("settings.theme.description")}>
|
||||
<ThemeToggle />
|
||||
</SettingsRow>
|
||||
<SettingsRow icon={Thermometer} title={t("settings.units.temperature.title")} description={t("settings.units.temperature.description")}>
|
||||
<div className="surface-control inline-flex rounded-full p-1" role="radiogroup" aria-label={t("settings.units.temperature.label")}>
|
||||
{TEMPERATURE_UNITS.map((unit) => (
|
||||
<button
|
||||
key={unit}
|
||||
type="button"
|
||||
role="radio"
|
||||
aria-checked={temperatureUnit === unit}
|
||||
className={`min-w-14 rounded-full border px-3.5 py-1.5 text-sm font-medium transition-colors focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent ${
|
||||
temperatureUnit === unit
|
||||
? "border-accent/45 bg-accent/10 text-accent shadow-soft"
|
||||
: "border-transparent text-muted hover:bg-surface-muted/70 hover:text-foreground"
|
||||
}`}
|
||||
onClick={() => setTemperatureUnit(unit)}
|
||||
>
|
||||
{t(temperatureUnitKeys[unit])}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</SettingsRow>
|
||||
<SettingsRow icon={Wind} title={t("settings.units.wind.title")} description={t("settings.units.wind.description")}>
|
||||
<div className="surface-control inline-flex rounded-full p-1" role="radiogroup" aria-label={t("settings.units.wind.label")}>
|
||||
{WIND_SPEED_UNITS.map((unit) => (
|
||||
|
||||
Reference in New Issue
Block a user