feat: implement pending month handling in calendar components
- Introduced a new `pendingMonth` state in the app store to manage month transitions without clearing current data, enhancing user experience during month navigation. - Updated `useMonthData` hook to load data for the `pendingMonth` when set, preventing empty-frame flicker and ensuring smooth month switching. - Modified `CalendarPage` and `CalendarGrid` components to utilize the new `pendingMonth` state, improving the rendering logic during month changes. - Enhanced `DutyList` to display a loading skeleton while data is being fetched, providing better feedback to users. - Updated relevant tests to cover the new loading behavior and state management for month transitions.
This commit is contained in:
@@ -14,6 +14,8 @@ export type DataForMonthKey = string | null;
|
||||
|
||||
export interface AppState {
|
||||
currentMonth: Date;
|
||||
/** When set, we are loading this month; currentMonth and data stay until load completes. */
|
||||
pendingMonth: Date | null;
|
||||
lang: "ru" | "en";
|
||||
duties: DutyWithUser[];
|
||||
calendarEvents: CalendarEvent[];
|
||||
@@ -40,7 +42,7 @@ export interface AppState {
|
||||
setCurrentView: (v: CurrentView) => void;
|
||||
setSelectedDay: (key: string | null) => void;
|
||||
/** Batch multiple state updates into a single re-render. */
|
||||
batchUpdate: (partial: Partial<Pick<AppState, "currentMonth" | "lang" | "duties" | "calendarEvents" | "dataForMonthKey" | "loading" | "error" | "accessDenied" | "accessDeniedDetail" | "currentView" | "selectedDay">>) => void;
|
||||
batchUpdate: (partial: Partial<Pick<AppState, "currentMonth" | "pendingMonth" | "lang" | "duties" | "calendarEvents" | "dataForMonthKey" | "loading" | "error" | "accessDenied" | "accessDeniedDetail" | "currentView" | "selectedDay">>) => void;
|
||||
}
|
||||
|
||||
const now = new Date();
|
||||
@@ -54,6 +56,7 @@ function getInitialView(): CurrentView {
|
||||
|
||||
export const useAppStore = create<AppState>((set) => ({
|
||||
currentMonth: initialMonth,
|
||||
pendingMonth: null,
|
||||
lang: "en",
|
||||
duties: [],
|
||||
calendarEvents: [],
|
||||
@@ -67,17 +70,13 @@ export const useAppStore = create<AppState>((set) => ({
|
||||
|
||||
setCurrentMonth: (d) => set({ currentMonth: d }),
|
||||
nextMonth: () =>
|
||||
set((s) => {
|
||||
const next = new Date(s.currentMonth);
|
||||
next.setMonth(next.getMonth() + 1);
|
||||
return { currentMonth: next };
|
||||
}),
|
||||
set((s) => ({
|
||||
pendingMonth: new Date(s.currentMonth.getFullYear(), s.currentMonth.getMonth() + 1, 1),
|
||||
})),
|
||||
prevMonth: () =>
|
||||
set((s) => {
|
||||
const prev = new Date(s.currentMonth);
|
||||
prev.setMonth(prev.getMonth() - 1);
|
||||
return { currentMonth: prev };
|
||||
}),
|
||||
set((s) => ({
|
||||
pendingMonth: new Date(s.currentMonth.getFullYear(), s.currentMonth.getMonth() - 1, 1),
|
||||
})),
|
||||
setDuties: (d) => set({ duties: d }),
|
||||
setCalendarEvents: (e) => set({ calendarEvents: e }),
|
||||
setLoading: (v) => set({ loading: v }),
|
||||
|
||||
Reference in New Issue
Block a user