diff --git a/apps/web/components/dialog/ReassignDialog.tsx b/apps/web/components/dialog/ReassignDialog.tsx index d402624448..ebf03e9c84 100644 --- a/apps/web/components/dialog/ReassignDialog.tsx +++ b/apps/web/components/dialog/ReassignDialog.tsx @@ -1,9 +1,24 @@ +import { useAutoAnimate } from "@formkit/auto-animate/react"; import type { Dispatch, SetStateAction } from "react"; +import { useMemo } from "react"; +import { useForm } from "react-hook-form"; +import { classNames } from "@calcom/lib"; import { ErrorCode } from "@calcom/lib/errorCodes"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { trpc } from "@calcom/trpc/react"; -import { Button, Dialog, DialogClose, DialogContent, DialogFooter, showToast } from "@calcom/ui"; +import { + Button, + Form, + Label, + Dialog, + DialogClose, + DialogContent, + DialogFooter, + showToast, + Select, + RadioGroup as RadioArea, +} from "@calcom/ui"; type ReassignDialog = { isOpenDialog: boolean; @@ -12,9 +27,44 @@ type ReassignDialog = { bookingId: number; }; +type FormValues = { + reassignType: "round_robin" | "team_member"; + teamMemberId?: number; +}; + export const ReassignDialog = ({ isOpenDialog, setIsOpenDialog, teamId, bookingId }: ReassignDialog) => { const { t } = useLocale(); const utils = trpc.useUtils(); + const [animationParentRef] = useAutoAnimate({ + duration: 150, + easing: "ease-in-out", + }); + // Were using legacy list members here because we don't currently have an easy way to paginate a select via infinite scroll + const teamMembers = trpc.viewer.teams.getRoundRobinHostsToReassign.useQuery({ + bookingId, + exclude: "fixedHosts", + }); + + const teamMemberOptions = useMemo(() => { + if (teamMembers.isLoading) + return [ + { + label: "Loading...", + value: 0, + }, + ]; + + return teamMembers.data?.map((member) => ({ + label: member.name, + value: member.id, + })); + }, [teamMembers]); + + const form = useForm({ + defaultValues: { + reassignType: "round_robin", + }, + }); const roundRobinReassignMutation = trpc.viewer.teams.roundRobinReassign.useMutation({ onSuccess: async () => { @@ -31,6 +81,33 @@ export const ReassignDialog = ({ isOpenDialog, setIsOpenDialog, teamId, bookingI }, }); + const roundRobinManualReassignMutation = trpc.viewer.teams.roundRobinManualReassign.useMutation({ + onSuccess: async () => { + await utils.viewer.bookings.get.invalidate(); + setIsOpenDialog(false); + showToast(t("booking_reassigned"), "success"); + }, + onError: async (error) => { + if (error.message.includes(ErrorCode.NoAvailableUsersFound)) { + showToast(t("no_available_hosts"), "error"); + } else { + showToast(t(error.message), "error"); + } + }, + }); + + const handleSubmit = (values: FormValues) => { + if (values.reassignType === "round_robin") { + roundRobinReassignMutation.mutate({ teamId, bookingId }); + } else { + if (values.teamMemberId) { + roundRobinManualReassignMutation.mutate({ bookingId, teamMemberId: values.teamMemberId }); + } + } + }; + + const watchedReassignType = form.watch("reassignType"); + return ( {/* TODO add team member reassignment*/} - - - - +
+ { + form.setValue("reassignType", val as "team_member" | "round_robin"); + }} + className={classNames("mt-1 flex flex-col gap-4")}> + + {t("round_robin")} +

{t("round_robin_reassign_description")}

+
+ + {t("team_member_round_robin_reassign")} +

{t("team_member_round_robin_reassign_description")}

+
+
+ + {watchedReassignType === "team_member" && ( +
+ +