'use client'; import Card from '../ui/Card'; import RankBadge from './RankBadge'; import { getLeagueRankings, getGetProfileOverviewUseCase } from '@/lib/di-container'; import { useState, useEffect } from 'react'; import { getPrimaryLeagueIdForDriver } from '@/lib/leagueMembership'; import type { ProfileOverviewViewModel } from '@gridpilot/racing/application/presenters/IProfileOverviewPresenter'; interface ProfileStatsProps { driverId?: string; stats?: { totalRaces: number; wins: number; podiums: number; dnfs: number; avgFinish: number; completionRate: number; }; } type DriverProfileOverviewViewModel = ProfileOverviewViewModel | null; export default function ProfileStats({ driverId, stats }: ProfileStatsProps) { const [profileData, setProfileData] = useState(null); useEffect(() => { if (driverId) { const load = async () => { const profileUseCase = getGetProfileOverviewUseCase(); const vm = await profileUseCase.execute({ driverId }); setProfileData(vm); }; void load(); } }, [driverId]); const driverStats = profileData?.stats || null; const totalDrivers = profileData?.currentDriver?.totalDrivers ?? 0; const primaryLeagueId = driverId ? getPrimaryLeagueIdForDriver(driverId) : null; const leagueRank = driverId && primaryLeagueId ? getLeagueRankings(driverId, primaryLeagueId) : null; const defaultStats = stats || (driverStats ? { totalRaces: driverStats.totalRaces, wins: driverStats.wins, podiums: driverStats.podiums, dnfs: driverStats.dnfs, avgFinish: driverStats.avgFinish ?? 0, completionRate: driverStats.totalRaces > 0 ? ((driverStats.totalRaces - driverStats.dnfs) / driverStats.totalRaces) * 100 : 0, } : null); const winRate = defaultStats && defaultStats.totalRaces > 0 ? ((defaultStats.wins / defaultStats.totalRaces) * 100).toFixed(1) : '0.0'; const podiumRate = defaultStats && defaultStats.totalRaces > 0 ? ((defaultStats.podiums / defaultStats.totalRaces) * 100).toFixed(1) : '0.0'; const getTrendIndicator = (value: number) => { if (value > 0) return '↑'; if (value < 0) return '↓'; return '→'; }; const getPercentileLabel = (percentile: number) => { if (percentile >= 90) return 'Top 10%'; if (percentile >= 75) return 'Top 25%'; if (percentile >= 50) return 'Top 50%'; return `${(100 - percentile).toFixed(0)}th percentile`; }; const getPercentileColor = (percentile: number) => { if (percentile >= 90) return 'text-green-400'; if (percentile >= 75) return 'text-primary-blue'; if (percentile >= 50) return 'text-warning-amber'; return 'text-gray-400'; }; return (
{driverStats && (

Rankings Dashboard

Overall Ranking
{driverStats.overallRank ?? 0} of {totalDrivers} drivers
{getPercentileLabel(driverStats.percentile ?? 0)}
Global Percentile
{driverStats.rating ?? 0}
Rating
{getTrendIndicator(5)} {winRate}%
Win Rate
{getTrendIndicator(2)} {podiumRate}%
Podium Rate
{leagueRank && leagueRank.totalDrivers > 0 && (
Primary League
{leagueRank.rank} of {leagueRank.totalDrivers} drivers
{getPercentileLabel(leagueRank.percentile)}
League Percentile
)}
)} {defaultStats ? ( <>
{[ { label: 'Total Races', value: defaultStats.totalRaces, color: 'text-primary-blue', }, { label: 'Wins', value: defaultStats.wins, color: 'text-green-400' }, { label: 'Podiums', value: defaultStats.podiums, color: 'text-warning-amber', }, { label: 'DNFs', value: defaultStats.dnfs, color: 'text-red-400' }, { label: 'Avg Finish', value: defaultStats.avgFinish.toFixed(1), color: 'text-white', }, { label: 'Completion', value: `${defaultStats.completionRate.toFixed(1)}%`, color: 'text-green-400', }, { label: 'Win Rate', value: `${winRate}%`, color: 'text-primary-blue' }, { label: 'Podium Rate', value: `${podiumRate}%`, color: 'text-warning-amber', }, ].map((stat, index) => (
{stat.label}
{stat.value}
))}
) : (

Career Statistics

No statistics available yet. Compete in races to start building your record.

)}
📊

Performance by Car Class

Detailed per-car and per-class performance breakdowns will be available in a future version once more race history data is tracked.

📈

Coming Soon

Performance trends, track-specific stats, head-to-head comparisons vs friends, and league member comparisons will be available in production.

); } function PerformanceRow({ label, races, wins, podiums, avgFinish }: { label: string; races: number; wins: number; podiums: number; avgFinish: number; }) { const winRate = ((wins / races) * 100).toFixed(0); return (
{label}
{races} races
Wins
{wins} ({winRate}%)
Podiums
{podiums}
Avg
{avgFinish.toFixed(1)}
); }