Files
calendar/packages/platform/atoms/availability/wrappers/WebAvailabilitySettingsWrapper.tsx
T
19d938ed60 feat: travel schedules to schedule timezone changes (#14512)
* add Travel Schedule modal

* UI to list schedules

* set shouldDirty

* add backend  to add new travelSchedule

* implement deleting a schedule

* check if schedule is overlapping

* WIP

* fix finding overlapping travel schedule

* only use travelSchedule when default availability is used

* adjust date overrides to timezone schedule

* first version of changeTimeZone cron job

* fix tests by adding travelSchedules

* fixes for cron job api call

* improve unit tests

* add migration

* fix type error

* fix collective-scheduling test

* clean up cron job

* code clean up

* code clean up

* show timezone from travel schedule for date override

* add date override tests

* show tz on date override only in default schedule

* fix deleting old schedules

* minor fixes in cron api handler

* code clean up

* code clean up from feedback

* fix asia/kalkota comment

* fix dark mode

* fix start and end date conversion to utc

* add first unit test for travel schedules

* Fix modal render issue

* show timezone city wtihout _

* fix dark more for datepicker

* reset values after closing dialog

* remove session from middleware

* exit loop early once schedule is found

* fix type error

* add getTravelSchedules handler

* clean up DatePicker

* fix type error

* code clean up

* code clean up

* add indexes

* use deleteMany

* fix icons

---------

Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: Alex van Andel <me@alexvanandel.com>
Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com>
2024-04-12 17:57:28 +00:00

106 lines
3.9 KiB
TypeScript

import { useRouter } from "next/navigation";
import { withErrorFromUnknown } from "@calcom/lib/getClientErrorFromUnknown";
import { useCompatSearchParams } from "@calcom/lib/hooks/useCompatSearchParams";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { HttpError } from "@calcom/lib/http-error";
import { trpc } from "@calcom/trpc/react";
import useMeQuery from "@calcom/trpc/react/hooks/useMeQuery";
import { showToast } from "@calcom/ui";
import { AvailabilitySettings } from "../AvailabilitySettings";
export const WebAvailabilitySettingsWrapper = () => {
const searchParams = useCompatSearchParams();
const { t } = useLocale();
const router = useRouter();
const utils = trpc.useUtils();
const me = useMeQuery();
const scheduleId = searchParams?.get("schedule") ? Number(searchParams.get("schedule")) : -1;
const fromEventType = searchParams?.get("fromEventType");
const { timeFormat } = me.data || { timeFormat: null };
const { data: schedule, isPending } = trpc.viewer.availability.schedule.get.useQuery(
{ scheduleId },
{
enabled: !!scheduleId,
}
);
const { data: travelSchedules, isPending: isPendingTravelSchedules } =
trpc.viewer.getTravelSchedules.useQuery();
const isDefaultSchedule = me.data?.defaultScheduleId === scheduleId;
const updateMutation = trpc.viewer.availability.schedule.update.useMutation({
onSuccess: async ({ prevDefaultId, currentDefaultId, ...data }) => {
if (prevDefaultId && currentDefaultId) {
// check weather the default schedule has been changed by comparing previous default schedule id and current default schedule id.
if (prevDefaultId !== currentDefaultId) {
// if not equal, invalidate previous default schedule id and refetch previous default schedule id.
utils.viewer.availability.schedule.get.invalidate({ scheduleId: prevDefaultId });
utils.viewer.availability.schedule.get.refetch({ scheduleId: prevDefaultId });
}
}
utils.viewer.availability.schedule.get.invalidate({ scheduleId: data.schedule.id });
utils.viewer.availability.list.invalidate();
showToast(
t("availability_updated_successfully", {
scheduleName: data.schedule.name,
}),
"success"
);
},
onError: (err) => {
if (err instanceof HttpError) {
const message = `${err.statusCode}: ${err.message}`;
showToast(message, "error");
}
},
});
const deleteMutation = trpc.viewer.availability.schedule.delete.useMutation({
onError: withErrorFromUnknown((err) => {
showToast(err.message, "error");
}),
onSettled: () => {
utils.viewer.availability.list.invalidate();
},
onSuccess: () => {
showToast(t("schedule_deleted_successfully"), "success");
router.push("/availability");
},
});
// TODO: reimplement Skeletons for this page in here
if (isPending) return null;
// We wait for the schedule to be loaded before rendering the form inside AvailabilitySettings
// since `defaultValues` cannot be redeclared after first render and using `values` will
// trigger a form reset when revalidating. Introducing flaky behavior.
if (!schedule) return null;
return (
<AvailabilitySettings
schedule={schedule}
travelSchedules={isDefaultSchedule ? travelSchedules || [] : []}
isDeleting={deleteMutation.isPending}
isLoading={isPending}
isSaving={updateMutation.isPending}
timeFormat={timeFormat}
weekStart={me.data?.weekStart || "Sunday"}
backPath={fromEventType ? true : "/availability"}
handleDelete={() => {
scheduleId && deleteMutation.mutate({ scheduleId });
}}
handleSubmit={async ({ dateOverrides, ...values }) => {
scheduleId &&
updateMutation.mutate({
scheduleId,
dateOverrides: dateOverrides.flatMap((override) => override.ranges),
...values,
});
}}
/>
);
};