/** * DriversLeaderboardPresenter - Pure data transformer * Transforms API response to view model without DI dependencies. */ import { apiClient, type DriversLeaderboardViewModel as ApiDriversLeaderboardViewModel } from '@/lib/apiClient'; export type SkillLevel = 'rookie' | 'amateur' | 'pro' | 'elite' | 'legend'; export interface DriverLeaderboardItemViewModel { id: string; name: string; rating: number; skillLevel: SkillLevel; nationality?: string | undefined; racesCompleted: number; wins: number; podiums: number; isActive: boolean; rank: number; avatarUrl?: string | undefined; } export interface DriversLeaderboardViewModel { drivers: DriverLeaderboardItemViewModel[]; totalRaces: number; totalWins: number; activeCount: number; } export interface IDriversLeaderboardPresenter { reset(): void; getViewModel(): DriversLeaderboardViewModel | null; } /** * Calculate skill level from rating */ function getSkillLevel(rating: number): SkillLevel { if (rating >= 5000) return 'legend'; if (rating >= 3500) return 'elite'; if (rating >= 2000) return 'pro'; if (rating >= 1000) return 'amateur'; return 'rookie'; } /** * Transform API response to view model */ function transformApiResponse(apiResponse: ApiDriversLeaderboardViewModel): DriversLeaderboardViewModel { const items: DriverLeaderboardItemViewModel[] = apiResponse.drivers.map((driver, index) => { const rating = driver.rating ?? 0; const skillLevel = getSkillLevel(rating); const viewModel: DriverLeaderboardItemViewModel = { id: driver.id, name: driver.name, rating, skillLevel, racesCompleted: driver.races ?? 0, wins: driver.wins ?? 0, podiums: 0, // API may not provide this, default to 0 isActive: true, rank: index + 1, }; if (driver.avatarUrl) { viewModel.avatarUrl = driver.avatarUrl; } return viewModel; }); const totalRaces = items.reduce((sum, d) => sum + d.racesCompleted, 0); const totalWins = items.reduce((sum, d) => sum + d.wins, 0); const activeCount = items.filter((d) => d.isActive).length; return { drivers: items, totalRaces, totalWins, activeCount, }; } export class DriversLeaderboardPresenter implements IDriversLeaderboardPresenter { private viewModel: DriversLeaderboardViewModel | null = null; reset(): void { this.viewModel = null; } async fetchAndPresent(): Promise { const apiResponse = await apiClient.drivers.getLeaderboard(); this.viewModel = transformApiResponse(apiResponse); } getViewModel(): DriversLeaderboardViewModel | null { return this.viewModel; } } /** * Convenience function to fetch and transform drivers leaderboard */ export async function fetchDriversLeaderboard(): Promise { const apiResponse = await apiClient.drivers.getLeaderboard(); return transformApiResponse(apiResponse); }