-
Notifications
You must be signed in to change notification settings - Fork 1
Feat/chunk availability #7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
5881c68
8aed12d
0c626f9
ca11f47
af0c4a5
73d9a12
286687f
c499230
999425d
b633f12
56d3333
df4f2d0
ff0f6ba
c594b05
51650d7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -10,8 +10,10 @@ import { useNonEmptyScheduleDays } from "@calcom/features/schedules/lib/use-sche | |||||
| import { useSlotsForAvailableDates } from "@calcom/features/schedules/lib/use-schedule/useSlotsForDate"; | ||||||
| import { PUBLIC_INVALIDATE_AVAILABLE_SLOTS_ON_BOOKING_FORM } from "@calcom/lib/constants"; | ||||||
| import { localStorage } from "@calcom/lib/webstorage"; | ||||||
| import { useLocale } from "@calcom/lib/hooks/useLocale"; | ||||||
| import { BookerLayouts } from "@calcom/prisma/zod-utils"; | ||||||
| import classNames from "@calcom/ui/classNames"; | ||||||
| import { Button } from "@calcom/ui/components/button"; | ||||||
|
|
||||||
| import { AvailableTimesHeader } from "@calcom/web/modules/bookings/components/AvailableTimesHeader"; | ||||||
| import type { useScheduleForEventReturnType } from "@calcom/features/bookings/Booker/utils/event"; | ||||||
|
|
@@ -50,6 +52,7 @@ type AvailableTimeSlotsProps = { | |||||
| unavailableTimeSlots: string[]; | ||||||
| confirmButtonDisabled?: boolean; | ||||||
| onAvailableTimeSlotSelect: (time: string) => void; | ||||||
| onLoadNextRoundRobinChunk?: () => void; | ||||||
| }; | ||||||
|
|
||||||
| /** | ||||||
|
|
@@ -74,8 +77,10 @@ export const AvailableTimeSlots = ({ | |||||
| confirmButtonDisabled, | ||||||
| confirmStepClassNames, | ||||||
| onAvailableTimeSlotSelect, | ||||||
| onLoadNextRoundRobinChunk, | ||||||
| ...props | ||||||
| }: AvailableTimeSlotsProps) => { | ||||||
| const { t } = useLocale(); | ||||||
| const selectedDate = useBookerStoreContext((state) => state.selectedDate); | ||||||
|
|
||||||
| const setSeatedEventData = useBookerStoreContext((state) => state.setSeatedEventData); | ||||||
|
|
@@ -108,6 +113,7 @@ export const AvailableTimeSlots = ({ | |||||
| }; | ||||||
|
|
||||||
| const scheduleData = schedule?.data; | ||||||
| const roundRobinChunkInfo = scheduleData?.roundRobinChunkInfo; | ||||||
|
|
||||||
| const nonEmptyScheduleDays = useNonEmptyScheduleDays(scheduleData?.slots); | ||||||
| const nonEmptyScheduleDaysFromSelectedDate = nonEmptyScheduleDays.filter( | ||||||
|
|
@@ -184,15 +190,60 @@ export const AvailableTimeSlots = ({ | |||||
| [overlayCalendarToggled, onTimeSelect, seatsPerTimeSlot, skipConfirmStep, toggleConfirmButton] | ||||||
| ); | ||||||
|
|
||||||
| const showLoadMoreButton = | ||||||
| roundRobinChunkInfo?.hasMoreNonFixedHosts && onLoadNextRoundRobinChunk; | ||||||
|
|
||||||
| const renderLoadMoreButton = () => { | ||||||
| if (!showLoadMoreButton) return null; | ||||||
|
|
||||||
| const totalLoadedHosts = | ||||||
| roundRobinChunkInfo.chunkOffset * roundRobinChunkInfo.chunkSize + | ||||||
| roundRobinChunkInfo.loadedNonFixedHosts; | ||||||
|
Comment on lines
+199
to
+201
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The Suggested fix const totalLoadedHosts =
(roundRobinChunkInfo.chunkOffset + 1) * roundRobinChunkInfo.chunkSize;
// Note: last chunk may be smaller; clamp to totalNonFixedHosts
const clampedTotalLoadedHosts = Math.min(
totalLoadedHosts,
roundRobinChunkInfo.totalNonFixedHosts || roundRobinChunkInfo.totalHosts
);Prompt for AI assistanceCopy the prompt below and paste it into ChatGPT, Claude, or any LLM:
Comment on lines
+199
to
+201
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The progress calculation for the "Load more" button computes Suggested fix const totalLoadedHosts = Math.min(
(roundRobinChunkInfo.chunkOffset + 1) * roundRobinChunkInfo.chunkSize,
roundRobinChunkInfo.totalNonFixedHosts || roundRobinChunkInfo.totalHosts || 0
);Prompt for AI assistanceCopy the prompt below and paste it into ChatGPT, Claude, or any LLM:
Comment on lines
+199
to
+201
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Progress percentage calculation is incorrect. The correct formula is: Suggested fix const totalLoadedHosts = Math.min(
roundRobinChunkInfo.chunkOffset * roundRobinChunkInfo.chunkSize +
roundRobinChunkInfo.loadedNonFixedHosts,
roundRobinChunkInfo.totalNonFixedHosts || roundRobinChunkInfo.totalHosts || 0
);Prompt for AI assistanceCopy the prompt below and paste it into ChatGPT, Claude, or any LLM:
Comment on lines
+193
to
+201
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested fix // chunkOffset is 0-based; hosts loaded up to and including the current chunk:
const totalLoadedHosts = Math.min(
(roundRobinChunkInfo.chunkOffset + 1) * roundRobinChunkInfo.chunkSize,
roundRobinChunkInfo.totalNonFixedHosts || roundRobinChunkInfo.totalHosts || 0
);Prompt for AI assistanceCopy the prompt below and paste it into ChatGPT, Claude, or any LLM: |
||||||
| const totalHosts = roundRobinChunkInfo.totalNonFixedHosts || roundRobinChunkInfo.totalHosts || 0; | ||||||
| const progressPercentage = | ||||||
| totalHosts > 0 ? Math.min(100, Math.round((totalLoadedHosts / totalHosts) * 100)) : 0; | ||||||
| const circumference = 2 * Math.PI * 8; | ||||||
| const dashArray = (progressPercentage / 100) * circumference; | ||||||
|
|
||||||
| const ProgressIcon = ( | ||||||
| <svg width="20" height="20" viewBox="0 0 20 20" className="text-emphasis" aria-hidden> | ||||||
| <circle cx="10" cy="10" r="8" stroke="rgba(255,255,255,0.35)" strokeWidth="2" fill="none" /> | ||||||
| <circle | ||||||
| cx="10" | ||||||
| cy="10" | ||||||
| r="8" | ||||||
| stroke="#FFFFFF" | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hard-coded color value
Suggested change
Prompt for AI assistanceCopy the prompt below and paste it into ChatGPT, Claude, or any LLM: |
||||||
| strokeWidth="2" | ||||||
| fill="none" | ||||||
| strokeDasharray={`${dashArray} ${circumference}`} | ||||||
| strokeLinecap="round" | ||||||
| transform="rotate(-90 10 10)" | ||||||
| /> | ||||||
| </svg> | ||||||
| ); | ||||||
|
|
||||||
| return ( | ||||||
| <Button | ||||||
| type="button" | ||||||
| color="primary" | ||||||
| className="w-full justify-center gap-2" | ||||||
| onClick={onLoadNextRoundRobinChunk} | ||||||
| disabled={isLoading || schedule?.isFetching} | ||||||
| CustomStartIcon={ProgressIcon} | ||||||
| aria-label={t("round_robin_load_next_hosts")}> | ||||||
| {t("round_robin_load_next_hosts")} | ||||||
| </Button> | ||||||
| ); | ||||||
| }; | ||||||
|
Comment on lines
+196
to
+237
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested fix const loadMoreButton = useMemo(() => {
if (!showLoadMoreButton) return null;
const totalLoadedHosts =
roundRobinChunkInfo.chunkOffset * roundRobinChunkInfo.chunkSize +
roundRobinChunkInfo.loadedNonFixedHosts;Prompt for AI assistanceCopy the prompt below and paste it into ChatGPT, Claude, or any LLM: |
||||||
|
|
||||||
| return ( | ||||||
| <> | ||||||
| <div className="relative flex h-full flex-col"> | ||||||
| <div className={classNames(`flex`, `${customClassNames?.availableTimeSlotsContainer}`)}> | ||||||
| {isLoading ? ( | ||||||
| <div className="mb-3 h-8" /> | ||||||
| ) : ( | ||||||
| slotsPerDay.length > 0 && | ||||||
| slotsPerDay.map((slots) => { | ||||||
| // Check if this day is OOO - since OOO is date-level, just check the first slot | ||||||
| const isOOODay = slots.slots.length > 0 && slots.slots[0]?.away; | ||||||
| return ( | ||||||
| <AvailableTimesHeader | ||||||
|
|
@@ -220,9 +271,10 @@ export const AvailableTimeSlots = ({ | |||||
| className={classNames( | ||||||
| limitHeight && "no-scrollbar grow overflow-auto md:h-[400px]", | ||||||
| !limitHeight && "flex h-full w-full flex-row gap-4", | ||||||
| showLoadMoreButton && "pb-14", | ||||||
| `${customClassNames?.availableTimeSlotsContainer}` | ||||||
| )}> | ||||||
| {isLoading && // Shows exact amount of days as skeleton. | ||||||
| {isLoading && | ||||||
| Array.from({ length: 1 + (extraDays ?? 0) }).map((_, i) => <AvailableTimesSkeleton key={i} />)} | ||||||
| {!isLoading && | ||||||
| slotsPerDay.length > 0 && | ||||||
|
|
@@ -247,6 +299,12 @@ export const AvailableTimeSlots = ({ | |||||
| </div> | ||||||
| ))} | ||||||
| </div> | ||||||
| </> | ||||||
|
|
||||||
| {showLoadMoreButton && ( | ||||||
| <div className="sticky right-0 bottom-0 left-0 border-subtle border-t bg-default px-4 py-3"> | ||||||
| {renderLoadMoreButton()} | ||||||
| </div> | ||||||
| )} | ||||||
| </div> | ||||||
| ); | ||||||
| }; | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,6 +21,7 @@ import { useBookerLayout } from "@calcom/features/bookings/Booker/components/hoo | |
| import { useBookingForm } from "@calcom/features/bookings/Booker/components/hooks/useBookingForm"; | ||
| import { useBookings } from "@calcom/features/bookings/Booker/components/hooks/useBookings"; | ||
| import { useCalendars } from "@calcom/features/bookings/Booker/components/hooks/useCalendars"; | ||
| import { useRoundRobinChunking } from "@calcom/features/bookings/Booker/components/hooks/useRoundRobinChunking"; | ||
| import { useSlots } from "@calcom/features/bookings/Booker/components/hooks/useSlots"; | ||
| import { useVerifyCode } from "@calcom/features/bookings/Booker/components/hooks/useVerifyCode"; | ||
| import { useVerifyEmail } from "@calcom/features/bookings/Booker/components/hooks/useVerifyEmail"; | ||
|
|
@@ -93,7 +94,10 @@ const BookerWebWrapperComponent = (props: BookerWebWrapperAtomProps) => { | |
| }); | ||
|
|
||
| const [dayCount] = useBookerStoreContext((state) => [state.dayCount, state.setDayCount], shallow); | ||
|
|
||
| const [roundRobinChunkSettings, setRoundRobinChunkSettings] = useBookerStoreContext( | ||
| (state) => [state.roundRobinChunkSettings, state.setRoundRobinChunkSettings], | ||
| shallow | ||
| ); | ||
| const { data: session } = useSession(); | ||
| const routerQuery = useRouterQuery(); | ||
| const hasSession = !!session; | ||
|
|
@@ -155,6 +159,21 @@ const BookerWebWrapperComponent = (props: BookerWebWrapperAtomProps) => { | |
| useApiV2: props.useApiV2, | ||
| bookerLayout, | ||
| ...(props.entity.orgSlug ? { orgSlug: props.entity.orgSlug } : {}), | ||
| roundRobinChunkSettings: roundRobinChunkSettings ?? undefined, | ||
| }); | ||
| const { roundRobinChunkInfo, handleLoadNextRoundRobinChunk } = | ||
| useRoundRobinChunking({ | ||
| roundRobinChunkInfo: schedule.data?.roundRobinChunkInfo, | ||
| isFetching: schedule.isFetching, | ||
| roundRobinChunkSettings, | ||
| setRoundRobinChunkSettings, | ||
| resetDeps: [ | ||
| props.username, | ||
| props.eventSlug, | ||
| props.entity.orgSlug, | ||
| props.entity.eventTypeId, | ||
| event.data?.id, | ||
| ], | ||
|
Comment on lines
+170
to
+176
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Once a user clicks "Load more availability", Suggested fix resetDeps: [
props.username,
props.eventSlug,
props.entity.orgSlug,
props.entity.eventTypeId,
event.data?.id,
selectedDate,
props.month,
props.duration,
dayCount,
props.teamMemberEmail,
],Prompt for AI assistanceCopy the prompt below and paste it into ChatGPT, Claude, or any LLM: |
||
| }); | ||
| const bookings = useBookings({ | ||
| event, | ||
|
|
@@ -256,6 +275,9 @@ const BookerWebWrapperComponent = (props: BookerWebWrapperAtomProps) => { | |
| event={event} | ||
| bookerLayout={bookerLayout} | ||
| schedule={schedule} | ||
| onLoadNextRoundRobinChunk={ | ||
| roundRobinChunkInfo?.hasMoreNonFixedHosts ? handleLoadNextRoundRobinChunk : undefined | ||
| } | ||
| verifyCode={verifyCode} | ||
| isPlatform={false} | ||
| areInstantMeetingParametersSet={areInstantMeetingParametersSet} | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,49 @@ | ||||||||||||||||||
| import { useCallback, useEffect } from "react"; | ||||||||||||||||||
| import type { DependencyList } from "react"; | ||||||||||||||||||
|
|
||||||||||||||||||
| import type { RoundRobinChunkSettings } from "@calcom/features/bookings/Booker/store"; | ||||||||||||||||||
| import { useBookerStoreContext } from "@calcom/features/bookings/Booker/BookerStoreProvider"; | ||||||||||||||||||
| import type { RoundRobinChunkInfo } from "@calcom/lib/types/roundRobinChunkInfo"; | ||||||||||||||||||
|
|
||||||||||||||||||
| type UseRoundRobinChunkingOptions = { | ||||||||||||||||||
| roundRobinChunkInfo?: RoundRobinChunkInfo | null; | ||||||||||||||||||
| isFetching: boolean; | ||||||||||||||||||
| resetDeps?: DependencyList; | ||||||||||||||||||
| roundRobinChunkSettings: RoundRobinChunkSettings | null; | ||||||||||||||||||
| setRoundRobinChunkSettings: (settings: RoundRobinChunkSettings | null) => void; | ||||||||||||||||||
| }; | ||||||||||||||||||
|
|
||||||||||||||||||
| export const useRoundRobinChunking = ({ | ||||||||||||||||||
| roundRobinChunkInfo, | ||||||||||||||||||
| isFetching, | ||||||||||||||||||
| resetDeps = [], | ||||||||||||||||||
| roundRobinChunkSettings, | ||||||||||||||||||
| setRoundRobinChunkSettings, | ||||||||||||||||||
| }: UseRoundRobinChunkingOptions) => { | ||||||||||||||||||
| const setRoundRobinChunkInfo = useBookerStoreContext((state) => state.setRoundRobinChunkInfo); | ||||||||||||||||||
|
|
||||||||||||||||||
| useEffect(() => { | ||||||||||||||||||
| setRoundRobinChunkInfo(roundRobinChunkInfo ?? null); | ||||||||||||||||||
| }, [roundRobinChunkInfo, setRoundRobinChunkInfo]); | ||||||||||||||||||
|
Comment on lines
+25
to
+27
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The effect that syncs Suggested fix useEffect(() => {
if (roundRobinChunkInfo !== undefined) {
setRoundRobinChunkInfo(roundRobinChunkInfo ?? null);
}
}, [roundRobinChunkInfo, setRoundRobinChunkInfo]);Prompt for AI assistanceCopy the prompt below and paste it into ChatGPT, Claude, or any LLM:
Comment on lines
+25
to
+27
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The first Suggested fix const isResettingRef = useRef(false);
useEffect(() => {
if (!isResettingRef.current) {
setRoundRobinChunkInfo(roundRobinChunkInfo ?? null);
}
isResettingRef.current = false;
}, [roundRobinChunkInfo, setRoundRobinChunkInfo]);
useEffect(() => {
isResettingRef.current = true;
setRoundRobinChunkSettings(null);
setRoundRobinChunkInfo(null);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [setRoundRobinChunkInfo, setRoundRobinChunkSettings, ...resetDeps]);Prompt for AI assistanceCopy the prompt below and paste it into ChatGPT, Claude, or any LLM: |
||||||||||||||||||
|
|
||||||||||||||||||
| useEffect(() => { | ||||||||||||||||||
| setRoundRobinChunkSettings(null); | ||||||||||||||||||
| setRoundRobinChunkInfo(null); | ||||||||||||||||||
| }, [setRoundRobinChunkInfo, setRoundRobinChunkSettings, ...resetDeps]); | ||||||||||||||||||
|
Comment on lines
+29
to
+32
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The reset Suggested fix // eslint-disable-next-line react-hooks/exhaustive-deps
useEffect(() => {
setRoundRobinChunkSettings(null);
setRoundRobinChunkInfo(null);
// Intentionally spreading resetDeps — these are stable primitive values (strings/numbers/null)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, resetDeps);Prompt for AI assistanceCopy the prompt below and paste it into ChatGPT, Claude, or any LLM:
Comment on lines
+29
to
+32
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The reset Suggested fix // eslint-disable-next-line react-hooks/exhaustive-deps
useEffect(() => {
setRoundRobinChunkSettings(null);
setRoundRobinChunkInfo(null);
// resetDeps intentionally spread — callers must memoize this array
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [setRoundRobinChunkInfo, setRoundRobinChunkSettings, ...resetDeps]);Prompt for AI assistanceCopy the prompt below and paste it into ChatGPT, Claude, or any LLM:
Comment on lines
+29
to
+32
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Spread syntax with dynamic arrays in Suggested fix // Derive a stable string key from the reset dependencies so the
// hook rule is satisfied and length changes can't silently break things.
// eslint-disable-next-line react-hooks/exhaustive-deps
const resetKey = resetDeps.map(String).join("|");
useEffect(() => {
setRoundRobinChunkSettings(null);
setRoundRobinChunkInfo(null);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [resetKey, setRoundRobinChunkInfo, setRoundRobinChunkSettings]);Prompt for AI assistanceCopy the prompt below and paste it into ChatGPT, Claude, or any LLM:
Comment on lines
+29
to
+32
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Spreading Suggested fix // eslint-disable-next-line react-hooks/exhaustive-deps
}, [setRoundRobinChunkInfo, setRoundRobinChunkSettings, JSON.stringify(resetDeps)]);Prompt for AI assistanceCopy the prompt below and paste it into ChatGPT, Claude, or any LLM:
Comment on lines
+29
to
+32
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The reset effect spreads Suggested fix const resetDepsRef = useRef(resetDeps);
useEffect(() => {
resetDepsRef.current = resetDeps;
});
useEffect(() => {
setRoundRobinChunkSettings(null);
setRoundRobinChunkInfo(null);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, resetDeps); // resetDeps must have a stable length; see useRef pattern above if it can changePrompt for AI assistanceCopy the prompt below and paste it into ChatGPT, Claude, or any LLM: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Spreading
Suggested change
Prompt for AI assistanceCopy the prompt below and paste it into ChatGPT, Claude, or any LLM: |
||||||||||||||||||
|
|
||||||||||||||||||
| const handleLoadNextRoundRobinChunk = useCallback(() => { | ||||||||||||||||||
| if (!roundRobinChunkInfo?.hasMoreNonFixedHosts || isFetching) return; | ||||||||||||||||||
| const currentOffset = roundRobinChunkSettings?.chunkOffset ?? roundRobinChunkInfo.chunkOffset ?? 0; | ||||||||||||||||||
| setRoundRobinChunkSettings({ | ||||||||||||||||||
| manual: true, | ||||||||||||||||||
| chunkOffset: currentOffset + 1, | ||||||||||||||||||
| }); | ||||||||||||||||||
|
Comment on lines
+34
to
+40
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Suggested change
Prompt for AI assistanceCopy the prompt below and paste it into ChatGPT, Claude, or any LLM: |
||||||||||||||||||
| }, [roundRobinChunkInfo, roundRobinChunkSettings, isFetching, setRoundRobinChunkSettings]); | ||||||||||||||||||
|
Comment on lines
+34
to
+41
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested fix const handleLoadNextRoundRobinChunk = useCallback(() => {
if (!roundRobinChunkInfo?.hasMoreNonFixedHosts || isFetching) return;
// Use functional update pattern with a ref to prevent double-invocation races
const currentOffset = roundRobinChunkSettings?.chunkOffset ?? roundRobinChunkInfo.chunkOffset ?? 0;
setRoundRobinChunkSettings({
manual: true,
chunkOffset: currentOffset + 1,
});
}, [roundRobinChunkInfo, roundRobinChunkSettings, isFetching, setRoundRobinChunkSettings]);Prompt for AI assistanceCopy the prompt below and paste it into ChatGPT, Claude, or any LLM: |
||||||||||||||||||
|
|
||||||||||||||||||
| return { | ||||||||||||||||||
| roundRobinChunkSettings, | ||||||||||||||||||
| roundRobinChunkInfo: roundRobinChunkInfo ?? null, | ||||||||||||||||||
| isManualRoundRobinChunking: roundRobinChunkSettings?.manual ?? false, | ||||||||||||||||||
| handleLoadNextRoundRobinChunk, | ||||||||||||||||||
| }; | ||||||||||||||||||
| }; | ||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -71,6 +71,7 @@ export const useScheduleForEvent = ({ | |
| isTeamEvent, | ||
| useApiV2 = true, | ||
| bookerLayout, | ||
| roundRobinChunkSettings, | ||
| }: { | ||
| username?: string | null; | ||
| eventSlug?: string | null; | ||
|
|
@@ -92,6 +93,10 @@ export const useScheduleForEvent = ({ | |
| extraDays: number; | ||
| columnViewExtraDays: { current: number }; | ||
| }; | ||
| roundRobinChunkSettings?: { | ||
| manual: boolean; | ||
| chunkOffset: number; | ||
| }; | ||
| }) => { | ||
| const { timezone } = useBookerTime(); | ||
| const [usernameFromStore, eventSlugFromStore, monthFromStore, durationFromStore] = useBookerStoreContext( | ||
|
|
@@ -117,6 +122,8 @@ export const useScheduleForEvent = ({ | |
| teamMemberEmail, | ||
| useApiV2: useApiV2, | ||
| bookerLayout, | ||
| roundRobinManualChunking: roundRobinChunkSettings?.manual, | ||
| roundRobinChunkOffset: roundRobinChunkSettings?.chunkOffset, | ||
|
Comment on lines
+125
to
+126
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested fix roundRobinManualChunking: roundRobinChunkSettings?.manual ?? undefined,
roundRobinChunkOffset: roundRobinChunkSettings?.manual ? roundRobinChunkSettings.chunkOffset : undefined,Prompt for AI assistanceCopy the prompt below and paste it into ChatGPT, Claude, or any LLM:
Comment on lines
+125
to
+126
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested fix roundRobinManualChunking: roundRobinChunkSettings?.manual || undefined,
roundRobinChunkOffset: roundRobinChunkSettings?.manual ? roundRobinChunkSettings.chunkOffset : undefined,Prompt for AI assistanceCopy the prompt below and paste it into ChatGPT, Claude, or any LLM: |
||
| }); | ||
|
|
||
| return { | ||
|
|
@@ -125,6 +132,7 @@ export const useScheduleForEvent = ({ | |
| isError: schedule?.isError, | ||
| isSuccess: schedule?.isSuccess, | ||
| isLoading: schedule?.isLoading, | ||
| isFetching: schedule?.isFetching, | ||
| invalidate: schedule?.invalidate, | ||
| dataUpdatedAt: schedule?.dataUpdatedAt, | ||
| }; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
showLoadMoreButtonis truthy whenroundRobinChunkInfo?.hasMoreNonFixedHosts && onLoadNextRoundRobinChunk: but bothrenderLoadMoreButton()and the sticky footer (line 303) are gated onshowLoadMoreButton. HowevershowLoadMoreButtonis used in the scrollable container's className at line 274 with"pb-14". IfonLoadNextRoundRobinChunkis defined buthasMoreNonFixedHostsisfalse, no button is shown and no padding is applied: correct. But the inverse case: ifhasMoreNonFixedHostsistrueand the callback isundefined(which can happen during SSR or if the parent forgets to pass the callback), the padding is never added but logically the button 'should' appear. More importantly, theButtoninsiderenderLoadMoreButton()re-referencesonLoadNextRoundRobinChunkdirectly on line 230 without the nullish guard thatshowLoadMoreButtonprovides: if someone callsrenderLoadMoreButton()outside this guard, aTypeError: onLoadNextRoundRobinChunk is not a functioncan occur.Suggested fix
const showLoadMoreButton = Boolean(roundRobinChunkInfo?.hasMoreNonFixedHosts && onLoadNextRoundRobinChunk);Prompt for AI assistance
Copy the prompt below and paste it into ChatGPT, Claude, or any LLM: