From 8a92d53125529749320df66e6c1cab51409018ed Mon Sep 17 00:00:00 2001 From: Linus Rath <139418639+rathlinus@users.noreply.github.com> Date: Tue, 17 Mar 2026 23:56:10 +0100 Subject: [PATCH] feat: improve calendar view mode handling with validation and defaulting --- app/[locale]/calendar/page.tsx | 24 +++++++++++++----------- stores/calendar-store.ts | 23 ++++++++++++++++++++++- 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/app/[locale]/calendar/page.tsx b/app/[locale]/calendar/page.tsx index 0679488a..ed252007 100644 --- a/app/[locale]/calendar/page.tsx +++ b/app/[locale]/calendar/page.tsx @@ -10,6 +10,7 @@ import { format, parseISO, } from "date-fns"; import { useCalendarStore } from "@/stores/calendar-store"; +import { isCalendarViewMode } from "@/stores/calendar-store"; import { useAuthStore } from "@/stores/auth-store"; import { useEmailStore } from "@/stores/email-store"; import { useSettingsStore } from "@/stores/settings-store"; @@ -64,6 +65,7 @@ export default function CalendarPage() { } = useCalendarStore(); const { firstDayOfWeek, timeFormat } = useSettingsStore(); const { identities } = useIdentityStore(); + const normalizedViewMode = isCalendarViewMode(viewMode) ? viewMode : "month"; const currentUserEmails = useMemo(() => identities.map(id => id.email).filter(Boolean), @@ -133,7 +135,7 @@ export default function CalendarPage() { const dateRange = useMemo(() => { const d = selectedDate; - switch (viewMode) { + switch (normalizedViewMode) { case "month": { const ms = startOfMonth(d); const me = endOfMonth(d); @@ -160,17 +162,17 @@ export default function CalendarPage() { end: format(addDays(d, 30), "yyyy-MM-dd'T'23:59:59"), }; } - }, [selectedDate, viewMode, firstDayOfWeek]); + }, [selectedDate, normalizedViewMode, firstDayOfWeek]); useEffect(() => { - if (client && calendars.length > 0) { + if (client && calendars.length > 0 && dateRange) { fetchEvents(client, dateRange.start, dateRange.end); } }, [client, calendars.length, dateRange, fetchEvents]); const navigatePrev = useCallback(() => { let next: Date; - switch (viewMode) { + switch (normalizedViewMode) { case "month": next = subMonths(selectedDate, 1); break; case "week": next = subWeeks(selectedDate, 1); break; case "day": next = subDays(selectedDate, 1); break; @@ -178,11 +180,11 @@ export default function CalendarPage() { } setSelectedDate(next); setMiniMonth(next); - }, [viewMode, selectedDate, setSelectedDate]); + }, [normalizedViewMode, selectedDate, setSelectedDate]); const navigateNext = useCallback(() => { let next: Date; - switch (viewMode) { + switch (normalizedViewMode) { case "month": next = addMonths(selectedDate, 1); break; case "week": next = addWeeks(selectedDate, 1); break; case "day": next = addDays(selectedDate, 1); break; @@ -190,7 +192,7 @@ export default function CalendarPage() { } setSelectedDate(next); setMiniMonth(next); - }, [viewMode, selectedDate, setSelectedDate]); + }, [normalizedViewMode, selectedDate, setSelectedDate]); const goToToday = useCallback(() => { setSelectedDate(new Date()); @@ -222,10 +224,10 @@ export default function CalendarPage() { setSelectedDate(date); setMiniMonth(date); // On mobile month view, tapping a date switches to day view - if (isMobile && viewMode === "month") { + if (isMobile && normalizedViewMode === "month") { setViewMode("day"); } - }, [setSelectedDate, isMobile, viewMode, setViewMode]); + }, [setSelectedDate, isMobile, normalizedViewMode, setViewMode]); const handleMiniMonthChange = useCallback((date: Date) => { setMiniMonth(date); @@ -625,7 +627,7 @@ export default function CalendarPage() { } const viewContent = (() => { - switch (viewMode) { + switch (normalizedViewMode) { case "month": return ( ()( persist( (set, get) => ({ @@ -299,7 +309,7 @@ export const useCalendarStore = create()( }, setSelectedDate: (date) => set({ selectedDate: date }), - setViewMode: (mode) => set({ viewMode: mode }), + setViewMode: (mode) => set({ viewMode: getSafeCalendarViewMode(mode) }), updateCalendar: async (client, calendarId, updates) => { set({ error: null }); @@ -575,6 +585,17 @@ export const useCalendarStore = create()( }), { name: 'calendar-storage', + merge: (persistedState, currentState) => { + const mergedState = { + ...currentState, + ...(persistedState as Partial | undefined), + }; + + return { + ...mergedState, + viewMode: getSafeCalendarViewMode(mergedState.viewMode), + }; + }, partialize: (state) => ({ selectedCalendarIds: state.selectedCalendarIds, viewMode: state.viewMode,