api client refactor

This commit is contained in:
2025-12-17 19:25:10 +01:00
parent 4177644b18
commit 26f7a2b6aa
27 changed files with 543 additions and 1329 deletions

View File

@@ -1,6 +1,13 @@
import { RaceDetailDto } from '../dtos';
import { RaceDetailViewModel } from '../view-models';
export class RaceDetailPresenter {
present(dto: RaceDetailDto): RaceDetailViewModel {
return new RaceDetailViewModel(dto);
}
}
export const presentRaceDetail = (dto: RaceDetailDto): RaceDetailViewModel => {
return new RaceDetailViewModel(dto);
const presenter = new RaceDetailPresenter();
return presenter.present(dto);
};

View File

@@ -0,0 +1,43 @@
import { RaceDetailViewModel } from '../view-models/RaceDetailViewModel';
import type { RaceDetailDto } from '../dtos/RaceDetailDto';
import type { RacesPageDataDto } from '../dtos/RacesPageDataDto';
import type { RacesPageViewModel } from '../view-models/RacesPageViewModel';
/**
* Race Presenter
*
* Stateless presenter that transforms race DTOs into view models.
* All methods are pure functions with no side effects.
*/
export class RacePresenter {
presentRaceDetail(dto: RaceDetailDto): RaceDetailViewModel {
return new RaceDetailViewModel(dto);
}
presentRacesPage(dto: RacesPageDataDto): RacesPageViewModel {
return {
upcomingRaces: dto.races.filter(r => r.isUpcoming).map(r => this.presentRaceCard(r)),
completedRaces: dto.races.filter(r => r.status === 'completed').map(r => this.presentRaceCard(r)),
totalCount: dto.races.length,
};
}
private presentRaceCard(race: any): any {
return {
id: race.id,
title: race.title || race.track,
scheduledTime: race.scheduledTime || race.scheduledAt,
status: this.formatStatus(race.status),
};
}
private formatStatus(status: string): string {
const statusMap: Record<string, string> = {
scheduled: 'Scheduled',
running: 'Live',
completed: 'Finished',
cancelled: 'Cancelled',
};
return statusMap[status] || status;
}
}

View File

@@ -1,6 +1,13 @@
import { RaceResultsDetailDto } from '../dtos';
import { RaceResultsDetailViewModel } from '../view-models';
export const presentRaceResultsDetail = (dto: RaceResultsDetailDto, currentUserId: string): RaceResultsDetailViewModel => {
return new RaceResultsDetailViewModel(dto, currentUserId);
export class RaceResultsDetailPresenter {
present(dto: RaceResultsDetailDto, currentUserId?: string): RaceResultsDetailViewModel {
return new RaceResultsDetailViewModel(dto, currentUserId);
}
}
export const presentRaceResultsDetail = (dto: RaceResultsDetailDto, currentUserId?: string): RaceResultsDetailViewModel => {
const presenter = new RaceResultsDetailPresenter();
return presenter.present(dto, currentUserId);
};

View File

@@ -5,10 +5,8 @@ import type {
} from '@core/racing/application/presenters/IRaceWithSOFPresenter';
export class RaceWithSOFPresenter implements IRaceWithSOFPresenter {
private viewModel: RaceWithSOFViewModel | null = null;
present(dto: RaceWithSOFResultDTO): void {
this.viewModel = {
present(dto: RaceWithSOFResultDTO): RaceWithSOFViewModel {
return {
id: dto.raceId,
leagueId: dto.leagueId,
scheduledAt: dto.scheduledAt.toISOString(),
@@ -24,12 +22,4 @@ export class RaceWithSOFPresenter implements IRaceWithSOFPresenter {
participantCount: dto.participantCount,
};
}
getViewModel(): RaceWithSOFViewModel | null {
return this.viewModel;
}
reset(): void {
this.viewModel = null;
}
}

View File

@@ -22,7 +22,9 @@ export { presentWalletTransaction } from './WalletTransactionPresenter';
export { presentRaceDetail } from './RaceDetailPresenter';
export { presentRaceListItem } from './RaceListItemPresenter';
export { presentRaceResult } from './RaceResultsPresenter';
export { presentRaceResultsDetail } from './RaceResultsDetailPresenter';
export { presentRaceResultsDetail, RaceResultsDetailPresenter } from './RaceResultsDetailPresenter';
export { RaceWithSOFPresenter } from './RaceWithSOFPresenter';
export { ImportRaceResultsPresenter } from './ImportRaceResultsPresenter';
// Sponsor Presenters
export { presentSponsor } from './SponsorPresenter';