'use client'; import { useMemo } from 'react'; import Link from 'next/link'; import Card from '@/components/ui/Card'; import Heading from '@/components/ui/Heading'; import { Calendar, Clock, Flag, ChevronRight, MapPin, Car, Trophy, Users, Zap, PlayCircle, CheckCircle2, XCircle, CalendarDays, ArrowRight, } from 'lucide-react'; import { RaceFilterModal } from '@/components/races/RaceFilterModal'; import { RaceJoinButton } from '@/components/races/RaceJoinButton'; export type TimeFilter = 'all' | 'upcoming' | 'live' | 'past'; export type RaceStatusFilter = 'scheduled' | 'running' | 'completed' | 'cancelled' | 'all'; export interface Race { id: string; track: string; car: string; scheduledAt: string; status: 'scheduled' | 'running' | 'completed' | 'cancelled'; sessionType: string; leagueId?: string; leagueName?: string; strengthOfField?: number | null; isUpcoming: boolean; isLive: boolean; isPast: boolean; } export interface RacesTemplateProps { races: Race[]; totalCount: number; scheduledRaces: Race[]; runningRaces: Race[]; completedRaces: Race[]; isLoading: boolean; // Filters statusFilter: RaceStatusFilter; setStatusFilter: (filter: RaceStatusFilter) => void; leagueFilter: string; setLeagueFilter: (filter: string) => void; timeFilter: TimeFilter; setTimeFilter: (filter: TimeFilter) => void; // Actions onRaceClick: (raceId: string) => void; onLeagueClick: (leagueId: string) => void; onRegister: (raceId: string, leagueId: string) => void; onWithdraw: (raceId: string) => void; onCancel: (raceId: string) => void; // UI State showFilterModal: boolean; setShowFilterModal: (show: boolean) => void; // User state currentDriverId?: string; userMemberships?: Array<{ leagueId: string; role: string }>; } export function RacesTemplate({ races, totalCount, scheduledRaces, runningRaces, completedRaces, isLoading, statusFilter, setStatusFilter, leagueFilter, setLeagueFilter, timeFilter, setTimeFilter, onRaceClick, onLeagueClick, onRegister, onWithdraw, onCancel, showFilterModal, setShowFilterModal, currentDriverId, userMemberships, }: RacesTemplateProps) { // Filter races const filteredRaces = useMemo(() => { return races.filter((race) => { // Status filter if (statusFilter !== 'all' && race.status !== statusFilter) { return false; } // League filter if (leagueFilter !== 'all' && race.leagueId !== leagueFilter) { return false; } // Time filter if (timeFilter === 'upcoming' && !race.isUpcoming) { return false; } if (timeFilter === 'live' && !race.isLive) { return false; } if (timeFilter === 'past' && !race.isPast) { return false; } return true; }); }, [races, statusFilter, leagueFilter, timeFilter]); // Group races by date for calendar view const racesByDate = useMemo(() => { const grouped = new Map(); filteredRaces.forEach((race) => { const dateKey = race.scheduledAt.split('T')[0]!; if (!grouped.has(dateKey)) { grouped.set(dateKey, []); } grouped.get(dateKey)!.push(race); }); return grouped; }, [filteredRaces]); const upcomingRaces = filteredRaces.filter(r => r.isUpcoming).slice(0, 5); const liveRaces = filteredRaces.filter(r => r.isLive); const recentResults = filteredRaces.filter(r => r.isPast).slice(0, 5); const stats = { total: totalCount, scheduled: scheduledRaces.length, running: runningRaces.length, completed: completedRaces.length, }; const formatDate = (date: Date | string) => { const d = typeof date === 'string' ? new Date(date) : date; return d.toLocaleDateString('en-US', { weekday: 'short', month: 'short', day: 'numeric', }); }; const formatTime = (date: Date | string) => { const d = typeof date === 'string' ? new Date(date) : date; return d.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', }); }; const formatFullDate = (date: Date | string) => { const d = typeof date === 'string' ? new Date(date) : date; return d.toLocaleDateString('en-US', { weekday: 'long', month: 'long', day: 'numeric', year: 'numeric', }); }; const getRelativeTime = (date?: Date | string) => { if (!date) return ''; const now = new Date(); const targetDate = typeof date === 'string' ? new Date(date) : date; const diffMs = targetDate.getTime() - now.getTime(); const diffHours = Math.floor(diffMs / (1000 * 60 * 60)); const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24)); if (diffMs < 0) return 'Past'; if (diffHours < 1) return 'Starting soon'; if (diffHours < 24) return `In ${diffHours}h`; if (diffDays === 1) return 'Tomorrow'; if (diffDays < 7) return `In ${diffDays} days`; return formatDate(targetDate); }; const statusConfig = { scheduled: { icon: Clock, color: 'text-primary-blue', bg: 'bg-primary-blue/10', border: 'border-primary-blue/30', label: 'Scheduled', }, running: { icon: PlayCircle, color: 'text-performance-green', bg: 'bg-performance-green/10', border: 'border-performance-green/30', label: 'LIVE', }, completed: { icon: CheckCircle2, color: 'text-gray-400', bg: 'bg-gray-500/10', border: 'border-gray-500/30', label: 'Completed', }, cancelled: { icon: XCircle, color: 'text-warning-amber', bg: 'bg-warning-amber/10', border: 'border-warning-amber/30', label: 'Cancelled', }, }; const isUserRegistered = (race: Race) => { // This would need actual registration data return false; }; const canRegister = (race: Race) => { // This would need actual registration rules return race.status === 'scheduled'; }; const isOwnerOrAdmin = (leagueId?: string) => { if (!leagueId || !userMemberships) return false; const membership = userMemberships.find(m => m.leagueId === leagueId); return membership?.role === 'owner' || membership?.role === 'admin'; }; if (isLoading) { return (
{[1, 2, 3, 4].map(i => (
))}
); } return (
{/* Hero Header */}
Race Calendar

Track upcoming races, view live events, and explore results across all your leagues.

{/* Quick Stats */}
Total

{stats.total}

Scheduled

{stats.scheduled}

Live Now

{stats.running}

Completed

{stats.completed}

{/* Live Races Banner */} {liveRaces.length > 0 && (
LIVE NOW
{liveRaces.map((race) => (
onRaceClick(race.id)} className="flex items-center justify-between p-4 bg-deep-graphite/80 rounded-lg border border-performance-green/20 cursor-pointer hover:border-performance-green/40 transition-all" >

{race.track}

{race.leagueName}

))}
)}
{/* Main Content - Race List */}
{/* Filters */}
{/* Time Filter Tabs */}
{(['upcoming', 'live', 'past', 'all'] as TimeFilter[]).map(filter => ( ))}
{/* League Filter */} {/* Filter Button */}
{/* Race List by Date */} {filteredRaces.length === 0 ? (

No races found

{totalCount === 0 ? 'No races have been scheduled yet' : 'Try adjusting your filters'}

) : (
{Array.from(racesByDate.entries()).map(([dateKey, dayRaces]) => (
{/* Date Header */}
{formatFullDate(new Date(dateKey))} {dayRaces.length} race{dayRaces.length !== 1 ? 's' : ''}
{/* Races for this date */}
{dayRaces.map((race) => { const config = statusConfig[race.status as keyof typeof statusConfig]; const StatusIcon = config.icon; return (
onRaceClick(race.id)} > {/* Live indicator */} {race.status === 'running' && (
)}
{/* Time Column */}

{formatTime(race.scheduledAt)}

{race.status === 'running' ? 'LIVE' : getRelativeTime(race.scheduledAt)}

{/* Divider */}
{/* Main Content */}

{race.track}

{race.car} {race.strengthOfField && ( SOF {race.strengthOfField} )}
{/* Status Badge */}
{config.label}
{/* League Link */}
e.stopPropagation()} className="inline-flex items-center gap-2 text-sm text-primary-blue hover:underline" > {race.leagueName}
{/* Arrow */}
); })}
))}
)} {/* View All Link */} {filteredRaces.length > 0 && (
View All Races
)}
{/* Sidebar */}
{/* Upcoming This Week */}

Next Up

This week
{upcomingRaces.length === 0 ? (

No races scheduled this week

) : (
{upcomingRaces.map((race) => { if (!race.scheduledAt) { return null; } const scheduledAtDate = new Date(race.scheduledAt); return (
onRaceClick(race.id)} className="flex items-center gap-3 p-2 rounded-lg hover:bg-deep-graphite cursor-pointer transition-colors" >
{scheduledAtDate.getDate()}

{race.track}

{formatTime(scheduledAtDate)}

); })}
)}
{/* Recent Results */}

Recent Results

{recentResults.length === 0 ? (

No completed races yet

) : (
{recentResults.map((race) => (
onRaceClick(race.id)} className="flex items-center gap-3 p-2 rounded-lg hover:bg-deep-graphite cursor-pointer transition-colors" >

{race.track}

{formatDate(new Date(race.scheduledAt))}

))}
)}
{/* Quick Actions */}

Quick Actions

Browse Leagues
View Leaderboards
{/* Filter Modal */} setShowFilterModal(false)} statusFilter={statusFilter} setStatusFilter={setStatusFilter} leagueFilter={leagueFilter} setLeagueFilter={setLeagueFilter} timeFilter={timeFilter} setTimeFilter={setTimeFilter} searchQuery="" setSearchQuery={() => {}} leagues={[...new Set(races.map(r => ({ id: r.leagueId || '', name: r.leagueName || '' })))]} showSearch={false} showTimeFilter={false} />
); }