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:
@@ -48,6 +48,7 @@ export function CalendarPage({ isAllowed, initDataRaw }: CalendarPageProps) {
|
||||
|
||||
const {
|
||||
currentMonth,
|
||||
pendingMonth,
|
||||
loading,
|
||||
error,
|
||||
accessDenied,
|
||||
@@ -62,6 +63,7 @@ export function CalendarPage({ isAllowed, initDataRaw }: CalendarPageProps) {
|
||||
} = useAppStore(
|
||||
useShallow((s) => ({
|
||||
currentMonth: s.currentMonth,
|
||||
pendingMonth: s.pendingMonth,
|
||||
loading: s.loading,
|
||||
error: s.error,
|
||||
accessDenied: s.accessDenied,
|
||||
|
||||
@@ -69,13 +69,13 @@ export function CalendarGrid({
|
||||
role="grid"
|
||||
aria-label="Calendar"
|
||||
>
|
||||
{cells.map(({ date, key, month }) => {
|
||||
{cells.map(({ date, key, month }, i) => {
|
||||
const isOtherMonth = month !== currentMonth.getMonth();
|
||||
const dayDuties = dutiesByDateMap[key] ?? [];
|
||||
const eventSummaries = calendarEventsByDateMap[key] ?? [];
|
||||
|
||||
return (
|
||||
<div key={key} role="gridcell" className="min-h-0">
|
||||
<div key={`cell-${i}`} role="gridcell" className="min-h-0">
|
||||
<CalendarDay
|
||||
dateKey={key}
|
||||
dayOfMonth={date.getDate()}
|
||||
|
||||
@@ -147,13 +147,13 @@ export function DutyList({ scrollMarginTop = 268, className }: DutyListProps) {
|
||||
if (!hasDataForMonth) {
|
||||
return (
|
||||
<div
|
||||
className={cn("min-h-[120px]", className)}
|
||||
role="status"
|
||||
aria-busy="true"
|
||||
aria-live="polite"
|
||||
aria-label={t("loading")}
|
||||
>
|
||||
<span className="sr-only">{t("loading")}</span>
|
||||
<DutyListSkeleton className={className} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user