import { useState, FC } from "react"; import Link from "next/link"; import { useRouter } from "next/router"; import { observer } from "mobx-react-lite"; import { mutate } from "swr"; import { ChevronDown, Dot, XCircle } from "lucide-react"; // mobx store import { useMobxStore } from "lib/mobx/store-provider"; // hooks import useToast from "hooks/use-toast"; // components import { ConfirmWorkspaceMemberRemove } from "components/workspace"; // ui import { CustomSelect, Tooltip } from "@plane/ui"; // types import { TUserWorkspaceRole } from "types"; // constants import { EUserWorkspaceRoles, ROLE } from "constants/workspace"; type Props = { member: { id: string; memberId: string; avatar: string; first_name: string; last_name: string; email: string | undefined; display_name: string; role: TUserWorkspaceRole; status: boolean; is_member: boolean; responded_at: string | null; accountCreated: boolean; }; }; export const WorkspaceMembersListItem: FC = observer((props) => { const { member } = props; // router const router = useRouter(); const { workspaceSlug } = router.query; // store const { workspaceMember: { removeMember, updateMember, updateMemberInvitation, deleteWorkspaceInvitation }, user: { currentWorkspaceMemberInfo, currentWorkspaceRole, currentUser, currentUserSettings, leaveWorkspace }, } = useMobxStore(); // states const [removeMemberModal, setRemoveMemberModal] = useState(false); // hooks const { setToastAlert } = useToast(); const handleLeaveWorkspace = async () => { if (!workspaceSlug || !currentUserSettings) return; await leaveWorkspace(workspaceSlug.toString()) .then(() => router.push("/profile")) .catch((err) => setToastAlert({ type: "error", title: "Error", message: err?.error || "Something went wrong. Please try again.", }) ); }; const handleRemoveMember = async () => { if (!workspaceSlug) return; await removeMember(workspaceSlug.toString(), member.id).catch((err) => setToastAlert({ type: "error", title: "Error", message: err?.error || "Something went wrong. Please try again.", }) ); }; const handleRemoveInvitation = async () => { if (!workspaceSlug) return; await deleteWorkspaceInvitation(workspaceSlug.toString(), member.id) .then(() => setToastAlert({ type: "success", title: "Success", message: "Invitation removed successfully.", }) ) .catch((err) => setToastAlert({ type: "error", title: "Error", message: err?.error || "Something went wrong. Please try again.", }) ) .finally(() => mutate(`WORKSPACE_INVITATIONS_${workspaceSlug.toString()}`, (prevData: any) => { if (!prevData) return prevData; return prevData.filter((item: any) => item.id !== member.id); }) ); }; const handleRemove = async () => { if (member.is_member) { const memberId = member.memberId; if (memberId === currentUser?.id) await handleLeaveWorkspace(); else await handleRemoveMember(); } else await handleRemoveInvitation(); }; // is the member current logged in user const isCurrentUser = member.memberId === currentWorkspaceMemberInfo?.member; // is the current logged in user admin const isAdmin = currentWorkspaceRole === EUserWorkspaceRoles.ADMIN; // role change access- // 1. user cannot change their own role // 2. only admin or member can change role // 3. user cannot change role of higher role const hasRoleChangeAccess = currentWorkspaceRole && !isCurrentUser && [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER].includes(currentWorkspaceRole) && member.role <= currentWorkspaceRole; if (!currentWorkspaceMemberInfo) return null; return ( <> setRemoveMemberModal(false)} data={member} onSubmit={handleRemove} />
{member.avatar && member.avatar !== "" ? ( {member.display_name ) : ( {(member.email ?? member.display_name ?? "?")[0]} )}
{member.is_member ? ( {member.first_name} {member.last_name} ) : (

{member.display_name || member.email}

)}

{member.display_name}

{isAdmin && ( <>

{member.email}

)}
{!member?.status && !member.responded_at && (

Pending

)} {member?.status && !member.is_member && (

Account not created

)} {!member?.status && member.responded_at && (

Rejected

)} {ROLE[member.role as keyof typeof ROLE]} {hasRoleChangeAccess && ( )}
} value={member.role} onChange={(value: TUserWorkspaceRole | undefined) => { if (!workspaceSlug || !value) return; if (!member?.status) updateMemberInvitation(workspaceSlug.toString(), member.id, { role: value, }).catch(() => { setToastAlert({ type: "error", title: "Error!", message: "An error occurred while updating member role. Please try again.", }); }); else updateMember(workspaceSlug.toString(), member.id, { role: value, }).catch(() => { setToastAlert({ type: "error", title: "Error!", message: "An error occurred while updating member role. Please try again.", }); }); }} disabled={!hasRoleChangeAccess} placement="bottom-end" > {Object.keys(ROLE).map((key) => { if (currentWorkspaceRole && currentWorkspaceRole !== 20 && currentWorkspaceRole < parseInt(key)) return null; return ( <>{ROLE[parseInt(key) as keyof typeof ROLE]} ); })}
); });