import { GetServerSidePropsContext } from "next"; import { Controller, useFieldArray, useForm } from "react-hook-form"; import { z } from "zod"; import { DateOverrideInputDialog, DateOverrideList } from "@calcom/features/schedules"; import Schedule from "@calcom/features/schedules/components/Schedule"; import { availabilityAsString } from "@calcom/lib/availability"; import { yyyymmdd } from "@calcom/lib/date-fns"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { stringOrNumber } from "@calcom/prisma/zod-utils"; 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, Form, Icon, Label, Shell, showToast, Skeleton, SkeletonText, Switch, TimezoneSelect, Tooltip, VerticalDivider, } from "@calcom/ui"; import { HttpError } from "@lib/core/http/error"; import { SelectSkeletonLoader } from "@components/availability/SkeletonLoader"; import EditableHeading from "@components/ui/EditableHeading"; import { ssrInit } from "@server/lib/ssr"; const querySchema = z.object({ schedule: stringOrNumber, }); type AvailabilityFormValues = { name: string; schedule: ScheduleType; dateOverrides: { ranges: TimeRange[] }[]; timeZone: string; isDefault: boolean; }; const DateOverride = ({ workingHours }: { workingHours: WorkingHours[] }) => { const { remove, append, update, fields } = useFieldArray({ name: "dateOverrides", }); const { t } = useLocale(); return (

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

{t("date_overrides_subtitle")}

yyyymmdd(field.ranges[0].start))} remove={remove} update={update} items={fields} workingHours={workingHours} /> yyyymmdd(field.ranges[0].start))} onChange={(ranges) => append({ ranges })} Trigger={ } />
); }; export default function Availability({ schedule }: { schedule: number }) { const { t, i18n } = useLocale(); const utils = trpc.useContext(); const me = useMeQuery(); const { timeFormat } = me.data || { timeFormat: null }; const { data, isLoading } = trpc.viewer.availability.schedule.get.useQuery({ scheduleId: schedule }); const { data: defaultValues } = trpc.viewer.availability.defaultValues.useQuery({ scheduleId: schedule }); const form = useForm({ defaultValues }); const { control } = form; 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"); } }, }); return ( } /> } subtitle={ data ? ( data.schedule.availability .filter((availability) => !!availability.days.length) .map((availability) => ( {availabilityAsString(availability, { locale: i18n.language, hour12: timeFormat === 12 })}
)) ) : ( ) } CTA={
{t("set_to_default")} { form.setValue("isDefault", e); }} />
}>
{/* TODO: Find a better way to guarantee alignment, but for now this'll do. */}
{ updateMutation.mutate({ scheduleId: schedule, dateOverrides: dateOverrides.flatMap((override) => override.ranges), ...values, }); }} className="-mx-4 flex flex-col pb-16 sm:mx-0 xl:flex-row xl:space-x-6">

{t("change_start_end")}

{typeof me.data?.weekStart === "string" && ( )}
{data?.workingHours && }
value ? ( onChange(timezone.value)} /> ) : ( ) } />

{t("something_doesnt_look_right")}

); } export const getServerSideProps = async (ctx: GetServerSidePropsContext) => { const params = querySchema.safeParse(ctx.params); const ssr = await ssrInit(ctx); if (!params.success) return { notFound: true }; const scheduleId = params.data.schedule; await ssr.viewer.availability.schedule.get.fetch({ scheduleId }); await ssr.viewer.availability.defaultValues.fetch({ scheduleId }); return { props: { schedule: scheduleId, trpcState: ssr.dehydrate(), }, }; };