52d5261b51
* display UTM parameters * persist view (list | calendar) in localStorage * move to next page on clicking "next" of last item in the page improve navigation ^ Conflicts: ^ apps/web/modules/bookings/components/BookingCalendarContainer.tsx * fix navigation on calendar view * Delete apps/web/modules/bookings/NAVIGATION_IMPLEMENTATION.md * avoid page size being 0 * check feature flag on user level * use map to improve useBookingListData * address feedback * feat(bookings): add smart navigation for calendar view - Add sort option to tRPC bookings.get schema and handler - Create NAVIGATION_PROBE_WINDOW_MONTHS constant (3 months) - Create useNearestFutureBooking hook to find nearest future booking - Create useNearestPastBooking hook to find nearest past booking - Update useCalendarNavigationCapabilities to use probe results - Update BookingCalendarContainer to wire up probe hooks This enables the booking details sheet to: - Disable next/prev buttons when no bookings exist in that direction - Jump directly to the week containing the nearest booking Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * fix type error * feat: add booking selection state when using slideover (#25637) * implement booking selection when using slideover * remove pixel shift * fix * auto scroll to selected event on calendar * make DateValues header sticky when scrolling --------- Co-authored-by: Eunjae Lee <hey@eunjae.dev> * prefetch previous / next weeks on calendar view * clean up classes * handle "fetched & but no data" situation more correctly in useCalendarAutoSelector --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
85 lines
2.8 KiB
TypeScript
85 lines
2.8 KiB
TypeScript
import { useEffect, useRef } from "react";
|
|
|
|
import { useBookingDetailsSheetStore } from "../store/bookingDetailsSheetStore";
|
|
import type { BookingsGetOutput } from "../types";
|
|
|
|
/**
|
|
* Calendar-specific auto-selection logic hook.
|
|
* Handles auto-selecting bookings when navigating across weeks in calendar view.
|
|
*
|
|
* - For "first": Selects as soon as the first page loads (immediate)
|
|
* - For "last": Waits for all pages to load to ensure we get the actual last booking
|
|
*/
|
|
export function useCalendarAutoSelector(
|
|
bookings: BookingsGetOutput["bookings"],
|
|
hasNextPage: boolean,
|
|
isFetched: boolean,
|
|
isFetchingNextPage: boolean
|
|
) {
|
|
const pendingSelection = useBookingDetailsSheetStore((state) => state.pendingSelection);
|
|
const setSelectedBookingUid = useBookingDetailsSheetStore((state) => state.setSelectedBookingUid);
|
|
const clearPendingSelection = useBookingDetailsSheetStore((state) => state.clearPendingSelection);
|
|
const setIsTransitioning = useBookingDetailsSheetStore((state) => state.setIsTransitioning);
|
|
const bookingsRef = useRef(bookings);
|
|
|
|
useEffect(() => {
|
|
// Early return if no pending selection
|
|
if (!pendingSelection) {
|
|
return;
|
|
}
|
|
|
|
const hasBookingsChanged = bookings !== bookingsRef.current;
|
|
bookingsRef.current = bookings;
|
|
|
|
if (!hasBookingsChanged) return;
|
|
|
|
if (pendingSelection === "first" && isFetched && bookings.length === 0) {
|
|
// data fetching is finished but there is no booking to select
|
|
setIsTransitioning(false);
|
|
clearPendingSelection();
|
|
return;
|
|
}
|
|
|
|
// For "first", we can select immediately when the first page arrives
|
|
if (pendingSelection === "first" && bookings.length > 0) {
|
|
setSelectedBookingUid(bookings[0].uid);
|
|
setIsTransitioning(false);
|
|
clearPendingSelection();
|
|
return;
|
|
}
|
|
|
|
// For "last", wait until all pages are loaded to ensure we get the actual last booking
|
|
if (pendingSelection === "last") {
|
|
const isAllDataLoaded = !hasNextPage && !isFetchingNextPage;
|
|
|
|
if (isAllDataLoaded && bookings.length === 0) {
|
|
// data fetching is finished but there is no booking to select
|
|
setIsTransitioning(false);
|
|
clearPendingSelection();
|
|
return;
|
|
}
|
|
|
|
// Wait for all data to load AND for bookings to actually arrive
|
|
if (!isAllDataLoaded || bookings.length === 0) {
|
|
return;
|
|
}
|
|
|
|
const lastBooking = bookings[bookings.length - 1];
|
|
setSelectedBookingUid(lastBooking.uid);
|
|
|
|
// Clear transition state and pending selection after handling
|
|
setIsTransitioning(false);
|
|
clearPendingSelection();
|
|
}
|
|
}, [
|
|
bookings,
|
|
hasNextPage,
|
|
isFetched,
|
|
isFetchingNextPage,
|
|
pendingSelection,
|
|
setSelectedBookingUid,
|
|
clearPendingSelection,
|
|
setIsTransitioning,
|
|
]);
|
|
}
|