import { useState } from "react"; import { useRouter } from "next/router"; import Link from "next/link"; import useSWR, { mutate } from "swr"; import { observer } from "mobx-react-lite"; import { useMobxStore } from "lib/mobx/store-provider"; // hooks import useToast from "hooks/use-toast"; // components import { ConfirmProjectMemberRemove } from "components/project"; // ui import { CustomSelect, Tooltip } from "@plane/ui"; // icons import { ChevronDown, Dot, XCircle } from "lucide-react"; // constants import { ROLE } from "constants/workspace"; // types import { TUserProjectRole } from "types"; type Props = { member: any; }; export const ProjectMemberListItem: React.FC = observer((props) => { const { member } = props; // router const router = useRouter(); const { workspaceSlug, projectId } = router.query; // states const [selectedRemoveMember, setSelectedRemoveMember] = useState(null); const [selectedInviteRemoveMember, setSelectedInviteRemoveMember] = useState(null); // store const { user: userStore, projectMember: { projectMembers, fetchProjectMembers, removeMemberFromProject, updateMember, deleteProjectInvitation, }, } = useMobxStore(); // hooks const { setToastAlert } = useToast(); // fetching project members useSWR( workspaceSlug && projectId ? `PROJECT_MEMBERS_${projectId.toString().toUpperCase()}` : null, workspaceSlug && projectId ? () => fetchProjectMembers(workspaceSlug.toString(), projectId.toString()) : null ); // derived values const user = userStore.currentUser; const { currentProjectMemberInfo, currentProjectRole } = userStore; const isAdmin = currentProjectRole === 20; const currentUser = projectMembers?.find((item) => item.member.id === user?.id); return ( <> { setSelectedRemoveMember(null); setSelectedInviteRemoveMember(null); }} data={selectedRemoveMember ?? selectedInviteRemoveMember} handleDelete={async () => { if (!workspaceSlug || !projectId) return; // if the user is a member if (selectedRemoveMember) { await removeMemberFromProject(workspaceSlug.toString(), projectId.toString(), selectedRemoveMember.id); } // if the user is an invite if (selectedInviteRemoveMember) { await deleteProjectInvitation( workspaceSlug.toString(), projectId.toString(), selectedInviteRemoveMember.id ); mutate(`PROJECT_INVITATIONS_${projectId.toString()}`); } setToastAlert({ type: "success", message: "Member removed successfully", title: "Success", }); }} />
{member.avatar && member.avatar !== "" ? ( {member.display_name ) : ( {(member.display_name ?? member.email ?? "?")[0]} )}
{member.member ? ( {member.first_name} {member.last_name} ) : (

{member.display_name || member.email}

)}

{member.display_name}

{isAdmin && ( <>

{member.email}

)}
{!member?.status && (

Pending

)} {ROLE[member.role as keyof typeof ROLE]} {member.memberId !== currentProjectMemberInfo?.id && ( )}
} value={member.role} onChange={(value: TUserProjectRole | undefined) => { if (!workspaceSlug || !projectId) return; updateMember(workspaceSlug.toString(), projectId.toString(), member.id, { role: value, }).catch((err) => { const error = err.error; const errorString = Array.isArray(error) ? error[0] : error; setToastAlert({ type: "error", title: "Error!", message: errorString ?? "An error occurred while updating member role. Please try again.", }); }); }} disabled={ member.memberId === user?.id || !member.member || (currentUser && currentUser.role !== 20 && currentUser.role < member.role) } placement="bottom-end" > {Object.keys(ROLE).map((key) => { if (currentProjectRole && currentProjectRole !== 20 && currentProjectRole < parseInt(key)) return null; return ( <>{ROLE[parseInt(key) as keyof typeof ROLE]} ); })} {isAdmin && ( )}
); });