'use client'; import { useState, useEffect } from 'react'; import { useRouter } from 'next/navigation'; import { Trophy, Medal, Crown, Star, TrendingUp, Shield, Search, Filter, Flag, ArrowLeft, Hash, Percent, } from 'lucide-react'; import Button from '@/components/ui/Button'; import Input from '@/components/ui/Input'; import Heading from '@/components/ui/Heading'; import { getGetDriversLeaderboardUseCase } from '@/lib/di-container'; import type { DriverLeaderboardItemViewModel, SkillLevel } from '@gridpilot/racing/application/presenters/IDriversLeaderboardPresenter'; import Image from 'next/image'; // ============================================================================ // TYPES // ============================================================================ type SortBy = 'rank' | 'rating' | 'wins' | 'podiums' | 'winRate'; type DriverListItem = DriverLeaderboardItemViewModel; // ============================================================================ // SKILL LEVEL CONFIG // ============================================================================ const SKILL_LEVELS: { id: SkillLevel; label: string; icon: React.ElementType; color: string; bgColor: string; borderColor: string; }[] = [ { id: 'pro', label: 'Pro', icon: Crown, color: 'text-yellow-400', bgColor: 'bg-yellow-400/10', borderColor: 'border-yellow-400/30' }, { id: 'advanced', label: 'Advanced', icon: Star, color: 'text-purple-400', bgColor: 'bg-purple-400/10', borderColor: 'border-purple-400/30' }, { id: 'intermediate', label: 'Intermediate', icon: TrendingUp, color: 'text-primary-blue', bgColor: 'bg-primary-blue/10', borderColor: 'border-primary-blue/30' }, { id: 'beginner', label: 'Beginner', icon: Shield, color: 'text-green-400', bgColor: 'bg-green-400/10', borderColor: 'border-green-400/30' }, ]; // ============================================================================ // SORT OPTIONS // ============================================================================ const SORT_OPTIONS: { id: SortBy; label: string; icon: React.ElementType }[] = [ { id: 'rank', label: 'Rank', icon: Hash }, { id: 'rating', label: 'Rating', icon: Star }, { id: 'wins', label: 'Wins', icon: Trophy }, { id: 'podiums', label: 'Podiums', icon: Medal }, { id: 'winRate', label: 'Win Rate', icon: Percent }, ]; // ============================================================================ // TOP 3 PODIUM COMPONENT // ============================================================================ interface TopThreePodiumProps { drivers: DriverListItem[]; onDriverClick: (id: string) => void; } function TopThreePodium({ drivers, onDriverClick }: TopThreePodiumProps) { if (drivers.length < 3) return null; const top3 = drivers.slice(0, 3) as [DriverListItem, DriverListItem, DriverListItem]; const podiumOrder: [DriverListItem, DriverListItem, DriverListItem] = [ top3[1], top3[0], top3[2], ]; // 2nd, 1st, 3rd const podiumHeights = ['h-32', 'h-40', 'h-24']; const podiumColors = [ 'from-gray-400/20 to-gray-500/10 border-gray-400/40', 'from-yellow-400/20 to-amber-500/10 border-yellow-400/40', 'from-amber-600/20 to-amber-700/10 border-amber-600/40', ]; const crownColors = ['text-gray-300', 'text-yellow-400', 'text-amber-600']; const positions = [2, 1, 3]; return (
{podiumOrder.map((driver, index) => { const levelConfig = SKILL_LEVELS.find((l) => l.id === driver.skillLevel); const position = positions[index]; return ( ); })}
); } // ============================================================================ // MAIN PAGE COMPONENT // ============================================================================ export default function DriverLeaderboardPage() { const router = useRouter(); const [drivers, setDrivers] = useState([]); const [loading, setLoading] = useState(true); const [searchQuery, setSearchQuery] = useState(''); const [selectedSkill, setSelectedSkill] = useState<'all' | SkillLevel>('all'); const [sortBy, setSortBy] = useState('rank'); const [showFilters, setShowFilters] = useState(false); useEffect(() => { const load = async () => { const useCase = getGetDriversLeaderboardUseCase(); await useCase.execute(); const viewModel = useCase.presenter.getViewModel(); setDrivers(viewModel.drivers); setLoading(false); }; void load(); }, []); const filteredDrivers = drivers.filter((driver) => { const matchesSearch = driver.name.toLowerCase().includes(searchQuery.toLowerCase()) || driver.nationality.toLowerCase().includes(searchQuery.toLowerCase()); const matchesSkill = selectedSkill === 'all' || driver.skillLevel === selectedSkill; return matchesSearch && matchesSkill; }); const sortedDrivers = [...filteredDrivers].sort((a, b) => { const rankA = Number.isFinite(a.rank) && a.rank > 0 ? a.rank : Number.POSITIVE_INFINITY; const rankB = Number.isFinite(b.rank) && b.rank > 0 ? b.rank : Number.POSITIVE_INFINITY; switch (sortBy) { case 'rank': return rankA - rankB || b.rating - a.rating || a.name.localeCompare(b.name); case 'rating': return b.rating - a.rating; case 'wins': return b.wins - a.wins; case 'podiums': return b.podiums - a.podiums; case 'winRate': { const aRate = a.racesCompleted > 0 ? a.wins / a.racesCompleted : 0; const bRate = b.racesCompleted > 0 ? b.wins / b.racesCompleted : 0; return bRate - aRate; } default: return 0; } }); const handleDriverClick = (driverId: string) => { if (driverId.startsWith('demo-')) return; router.push(`/drivers/${driverId}`); }; const getMedalColor = (position: number) => { switch (position) { case 1: return 'text-yellow-400'; case 2: return 'text-gray-300'; case 3: return 'text-amber-600'; default: return 'text-gray-500'; } }; const getMedalBg = (position: number) => { switch (position) { case 1: return 'bg-gradient-to-br from-yellow-400/20 to-yellow-600/10 border-yellow-400/40'; case 2: return 'bg-gradient-to-br from-gray-300/20 to-gray-400/10 border-gray-300/40'; case 3: return 'bg-gradient-to-br from-amber-600/20 to-amber-700/10 border-amber-600/40'; default: return 'bg-iron-gray/50 border-charcoal-outline'; } }; if (loading) { return (

Loading driver rankings...

); } return (
{/* Header */}
Driver Leaderboard

Full rankings of all drivers by performance metrics

{/* Top 3 Podium */} {!searchQuery && sortBy === 'rank' && } {/* Filters */}
setSearchQuery(e.target.value)} className="pl-11" />
{SKILL_LEVELS.map((level) => { const LevelIcon = level.icon; return ( ); })}
Sort by:
{SORT_OPTIONS.map((option) => ( ))}
{/* Leaderboard Table */}
{/* Table Header */}
Rank
Driver
Races
Rating
Wins
Podiums
Win Rate
{/* Table Body */}
{sortedDrivers.map((driver, index) => { const levelConfig = SKILL_LEVELS.find((l) => l.id === driver.skillLevel); const LevelIcon = levelConfig?.icon || Shield; const winRate = driver.racesCompleted > 0 ? ((driver.wins / driver.racesCompleted) * 100).toFixed(1) : '0.0'; const position = index + 1; return ( ); })}
{/* Empty State */} {sortedDrivers.length === 0 && (

No drivers found

Try adjusting your filters or search query

)}
); }