website refactor
This commit is contained in:
@@ -1,167 +0,0 @@
|
||||
import { RacesApiClient } from '../../api/races/RacesApiClient';
|
||||
import { RaceDetailEntryViewModel } from '../../view-models/RaceDetailEntryViewModel';
|
||||
import { RaceDetailUserResultViewModel } from '../../view-models/RaceDetailUserResultViewModel';
|
||||
import { RaceDetailViewModel } from '../../view-models/RaceDetailViewModel';
|
||||
import { RacesPageViewModel } from '../../view-models/RacesPageViewModel';
|
||||
import { RaceStatsViewModel } from '../../view-models/RaceStatsViewModel';
|
||||
import type { RaceDetailsViewModel } from '../../view-models/RaceDetailsViewModel';
|
||||
import type { FileProtestCommandDTO } from '../../types/generated/FileProtestCommandDTO';
|
||||
import type { RaceStatsDTO } from '../../types/generated/RaceStatsDTO';
|
||||
/**
|
||||
* 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<RaceDetailViewModel> {
|
||||
const dto = await this.apiClient.getDetail(raceId, driverId);
|
||||
return new RaceDetailViewModel(dto, driverId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get race details for pages/components (DTO-free shape)
|
||||
*/
|
||||
async getRaceDetails(
|
||||
raceId: string,
|
||||
driverId: string
|
||||
): Promise<RaceDetailsViewModel> {
|
||||
const dto: any = await this.apiClient.getDetail(raceId, driverId);
|
||||
|
||||
const raceDto: any = dto?.race ?? null;
|
||||
const leagueDto: any = dto?.league ?? null;
|
||||
|
||||
const registrationDto: any = dto?.registration ?? {};
|
||||
const isUserRegistered = Boolean(registrationDto.isUserRegistered ?? registrationDto.isRegistered ?? false);
|
||||
const canRegister = Boolean(registrationDto.canRegister);
|
||||
|
||||
const status = String(raceDto?.status ?? '');
|
||||
const canReopenRace = status === 'completed' || status === 'cancelled';
|
||||
|
||||
return {
|
||||
race: raceDto
|
||||
? {
|
||||
id: String(raceDto.id ?? ''),
|
||||
track: String(raceDto.track ?? ''),
|
||||
car: String(raceDto.car ?? ''),
|
||||
scheduledAt: String(raceDto.scheduledAt ?? ''),
|
||||
status,
|
||||
sessionType: String(raceDto.sessionType ?? ''),
|
||||
}
|
||||
: null,
|
||||
league: leagueDto
|
||||
? {
|
||||
id: String(leagueDto.id ?? ''),
|
||||
name: String(leagueDto.name ?? ''),
|
||||
description: leagueDto.description ?? null,
|
||||
settings: leagueDto.settings,
|
||||
}
|
||||
: null,
|
||||
entryList: (dto?.entryList ?? []).map((entry: any) => new RaceDetailEntryViewModel(entry, driverId)),
|
||||
registration: {
|
||||
canRegister,
|
||||
isUserRegistered,
|
||||
},
|
||||
userResult: dto?.userResult ? new RaceDetailUserResultViewModel(dto.userResult) : null,
|
||||
canReopenRace,
|
||||
error: dto?.error,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get races page data with view model transformation
|
||||
*/
|
||||
async getRacesPageData(): Promise<RacesPageViewModel> {
|
||||
const dto = await this.apiClient.getPageData();
|
||||
return new RacesPageViewModel(dto);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get races page data filtered by league
|
||||
*/
|
||||
async getLeagueRacesPageData(leagueId: string): Promise<RacesPageViewModel> {
|
||||
const dto = await this.apiClient.getPageData(leagueId);
|
||||
return new RacesPageViewModel(dto);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all races page data with view model transformation
|
||||
* Currently same as getRacesPageData, but can be extended for different filtering
|
||||
*/
|
||||
async getAllRacesPageData(): Promise<RacesPageViewModel> {
|
||||
const dto = await this.apiClient.getPageData();
|
||||
return new RacesPageViewModel(dto);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get total races statistics with view model transformation
|
||||
*/
|
||||
async getRacesTotal(): Promise<RaceStatsViewModel> {
|
||||
const dto: RaceStatsDTO = await this.apiClient.getTotal();
|
||||
return new RaceStatsViewModel(dto);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register for a race
|
||||
*/
|
||||
async registerForRace(raceId: string, leagueId: string, driverId: string): Promise<void> {
|
||||
await this.apiClient.register(raceId, { raceId, leagueId, driverId });
|
||||
}
|
||||
|
||||
/**
|
||||
* Withdraw from a race
|
||||
*/
|
||||
async withdrawFromRace(raceId: string, driverId: string): Promise<void> {
|
||||
await this.apiClient.withdraw(raceId, { raceId, driverId });
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel a race
|
||||
*/
|
||||
async cancelRace(raceId: string): Promise<void> {
|
||||
await this.apiClient.cancel(raceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete a race
|
||||
*/
|
||||
async completeRace(raceId: string): Promise<void> {
|
||||
await this.apiClient.complete(raceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-open a race
|
||||
*/
|
||||
async reopenRace(raceId: string): Promise<void> {
|
||||
await this.apiClient.reopen(raceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* File a protest
|
||||
*/
|
||||
async fileProtest(input: FileProtestCommandDTO): Promise<void> {
|
||||
await this.apiClient.fileProtest(input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find races by league ID
|
||||
*
|
||||
* The races API does not currently expose a league-filtered listing endpoint in this build,
|
||||
* so this method deliberately signals that the operation is unavailable instead of making
|
||||
* assumptions about URL structure.
|
||||
*/
|
||||
async findByLeagueId(leagueId: string): Promise<RacesPageViewModel['races']> {
|
||||
const page = await this.getLeagueRacesPageData(leagueId);
|
||||
return page.races;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user