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"; // services import { ProjectInvitationService } from "services/project"; // hooks import useToast from "hooks/use-toast"; // components import { ConfirmProjectMemberRemove } from "components/project"; // ui import { CustomMenu, CustomSelect } from "@plane/ui"; // icons import { ChevronDown, X } from "lucide-react"; // constants import { ROLE } from "constants/workspace"; // services const projectInvitationService = new ProjectInvitationService(); 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, project: projectStore } = useMobxStore(); // hooks const { setToastAlert } = useToast(); // fetching project members useSWR( workspaceSlug && projectId ? `PROJECT_MEMBERS_${projectId.toString().toUpperCase()}` : null, workspaceSlug && projectId ? () => projectStore.fetchProjectMembers(workspaceSlug.toString(), projectId.toString()) : null ); // derived values const user = userStore.currentUser; const { currentProjectRole } = userStore; const isAdmin = currentProjectRole === 20; const isOwner = currentProjectRole === 20; const projectMembers = projectStore.members?.[projectId?.toString()!]; 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 projectStore.removeMemberFromProject( workspaceSlug.toString(), projectId.toString(), selectedRemoveMember ); } // if the user is an invite if (selectedInviteRemoveMember) { await projectInvitationService.deleteProjectInvitation( workspaceSlug.toString(), projectId.toString(), selectedInviteRemoveMember ); 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 ? (
{(member.display_name || member.email)?.charAt(0)}
) : (
?
)}
{member.member ? ( {member.first_name} {member.last_name} ({member.display_name}) ) : (

{member.display_name || member.email}

)} {isOwner &&

{member.email}

}
{!member.member && (
Pending
)} {ROLE[member.role as keyof typeof ROLE]} {member.memberId !== user?.id && }
} value={member.role} onChange={(value: 5 | 10 | 15 | 20 | undefined) => { if (!workspaceSlug || !projectId) return; projectStore .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) } > {Object.keys(ROLE).map((key) => { if (currentUser && currentUser.role !== 20 && currentUser.role < parseInt(key)) return null; return ( <>{ROLE[parseInt(key) as keyof typeof ROLE]} ); })} { if (member.member) setSelectedRemoveMember(member.id); else setSelectedInviteRemoveMember(member.id); }} > {member.memberId !== user?.id ? "Remove member" : "Leave project"}
); });