'use client'; import { useState, useEffect } from 'react'; import Card from '@/components/ui/Card'; import DriverIdentity from '@/components/drivers/DriverIdentity'; import { getTeamRosterViewModel, type TeamRosterViewModel, } from '@/lib/presenters/TeamRosterPresenter'; import type { TeamRole } from '@gridpilot/racing/domain/types/TeamMembership'; interface TeamMembershipSummary { driverId: string; role: TeamRole; joinedAt: Date; } interface TeamRosterProps { teamId: string; memberships: TeamMembershipSummary[]; isAdmin: boolean; onRemoveMember?: (driverId: string) => void; onChangeRole?: (driverId: string, newRole: TeamRole) => void; } export default function TeamRoster({ teamId, memberships, isAdmin, onRemoveMember, onChangeRole, }: TeamRosterProps) { const [viewModel, setViewModel] = useState(null); const [loading, setLoading] = useState(true); const [sortBy, setSortBy] = useState<'role' | 'rating' | 'name'>('rating'); useEffect(() => { const load = async () => { setLoading(true); try { const fullMemberships = memberships.map((m) => ({ teamId, driverId: m.driverId, role: m.role, joinedAt: m.joinedAt, status: 'active' as const, })); const vm = await getTeamRosterViewModel(fullMemberships); setViewModel(vm); } finally { setLoading(false); } }; void load(); }, [memberships]); const getRoleBadgeColor = (role: TeamRole) => { switch (role) { case 'owner': return 'bg-warning-amber/20 text-warning-amber'; case 'manager': return 'bg-primary-blue/20 text-primary-blue'; default: return 'bg-charcoal-outline text-gray-300'; } }; const getRoleLabel = (role: TeamRole) => { return role.charAt(0).toUpperCase() + role.slice(1); }; function getRoleOrder(role: TeamRole): number { switch (role) { case 'owner': return 0; case 'manager': return 1; case 'driver': return 2; default: return 3; } } const sortedMembers = viewModel ? [...viewModel.members].sort((a, b) => { switch (sortBy) { case 'rating': { const ratingA = a.rating ?? 0; const ratingB = b.rating ?? 0; return ratingB - ratingA; } case 'role': { return getRoleOrder(a.role) - getRoleOrder(b.role); } case 'name': { return a.driver.name.localeCompare(b.driver.name); } default: return 0; } }) : []; const teamAverageRating = viewModel?.averageRating ?? 0; if (loading) { return (
Loading roster...
); } return (

Team Roster

{memberships.length} {memberships.length === 1 ? 'member' : 'members'} • Avg Rating:{' '} {teamAverageRating}

{sortedMembers.map((member) => { const { driver, role, joinedAt, rating, overallRank } = member; const canManageMembership = isAdmin && role !== 'owner'; return (
{driver.country} • Joined {new Date(joinedAt).toLocaleDateString()} } size="md" /> {rating !== null && (
{rating}
Rating
{overallRank !== null && (
#{overallRank}
Rank
)}
)} {canManageMembership && (
)}
); })}
{memberships.length === 0 && (
No team members yet.
)}
); }