feat: add dashboard section visibility settings
This commit is contained in:
38
lib/dashboard-sections.ts
Normal file
38
lib/dashboard-sections.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import type { TranslationKey } from "@/lib/i18n";
|
||||
|
||||
export const DASHBOARD_SECTION_SETTINGS = [
|
||||
{
|
||||
id: "weatherBrief",
|
||||
titleKey: "settings.dashboardSections.weatherBrief.title",
|
||||
descriptionKey: "settings.dashboardSections.weatherBrief.description",
|
||||
defaultVisible: true,
|
||||
},
|
||||
{
|
||||
id: "featuredStations",
|
||||
titleKey: "settings.dashboardSections.featuredStations.title",
|
||||
descriptionKey: "settings.dashboardSections.featuredStations.description",
|
||||
defaultVisible: false,
|
||||
},
|
||||
] as const satisfies ReadonlyArray<{
|
||||
id: string;
|
||||
titleKey: TranslationKey;
|
||||
descriptionKey: TranslationKey;
|
||||
defaultVisible: boolean;
|
||||
}>;
|
||||
|
||||
export type DashboardSectionId = typeof DASHBOARD_SECTION_SETTINGS[number]["id"];
|
||||
|
||||
export type DashboardSectionVisibility = Record<DashboardSectionId, boolean>;
|
||||
|
||||
export const DEFAULT_DASHBOARD_SECTION_VISIBILITY = DASHBOARD_SECTION_SETTINGS.reduce((visibility, section) => ({
|
||||
...visibility,
|
||||
[section.id]: section.defaultVisible,
|
||||
}), {} as DashboardSectionVisibility);
|
||||
|
||||
export function normalizeDashboardSectionVisibility(value: unknown): DashboardSectionVisibility {
|
||||
const stored = value && typeof value === "object" ? value as Partial<Record<DashboardSectionId, unknown>> : {};
|
||||
return DASHBOARD_SECTION_SETTINGS.reduce((visibility, section) => ({
|
||||
...visibility,
|
||||
[section.id]: typeof stored[section.id] === "boolean" ? stored[section.id] : section.defaultVisible,
|
||||
}), {} as DashboardSectionVisibility);
|
||||
}
|
||||
12
lib/i18n.tsx
12
lib/i18n.tsx
@@ -26,6 +26,12 @@ const translations = {
|
||||
"settings.language.description": "Zmieniaj język interfejsu. Nazwy stacji i treści IMGW pozostają bez automatycznego tłumaczenia.",
|
||||
"settings.theme.title": "Motyw",
|
||||
"settings.theme.description": "Przełącz jasny lub ciemny wygląd aplikacji na tym urządzeniu.",
|
||||
"settings.dashboardSections.title": "Strona główna",
|
||||
"settings.dashboardSections.description": "Wybierz, które dodatkowe sekcje mają być widoczne na dashboardzie.",
|
||||
"settings.dashboardSections.weatherBrief.title": "Brief dnia",
|
||||
"settings.dashboardSections.weatherBrief.description": "Pokazuje deterministyczne podsumowanie dnia i krótką prognozę na jutro.",
|
||||
"settings.dashboardSections.featuredStations.title": "Szybki wybór",
|
||||
"settings.dashboardSections.featuredStations.description": "Pokazuje listę popularnych lokalizacji na dole strony głównej.",
|
||||
"settings.units.temperature.title": "Jednostka temperatury",
|
||||
"settings.units.temperature.description": "Stosowana w prognozie, briefach, powiadomieniach i bieżących pomiarach na tym urządzeniu.",
|
||||
"settings.units.temperature.label": "Wybierz jednostkę temperatury",
|
||||
@@ -283,6 +289,12 @@ const translations = {
|
||||
"settings.language.description": "Change the interface language. Station names and IMGW content are not translated automatically.",
|
||||
"settings.theme.title": "Theme",
|
||||
"settings.theme.description": "Switch the light or dark appearance on this device.",
|
||||
"settings.dashboardSections.title": "Home screen",
|
||||
"settings.dashboardSections.description": "Choose which additional sections are visible on the dashboard.",
|
||||
"settings.dashboardSections.weatherBrief.title": "Daily brief",
|
||||
"settings.dashboardSections.weatherBrief.description": "Shows the deterministic daily summary and a short forecast for tomorrow.",
|
||||
"settings.dashboardSections.featuredStations.title": "Quick select",
|
||||
"settings.dashboardSections.featuredStations.description": "Shows the popular locations list at the bottom of the home screen.",
|
||||
"settings.units.temperature.title": "Temperature unit",
|
||||
"settings.units.temperature.description": "Used in forecasts, briefs, notifications and current readings on this device.",
|
||||
"settings.units.temperature.label": "Choose temperature unit",
|
||||
|
||||
12
lib/store.ts
12
lib/store.ts
@@ -5,6 +5,7 @@ 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_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";
|
||||
@@ -22,6 +23,7 @@ interface WeatherStore {
|
||||
warningNotificationProvince: Province | null;
|
||||
temperatureUnit: TemperatureUnit;
|
||||
windSpeedUnit: WindSpeedUnit;
|
||||
dashboardSections: DashboardSectionVisibility;
|
||||
toggleFavorite: (id: string) => void;
|
||||
selectStation: (id: string) => void;
|
||||
selectLocation: (location: SelectedLocation) => void;
|
||||
@@ -32,6 +34,7 @@ interface WeatherStore {
|
||||
setWarningNotificationProvince: (province: Province | null) => void;
|
||||
setTemperatureUnit: (unit: TemperatureUnit) => void;
|
||||
setWindSpeedUnit: (unit: WindSpeedUnit) => void;
|
||||
setDashboardSectionVisible: (section: DashboardSectionId, visible: boolean) => void;
|
||||
}
|
||||
|
||||
export const useWeatherStore = create<WeatherStore>()(
|
||||
@@ -47,6 +50,7 @@ export const useWeatherStore = create<WeatherStore>()(
|
||||
warningNotificationProvince: null,
|
||||
temperatureUnit: DEFAULT_TEMPERATURE_UNIT,
|
||||
windSpeedUnit: DEFAULT_WIND_SPEED_UNIT,
|
||||
dashboardSections: DEFAULT_DASHBOARD_SECTION_VISIBILITY,
|
||||
toggleFavorite: (id) =>
|
||||
set((state) => ({
|
||||
favorites: state.favorites.includes(id)
|
||||
@@ -62,17 +66,23 @@ export const useWeatherStore = create<WeatherStore>()(
|
||||
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 },
|
||||
})),
|
||||
}),
|
||||
{
|
||||
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 || !location) return persisted;
|
||||
if (!state) return persisted;
|
||||
const dashboardSections = normalizeDashboardSectionVisibility(state.dashboardSections);
|
||||
if (!location) return { ...state, dashboardSections };
|
||||
const countryCode = location.countryCode ?? (location.province ? "PL" : null);
|
||||
const region = location.region ?? getWeatherRegionForCountryCode(countryCode);
|
||||
return {
|
||||
...state,
|
||||
dashboardSections,
|
||||
selectedLocation: {
|
||||
...location,
|
||||
country: location.country ?? (countryCode === "PL" ? "Polska" : null),
|
||||
|
||||
Reference in New Issue
Block a user