diff --git a/apps/website/app/leaderboards/page.tsx b/apps/website/app/leaderboards/page.tsx
index 1b40a3ebd..f4e1b1ad3 100644
--- a/apps/website/app/leaderboards/page.tsx
+++ b/apps/website/app/leaderboards/page.tsx
@@ -2,275 +2,19 @@
import { useState, useEffect } from 'react';
import { useRouter } from 'next/navigation';
-import {
- Trophy,
- Users,
- Crown,
- Star,
- TrendingUp,
- Shield,
- Medal,
- ChevronRight,
- Award,
- Flag,
- Target,
- Zap,
- Hash,
- Percent,
-} from 'lucide-react';
+import { Trophy, Users, Award, ChevronRight } from 'lucide-react';
import Button from '@/components/ui/Button';
import Heading from '@/components/ui/Heading';
+import DriverLeaderboardPreview from '@/components/leaderboards/DriverLeaderboardPreview';
+import TeamLeaderboardPreview from '@/components/leaderboards/TeamLeaderboardPreview';
import type { DriverLeaderboardItemViewModel } from '@/lib/view-models/DriverLeaderboardItemViewModel';
import type { TeamSummaryViewModel } from '@/lib/view-models/TeamSummaryViewModel';
import { useServices } from '@/lib/services/ServiceProvider';
-import Image from 'next/image';
// ============================================================================
// TYPES
// ============================================================================
-type SkillLevel = 'pro' | 'advanced' | 'intermediate' | 'beginner';
-
-type DriverListItem = DriverLeaderboardItemViewModel;
-
-type TeamDisplayData = TeamSummaryViewModel;
-
-// ============================================================================
-// 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' },
-];
-
-// ============================================================================
-// DRIVER LEADERBOARD PREVIEW
-// ============================================================================
-
-interface DriverLeaderboardPreviewProps {
- drivers: DriverListItem[];
- onDriverClick: (id: string) => void;
-}
-
-function DriverLeaderboardPreview({ drivers, onDriverClick }: DriverLeaderboardPreviewProps) {
- const router = useRouter();
- const top10 = drivers.slice(0, 10);
-
- 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-yellow-400/10 border-yellow-400/30';
- case 2: return 'bg-gray-300/10 border-gray-300/30';
- case 3: return 'bg-amber-600/10 border-amber-600/30';
- default: return 'bg-iron-gray/50 border-charcoal-outline';
- }
- };
-
- return (
-
- {/* Header */}
-
-
-
-
-
-
-
Driver Rankings
-
Top performers across all leagues
-
-
-
-
-
- {/* Leaderboard Rows */}
-
- {top10.map((driver, index) => {
- const levelConfig = SKILL_LEVELS.find((l) => l.id === driver.skillLevel);
- const position = index + 1;
-
- return (
-
- );
- })}
-
-
- );
-}
-
-// ============================================================================
-// TEAM LEADERBOARD PREVIEW
-// ============================================================================
-
-interface TeamLeaderboardPreviewProps {
- teams: TeamDisplayData[];
- onTeamClick: (id: string) => void;
-}
-
-function TeamLeaderboardPreview({ teams, onTeamClick }: TeamLeaderboardPreviewProps) {
- const router = useRouter();
- const top5 = [...teams]
- .sort((a, b) => b.memberCount - a.memberCount)
- .slice(0, 5);
-
- 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-yellow-400/10 border-yellow-400/30';
- case 2: return 'bg-gray-300/10 border-gray-300/30';
- case 3: return 'bg-amber-600/10 border-amber-600/30';
- default: return 'bg-iron-gray/50 border-charcoal-outline';
- }
- };
-
- return (
-
- {/* Header */}
-
-
-
-
-
-
-
Team Rankings
-
Top performing racing teams
-
-
-
-
-
- {/* Leaderboard Rows */}
-
- {top5.map((team, index) => {
- const levelConfig = SKILL_LEVELS.find((l) => l.id === team.performanceLevel);
- const LevelIcon = levelConfig?.icon || Shield;
- const position = index + 1;
-
- return (
-
- );
- })}
-
-
- );
-}
// ============================================================================
// MAIN PAGE COMPONENT
diff --git a/apps/website/components/leaderboards/DriverLeaderboardPreview.tsx b/apps/website/components/leaderboards/DriverLeaderboardPreview.tsx
new file mode 100644
index 000000000..5e210e391
--- /dev/null
+++ b/apps/website/components/leaderboards/DriverLeaderboardPreview.tsx
@@ -0,0 +1,117 @@
+import React from 'react';
+import { useRouter } from 'next/navigation';
+import { Trophy, Crown, Flag, ChevronRight } from 'lucide-react';
+import Button from '@/components/ui/Button';
+import Image from 'next/image';
+import type { DriverLeaderboardItemViewModel } from '@/lib/view-models/DriverLeaderboardItemViewModel';
+
+interface DriverLeaderboardPreviewProps {
+ drivers: DriverLeaderboardItemViewModel[];
+ onDriverClick: (id: string) => void;
+}
+
+const SKILL_LEVELS = [
+ { id: 'pro', label: 'Pro', color: 'text-yellow-400' },
+ { id: 'advanced', label: 'Advanced', color: 'text-purple-400' },
+ { id: 'intermediate', label: 'Intermediate', color: 'text-primary-blue' },
+ { id: 'beginner', label: 'Beginner', color: 'text-green-400' },
+];
+
+export default function DriverLeaderboardPreview({ drivers, onDriverClick }: DriverLeaderboardPreviewProps) {
+ const router = useRouter();
+ const top10 = drivers.slice(0, 10);
+
+ 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-yellow-400/10 border-yellow-400/30';
+ case 2: return 'bg-gray-300/10 border-gray-300/30';
+ case 3: return 'bg-amber-600/10 border-amber-600/30';
+ default: return 'bg-iron-gray/50 border-charcoal-outline';
+ }
+ };
+
+ return (
+
+ {/* Header */}
+
+
+
+
+
+
+
Driver Rankings
+
Top performers across all leagues
+
+
+
+
+
+ {/* Leaderboard Rows */}
+
+ {top10.map((driver, index) => {
+ const levelConfig = SKILL_LEVELS.find((l) => l.id === driver.skillLevel);
+ const position = index + 1;
+
+ return (
+
+ );
+ })}
+
+
+ );
+}
\ No newline at end of file
diff --git a/apps/website/components/leaderboards/TeamLeaderboardPreview.tsx b/apps/website/components/leaderboards/TeamLeaderboardPreview.tsx
new file mode 100644
index 000000000..cc970d3c4
--- /dev/null
+++ b/apps/website/components/leaderboards/TeamLeaderboardPreview.tsx
@@ -0,0 +1,119 @@
+import React from 'react';
+import { useRouter } from 'next/navigation';
+import { Users, Crown, Shield, ChevronRight } from 'lucide-react';
+import Button from '@/components/ui/Button';
+import type { TeamSummaryViewModel } from '@/lib/view-models/TeamSummaryViewModel';
+
+interface TeamLeaderboardPreviewProps {
+ teams: TeamSummaryViewModel[];
+ onTeamClick: (id: string) => void;
+}
+
+const SKILL_LEVELS = [
+ { 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: Crown, color: 'text-purple-400', bgColor: 'bg-purple-400/10', borderColor: 'border-purple-400/30' },
+ { id: 'intermediate', label: 'Intermediate', icon: Crown, 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' },
+];
+
+export default function TeamLeaderboardPreview({ teams, onTeamClick }: TeamLeaderboardPreviewProps) {
+ const router = useRouter();
+ const top5 = [...teams]
+ .sort((a, b) => b.memberCount - a.memberCount)
+ .slice(0, 5);
+
+ 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-yellow-400/10 border-yellow-400/30';
+ case 2: return 'bg-gray-300/10 border-gray-300/30';
+ case 3: return 'bg-amber-600/10 border-amber-600/30';
+ default: return 'bg-iron-gray/50 border-charcoal-outline';
+ }
+ };
+
+ return (
+
+ {/* Header */}
+
+
+
+
+
+
+
Team Rankings
+
Top performing racing teams
+
+
+
+
+
+ {/* Leaderboard Rows */}
+
+ {top5.map((team, index) => {
+ const levelConfig = SKILL_LEVELS.find((l) => l.id === team.performanceLevel);
+ const LevelIcon = levelConfig?.icon || Shield;
+ const position = index + 1;
+
+ return (
+
+ );
+ })}
+
+
+ );
+}
\ No newline at end of file