import { IconCrown as Crown, IconLoader2 as Loader2, IconDots as MoreHorizontal, IconShield as Shield, IconTrash as Trash2, IconUser as User, IconUserPlus as UserPlus, } from '@tabler/icons-react'; import { useState } from 'react'; import { useNavigate, useParams } from 'react-router'; import { useAuth } from '@/components/auth/AuthProvider'; import { PageHeader } from '@/components/PageHeader'; import { Avatar, AvatarFallback } from '@/components/ui/avatar'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select'; import { type Member, type MemberRole, useOrganizationMembers, } from '@/hooks/useOrganizationMembers'; import { useOrganizations } from '@/hooks/useOrganizations'; import { ContentPanel } from '../../components/ContentPanel'; function getRoleIcon(role: MemberRole) { switch (role) { case 'OWNER': return ; case 'ADMIN': return ; default: return ; } } function getRoleBadgeVariant(role: MemberRole) { switch (role) { case 'OWNER': return 'default'; case 'ADMIN': return 'secondary'; default: return 'outline'; } } function getUserInitials(member: Member) { if (!member.user) return '?'; const name = member.user.name; if (name) { return name .split(' ') .map((n) => n[0]) .join('') .toUpperCase() .slice(0, 2); } return member.user.email?.[0]?.toUpperCase() || '?'; } export default function Members() { const { orgId } = useParams<{ orgId: string }>(); const navigate = useNavigate(); const { user } = useAuth(); const { organizations } = useOrganizations(); const { members, isLoading, error, addMember, updateRole, removeMember } = useOrganizationMembers(orgId); const [isAddMemberOpen, setIsAddMemberOpen] = useState(false); const [newMemberEmail, setNewMemberEmail] = useState(''); const [newMemberRole, setNewMemberRole] = useState<'ADMIN' | 'MEMBER'>('MEMBER'); const [memberToRemove, setMemberToRemove] = useState(null); const organization = organizations.find((org) => org.id === orgId); const currentUserMembership = members.find((m) => m.user?.id === user?.id); const isAdmin = currentUserMembership?.role === 'OWNER' || currentUserMembership?.role === 'ADMIN'; const isOwner = currentUserMembership?.role === 'OWNER'; const handleAddMember = async () => { if (!newMemberEmail.trim()) return; try { await addMember.mutateAsync({ email: newMemberEmail.trim(), role: newMemberRole }); setNewMemberEmail(''); setNewMemberRole('MEMBER'); setIsAddMemberOpen(false); } catch { // Error is handled by mutation } }; const handleUpdateRole = async (userId: string, role: MemberRole) => { try { await updateRole.mutateAsync({ userId, role }); } catch { // Error is handled by mutation } }; const handleRemoveMember = async () => { if (!memberToRemove?.user) return; try { await removeMember.mutateAsync(memberToRemove.user.id); setMemberToRemove(null); } catch { // Error is handled by mutation } }; if (!organization) { return ( <>

The organization you're looking for doesn't exist or you don't have access.

); } return ( <>

Team Members

Manage who has access to {organization.name}

{isAdmin && ( )}
Members ({members.length}) People with access to this organization. {isLoading ? (
) : error ? (
{error instanceof Error ? error.message : 'Failed to load members'}
) : (
{members.map((member) => (
{getUserInitials(member)}

{member.user?.name || member.user?.email || 'Unknown'} {member.user?.id === user?.id && ( (you) )}

{member.user?.name && (

{member.user.email}

)}
{getRoleIcon(member.role)} {member.role} {isAdmin && member.user?.id !== user?.id && ( }> {isOwner && member.role !== 'OWNER' && member.user && ( <> handleUpdateRole(member.user?.id ?? '', 'OWNER')} > Transfer Ownership )} {member.role === 'MEMBER' && member.user && ( handleUpdateRole(member.user?.id ?? '', 'ADMIN')} > Make Admin )} {member.role === 'ADMIN' && isOwner && member.user && ( handleUpdateRole(member.user?.id ?? '', 'MEMBER')} > Remove Admin )} {member.role !== 'OWNER' && (isOwner || member.role === 'MEMBER') && ( <> setMemberToRemove(member)} > Remove )} )} {member.user?.id === user?.id && member.role !== 'OWNER' && ( )}
))}
)}
{/* Add Member Dialog */} Add Member Invite someone to join this organization. They must already have an account.
setNewMemberEmail(e.target.value)} onKeyDown={(e) => { if (e.key === 'Enter' && !addMember.isPending) { handleAddMember(); } }} disabled={addMember.isPending} />
{addMember.error && (

{addMember.error instanceof Error ? addMember.error.message : 'Failed to add member'}

)}
{/* Remove Member Dialog */} setMemberToRemove(null)}> {memberToRemove?.user?.id === user?.id ? 'Leave Organization' : 'Remove Member'} {memberToRemove?.user?.id === user?.id ? 'Are you sure you want to leave this organization? You will lose access to all organization resources.' : `Are you sure you want to remove ${memberToRemove?.user?.name || memberToRemove?.user?.email} from this organization?`} {removeMember.error && (

{removeMember.error instanceof Error ? removeMember.error.message : 'Failed to remove member'}

)}
); }