'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 { getDriverRepository, getDriverStats, getAllDriverRankings, getImageService } from '@/lib/di-container';
import Image from 'next/image';
// ============================================================================
// TYPES
// ============================================================================
type SkillLevel = 'beginner' | 'intermediate' | 'advanced' | 'pro';
type SortBy = 'rank' | 'rating' | 'wins' | 'podiums' | 'winRate';
interface DriverListItem {
id: string;
name: string;
rating: number;
skillLevel: SkillLevel;
nationality: string;
racesCompleted: number;
wins: number;
podiums: number;
rank: number;
}
// ============================================================================
// DEMO DATA
// ============================================================================
const DEMO_DRIVERS: DriverListItem[] = [
{ id: 'demo-1', name: 'Max Verstappen', rating: 4250, skillLevel: 'pro', nationality: 'NL', racesCompleted: 156, wins: 47, podiums: 89, rank: 1 },
{ id: 'demo-2', name: 'Lewis Hamilton', rating: 4180, skillLevel: 'pro', nationality: 'GB', racesCompleted: 198, wins: 52, podiums: 112, rank: 2 },
{ id: 'demo-3', name: 'Charles Leclerc', rating: 3950, skillLevel: 'pro', nationality: 'MC', racesCompleted: 134, wins: 28, podiums: 67, rank: 3 },
{ id: 'demo-4', name: 'Lando Norris', rating: 3820, skillLevel: 'advanced', nationality: 'GB', racesCompleted: 112, wins: 18, podiums: 45, rank: 4 },
{ id: 'demo-5', name: 'Carlos Sainz', rating: 3750, skillLevel: 'advanced', nationality: 'ES', racesCompleted: 145, wins: 15, podiums: 52, rank: 5 },
{ id: 'demo-6', name: 'Oscar Piastri', rating: 3680, skillLevel: 'advanced', nationality: 'AU', racesCompleted: 78, wins: 8, podiums: 24, rank: 6 },
{ id: 'demo-7', name: 'George Russell', rating: 3620, skillLevel: 'advanced', nationality: 'GB', racesCompleted: 98, wins: 6, podiums: 31, rank: 7 },
{ id: 'demo-8', name: 'Fernando Alonso', rating: 3580, skillLevel: 'advanced', nationality: 'ES', racesCompleted: 256, wins: 32, podiums: 98, rank: 8 },
{ id: 'demo-9', name: 'Nico Hülkenberg', rating: 3420, skillLevel: 'advanced', nationality: 'DE', racesCompleted: 167, wins: 2, podiums: 18, rank: 9 },
{ id: 'demo-10', name: 'Yuki Tsunoda', rating: 3250, skillLevel: 'intermediate', nationality: 'JP', racesCompleted: 89, wins: 1, podiums: 8, rank: 10 },
{ id: 'demo-11', name: 'Alex Albon', rating: 3180, skillLevel: 'intermediate', nationality: 'TH', racesCompleted: 102, wins: 0, podiums: 4, rank: 11 },
{ id: 'demo-12', name: 'Kevin Magnussen', rating: 3050, skillLevel: 'intermediate', nationality: 'DK', racesCompleted: 145, wins: 0, podiums: 2, rank: 12 },
{ id: 'demo-13', name: 'Pierre Gasly', rating: 2980, skillLevel: 'intermediate', nationality: 'FR', racesCompleted: 124, wins: 1, podiums: 5, rank: 13 },
{ id: 'demo-14', name: 'Esteban Ocon', rating: 2920, skillLevel: 'intermediate', nationality: 'FR', racesCompleted: 118, wins: 1, podiums: 4, rank: 14 },
{ id: 'demo-15', name: 'Lance Stroll', rating: 2850, skillLevel: 'intermediate', nationality: 'CA', racesCompleted: 134, wins: 0, podiums: 3, rank: 15 },
];
// ============================================================================
// 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) {
const imageService = getImageService();
const top3 = drivers.slice(0, 3);
if (top3.length < 3) return null;
const podiumOrder = [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 imageService = getImageService();
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 driverRepo = getDriverRepository();
const allDrivers = await driverRepo.findAll();
const rankings = getAllDriverRankings();
const items: DriverListItem[] = allDrivers.map((driver) => {
const stats = getDriverStats(driver.id);
const rating = stats?.rating ?? 0;
const wins = stats?.wins ?? 0;
const podiums = stats?.podiums ?? 0;
const totalRaces = stats?.totalRaces ?? 0;
let effectiveRank = Number.POSITIVE_INFINITY;
if (typeof stats?.overallRank === 'number' && stats.overallRank > 0) {
effectiveRank = stats.overallRank;
} else {
const indexInGlobal = rankings.findIndex((entry) => entry.driverId === driver.id);
if (indexInGlobal !== -1) {
effectiveRank = indexInGlobal + 1;
}
}
const skillLevel: SkillLevel =
rating >= 3000 ? 'pro' : rating >= 2500 ? 'advanced' : rating >= 1800 ? 'intermediate' : 'beginner';
return {
id: driver.id,
name: driver.name,
rating,
skillLevel,
nationality: driver.country,
racesCompleted: totalRaces,
wins,
podiums,
rank: effectiveRank,
};
});
setDrivers(items.length > 0 ? items : DEMO_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 */}
{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
)}
);
}