'use client'; import { useState, useEffect, useCallback } from 'react'; import { useRouter } from 'next/navigation'; import { Race } from '@gridpilot/racing/domain/entities/Race'; import { getRaceRepository, getIsDriverRegisteredForRaceQuery, getRegisterForRaceUseCase, getWithdrawFromRaceUseCase, } from '@/lib/di-container'; import { useEffectiveDriverId } from '@/lib/currentDriver'; interface LeagueScheduleProps { leagueId: string; } export default function LeagueSchedule({ leagueId }: LeagueScheduleProps) { const router = useRouter(); const [races, setRaces] = useState([]); const [loading, setLoading] = useState(true); const [filter, setFilter] = useState<'all' | 'upcoming' | 'past'>('upcoming'); const [registrationStates, setRegistrationStates] = useState>({}); const [processingRace, setProcessingRace] = useState(null); const currentDriverId = useEffectiveDriverId(); const loadRaces = useCallback(async () => { setLoading(true); try { const raceRepo = getRaceRepository(); const allRaces = await raceRepo.findAll(); const leagueRaces = allRaces .filter((race) => race.leagueId === leagueId) .sort( (a, b) => new Date(a.scheduledAt).getTime() - new Date(b.scheduledAt).getTime(), ); setRaces(leagueRaces); const isRegisteredQuery = getIsDriverRegisteredForRaceQuery(); const states: Record = {}; await Promise.all( leagueRaces.map(async (race) => { const registered = await isRegisteredQuery.execute({ raceId: race.id, driverId: currentDriverId, }); states[race.id] = registered; }), ); setRegistrationStates(states); } catch (error) { console.error('Failed to load races:', error); } finally { setLoading(false); } }, [leagueId, currentDriverId]); useEffect(() => { loadRaces(); }, [loadRaces]); const handleRegister = async (race: Race, e: React.MouseEvent) => { e.stopPropagation(); const confirmed = window.confirm( `Register for ${race.track}?` ); if (!confirmed) return; setProcessingRace(race.id); try { const useCase = getRegisterForRaceUseCase(); await useCase.execute({ raceId: race.id, leagueId, driverId: currentDriverId, }); setRegistrationStates((prev) => ({ ...prev, [race.id]: true })); } catch (err) { alert(err instanceof Error ? err.message : 'Failed to register'); } finally { setProcessingRace(null); } }; const handleWithdraw = async (race: Race, e: React.MouseEvent) => { e.stopPropagation(); const confirmed = window.confirm( 'Withdraw from this race?' ); if (!confirmed) return; setProcessingRace(race.id); try { const useCase = getWithdrawFromRaceUseCase(); await useCase.execute({ raceId: race.id, driverId: currentDriverId, }); setRegistrationStates((prev) => ({ ...prev, [race.id]: false })); } catch (err) { alert(err instanceof Error ? err.message : 'Failed to withdraw'); } finally { setProcessingRace(null); } }; const now = new Date(); const upcomingRaces = races.filter(race => race.status === 'scheduled' && new Date(race.scheduledAt) > now); const pastRaces = races.filter(race => race.status === 'completed' || new Date(race.scheduledAt) <= now); const getDisplayRaces = () => { switch (filter) { case 'upcoming': return upcomingRaces; case 'past': return pastRaces.reverse(); case 'all': return [...upcomingRaces, ...pastRaces.reverse()]; default: return races; } }; const displayRaces = getDisplayRaces(); if (loading) { return (
Loading schedule...
); } return (
{/* Filter Controls */}

{displayRaces.length} {displayRaces.length === 1 ? 'race' : 'races'}

{/* Race List */} {displayRaces.length === 0 ? (

No {filter} races

{filter === 'upcoming' && (

Schedule your first race to get started

)}
) : (
{displayRaces.map((race) => { const isPast = race.status === 'completed' || new Date(race.scheduledAt) <= now; const isUpcoming = race.status === 'scheduled' && new Date(race.scheduledAt) > now; return (
router.push(`/leagues/${leagueId}/races/${race.id}`)} >

{race.track}

{isUpcoming && !registrationStates[race.id] && ( Upcoming )} {isUpcoming && registrationStates[race.id] && ( ✓ Registered )} {isPast && ( Completed )}

{race.car}

{race.sessionType}

{new Date(race.scheduledAt).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric', })}

{new Date(race.scheduledAt).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', })}

{isPast && race.status === 'completed' && (

View Results →

)}
{/* Registration Actions */} {isUpcoming && (
e.stopPropagation()}> {!registrationStates[race.id] ? ( ) : ( )}
)}
); })}
)}
); }