'use client'; import { useState, useEffect, useCallback } from 'react'; import DriverIdentity from '@/components/drivers/DriverIdentity'; import type { DriverDTO } from '@gridpilot/racing/application/dto/DriverDTO'; import { EntityMappers } from '@gridpilot/racing/application/mappers/EntityMappers'; import { getDriverRepository, getDriverStats } from '@/lib/di-container'; import { getLeagueMembers, type LeagueMembership, type MembershipRole, } from '@/lib/leagueMembership'; import { useEffectiveDriverId } from '@/lib/currentDriver'; interface LeagueMembersProps { leagueId: string; onRemoveMember?: (driverId: string) => void; onUpdateRole?: (driverId: string, role: MembershipRole) => void; showActions?: boolean; } export default function LeagueMembers({ leagueId, onRemoveMember, onUpdateRole, showActions = false }: LeagueMembersProps) { const [members, setMembers] = useState([]); const [driversById, setDriversById] = useState>({}); const [loading, setLoading] = useState(true); const [sortBy, setSortBy] = useState<'role' | 'name' | 'date' | 'rating' | 'points' | 'wins'>('rating'); const currentDriverId = useEffectiveDriverId(); const loadMembers = useCallback(async () => { setLoading(true); try { const membershipData = getLeagueMembers(leagueId); setMembers(membershipData); const driverRepo = getDriverRepository(); const driverEntities = await Promise.all( membershipData.map((m) => driverRepo.findById(m.driverId)) ); const driverDtos = driverEntities .map((driver) => (driver ? EntityMappers.toDriverDTO(driver) : null)) .filter((dto): dto is DriverDTO => dto !== null); const byId: Record = {}; for (const dto of driverDtos) { byId[dto.id] = dto; } setDriversById(byId); } catch (error) { console.error('Failed to load members:', error); } finally { setLoading(false); } }, [leagueId]); useEffect(() => { loadMembers(); }, [loadMembers]); const getDriverName = (driverId: string): string => { const driver = driversById[driverId]; return driver?.name || 'Unknown Driver'; }; const getRoleOrder = (role: MembershipRole): number => { const order = { owner: 0, admin: 1, steward: 2, member: 3 }; return order[role]; }; const sortedMembers = [...members].sort((a, b) => { switch (sortBy) { case 'role': return getRoleOrder(a.role) - getRoleOrder(b.role); case 'name': return getDriverName(a.driverId).localeCompare(getDriverName(b.driverId)); case 'date': return new Date(b.joinedAt).getTime() - new Date(a.joinedAt).getTime(); case 'rating': { const statsA = getDriverStats(a.driverId); const statsB = getDriverStats(b.driverId); return (statsB?.rating || 0) - (statsA?.rating || 0); } case 'points': return 0; case 'wins': { const statsA = getDriverStats(a.driverId); const statsB = getDriverStats(b.driverId); return (statsB?.wins || 0) - (statsA?.wins || 0); } default: return 0; } }); const getRoleBadgeColor = (role: MembershipRole): string => { switch (role) { case 'owner': return 'bg-yellow-500/10 text-yellow-500 border-yellow-500/30'; case 'admin': return 'bg-purple-500/10 text-purple-400 border-purple-500/30'; case 'steward': return 'bg-blue-500/10 text-blue-400 border-blue-500/30'; case 'member': return 'bg-primary-blue/10 text-primary-blue border-primary-blue/30'; } }; if (loading) { return (
Loading members...
); } if (members.length === 0) { return (
No members found
); } return (
{/* Sort Controls */}

{members.length} {members.length === 1 ? 'member' : 'members'}

{/* Members Table */}
{showActions && } {sortedMembers.map((member, index) => { const isCurrentUser = member.driverId === currentDriverId; const cannotModify = member.role === 'owner'; const driverStats = getDriverStats(member.driverId); const isTopPerformer = index < 3 && sortBy === 'rating'; const driver = driversById[member.driverId]; const roleLabel = member.role.charAt(0).toUpperCase() + member.role.slice(1); const ratingAndWinsMeta = driverStats && typeof driverStats.rating === 'number' ? `Rating ${driverStats.rating} • ${driverStats.wins ?? 0} wins` : null; return ( {showActions && ( )} ); })}
Driver Rating Rank Wins Role JoinedActions
{driver ? ( ) : ( Unknown Driver )} {isCurrentUser && ( (You) )} {isTopPerformer && ( )}
{driverStats?.rating || '—'} #{driverStats?.overallRank || '—'} {driverStats?.wins || 0} {member.role.charAt(0).toUpperCase() + member.role.slice(1)} {new Date(member.joinedAt).toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric', })} {!cannotModify && !isCurrentUser && (
{onUpdateRole && ( )} {onRemoveMember && ( )}
)} {cannotModify && ( )}
); }