import { RacesApiClient } from '../../api/races/RacesApiClient'; import { RaceDetailViewModel } from '../../view-models/RaceDetailViewModel'; import { RacesPageViewModel } from '../../view-models/RacesPageViewModel'; import { RaceStatsViewModel } from '../../view-models/RaceStatsViewModel'; // TODO: Move these types to apps/website/lib/types/generated when available type RacesPageDataRaceDTO = { id: string; track: string; car: string; scheduledAt: string; status: string; leagueId: string; leagueName: string; }; type RacesPageDataDto = { races: RacesPageDataRaceDTO[] }; type RaceStatsDTO = { totalRaces: number }; /** * Race Service * * Orchestrates race operations by coordinating API calls and view model creation. * All dependencies are injected via constructor. */ export class RaceService { constructor( private readonly apiClient: RacesApiClient ) {} /** * Get race detail with view model transformation */ async getRaceDetail( raceId: string, driverId: string ): Promise { const dto = await this.apiClient.getDetail(raceId, driverId); return new RaceDetailViewModel(dto); } /** * Get races page data with view model transformation */ async getRacesPageData(): Promise { const dto = await this.apiClient.getPageData(); return new RacesPageViewModel(this.transformRacesPageData(dto)); } /** * Get total races statistics with view model transformation */ async getRacesTotal(): Promise { const dto: RaceStatsDTO = await this.apiClient.getTotal(); return new RaceStatsViewModel(dto); } /** * Register for a race */ async registerForRace(raceId: string, leagueId: string, driverId: string): Promise { await this.apiClient.register(raceId, { leagueId, driverId }); } /** * Withdraw from a race */ async withdrawFromRace(raceId: string, driverId: string): Promise { await this.apiClient.withdraw(raceId, { driverId }); } /** * Cancel a race */ async cancelRace(raceId: string): Promise { await this.apiClient.cancel(raceId); } /** * Complete a race */ async completeRace(raceId: string): Promise { await this.apiClient.complete(raceId); } /** * Transform API races page data to view model format */ private transformRacesPageData(dto: RacesPageDataDto): { upcomingRaces: Array<{ id: string; title: string; scheduledTime: string; status: string }>; completedRaces: Array<{ id: string; title: string; scheduledTime: string; status: string }>; totalCount: number; } { const upcomingRaces = dto.races .filter(race => race.status !== 'completed') .map(race => ({ id: race.id, title: `${race.track} - ${race.car}`, scheduledTime: race.scheduledAt, status: race.status, })); const completedRaces = dto.races .filter(race => race.status === 'completed') .map(race => ({ id: race.id, title: `${race.track} - ${race.car}`, scheduledTime: race.scheduledAt, status: race.status, })); return { upcomingRaces, completedRaces, totalCount: dto.races.length, }; } /** * Find races by league ID */ async findByLeagueId(leagueId: string): Promise { // Assuming the API has /races?leagueId=... // TODO: Update when API is implemented const dto = await this.apiClient.get('/races?leagueId=' + leagueId) as { races: any[] }; return dto.races; } }