import { zodResolver } from "@hookform/resolvers/zod"; import { useSession } from "next-auth/react"; import type { Dispatch } from "react"; import { useMemo } from "react"; import { Controller, useForm } from "react-hook-form"; import { z } from "zod"; import { shallow } from "zustand/shallow"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { MembershipRole } from "@calcom/prisma/enums"; import { trpc, type RouterOutputs } from "@calcom/trpc/react"; import { Form, TextField, ToggleGroup, TextAreaField, TimezoneSelect, Label, showToast, Avatar, ImageUploader, SheetHeader, SheetBody, SheetFooter, } from "@calcom/ui"; import type { Action } from "../UserListTable"; import { SheetFooterControls } from "./SheetFooterControls"; import { useEditMode } from "./store"; type MembershipOption = { value: MembershipRole; label: string; }; const editSchema = z.object({ name: z.string(), username: z.string(), email: z.string().email(), avatar: z.string(), bio: z.string(), role: z.enum([MembershipRole.MEMBER, MembershipRole.ADMIN, MembershipRole.OWNER]), timeZone: z.string(), // schedules: z.array(z.string()), // teams: z.array(z.string()), }); type EditSchema = z.infer; export function EditForm({ selectedUser, avatarUrl, domainUrl, dispatch, }: { selectedUser: RouterOutputs["viewer"]["organizations"]["getUser"]; avatarUrl: string; domainUrl: string; dispatch: Dispatch; }) { const [setMutationLoading] = useEditMode((state) => [state.setMutationloading], shallow); const { t } = useLocale(); const session = useSession(); const org = session?.data?.user?.org; const utils = trpc.useUtils(); const form = useForm({ resolver: zodResolver(editSchema), defaultValues: { name: selectedUser?.name ?? "", username: selectedUser?.username ?? "", email: selectedUser?.email ?? "", avatar: avatarUrl, bio: selectedUser?.bio ?? "", role: selectedUser?.role ?? "", timeZone: selectedUser?.timeZone ?? "", }, }); const isOwner = org?.role === MembershipRole.OWNER; const membershipOptions = useMemo(() => { const options: MembershipOption[] = [ { value: MembershipRole.MEMBER, label: t("member"), }, { value: MembershipRole.ADMIN, label: t("admin"), }, ]; if (isOwner) { options.push({ value: MembershipRole.OWNER, label: t("owner"), }); } return options; }, [t, isOwner]); const mutation = trpc.viewer.organizations.updateUser.useMutation({ onSuccess: () => { dispatch({ type: "CLOSE_MODAL" }); utils.viewer.organizations.listMembers.invalidate(); showToast(t("profile_updated_successfully"), "success"); }, onError: (error) => { showToast(error.message, "error"); }, onSettled: () => { /** * /We need to do this as the submit button lives out side * the form for some complicated reason so we can't relay on mutationState */ setMutationLoading(false); }, }); const watchTimezone = form.watch("timeZone"); return ( <>
{ setMutationLoading(true); mutation.mutate({ userId: selectedUser?.id ?? "", role: values.role, username: values.username, name: values.name, email: values.email, avatar: values.avatar, bio: values.bio, timeZone: values.timeZone, }); }}>
(
{ form.setValue("avatar", newAvatar, { shouldDirty: true }); }} imageSrc={value || undefined} />
)} />
{selectedUser?.name ?? "Nameless User"}

{domainUrl}/{selectedUser?.username}

{ form.setValue("role", value); }} />
); }