'use client'; import { useState, useEffect } from 'react'; import { useRouter, useParams } from 'next/navigation'; import Button from '@/components/ui/Button'; import Card from '@/components/ui/Card'; import FeatureLimitationTooltip from '@/components/alpha/FeatureLimitationTooltip'; import type { Race } from '@gridpilot/racing/domain/entities/Race'; import type { League } from '@gridpilot/racing/domain/entities/League'; import type { Driver } from '@gridpilot/racing/domain/entities/Driver'; import { getRaceRepository, getLeagueRepository, getDriverRepository } from '@/lib/di-container'; import { getMembership, getCurrentDriverId, isRegistered, registerForRace, withdrawFromRace, getRegisteredDrivers, } from '@gridpilot/racing/application'; import CompanionStatus from '@/components/alpha/CompanionStatus'; import CompanionInstructions from '@/components/alpha/CompanionInstructions'; import Breadcrumbs from '@/components/layout/Breadcrumbs'; export default function RaceDetailPage() { const router = useRouter(); const params = useParams(); const raceId = params.id as string; const [race, setRace] = useState(null); const [league, setLeague] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [cancelling, setCancelling] = useState(false); const [registering, setRegistering] = useState(false); const [entryList, setEntryList] = useState([]); const [isUserRegistered, setIsUserRegistered] = useState(false); const [canRegister, setCanRegister] = useState(false); const currentDriverId = getCurrentDriverId(); const loadRaceData = async () => { try { const raceRepo = getRaceRepository(); const leagueRepo = getLeagueRepository(); const raceData = await raceRepo.findById(raceId); if (!raceData) { setError('Race not found'); setLoading(false); return; } setRace(raceData); // Load league data const leagueData = await leagueRepo.findById(raceData.leagueId); setLeague(leagueData); // Load entry list await loadEntryList(raceData.id, raceData.leagueId); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to load race'); } finally { setLoading(false); } }; const loadEntryList = async (raceId: string, leagueId: string) => { try { const driverRepo = getDriverRepository(); const registeredDriverIds = getRegisteredDrivers(raceId); const drivers = await Promise.all( registeredDriverIds.map(id => driverRepo.findById(id)) ); setEntryList( drivers.filter((d: Driver | null): d is Driver => d !== null) ); // Check user registration status const userIsRegistered = isRegistered(raceId, currentDriverId); setIsUserRegistered(userIsRegistered); // Check if user can register (is league member and race is upcoming) const membership = getMembership(leagueId, currentDriverId); const isUpcoming = race?.status === 'scheduled'; setCanRegister(!!membership && membership.status === 'active' && !!isUpcoming); } catch (err) { console.error('Failed to load entry list:', err); } }; useEffect(() => { loadRaceData(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [raceId]); const handleCancelRace = async () => { if (!race || race.status !== 'scheduled') return; const confirmed = window.confirm( 'Are you sure you want to cancel this race? This action cannot be undone.' ); if (!confirmed) return; setCancelling(true); try { const raceRepo = getRaceRepository(); const cancelledRace = race.cancel(); await raceRepo.update(cancelledRace); setRace(cancelledRace); } catch (err) { alert(err instanceof Error ? err.message : 'Failed to cancel race'); } finally { setCancelling(false); } }; const handleRegister = async () => { if (!race || !league) return; const confirmed = window.confirm( `Register for ${race.track}?\n\nYou'll be added to the entry list for this race.` ); if (!confirmed) return; setRegistering(true); try { registerForRace(race.id, currentDriverId, league.id); await loadEntryList(race.id, league.id); } catch (err) { alert(err instanceof Error ? err.message : 'Failed to register for race'); } finally { setRegistering(false); } }; const handleWithdraw = async () => { if (!race || !league) return; const confirmed = window.confirm( 'Withdraw from this race?\n\nYou can register again later if you change your mind.' ); if (!confirmed) return; setRegistering(true); try { withdrawFromRace(race.id, currentDriverId); await loadEntryList(race.id, league.id); } catch (err) { alert(err instanceof Error ? err.message : 'Failed to withdraw from race'); } finally { setRegistering(false); } }; const formatDate = (date: Date) => { return new Date(date).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric', }); }; const formatTime = (date: Date) => { return new Date(date).toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', timeZoneName: 'short', }); }; const formatDateTime = (date: Date) => { return new Date(date).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric', hour: '2-digit', minute: '2-digit', timeZoneName: 'short', }); }; const statusColors = { scheduled: 'bg-primary-blue/20 text-primary-blue border-primary-blue/30', completed: 'bg-green-500/20 text-green-400 border-green-500/30', cancelled: 'bg-gray-500/20 text-gray-400 border-gray-500/30', } as const; if (loading) { return (
Loading race details...
); } if (error || !race) { return (
{error || 'Race not found'}
); } return (
{/* Breadcrumb */}
{/* Companion Status */}
{/* Race Header */}

{race.track}

{league && (

{league.name}

)}
{race.status.charAt(0).toUpperCase() + race.status.slice(1)}
{/* Companion Instructions for Scheduled Races */} {race.status === 'scheduled' && (
)}
{/* Race Details */}

Race Details

{/* Date & Time */}

{formatDateTime(race.scheduledAt)}

{formatDate(race.scheduledAt)} {formatTime(race.scheduledAt)}
{/* Track */}

{race.track}

{/* Car */}

{race.car}

{/* Session Type */}

{race.sessionType}

{/* League */}
{league ? ( ) : (

ID: {race.leagueId.slice(0, 8)}...

)}
{/* Actions */}

Actions

{/* Registration Actions */} {race.status === 'scheduled' && canRegister && !isUserRegistered && ( )} {race.status === 'scheduled' && isUserRegistered && (
✓ Registered
)} {race.status === 'completed' && ( )} {race.status === 'scheduled' && ( )}
{/* Entry List */} {race.status === 'scheduled' && (

Entry List

{entryList.length} {entryList.length === 1 ? 'driver' : 'drivers'} registered
{entryList.length === 0 ? (

No drivers registered yet

Be the first to register!

) : (
{entryList.map((driver, index) => (
router.push(`/drivers/${driver.id}`)} >
#{index + 1}
{driver.name.charAt(0)}

{driver.name}

{driver.country}

{driver.id === currentDriverId && ( You )}
))}
)}
)}
); }