import { FC, ReactElement, useState } from 'react'; import { Button, Input } from '@imphnen-frontend-service/ui/atoms'; import { useNavigate, useParams } from 'react-router'; import { useTeamById, useTeamMembers, useTeamJoinRequests, useInviteMember, useRemoveMember, useRespondToJoinRequest, ETeamMemberStatus, inviteMemberSchema, TInviteMemberForm, useAuthStore, } from '@imphnen-frontend-service/service'; import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { toast } from 'sonner'; const ManageMembersPage: FC = (): ReactElement => { const { teamId } = useParams<{ teamId: string }>(); const navigate = useNavigate(); const { session } = useAuthStore(); const [showInviteModal, setShowInviteModal] = useState(false); const { data: teamData, isLoading: isLoadingTeam } = useTeamById( teamId || '' ); const { data: membersData, isLoading: isLoadingMembers } = useTeamMembers( teamId || '' ); const { data: joinRequestsData } = useTeamJoinRequests(teamId || ''); const { mutateAsync: inviteMember, isPending: isInviting } = useInviteMember( teamId || '' ); const { mutateAsync: removeMember, isPending: isRemoving } = useRemoveMember( teamId || '' ); const { mutateAsync: respondToRequest, isPending: isResponding } = useRespondToJoinRequest(teamId || ''); const team = teamData?.data; const members = membersData?.data || []; const joinRequests = Array.isArray(joinRequestsData?.data) ? joinRequestsData.data : []; const currentUserId = session?.user?.id; const isLeader = currentUserId === team?.leader_id; const hasSubmission = team?.has_submission; const form = useForm({ resolver: zodResolver(inviteMemberSchema), mode: 'all', }); // Show loading state while fetching team data if (isLoadingTeam) { return (

Loading...

); } if (!isLeader) { return (

Access Denied

Only the team leader can manage members

); } const handleInvite = form.handleSubmit(async (data) => { try { await inviteMember(data); setShowInviteModal(false); form.reset(); } catch (error) { console.error('Failed to invite member:', error); } }); const handleRemove = async (userId: string) => { // eslint-disable-next-line no-restricted-globals if (confirm('Are you sure you want to remove this member?')) { try { await removeMember(userId); } catch (error) { console.error('Failed to remove member:', error); } } }; const handleApproveRequest = async (requestId: string) => { try { await respondToRequest({ requestId, action: 'approve' }); toast.success('Member added successfully!'); } catch (error) { console.error('Failed to approve request:', error); toast.error((error as Error).message || 'Failed to approve request'); } }; const handleRejectRequest = async (requestId: string) => { try { await respondToRequest({ requestId, action: 'reject' }); toast.success('Request rejected'); } catch (error) { console.error('Failed to reject request:', error); toast.error((error as Error).message || 'Failed to reject request'); } }; return (

Manage Members

{team?.name}

{/* Submission Lock Warning */} {hasSubmission && (
🔒

Team Locked

Your team has submitted a project. You cannot add or remove members after submission to maintain competition integrity.

)} {/* Join Requests */} {joinRequests.length > 0 && (

Join Requests ({joinRequests.length})

{joinRequests.map((request) => (
{request.user.avatar ? ( {request.user.fullname} ) : (
👤
)}

{request.user.fullname}

{request.user.email}

{request.user.location && (

📍 {request.user.location}

)}

"{request.message}"

))}
)} {/* Current Members */}

Current Members ({members.length})

{isLoadingMembers ? (

Loading members...

) : (
{members.map((member) => (
{member.user.avatar ? ( {member.user.fullname} ) : (
👤
)}

{member.user.fullname}

{member.user.email}

{member.user.location && (

📍 {member.user.location}

)}
{member.role === 'leader' && ( Leader )} {member.status === ETeamMemberStatus.PENDING && ( Pending Invitation )}
{member.role !== 'leader' && !hasSubmission && ( )}
))}
)}
{/* Warning */} {!hasSubmission && (

Note: Members cannot leave the team without your approval. Only you can remove members from the team.

)}
{/* Invite Member Modal */} {showInviteModal && (

Invite Member

Send an invitation to join your team. The invited member will see the invitation on their dashboard after logging in.

Important: The email you enter must match the GitHub email address the member uses to sign in.

{form.formState.errors.email && (

{form.formState.errors.email.message}

)}
)}
); }; export default ManageMembersPage;