'use client'; import { useMemo, useState } from 'react'; import { useRouter } from 'next/navigation'; import type { LeagueScheduleViewModel, LeagueScheduleRaceViewModel } from '@/lib/view-models/LeagueScheduleViewModel'; import { StateContainer } from '@/components/shared/state/StateContainer'; import { EmptyState } from '@/components/shared/state/EmptyState'; import { Calendar } from 'lucide-react'; import { useEffectiveDriverId } from "@/lib/hooks/useEffectiveDriverId"; import { useRegisterForRace } from "@/lib/hooks/race/useRegisterForRace"; import { useWithdrawFromRace } from "@/lib/hooks/race/useWithdrawFromRace"; import Card from '@/components/ui/Card'; // ============================================================================ // TYPES // ============================================================================ interface LeagueScheduleTemplateProps { data: LeagueScheduleViewModel; leagueId: string; } // ============================================================================ // MAIN TEMPLATE COMPONENT // ============================================================================ export function LeagueScheduleTemplate({ data, leagueId, }: LeagueScheduleTemplateProps) { const router = useRouter(); const [filter, setFilter] = useState<'all' | 'upcoming' | 'past'>('upcoming'); const currentDriverId = useEffectiveDriverId(); const registerMutation = useRegisterForRace(); const withdrawMutation = useWithdrawFromRace(); const races = useMemo(() => { return data?.races ?? []; }, [data]); const upcomingRaces = races.filter((race) => race.isUpcoming); const pastRaces = races.filter((race) => race.isPast); 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(); const handleRegister = async (race: LeagueScheduleRaceViewModel, e: React.MouseEvent) => { e.stopPropagation(); const confirmed = window.confirm(`Register for ${race.track ?? race.name}?`); if (!confirmed) return; if (!currentDriverId) { alert('You must be logged in to register for races'); return; } try { await registerMutation.mutateAsync({ raceId: race.id, leagueId, driverId: currentDriverId }); } catch (err) { alert(err instanceof Error ? err.message : 'Failed to register'); } }; const handleWithdraw = async (race: LeagueScheduleRaceViewModel, e: React.MouseEvent) => { e.stopPropagation(); const confirmed = window.confirm('Withdraw from this race?'); if (!confirmed) return; if (!currentDriverId) { alert('You must be logged in to withdraw from races'); return; } try { await withdrawMutation.mutateAsync({ raceId: race.id, driverId: currentDriverId }); } catch (err) { alert(err instanceof Error ? err.message : 'Failed to withdraw'); } }; return (

Schedule

{/* 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.isPast; const isUpcoming = race.isUpcoming; const isRegistered = Boolean(race.isRegistered); const trackLabel = race.track ?? race.name; const carLabel = race.car ?? '—'; const sessionTypeLabel = (race.sessionType ?? 'race').toLowerCase(); const isProcessing = registerMutation.isPending || withdrawMutation.isPending; return (
router.push(`/races/${race.id}`)} >

{trackLabel}

{isUpcoming && !isRegistered && ( Upcoming )} {isUpcoming && isRegistered && ( ✓ Registered )} {isPast && ( Completed )}

{carLabel}

{sessionTypeLabel}

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

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

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

View Results →

)}
{/* Registration Actions */} {isUpcoming && (
e.stopPropagation()}> {!isRegistered ? ( ) : ( )}
)}
); })}
)}
); }