diff --git a/docs/architecture.md b/docs/architecture.md
index 884962a..84dc0d3 100644
--- a/docs/architecture.md
+++ b/docs/architecture.md
@@ -22,7 +22,7 @@ Najważniejsze widoki:
- `/` - dashboard pogody, wyszukiwarka lokalizacji, hero, prognoza, briefy i ostrzeżenia regionalne,
- `/warnings` - pełny widok ostrzeżeń meteo i hydro,
- `/hydro` - stacje hydrologiczne,
-- `/settings` - język, motyw, lokalizacja powiadomień i Web Push,
+- `/settings` - język, motyw, widoczność sekcji dashboardu, lokalizacja powiadomień i Web Push,
- `/station/[id]` - szczegóły stacji,
- `/offline` - fallback offline.
@@ -42,7 +42,8 @@ Zustand w `lib/store.ts` przechowuje trwałe preferencje użytkownika w `localSt
- ulubione stacje,
- wybraną stację albo lokalizację,
- ustawienia powiadomień,
-- tryb wyboru województwa dla alertów.
+- tryb wyboru województwa dla alertów,
+- widoczność opcjonalnych sekcji dashboardu.
Język interfejsu jest przechowywany osobno w `localStorage` pod kluczem `wtr:language`.
diff --git a/lib/dashboard-sections.ts b/lib/dashboard-sections.ts
new file mode 100644
index 0000000..4758d1e
--- /dev/null
+++ b/lib/dashboard-sections.ts
@@ -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;
+
+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> : {};
+ return DASHBOARD_SECTION_SETTINGS.reduce((visibility, section) => ({
+ ...visibility,
+ [section.id]: typeof stored[section.id] === "boolean" ? stored[section.id] : section.defaultVisible,
+ }), {} as DashboardSectionVisibility);
+}
diff --git a/lib/i18n.tsx b/lib/i18n.tsx
index 92b9006..6b2e2d9 100644
--- a/lib/i18n.tsx
+++ b/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",
diff --git a/lib/store.ts b/lib/store.ts
index 9930ce2..b78dc13 100644
--- a/lib/store.ts
+++ b/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()(
@@ -47,6 +50,7 @@ export const useWeatherStore = create()(
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()(
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 | undefined;
const location = state?.selectedLocation as (Partial & { 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),