import { useSession } from "next-auth/react"; import { useRouter, useSearchParams } from "next/navigation"; import { useState } from "react"; import { useOrgBranding } from "@calcom/features/ee/organizations/context/provider"; import InviteLinkSettingsModal from "@calcom/features/ee/teams/components/InviteLinkSettingsModal"; import MemberInvitationModal from "@calcom/features/ee/teams/components/MemberInvitationModal"; import { classNames } from "@calcom/lib"; import { APP_NAME, WEBAPP_URL } from "@calcom/lib/constants"; import { useBookerUrl } from "@calcom/lib/hooks/useBookerUrl"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { MembershipRole } from "@calcom/prisma/enums"; import type { RouterOutputs } from "@calcom/trpc/react"; import { trpc } from "@calcom/trpc/react"; import { Avatar, Badge, Button, showToast, SkeletonButton, SkeletonContainer, SkeletonText, } from "@calcom/ui"; import { ArrowRight, Plus, Trash2 } from "@calcom/ui/components/icon"; type TeamMember = RouterOutputs["viewer"]["teams"]["get"]["members"][number]; type FormValues = { members: TeamMember[]; }; const AddNewTeamMembers = () => { const searchParams = useSearchParams(); const session = useSession(); const teamId = searchParams?.get("id") ? Number(searchParams.get("id")) : -1; const teamQuery = trpc.viewer.teams.get.useQuery( { teamId }, { enabled: session.status === "authenticated" } ); if (session.status === "loading" || !teamQuery.data) return ; return ; }; export const AddNewTeamMembersForm = ({ defaultValues, teamId, }: { defaultValues: FormValues; teamId: number; }) => { const searchParams = useSearchParams(); const { t, i18n } = useLocale(); const router = useRouter(); const utils = trpc.useContext(); const orgBranding = useOrgBranding(); const showDialog = searchParams?.get("inviteModal") === "true"; const [memberInviteModal, setMemberInviteModal] = useState(showDialog); const [inviteLinkSettingsModal, setInviteLinkSettingsModal] = useState(false); const { data: team, isLoading } = trpc.viewer.teams.get.useQuery({ teamId }, { enabled: !!teamId }); const { data: orgMembersNotInThisTeam } = trpc.viewer.organizations.getMembers.useQuery( { teamIdToExclude: teamId, distinctUser: true, }, { enabled: orgBranding !== null, } ); const inviteMemberMutation = trpc.viewer.teams.inviteMember.useMutation(); const publishTeamMutation = trpc.viewer.teams.publish.useMutation({ onSuccess(data) { router.push(data.url); }, onError: (error) => { showToast(error.message, "error"); }, }); return ( <>
{defaultValues.members.length > 0 && (
    {defaultValues.members.map((member, index) => ( ))}
)}
{isLoading ? ( ) : ( <> setMemberInviteModal(false)} onSubmit={(values, resetFields) => { inviteMemberMutation.mutate( { teamId, language: i18n.language, role: values.role, usernameOrEmail: values.emailOrUsername, sendEmailInvitation: values.sendInviteEmail, }, { onSuccess: async (data) => { await utils.viewer.teams.get.invalidate(); setMemberInviteModal(false); if (data.sendEmailInvitation) { if (Array.isArray(data.usernameOrEmail)) { showToast( t("email_invite_team_bulk", { userCount: data.usernameOrEmail.length, }), "success" ); resetFields(); } else { showToast( t("email_invite_team", { email: data.usernameOrEmail, }), "success" ); } } }, onError: (error) => { showToast(error.message, "error"); }, } ); }} onSettingsOpen={() => { setMemberInviteModal(false); setInviteLinkSettingsModal(true); }} members={defaultValues.members} /> {team?.inviteToken && ( { setInviteLinkSettingsModal(false); setMemberInviteModal(true); }} /> )} )}
); }; export default AddNewTeamMembers; const AddNewTeamMemberSkeleton = () => { return (

); }; const PendingMemberItem = (props: { member: TeamMember; index: number; teamId: number }) => { const { member, index, teamId } = props; const { t } = useLocale(); const utils = trpc.useContext(); const session = useSession(); const bookerUrl = useBookerUrl(); const { data: currentOrg } = trpc.viewer.organizations.listCurrent.useQuery(undefined, { enabled: !!session.data?.user?.org, }); const removeMemberMutation = trpc.viewer.teams.removeMember.useMutation({ async onSuccess() { await utils.viewer.teams.get.invalidate(); await utils.viewer.eventTypes.invalidate(); showToast(t("member_removed"), "success"); }, async onError(err) { showToast(err.message, "error"); }, }); const isOrgAdminOrOwner = currentOrg && (currentOrg.user.role === MembershipRole.OWNER || currentOrg.user.role === MembershipRole.ADMIN); return (
  • {member.name || member.email || t("team_member")}

    {/* Assume that the first member of the team is the creator */} {member.id === session.data?.user.id && {t("you")}} {!member.accepted && {t("pending")}} {member.role === "MEMBER" && {t("member")}} {member.role === "ADMIN" && {t("admin")}}
    {member.username ? (

    {`${WEBAPP_URL}/${member.username}`}

    ) : (

    {t("not_on_cal", { appName: APP_NAME })}

    )}
    {(member.role !== "OWNER" || isOrgAdminOrOwner) && (
  • ); };