From ec3656e646dd0fde90e4e604b3c87c23b01402a9 Mon Sep 17 00:00:00 2001 From: Rajiv Sahal Date: Fri, 17 Oct 2025 10:42:25 +0200 Subject: [PATCH] fix: add `isDryRun` behaviour for date overrides (#24464) * chore: add `isDryRun` prop for date overrides * chore: add changesets * chore: implement PR feedback * fix: merge conflicts --- .changeset/crazy-spoons-film.md | 5 +++++ .../components/DateOverrideInputDialog.tsx | 11 ++++++++++- .../schedules/components/DateOverrideList.tsx | 16 +++++++++++----- .../atoms/availability/AvailabilitySettings.tsx | 11 ++++++++++- .../AvailabilitySettingsPlatformWrapper.tsx | 1 + 5 files changed, 37 insertions(+), 7 deletions(-) create mode 100644 .changeset/crazy-spoons-film.md diff --git a/.changeset/crazy-spoons-film.md b/.changeset/crazy-spoons-film.md new file mode 100644 index 0000000000..a96d7c2803 --- /dev/null +++ b/.changeset/crazy-spoons-film.md @@ -0,0 +1,5 @@ +--- +"@calcom/atoms": patch +--- + +This PR adds dry run behaviour for date overrides in the `AvailabilitySettings` atom diff --git a/packages/features/schedules/components/DateOverrideInputDialog.tsx b/packages/features/schedules/components/DateOverrideInputDialog.tsx index b4d0e31f92..84d9035729 100644 --- a/packages/features/schedules/components/DateOverrideInputDialog.tsx +++ b/packages/features/schedules/components/DateOverrideInputDialog.tsx @@ -26,6 +26,7 @@ const DateOverrideForm = ({ onChange, userTimeFormat, weekStart, + isDryRun = false, }: { workingHours?: WorkingHours[]; onChange: (newValue: TimeRange[]) => void; @@ -34,6 +35,7 @@ const DateOverrideForm = ({ onClose?: () => void; userTimeFormat: number | null; weekStart: 0 | 1 | 2 | 3 | 4 | 5 | 6; + isDryRun?: boolean; }) => { const [browsingDate, setBrowsingDate] = useState(); const { t, i18n, isLocaleReady } = useLocale(); @@ -109,6 +111,11 @@ const DateOverrideForm = ({ if (selectedDates.length === 0) return; + if (isDryRun) { + setSelectedDates([]); + return; + } + if (datesUnavailable) { selectedDates.map((date) => { datesInRanges.push({ @@ -116,6 +123,7 @@ const DateOverrideForm = ({ end: date.utc(true).startOf("day").toDate(), }); }); + onChange(datesInRanges); } else { selectedDates.map((date) => { values.range.map((item) => { @@ -129,9 +137,9 @@ const DateOverrideForm = ({ }); }); }); + onChange(datesInRanges); } - onChange(datesInRanges); setSelectedDates([]); }} className="p-6 sm:flex sm:p-0 xl:flex-row"> @@ -215,6 +223,7 @@ const DateOverrideInputDialog = ({ userTimeFormat: number | null; weekStart?: 0 | 1 | 2 | 3 | 4 | 5 | 6; className?: string; + isDryRun?: boolean; }) => { const [open, setOpen] = useState(false); return ( diff --git a/packages/features/schedules/components/DateOverrideList.tsx b/packages/features/schedules/components/DateOverrideList.tsx index 9f0c8b2fbc..a81a899d2a 100644 --- a/packages/features/schedules/components/DateOverrideList.tsx +++ b/packages/features/schedules/components/DateOverrideList.tsx @@ -27,6 +27,7 @@ const DateOverrideList = ({ fields, weekStart = 0, handleAvailabilityUpdate = noop, + isDryRun = false, }: { // eslint-disable-next-line @typescript-eslint/no-explicit-any replace: any; @@ -38,6 +39,7 @@ const DateOverrideList = ({ travelSchedules?: RouterOutputs["viewer"]["travelSchedules"]["get"]; weekStart?: 0 | 1 | 2 | 3 | 4 | 5 | 6; handleAvailabilityUpdate?: VoidFunction; + isDryRun?: boolean; }) => { const { t, i18n } = useLocale(); const isPlatform = useIsPlatform(); @@ -109,10 +111,12 @@ const DateOverrideList = ({ }))} weekStart={weekStart} onChange={(ranges) => { - // update has very weird side-effects with sorting. - replace([...fields.filter((currentItem) => currentItem.id !== item.id), { ranges }]); - delete unsortedFieldArrayMap[item.id]; - handleAvailabilityUpdate(); + if (!isDryRun) { + // update has very weird side-effects with sorting. + replace([...fields.filter((currentItem) => currentItem.id !== item.id), { ranges }]); + delete unsortedFieldArrayMap[item.id]; + handleAvailabilityUpdate(); + } }} Trigger={ @@ -145,7 +149,9 @@ const DateOverrideList = ({ StartIcon="trash-2" onClick={() => { replace([...fields.filter((currentItem) => currentItem.id !== item.id)]); - handleAvailabilityUpdate(); + if (!isDryRun) { + handleAvailabilityUpdate(); + } }} /> diff --git a/packages/platform/atoms/availability/AvailabilitySettings.tsx b/packages/platform/atoms/availability/AvailabilitySettings.tsx index 5e1cd79728..888a77c34f 100644 --- a/packages/platform/atoms/availability/AvailabilitySettings.tsx +++ b/packages/platform/atoms/availability/AvailabilitySettings.tsx @@ -125,6 +125,7 @@ type AvailabilitySettingsProps = { handleBulkEditDialogToggle: () => void; }; callbacksRef?: React.MutableRefObject<{ onSuccess?: () => void; onError?: (error: Error) => void }>; + isDryRun?: boolean; }; const DeleteDialogButton = ({ @@ -190,6 +191,7 @@ const DateOverride = ({ overridesModalClassNames, classNames, handleSubmit, + isDryRun = false, }: { workingHours: WorkingHours[]; userTimeFormat: number | null; @@ -203,6 +205,7 @@ const DateOverride = ({ button?: string; }; handleSubmit: (data: AvailabilityFormValues) => Promise; + isDryRun?: boolean; }) => { const { append, replace, fields } = useFieldArray({ name: "dateOverrides", @@ -213,7 +216,9 @@ const DateOverride = ({ const handleAvailabilityUpdate = () => { const updatedValues = getValues() as AvailabilityFormValues; - handleSubmit(updatedValues); + if (!isDryRun) { + handleSubmit(updatedValues); + } }; return ( @@ -240,6 +245,7 @@ const DateOverride = ({ hour12={Boolean(userTimeFormat === 12)} travelSchedules={travelSchedules} handleAvailabilityUpdate={handleAvailabilityUpdate} + isDryRun={isDryRun} /> );