import { useRouter, useSearchParams } from "next/navigation"; import { useState } from "react"; import { Controller, useFieldArray, useForm } from "react-hook-form"; import dayjs from "@calcom/dayjs"; import { DateOverrideInputDialog, DateOverrideList } from "@calcom/features/schedules"; import Schedule from "@calcom/features/schedules/components/Schedule"; import Shell from "@calcom/features/shell/Shell"; import { availabilityAsString } from "@calcom/lib/availability"; 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 type { Schedule as ScheduleType, TimeRange, WorkingHours } from "@calcom/types/schedule"; import { Button, ConfirmationDialogContent, Dialog, DialogTrigger, Dropdown, DropdownItem, DropdownMenuContent, DropdownMenuSeparator, DropdownMenuTrigger, Form, Label, showToast, Skeleton, SkeletonText, Switch, TimezoneSelect, Tooltip, VerticalDivider, } from "@calcom/ui"; import { Info, MoreHorizontal, Plus, Trash } from "@calcom/ui/components/icon"; import PageWrapper from "@components/PageWrapper"; import { SelectSkeletonLoader } from "@components/availability/SkeletonLoader"; import EditableHeading from "@components/ui/EditableHeading"; type AvailabilityFormValues = { name: string; schedule: ScheduleType; dateOverrides: { ranges: TimeRange[] }[]; timeZone: string; isDefault: boolean; }; const DateOverride = ({ workingHours }: { workingHours: WorkingHours[] }) => { const { remove, append, replace, fields } = useFieldArray({ name: "dateOverrides", }); const excludedDates = fields.map((field) => dayjs(field.ranges[0].start).utc().format("YYYY-MM-DD")); const { t } = useLocale(); return (

{t("date_overrides")}{" "}

{t("date_overrides_subtitle")}

ranges.forEach((range) => append({ ranges: [range] }))} Trigger={ } />
); }; export default function Availability() { const searchParams = useSearchParams(); const { t, i18n } = useLocale(); const router = useRouter(); const utils = trpc.useContext(); 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 [deleteDialogOpen, setDeleteDialogOpen] = useState(false); const { data: schedule, isLoading } = trpc.viewer.availability.schedule.get.useQuery( { scheduleId }, { enabled: !!scheduleId, } ); const form = useForm({ values: schedule && { ...schedule, schedule: schedule?.availability || [], }, }); 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: (err) => { if (err instanceof HttpError) { const message = `${err.statusCode}: ${err.message}`; showToast(message, "error"); } }, onSettled: () => { utils.viewer.availability.list.invalidate(); }, onSuccess: () => { showToast(t("schedule_deleted_successfully"), "success"); router.push("/availability"); }, }); return ( ( )} /> } subtitle={ schedule ? ( schedule.schedule .filter((availability) => !!availability.days.length) .map((availability) => ( {availabilityAsString(availability, { locale: i18n.language, hour12: timeFormat === 12 })}
)) ) : ( ) } CTA={
{t("set_to_default")} { form.setValue("isDefault", e); }} />
}>
{ scheduleId && updateMutation.mutate({ scheduleId, dateOverrides: dateOverrides.flatMap((override) => override.ranges), ...values, }); }} className="flex flex-col sm:mx-0 xl:flex-row xl:space-x-6">
{typeof me.data?.weekStart === "string" && ( )}
{schedule?.workingHours && }
{t("timezone")} value ? ( onChange(timezone.value)} /> ) : ( ) } />

{t("something_doesnt_look_right")}
{t("launch_troubleshooter")}
); } Availability.PageWrapper = PageWrapper;