'use client'; import { useState, useEffect, useMemo } from 'react'; import { useRouter, useParams } from 'next/navigation'; import Button from '@/components/ui/Button'; import Card from '@/components/ui/Card'; import JoinLeagueButton from '@/components/leagues/JoinLeagueButton'; import LeagueActivityFeed from '@/components/leagues/LeagueActivityFeed'; import DriverIdentity from '@/components/drivers/DriverIdentity'; import DriverSummaryPill from '@/components/profile/DriverSummaryPill'; import { League, Driver, EntityMappers, type DriverDTO, type LeagueScoringConfigDTO, } from '@gridpilot/racing'; import { getLeagueRepository, getRaceRepository, getDriverRepository, getGetLeagueScoringConfigQuery, getDriverStats, getAllDriverRankings, getGetLeagueStatsQuery, } from '@/lib/di-container'; import { Zap, Users, Trophy, Calendar } from 'lucide-react'; import { getMembership, getLeagueMembers } from '@/lib/leagueMembership'; import { useEffectiveDriverId } from '@/lib/currentDriver'; import { getLeagueRoleDisplay } from '@/lib/leagueRoles'; export default function LeagueDetailPage() { const router = useRouter(); const params = useParams(); const leagueId = params.id as string; const [league, setLeague] = useState(null); const [owner, setOwner] = useState(null); const [drivers, setDrivers] = useState([]); const [scoringConfig, setScoringConfig] = useState(null); const [averageSOF, setAverageSOF] = useState(null); const [completedRacesCount, setCompletedRacesCount] = useState(0); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [refreshKey, setRefreshKey] = useState(0); const currentDriverId = useEffectiveDriverId(); const membership = getMembership(leagueId, currentDriverId); const loadLeagueData = async () => { try { const leagueRepo = getLeagueRepository(); const raceRepo = getRaceRepository(); const driverRepo = getDriverRepository(); const leagueStatsQuery = getGetLeagueStatsQuery(); const leagueData = await leagueRepo.findById(leagueId); if (!leagueData) { setError('League not found'); setLoading(false); return; } setLeague(leagueData); // Load owner data const ownerData = await driverRepo.findById(leagueData.ownerId); setOwner(ownerData); // Load scoring configuration for the active season const getLeagueScoringConfigQuery = getGetLeagueScoringConfigQuery(); const scoring = await getLeagueScoringConfigQuery.execute({ leagueId }); setScoringConfig(scoring); // Load all drivers for standings and map to DTOs for UI components const allDrivers = await driverRepo.findAll(); const driverDtos: DriverDTO[] = allDrivers .map((driver) => EntityMappers.toDriverDTO(driver)) .filter((dto): dto is DriverDTO => dto !== null); setDrivers(driverDtos); // Load league stats including average SOF from application query const leagueStats = await leagueStatsQuery.execute({ leagueId }); if (leagueStats) { setAverageSOF(leagueStats.averageSOF); setCompletedRacesCount(leagueStats.completedRaces); } else { // Fallback: count completed races manually const leagueRaces = await raceRepo.findByLeagueId(leagueId); const completedRaces = leagueRaces.filter(r => r.status === 'completed'); setCompletedRacesCount(completedRaces.length); } } catch (err) { setError(err instanceof Error ? err.message : 'Failed to load league'); } finally { setLoading(false); } }; useEffect(() => { loadLeagueData(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [leagueId]); const handleMembershipChange = () => { setRefreshKey(prev => prev + 1); loadLeagueData(); }; const driversById = useMemo(() => { const map: Record = {}; for (const d of drivers) { map[d.id] = d; } return map; }, [drivers]); const leagueMemberships = getLeagueMembers(leagueId); const ownerMembership = leagueMemberships.find((m) => m.role === 'owner') ?? null; const adminMemberships = leagueMemberships.filter((m) => m.role === 'admin'); const stewardMemberships = leagueMemberships.filter((m) => m.role === 'steward'); const buildDriverSummary = (driverId: string) => { const driverDto = driversById[driverId]; if (!driverDto) { return null; } const stats = getDriverStats(driverDto.id); const allRankings = getAllDriverRankings(); let rating: number | null = stats?.rating ?? null; let rank: number | null = null; if (stats) { if (typeof stats.overallRank === 'number' && stats.overallRank > 0) { rank = stats.overallRank; } else { const indexInGlobal = allRankings.findIndex( (stat) => stat.driverId === stats.driverId, ); if (indexInGlobal !== -1) { rank = indexInGlobal + 1; } } if (rating === null) { const globalEntry = allRankings.find( (stat) => stat.driverId === stats.driverId, ); if (globalEntry) { rating = globalEntry.rating; } } } return { driver: driverDto, rating, rank, }; }; return loading ? (
Loading league...
) : error || !league ? (
{error || 'League not found'}
) : ( <> {/* Action Card */} {!membership && (

Join This League

Become a member to participate in races and track your progress

)} {/* League Overview - Activity Center with Info Sidebar */}
{/* Center - Activity Feed */}

Recent Activity

{/* Right Sidebar - League Info */}
{/* League Info - Combined */}

About

{/* Stats Grid */}
{leagueMemberships.length}
Members
{completedRacesCount}
Races
{averageSOF ?? '—'}
Avg SOF
{/* Details */}
Structure Solo • {league.settings.maxDrivers ?? 32} max
Scoring {scoringConfig?.scoringPresetName ?? 'Standard'}
Created {new Date(league.createdAt).toLocaleDateString('en-US', { month: 'short', year: 'numeric' })}
{league.socialLinks && (
{league.socialLinks.discordUrl && ( Discord )} {league.socialLinks.youtubeUrl && ( YouTube )} {league.socialLinks.websiteUrl && ( Website )}
)}
{/* Management */} {(ownerMembership || adminMemberships.length > 0 || stewardMemberships.length > 0) && (

Management

{ownerMembership && (() => { const driverDto = driversById[ownerMembership.driverId]; const summary = buildDriverSummary(ownerMembership.driverId); const roleDisplay = getLeagueRoleDisplay('owner'); const meta = summary && summary.rating !== null ? `Rating ${summary.rating}${summary.rank ? ` • Rank ${summary.rank}` : ''}` : null; return driverDto ? (
{roleDisplay.text}
) : null; })()} {adminMemberships.slice(0, 3).map((membership) => { const driverDto = driversById[membership.driverId]; const summary = buildDriverSummary(membership.driverId); const roleDisplay = getLeagueRoleDisplay('admin'); const meta = summary && summary.rating !== null ? `Rating ${summary.rating}${summary.rank ? ` • Rank ${summary.rank}` : ''}` : null; return driverDto ? (
{roleDisplay.text}
) : null; })} {stewardMemberships.slice(0, 3).map((membership) => { const driverDto = driversById[membership.driverId]; const summary = buildDriverSummary(membership.driverId); const roleDisplay = getLeagueRoleDisplay('steward'); const meta = summary && summary.rating !== null ? `Rating ${summary.rating}${summary.rank ? ` • Rank ${summary.rank}` : ''}` : null; return driverDto ? (
{roleDisplay.text}
) : null; })}
)}
); }