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
This commit is contained in:
Rajiv Sahal
2025-10-17 08:42:25 +00:00
committed by GitHub
parent ae4b807500
commit ec3656e646
5 changed files with 37 additions and 7 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"@calcom/atoms": patch
---
This PR adds dry run behaviour for date overrides in the `AvailabilitySettings` atom
@@ -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<Dayjs>();
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 (
@@ -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={
<DialogTrigger asChild>
@@ -145,7 +149,9 @@ const DateOverrideList = ({
StartIcon="trash-2"
onClick={() => {
replace([...fields.filter((currentItem) => currentItem.id !== item.id)]);
handleAvailabilityUpdate();
if (!isDryRun) {
handleAvailabilityUpdate();
}
}}
/>
</Tooltip>
@@ -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<void>;
isDryRun?: boolean;
}) => {
const { append, replace, fields } = useFieldArray<AvailabilityFormValues, "dateOverrides">({
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}
/>
<DateOverrideInputDialog
className={overridesModalClassNames}
@@ -251,6 +257,7 @@ const DateOverride = ({
}}
userTimeFormat={userTimeFormat}
weekStart={weekStart}
isDryRun={isDryRun}
Trigger={
<Button
className={classNames?.button}
@@ -308,6 +315,7 @@ export const AvailabilitySettings = forwardRef<AvailabilitySettingsFormRef, Avai
allowSetToDefault = true,
allowDelete = true,
callbacksRef,
isDryRun,
} = props;
const [openSidebar, setOpenSidebar] = useState(false);
const { t, i18n } = useLocale();
@@ -675,6 +683,7 @@ export const AvailabilitySettings = forwardRef<AvailabilitySettingsFormRef, Avai
{enableOverrides && (
<BookerStoreProvider>
<DateOverride
isDryRun={isDryRun}
workingHours={schedule.workingHours}
userTimeFormat={timeFormat}
handleSubmit={handleSubmit}
@@ -203,6 +203,7 @@ export const AvailabilitySettingsPlatformWrapper = forwardRef<
allowSetToDefault={allowSetToDefault}
onFormStateChange={onFormStateChange}
callbacksRef={callbacksRef}
isDryRun={isDryRun}
/>
</AtomsWrapper>
);