'use client' import { useState, useEffect } from 'react' import { Button, Input, Select, toast, Spinner } from '@ciphera-net/ui' import { Plus, Trash, EnvelopeSimple, Crown, UserCircle } from '@phosphor-icons/react' import { useAuth } from '@/lib/auth/context' import { getOrganizationMembers, sendInvitation, type OrganizationMember } from '@/lib/api/organization' import { getAuthErrorMessage } from '@ciphera-net/ui' const ROLE_OPTIONS = [ { value: 'admin', label: 'Admin' }, { value: 'member', label: 'Member' }, ] function RoleBadge({ role }: { role: string }) { if (role === 'owner') return ( Owner ) if (role === 'admin') return ( Admin ) return ( Member ) } export default function WorkspaceMembersTab() { const { user } = useAuth() const [members, setMembers] = useState([]) const [loading, setLoading] = useState(true) const [inviteEmail, setInviteEmail] = useState('') const [inviteRole, setInviteRole] = useState('member') const [inviting, setInviting] = useState(false) const [showInvite, setShowInvite] = useState(false) const canManage = user?.role === 'owner' || user?.role === 'admin' const loadMembers = async () => { if (!user?.org_id) return try { const data = await getOrganizationMembers(user.org_id) setMembers(data) } catch { } finally { setLoading(false) } } useEffect(() => { loadMembers() }, [user?.org_id]) const handleInvite = async () => { if (!user?.org_id || !inviteEmail.trim()) return setInviting(true) try { await sendInvitation(user.org_id, inviteEmail.trim(), inviteRole) toast.success(`Invitation sent to ${inviteEmail}`) setInviteEmail('') setShowInvite(false) loadMembers() } catch (err) { toast.error(getAuthErrorMessage(err as Error) || 'Failed to invite member') } finally { setInviting(false) } } const handleRemove = async (_memberId: string, email: string) => { // Member removal requires the full org settings page (auth API endpoint) toast.message(`To remove ${email}, use Organization Settings → Members.`, { action: { label: 'Open', onClick: () => { window.location.href = '/org-settings?tab=members' } }, }) } if (loading) return return ( Members {members.length} member{members.length !== 1 ? 's' : ''} in your organization. {canManage && !showInvite && ( setShowInvite(true)} variant="primary" className="text-sm gap-1.5"> Invite )} {/* Invite form */} {showInvite && ( setInviteEmail(e.target.value)} placeholder="email@example.com" type="email" /> setShowInvite(false)} variant="secondary" className="text-sm">Cancel {inviting ? 'Sending...' : 'Send Invite'} )} {/* Members list */} {members.map(member => ( {member.user_email || member.user_id} {canManage && member.role !== 'owner' && member.user_id !== user?.id && ( handleRemove(member.user_id, member.user_email || member.user_id)} className="p-1.5 rounded-lg text-neutral-500 hover:text-red-400 hover:bg-red-900/20 transition-colors opacity-0 group-hover:opacity-100" > )} ))} ) }
{members.length} member{members.length !== 1 ? 's' : ''} in your organization.
{member.user_email || member.user_id}