"use client"; import { useEffect, useMemo, useState } from "react"; import { Bell, BellRing, Languages, MapPinned, Palette, Settings, Smartphone } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Card } from "@/components/ui/card"; import { LanguageToggle } from "@/components/ui/language-toggle"; import { ThemeToggle } from "@/components/ui/theme-toggle"; import { DEFAULT_STATION_ID } from "@/lib/constants"; import { useI18n } from "@/lib/i18n"; import { formatProvinceName, getProvinceForSelection, PROVINCES } from "@/lib/provinces"; import { useWeatherStore } from "@/lib/store"; import type { Province } from "@/types/province"; type NotificationSupportStatus = "checking" | "unsupported" | "needs-install" | "default" | "denied" | "granted"; function isStandaloneApp() { if (typeof window === "undefined") return false; const navigatorWithStandalone = window.navigator as Navigator & { standalone?: boolean }; return window.matchMedia("(display-mode: standalone)").matches || navigatorWithStandalone.standalone === true; } function getNotificationSupportStatus(): NotificationSupportStatus { if (typeof window === "undefined") return "checking"; if (!("Notification" in window) || !("serviceWorker" in navigator) || !("PushManager" in window)) return "unsupported"; if (!isStandaloneApp()) return "needs-install"; return Notification.permission; } function SettingsRow({ icon: Icon, title, description, children }: { icon: typeof Settings; title: string; description: string; children: React.ReactNode }) { return (

{title}

{description}

{children}
); } export function SettingsPage() { const { language, t } = useI18n(); const [notificationStatus, setNotificationStatus] = useState("checking"); const selectedStationId = useWeatherStore((state) => state.selectedStationId); const selectedLocation = useWeatherStore((state) => state.selectedLocation); const notificationsEnabled = useWeatherStore((state) => state.warningNotificationsEnabled); const provinceMode = useWeatherStore((state) => state.warningNotificationProvinceMode); const manualProvince = useWeatherStore((state) => state.warningNotificationProvince); const setNotificationsEnabled = useWeatherStore((state) => state.setWarningNotificationsEnabled); const setProvinceMode = useWeatherStore((state) => state.setWarningNotificationProvinceMode); const setManualProvince = useWeatherStore((state) => state.setWarningNotificationProvince); const selectedProvince = getProvinceForSelection(selectedLocation?.province, selectedStationId ?? DEFAULT_STATION_ID); const effectiveProvince = provinceMode === "manual" ? manualProvince : selectedProvince; const effectiveProvinceLabel = effectiveProvince ? formatProvinceName(effectiveProvince, language) : t("settings.notifications.noProvince"); useEffect(() => { const animationFrame = window.requestAnimationFrame(() => setNotificationStatus(getNotificationSupportStatus())); return () => window.cancelAnimationFrame(animationFrame); }, []); const notificationStatusLabel = useMemo(() => { switch (notificationStatus) { case "unsupported": return t("settings.notifications.statusUnsupported"); case "needs-install": return t("settings.notifications.statusNeedsInstall"); case "denied": return t("settings.notifications.statusDenied"); case "granted": return t("settings.notifications.statusGranted"); case "default": return t("settings.notifications.statusReady"); default: return t("settings.notifications.statusChecking"); } }, [notificationStatus, t]); const canRequestPermission = notificationStatus === "default"; const canEnablePreference = notificationStatus === "granted"; async function requestNotificationPermission() { if (!("Notification" in window)) { setNotificationStatus("unsupported"); return; } const permission = await Notification.requestPermission(); setNotificationStatus(permission); setNotificationsEnabled(permission === "granted"); } return (

{t("settings.section")}

{t("settings.title")}

{t("settings.description")}

IMGW

{t("settings.notifications.title")}

{t("settings.notifications.description")}

{t("settings.notifications.implementationNote")}

); }