import { ArrowRight, Check, User, X } from 'lucide-react' import Link from 'next/link' import { useMemo } from 'react' import { useParams } from 'common' import PartnerIcon from 'components/ui/PartnerIcon' import { ProfileImage } from 'components/ui/ProfileImage' import { useOrganizationRolesV2Query } from 'data/organization-members/organization-roles-query' import { OrganizationMember } from 'data/organizations/organization-members-query' import { useOrgProjectsInfiniteQuery } from 'data/projects/org-projects-infinite-query' import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { getGitHubProfileImgUrl } from 'lib/github' import { useProfile } from 'lib/profile' import { Badge, HoverCardContent_Shadcn_, HoverCardTrigger_Shadcn_, HoverCard_Shadcn_, ScrollArea, TableCell, TableRow, cn, } from 'ui' import { ShimmeringLoader } from 'ui-patterns/ShimmeringLoader' import { isInviteExpired } from '../Organization.utils' import { MemberActions } from './MemberActions' interface MemberRowProps { member: OrganizationMember } const MEMBER_ORIGIN_TO_MANAGED_BY = { vercel: 'vercel-marketplace', } as const export const MemberRow = ({ member }: MemberRowProps) => { const { slug } = useParams() const { profile } = useProfile() const { data: selectedOrganization } = useSelectedOrganizationQuery() const { data: roles, isPending: isLoadingRoles } = useOrganizationRolesV2Query({ slug: selectedOrganization?.slug, }) const hasProjectScopedRoles = (roles?.project_scoped_roles ?? []).length > 0 const { data: projectsData } = useOrgProjectsInfiniteQuery({ slug }) const orgProjects = useMemo(() => projectsData?.pages.flatMap((page) => page.projects), [projectsData?.pages]) || [] const isInvitedUser = Boolean(member.invited_id) const isEmailUser = member.username === member.primary_email const isFlyUser = Boolean(member.primary_email?.endsWith('customer.fly.io')) const profileImageUrl = isInvitedUser || isEmailUser || isFlyUser ? undefined : getGitHubProfileImgUrl(member.username) return (
} />

{member.primary_email}

{member.gotrue_id === profile?.gotrue_id && You}
{(member.metadata as any)?.origin && ( )}
{isInvitedUser && member.invited_at && ( {isInviteExpired(member.invited_at) ? 'Expired' : 'Invited'} )} {member.is_sso_user && SSO}
{member.mfa_enabled ? ( ) : ( )}
{isLoadingRoles ? ( ) : ( member.role_ids.map((id) => { const orgScopedRole = (roles?.org_scoped_roles ?? []).find((role) => role.id === id) const projectScopedRole = (roles?.project_scoped_roles ?? []).find( (role) => role.id === id ) const role = orgScopedRole || projectScopedRole const roleName = (role?.name ?? '').split('_')[0] const projectsApplied = role?.projects.length === 0 ? orgProjects?.map((p) => p.name) ?? [] : (role?.projects ?? []) .map(({ ref }) => orgProjects?.find((p) => p.ref === ref)?.name ?? '') .filter((x) => x.length > 0) return (

{roleName}

{hasProjectScopedRoles && ( <> • {projectsApplied.length === 1 ? ( {projectsApplied[0]} ) : ( {role?.projects.length === 0 ? 'Organization' : `${projectsApplied.length} project${projectsApplied.length > 1 ? 's' : ''}`}

{roleName} role applies to {projectsApplied.length} project {projectsApplied.length > 1 ? 's' : ''}

5 ? 'h-[130px]' : '')} > {projectsApplied.map((name) => { const ref = orgProjects?.find((p) => p.name === name)?.ref return ( {name} Go to project ) })}
)} )}
) }) )}
) }