feat: add date overrides to availability settings atom (#15459)
* remove console.log * fixup: logic to convert overrides was not calling functions * refactor handleSubmit function * add portal to platform dialog component * cleanup * add props to enable and disable date overrides * show date overrides for availability settings atom * fix: date overrides formatting for api request --------- Co-authored-by: Rajiv Sahal <rajivsahal@Rajivs-MacBook-Pro.local> Co-authored-by: supalarry <laurisskraucis@gmail.com> Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
This commit is contained in:
co-authored by
Rajiv Sahal
supalarry
Morgan
parent
87d2ec9e75
commit
d2d7453962
@@ -108,11 +108,18 @@ const DateOverrideForm = ({
|
||||
<Form
|
||||
form={form}
|
||||
handleSubmit={(values) => {
|
||||
if (selectedDates.length === 0) return;
|
||||
|
||||
const datesInRanges: TimeRange[] = [];
|
||||
|
||||
if (!datesUnavailable) {
|
||||
if (selectedDates.length === 0) return;
|
||||
|
||||
if (datesUnavailable) {
|
||||
selectedDates.map((date) => {
|
||||
datesInRanges.push({
|
||||
start: date.utc(true).startOf("day").toDate(),
|
||||
end: date.utc(true).startOf("day").toDate(),
|
||||
});
|
||||
});
|
||||
} else {
|
||||
selectedDates.map((date) => {
|
||||
values.range.map((item) => {
|
||||
datesInRanges.push({
|
||||
@@ -127,16 +134,7 @@ const DateOverrideForm = ({
|
||||
});
|
||||
}
|
||||
|
||||
onChange(
|
||||
datesUnavailable
|
||||
? selectedDates.map((date) => {
|
||||
return {
|
||||
start: date.utc(true).startOf("day").toDate(),
|
||||
end: date.utc(true).startOf("day").toDate(),
|
||||
};
|
||||
})
|
||||
: datesInRanges
|
||||
);
|
||||
onChange(datesInRanges);
|
||||
setSelectedDates([]);
|
||||
}}
|
||||
className="p-6 sm:flex sm:p-0 xl:flex-row">
|
||||
|
||||
@@ -89,6 +89,7 @@ type AvailabilitySettingsProps = {
|
||||
isPlatform?: boolean;
|
||||
customClassNames?: CustomClassNames;
|
||||
disableEditableHeading?: boolean;
|
||||
enableOverrides?: boolean;
|
||||
};
|
||||
|
||||
const DeleteDialogButton = ({
|
||||
@@ -234,6 +235,7 @@ export function AvailabilitySettings({
|
||||
isPlatform = false,
|
||||
customClassNames,
|
||||
disableEditableHeading = false,
|
||||
enableOverrides = false,
|
||||
}: AvailabilitySettingsProps) {
|
||||
const [openSidebar, setOpenSidebar] = useState(false);
|
||||
const { t, i18n } = useLocale();
|
||||
@@ -248,7 +250,6 @@ export function AvailabilitySettings({
|
||||
useEffect(() => {
|
||||
const subscription = form.watch(
|
||||
(value, { name }) => {
|
||||
console.log(name);
|
||||
if (!!name && name.split(".")[0] !== "schedule" && name !== "name")
|
||||
handleSubmit(value as AvailabilityFormValues);
|
||||
},
|
||||
@@ -507,23 +508,17 @@ export function AvailabilitySettings({
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{!isPlatform ? (
|
||||
<div className="border-subtle my-6 rounded-md border">
|
||||
{schedule?.workingHours && (
|
||||
<DateOverride
|
||||
workingHours={schedule.workingHours}
|
||||
userTimeFormat={timeFormat}
|
||||
travelSchedules={travelSchedules}
|
||||
weekStart={
|
||||
["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"].indexOf(
|
||||
weekStart
|
||||
) as 0 | 1 | 2 | 3 | 4 | 5 | 6
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
{enableOverrides && (
|
||||
<DateOverride
|
||||
workingHours={schedule.workingHours}
|
||||
userTimeFormat={timeFormat}
|
||||
travelSchedules={travelSchedules}
|
||||
weekStart={
|
||||
["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"].indexOf(
|
||||
weekStart
|
||||
) as 0 | 1 | 2 | 3 | 4 | 5 | 6
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div className="min-w-40 col-span-3 hidden space-y-2 md:block lg:col-span-1">
|
||||
|
||||
+27
-5
@@ -12,11 +12,7 @@ export function transformAtomScheduleForApi(body: AvailabilityFormValues): Updat
|
||||
const overrides =
|
||||
dateOverrides.flatMap(
|
||||
(dateOverridesRanges) =>
|
||||
dateOverridesRanges?.ranges?.map((range) => ({
|
||||
date: `${range.start.getUTCFullYear}-${range.start.getUTCMonth}-${range.start.getUTCDate}`,
|
||||
startTime: `${range.start.getUTCHours}-${range.start.getUTCMinutes}`,
|
||||
endTime: `${range.end.getUTCHours}-${range.end.getUTCMinutes}`,
|
||||
})) ?? []
|
||||
dateOverridesRanges?.ranges?.map((range) => transfromAtomOverrideForApi(range)) ?? []
|
||||
) ?? [];
|
||||
|
||||
const availability = formatScheduleTime(schedule);
|
||||
@@ -24,6 +20,32 @@ export function transformAtomScheduleForApi(body: AvailabilityFormValues): Updat
|
||||
return { name, timeZone, isDefault, availability, overrides };
|
||||
}
|
||||
|
||||
type AtomDateOverride = {
|
||||
start: Date;
|
||||
end: Date;
|
||||
};
|
||||
|
||||
function transfromAtomOverrideForApi(override: AtomDateOverride) {
|
||||
const date = `${override.start.getUTCFullYear()}-${(override.start.getUTCMonth() + 1)
|
||||
.toString()
|
||||
.padStart(2, "0")}-${override.start.getUTCDate().toString().padStart(2, "0")}`;
|
||||
|
||||
return {
|
||||
date,
|
||||
startTime: padHoursMinutesWithZeros(`${override.start.getUTCHours()}:${override.start.getUTCMinutes()}`),
|
||||
endTime: padHoursMinutesWithZeros(`${override.end.getUTCHours()}:${override.end.getUTCMinutes()}`),
|
||||
};
|
||||
}
|
||||
|
||||
function padHoursMinutesWithZeros(hhMM: string) {
|
||||
const [hours, minutes] = hhMM.split(":");
|
||||
|
||||
const formattedHours = hours.padStart(2, "0");
|
||||
const formattedMinutes = minutes.padStart(2, "0");
|
||||
|
||||
return `${formattedHours}:${formattedMinutes}`;
|
||||
}
|
||||
|
||||
function formatScheduleTime(
|
||||
weekSchedule: AvailabilityFormValues["schedule"]
|
||||
): UpdateScheduleInput_2024_06_11["availability"] {
|
||||
|
||||
@@ -26,6 +26,7 @@ type AvailabilitySettingsPlatformWrapperProps = {
|
||||
onDeleteSuccess?: (res: ApiResponse) => void;
|
||||
onDeleteError?: (err: ApiErrorResponse) => void;
|
||||
disableEditableHeading?: boolean;
|
||||
enableOverrides?: boolean;
|
||||
};
|
||||
|
||||
export const AvailabilitySettingsPlatformWrapper = ({
|
||||
@@ -36,6 +37,7 @@ export const AvailabilitySettingsPlatformWrapper = ({
|
||||
onUpdateError,
|
||||
onUpdateSuccess,
|
||||
disableEditableHeading = false,
|
||||
enableOverrides = false,
|
||||
}: AvailabilitySettingsPlatformWrapperProps) => {
|
||||
const { isLoading, data: schedule } = useSchedule(id);
|
||||
const { data: schedules } = useSchedules();
|
||||
@@ -99,6 +101,7 @@ export const AvailabilitySettingsPlatformWrapper = ({
|
||||
}}
|
||||
weekStart="Sunday"
|
||||
timeFormat={timeFormat}
|
||||
enableOverrides={enableOverrides}
|
||||
isLoading={isLoading}
|
||||
schedule={{
|
||||
name: atomSchedule.name,
|
||||
|
||||
@@ -86,6 +86,7 @@ export const AvailabilitySettingsWebWrapper = () => {
|
||||
isDeleting={deleteMutation.isPending}
|
||||
isLoading={isPending}
|
||||
isSaving={updateMutation.isPending}
|
||||
enableOverrides={true}
|
||||
timeFormat={timeFormat}
|
||||
weekStart={me.data?.weekStart || "Sunday"}
|
||||
backPath={fromEventType ? true : "/availability"}
|
||||
|
||||
@@ -33,20 +33,24 @@ const DialogContent = React.forwardRef<
|
||||
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
|
||||
>(({ className, children, ...props }, ref) => (
|
||||
<>
|
||||
<DialogOverlay />
|
||||
<DialogPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border p-6 shadow-lg duration-200 sm:rounded-lg",
|
||||
className
|
||||
)}
|
||||
{...props}>
|
||||
{children}
|
||||
<DialogPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:pointer-events-none">
|
||||
<Icon name="x" className="h-4 w-4" />
|
||||
<span className="sr-only">Close</span>
|
||||
</DialogPrimitive.Close>
|
||||
</DialogPrimitive.Content>
|
||||
<DialogPortal>
|
||||
<div className="calcom-atoms">
|
||||
<DialogOverlay />
|
||||
<DialogPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border p-6 shadow-lg duration-200 sm:rounded-lg",
|
||||
className
|
||||
)}
|
||||
{...props}>
|
||||
{children}
|
||||
<DialogPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:pointer-events-none">
|
||||
<Icon name="x" className="h-4 w-4" />
|
||||
<span className="sr-only">Close</span>
|
||||
</DialogPrimitive.Close>
|
||||
</DialogPrimitive.Content>
|
||||
</div>
|
||||
</DialogPortal>
|
||||
</>
|
||||
));
|
||||
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
||||
|
||||
@@ -11,6 +11,7 @@ export default function Availability(props: { calUsername: string; calEmail: str
|
||||
<Navbar username={props.calUsername} />
|
||||
<div>
|
||||
<AvailabilitySettings
|
||||
enableOverrides={true}
|
||||
customClassNames={{
|
||||
subtitlesClassName: "text-red-500",
|
||||
ctaClassName: "border p-4 rounded-md",
|
||||
|
||||
Reference in New Issue
Block a user