api client refactor
This commit is contained in:
@@ -1,109 +1,6 @@
|
||||
/**
|
||||
* DriversLeaderboardPresenter - Pure data transformer
|
||||
* Transforms API response to view model without DI dependencies.
|
||||
*/
|
||||
import { DriversLeaderboardDto, DriverLeaderboardItemDto } from '../dtos';
|
||||
import { DriverLeaderboardViewModel } from '../view-models';
|
||||
|
||||
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<void> {
|
||||
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<DriversLeaderboardViewModel> {
|
||||
const apiResponse = await apiClient.drivers.getLeaderboard();
|
||||
return transformApiResponse(apiResponse);
|
||||
}
|
||||
export const presentDriversLeaderboard = (dto: DriversLeaderboardDto, previousDrivers?: DriverLeaderboardItemDto[]): DriverLeaderboardViewModel => {
|
||||
return new DriverLeaderboardViewModel(dto, previousDrivers);
|
||||
};
|
||||
Reference in New Issue
Block a user