Files
wtr/lib/store.ts
zv ee55521803
All checks were successful
CI / Lint, typecheck and build (push) Successful in 9m56s
chore: add prettier formatting
2026-06-14 20:26:56 +02:00

127 lines
5.5 KiB
TypeScript

"use client";
import { create } from "zustand";
import { persist } from "zustand/middleware";
import type { SelectedLocation } from "@/types/location";
import type { Province } from "@/types/province";
import type { TemperatureUnit, WindSpeedUnit } from "@/types/units";
import {
DEFAULT_APP_SECTION_VISIBILITY,
normalizeAppSectionVisibility,
type AppSectionId,
type AppSectionVisibility,
} from "@/lib/app-sections";
import {
DEFAULT_DASHBOARD_SECTION_VISIBILITY,
normalizeDashboardSectionVisibility,
type DashboardSectionId,
type DashboardSectionVisibility,
} from "@/lib/dashboard-sections";
import { DEFAULT_TEMPERATURE_UNIT, DEFAULT_WIND_SPEED_UNIT } from "@/lib/weather-utils";
import type { WeatherRegion } from "@/types/weather-region";
import { getWeatherRegionForCountryCode } from "@/types/weather-region";
type NotificationProvinceMode = "selected" | "manual";
interface WeatherStore {
favorites: string[];
selectedStationId: string | null;
selectedLocation: SelectedLocation | null;
warningNotificationsEnabled: boolean;
morningBriefNotificationsEnabled: boolean;
tomorrowBriefNotificationsEnabled: boolean;
warningNotificationProvinceMode: NotificationProvinceMode;
warningNotificationProvince: Province | null;
temperatureUnit: TemperatureUnit;
windSpeedUnit: WindSpeedUnit;
dashboardSections: DashboardSectionVisibility;
appSections: AppSectionVisibility;
toggleFavorite: (id: string) => void;
selectStation: (id: string) => void;
selectLocation: (location: SelectedLocation) => void;
setWarningNotificationsEnabled: (enabled: boolean) => void;
setMorningBriefNotificationsEnabled: (enabled: boolean) => void;
setTomorrowBriefNotificationsEnabled: (enabled: boolean) => void;
setWarningNotificationProvinceMode: (mode: NotificationProvinceMode) => void;
setWarningNotificationProvince: (province: Province | null) => void;
setTemperatureUnit: (unit: TemperatureUnit) => void;
setWindSpeedUnit: (unit: WindSpeedUnit) => void;
setDashboardSectionVisible: (section: DashboardSectionId, visible: boolean) => void;
setAppSectionVisible: (section: AppSectionId, visible: boolean) => void;
}
export const useWeatherStore = create<WeatherStore>()(
persist(
(set) => ({
favorites: [],
selectedStationId: null,
selectedLocation: null,
warningNotificationsEnabled: false,
morningBriefNotificationsEnabled: false,
tomorrowBriefNotificationsEnabled: false,
warningNotificationProvinceMode: "selected",
warningNotificationProvince: null,
temperatureUnit: DEFAULT_TEMPERATURE_UNIT,
windSpeedUnit: DEFAULT_WIND_SPEED_UNIT,
dashboardSections: DEFAULT_DASHBOARD_SECTION_VISIBILITY,
appSections: DEFAULT_APP_SECTION_VISIBILITY,
toggleFavorite: (id) =>
set((state) => ({
favorites: state.favorites.includes(id)
? state.favorites.filter((favoriteId) => favoriteId !== id)
: [...state.favorites, id],
})),
selectStation: (id) => set({ selectedStationId: id, selectedLocation: null }),
selectLocation: (location) => set({ selectedStationId: location.stationId, selectedLocation: location }),
setWarningNotificationsEnabled: (enabled) => set({ warningNotificationsEnabled: enabled }),
setMorningBriefNotificationsEnabled: (enabled) => set({ morningBriefNotificationsEnabled: enabled }),
setTomorrowBriefNotificationsEnabled: (enabled) => set({ tomorrowBriefNotificationsEnabled: enabled }),
setWarningNotificationProvinceMode: (mode) => set({ warningNotificationProvinceMode: mode }),
setWarningNotificationProvince: (province) => set({ warningNotificationProvince: province }),
setTemperatureUnit: (unit) => set({ temperatureUnit: unit }),
setWindSpeedUnit: (unit) => set({ windSpeedUnit: unit }),
setDashboardSectionVisible: (section, visible) =>
set((state) => ({
dashboardSections: { ...state.dashboardSections, [section]: visible },
})),
setAppSectionVisible: (section, visible) =>
set((state) => ({
appSections: { ...state.appSections, [section]: visible },
})),
}),
{
name: "wtr:preferences",
migrate: (persisted) => {
const state = persisted as Partial<WeatherStore> | undefined;
const location = state?.selectedLocation as
| (Partial<SelectedLocation> & { region?: WeatherRegion })
| null
| undefined;
if (!state) return persisted;
const dashboardSections = normalizeDashboardSectionVisibility(state.dashboardSections);
const appSections = normalizeAppSectionVisibility(state.appSections);
if (!location) return { ...state, dashboardSections, appSections };
const countryCode = location.countryCode ?? (location.province ? "PL" : null);
const region = location.region ?? getWeatherRegionForCountryCode(countryCode);
return {
...state,
dashboardSections,
appSections,
selectedLocation: {
...location,
country: location.country ?? (countryCode === "PL" ? "Polska" : null),
countryCode,
admin1: location.admin1 ?? location.province ?? null,
admin2: location.admin2 ?? location.district ?? null,
timezone: location.timezone ?? (countryCode === "PL" ? "Europe/Warsaw" : null),
region,
stationId: location.stationId ?? null,
stationName: location.stationName ?? null,
distanceKm: location.distanceKm ?? null,
},
};
},
},
),
);