refactor core presenters
This commit is contained in:
@@ -46,8 +46,8 @@ export class RaceController {
|
||||
|
||||
@Get('all/page-data')
|
||||
@ApiOperation({ summary: 'Get all races page data' })
|
||||
@ApiResponse({ status: 200, description: 'All races page data', type: RacesPageDataDTO })
|
||||
async getAllRacesPageData(): Promise<RacesPageDataDTO> {
|
||||
@ApiResponse({ status: 200, description: 'All races page data', type: AllRacesPageDTO })
|
||||
async getAllRacesPageData(): Promise<AllRacesPageDTO> {
|
||||
return this.raceService.getAllRacesPageData();
|
||||
}
|
||||
|
||||
|
||||
@@ -146,8 +146,6 @@ export const RaceProviders: Provider[] = [
|
||||
raceRegRepo: IRaceRegistrationRepository,
|
||||
resultRepo: IResultRepository,
|
||||
leagueMembershipRepo: ILeagueMembershipRepository,
|
||||
driverRatingProvider: DriverRatingProvider,
|
||||
imageService: IImageServicePort,
|
||||
) => new GetRaceDetailUseCase(
|
||||
raceRepo,
|
||||
leagueRepo,
|
||||
@@ -155,8 +153,6 @@ export const RaceProviders: Provider[] = [
|
||||
raceRegRepo,
|
||||
resultRepo,
|
||||
leagueMembershipRepo,
|
||||
driverRatingProvider,
|
||||
imageService,
|
||||
),
|
||||
inject: [
|
||||
RACE_REPOSITORY_TOKEN,
|
||||
@@ -165,8 +161,6 @@ export const RaceProviders: Provider[] = [
|
||||
RACE_REGISTRATION_REPOSITORY_TOKEN,
|
||||
RESULT_REPOSITORY_TOKEN,
|
||||
LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN,
|
||||
DRIVER_RATING_PROVIDER_TOKEN,
|
||||
IMAGE_SERVICE_TOKEN,
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import { Injectable, Inject } from '@nestjs/common';
|
||||
import type { AllRacesPageViewModel } from '@core/racing/application/presenters/IGetAllRacesPresenter';
|
||||
import type { GetTotalRacesViewModel } from '@core/racing/application/presenters/IGetTotalRacesPresenter';
|
||||
import type { RaceDetailViewModel } from '@core/racing/application/presenters/IRaceDetailPresenter';
|
||||
import type { RacesPageViewModel } from '@core/racing/application/presenters/IRacesPagePresenter';
|
||||
import type { RaceResultsDetailViewModel } from '@core/racing/application/presenters/IRaceResultsDetailPresenter';
|
||||
import type { RaceWithSOFViewModel } from '@core/racing/application/presenters/IRaceWithSOFPresenter';
|
||||
import type { RaceProtestsViewModel } from '@core/racing/application/presenters/IRaceProtestsPresenter';
|
||||
import type { RacePenaltiesViewModel } from '@core/racing/application/presenters/IRacePenaltiesPresenter';
|
||||
import type { RaceDetailOutputPort } from '@core/racing/application/ports/output/RaceDetailOutputPort';
|
||||
import type { RacesPageOutputPort } from '@core/racing/application/ports/output/RacesPageOutputPort';
|
||||
import type { RaceResultsDetailOutputPort } from '@core/racing/application/ports/output/RaceResultsDetailOutputPort';
|
||||
import type { RaceWithSOFOutputPort } from '@core/racing/application/ports/output/RaceWithSOFOutputPort';
|
||||
import type { RaceProtestsOutputPort } from '@core/racing/application/ports/output/RaceProtestsOutputPort';
|
||||
import type { RacePenaltiesOutputPort } from '@core/racing/application/ports/output/RacePenaltiesOutputPort';
|
||||
|
||||
// DTOs
|
||||
import { GetRaceDetailParamsDTO } from './dtos/GetRaceDetailParamsDTO';
|
||||
@@ -14,9 +13,18 @@ import { RegisterForRaceParamsDTO } from './dtos/RegisterForRaceParamsDTO';
|
||||
import { WithdrawFromRaceParamsDTO } from './dtos/WithdrawFromRaceParamsDTO';
|
||||
import { RaceActionParamsDTO } from './dtos/RaceActionParamsDTO';
|
||||
import { ImportRaceResultsDTO } from './dtos/ImportRaceResultsDTO';
|
||||
import { AllRacesPageDTO } from './dtos/AllRacesPageDTO';
|
||||
import { RaceStatsDTO } from './dtos/RaceStatsDTO';
|
||||
import { RacePenaltiesDTO } from './dtos/RacePenaltiesDTO';
|
||||
import { RaceProtestsDTO } from './dtos/RaceProtestsDTO';
|
||||
import { RaceResultsDetailDTO } from './dtos/RaceResultsDetailDTO';
|
||||
|
||||
// Core imports
|
||||
import type { Logger } from '@core/shared/application/Logger';
|
||||
import { Result } from '@core/shared/application/Result';
|
||||
import { DriverRatingProvider } from '@core/racing/application/ports/DriverRatingProvider';
|
||||
import { IImageServicePort } from '@core/racing/application/ports/IImageServicePort';
|
||||
import type { ILeagueRepository } from '@core/racing/domain/repositories/ILeagueRepository';
|
||||
|
||||
// Use cases
|
||||
import { GetAllRacesUseCase } from '@core/racing/application/use-cases/GetAllRacesUseCase';
|
||||
@@ -53,7 +61,7 @@ import { RequestProtestDefenseCommandDTO } from './dtos/RequestProtestDefenseCom
|
||||
import { ReviewProtestCommandDTO } from './dtos/ReviewProtestCommandDTO';
|
||||
|
||||
// Tokens
|
||||
import { LOGGER_TOKEN } from './RaceProviders';
|
||||
import { LOGGER_TOKEN, DRIVER_RATING_PROVIDER_TOKEN, IMAGE_SERVICE_TOKEN, LEAGUE_REPOSITORY_TOKEN } from './RaceProviders';
|
||||
|
||||
@Injectable()
|
||||
export class RaceService {
|
||||
@@ -77,7 +85,10 @@ export class RaceService {
|
||||
private readonly applyPenaltyUseCase: ApplyPenaltyUseCase,
|
||||
private readonly requestProtestDefenseUseCase: RequestProtestDefenseUseCase,
|
||||
private readonly reviewProtestUseCase: ReviewProtestUseCase,
|
||||
@Inject(LEAGUE_REPOSITORY_TOKEN) private readonly leagueRepository: ILeagueRepository,
|
||||
@Inject(LOGGER_TOKEN) private readonly logger: Logger,
|
||||
@Inject(DRIVER_RATING_PROVIDER_TOKEN) private readonly driverRatingProvider: DriverRatingProvider,
|
||||
@Inject(IMAGE_SERVICE_TOKEN) private readonly imageService: IImageServicePort,
|
||||
) {}
|
||||
|
||||
async getAllRaces(): Promise<AllRacesPageViewModel> {
|
||||
@@ -88,21 +99,29 @@ export class RaceService {
|
||||
return presenter.getViewModel()!;
|
||||
}
|
||||
|
||||
async getTotalRaces(): Promise<GetTotalRacesViewModel> {
|
||||
async getTotalRaces(): Promise<RaceStatsDTO> {
|
||||
this.logger.debug('[RaceService] Fetching total races count.');
|
||||
const result = await this.getTotalRacesUseCase.execute();
|
||||
if (result.isErr()) {
|
||||
throw new Error(result.unwrapErr().code);
|
||||
}
|
||||
const presenter = new GetTotalRacesPresenter();
|
||||
await this.getTotalRacesUseCase.execute({}, presenter);
|
||||
presenter.present(result.unwrap());
|
||||
return presenter.getViewModel()!;
|
||||
}
|
||||
|
||||
async importRaceResults(input: ImportRaceResultsDTO): Promise<ImportRaceResultsSummaryDTO> {
|
||||
this.logger.debug('Importing race results:', input);
|
||||
const result = await this.importRaceResultsApiUseCase.execute({ raceId: input.raceId, resultsFileContent: input.resultsFileContent });
|
||||
if (result.isErr()) {
|
||||
throw new Error(result.unwrapErr().code);
|
||||
}
|
||||
const presenter = new ImportRaceResultsApiPresenter();
|
||||
await this.importRaceResultsApiUseCase.execute({ raceId: input.raceId, resultsFileContent: input.resultsFileContent }, presenter);
|
||||
presenter.present(result.unwrap());
|
||||
return presenter.getViewModel()!;
|
||||
}
|
||||
|
||||
async getRaceDetail(params: GetRaceDetailParamsDTO): Promise<RaceDetailViewModel> {
|
||||
async getRaceDetail(params: GetRaceDetailParamsDTO): Promise<RaceDetailDTO> {
|
||||
this.logger.debug('[RaceService] Fetching race detail:', params);
|
||||
|
||||
const result = await this.getRaceDetailUseCase.execute(params);
|
||||
@@ -111,10 +130,71 @@ export class RaceService {
|
||||
throw new Error('Failed to get race detail');
|
||||
}
|
||||
|
||||
return result.value;
|
||||
const outputPort = result.value;
|
||||
|
||||
// Map to DTO
|
||||
const raceDTO = outputPort.race ? {
|
||||
id: outputPort.race.id,
|
||||
leagueId: outputPort.race.leagueId,
|
||||
track: outputPort.race.track,
|
||||
car: outputPort.race.car,
|
||||
scheduledAt: outputPort.race.scheduledAt.toISOString(),
|
||||
sessionType: outputPort.race.sessionType,
|
||||
status: outputPort.race.status,
|
||||
strengthOfField: outputPort.race.strengthOfField ?? null,
|
||||
registeredCount: outputPort.race.registeredCount ?? undefined,
|
||||
maxParticipants: outputPort.race.maxParticipants ?? undefined,
|
||||
} : null;
|
||||
|
||||
const leagueDTO = outputPort.league ? {
|
||||
id: outputPort.league.id.toString(),
|
||||
name: outputPort.league.name.toString(),
|
||||
description: outputPort.league.description.toString(),
|
||||
settings: {
|
||||
maxDrivers: outputPort.league.settings.maxDrivers ?? undefined,
|
||||
qualifyingFormat: outputPort.league.settings.qualifyingFormat ?? undefined,
|
||||
},
|
||||
} : null;
|
||||
|
||||
const entryListDTO = await Promise.all(outputPort.drivers.map(async driver => {
|
||||
const ratingResult = await this.driverRatingProvider.getDriverRating({ driverId: driver.id });
|
||||
const avatarResult = await this.imageService.getDriverAvatar({ driverId: driver.id });
|
||||
return {
|
||||
id: driver.id,
|
||||
name: driver.name.toString(),
|
||||
country: driver.country.toString(),
|
||||
avatarUrl: avatarResult.avatarUrl,
|
||||
rating: ratingResult.rating,
|
||||
isCurrentUser: driver.id === params.driverId,
|
||||
};
|
||||
}));
|
||||
|
||||
const registrationDTO = {
|
||||
isUserRegistered: outputPort.isUserRegistered,
|
||||
canRegister: outputPort.canRegister,
|
||||
};
|
||||
|
||||
const userResultDTO = outputPort.userResult ? {
|
||||
position: outputPort.userResult.position.toNumber(),
|
||||
startPosition: outputPort.userResult.startPosition.toNumber(),
|
||||
incidents: outputPort.userResult.incidents.toNumber(),
|
||||
fastestLap: outputPort.userResult.fastestLap.toNumber(),
|
||||
positionChange: outputPort.userResult.getPositionChange(),
|
||||
isPodium: outputPort.userResult.isPodium(),
|
||||
isClean: outputPort.userResult.isClean(),
|
||||
ratingChange: this.calculateRatingChange(outputPort.userResult.position.toNumber()),
|
||||
} : null;
|
||||
|
||||
return {
|
||||
race: raceDTO,
|
||||
league: leagueDTO,
|
||||
entryList: entryListDTO,
|
||||
registration: registrationDTO,
|
||||
userResult: userResultDTO,
|
||||
};
|
||||
}
|
||||
|
||||
async getRacesPageData(): Promise<RacesPageViewModel> {
|
||||
async getRacesPageData(): Promise<RacesPageDataDTO> {
|
||||
this.logger.debug('[RaceService] Fetching races page data.');
|
||||
|
||||
const result = await this.getRacesPageDataUseCase.execute();
|
||||
@@ -123,10 +203,33 @@ export class RaceService {
|
||||
throw new Error('Failed to get races page data');
|
||||
}
|
||||
|
||||
return result.value;
|
||||
const outputPort = result.value;
|
||||
|
||||
// Fetch leagues for league names
|
||||
const allLeagues = await this.leagueRepository.findAll();
|
||||
const leagueMap = new Map(allLeagues.map(l => [l.id, l.name]));
|
||||
|
||||
// Map to DTO
|
||||
const racesDTO = outputPort.races.map(race => ({
|
||||
id: race.id,
|
||||
track: race.track,
|
||||
car: race.car,
|
||||
scheduledAt: race.scheduledAt.toISOString(),
|
||||
status: race.status,
|
||||
leagueId: race.leagueId,
|
||||
leagueName: leagueMap.get(race.leagueId) ?? 'Unknown League',
|
||||
strengthOfField: race.strengthOfField,
|
||||
isUpcoming: race.scheduledAt > new Date(),
|
||||
isLive: race.status === 'running',
|
||||
isPast: race.scheduledAt < new Date() && race.status === 'completed',
|
||||
}));
|
||||
|
||||
return {
|
||||
races: racesDTO,
|
||||
};
|
||||
}
|
||||
|
||||
async getAllRacesPageData(): Promise<RacesPageViewModel> {
|
||||
async getAllRacesPageData(): Promise<AllRacesPageDTO> {
|
||||
this.logger.debug('[RaceService] Fetching all races page data.');
|
||||
|
||||
const result = await this.getAllRacesPageDataUseCase.execute();
|
||||
@@ -135,10 +238,10 @@ export class RaceService {
|
||||
throw new Error('Failed to get all races page data');
|
||||
}
|
||||
|
||||
return result.value;
|
||||
return result.value as AllRacesPageDTO;
|
||||
}
|
||||
|
||||
async getRaceResultsDetail(raceId: string): Promise<RaceResultsDetailViewModel> {
|
||||
async getRaceResultsDetail(raceId: string): Promise<RaceResultsDetailDTO> {
|
||||
this.logger.debug('[RaceService] Fetching race results detail:', { raceId });
|
||||
|
||||
const result = await this.getRaceResultsDetailUseCase.execute({ raceId });
|
||||
@@ -147,10 +250,41 @@ export class RaceService {
|
||||
throw new Error('Failed to get race results detail');
|
||||
}
|
||||
|
||||
return result.value;
|
||||
const outputPort = result.value;
|
||||
|
||||
// Create a map of driverId to driver for easy lookup
|
||||
const driverMap = new Map(outputPort.drivers.map(driver => [driver.id, driver]));
|
||||
|
||||
const resultsDTO = await Promise.all(outputPort.results.map(async (result) => {
|
||||
const driver = driverMap.get(result.driverId.toString());
|
||||
if (!driver) {
|
||||
throw new Error(`Driver not found for result: ${result.driverId}`);
|
||||
}
|
||||
|
||||
const avatarResult = await this.imageService.getDriverAvatar({ driverId: driver.id });
|
||||
|
||||
return {
|
||||
driverId: result.driverId.toString(),
|
||||
driverName: driver.name.toString(),
|
||||
avatarUrl: avatarResult.avatarUrl,
|
||||
position: result.position.toNumber(),
|
||||
startPosition: result.startPosition.toNumber(),
|
||||
incidents: result.incidents.toNumber(),
|
||||
fastestLap: result.fastestLap.toNumber(),
|
||||
positionChange: result.getPositionChange(),
|
||||
isPodium: result.isPodium(),
|
||||
isClean: result.isClean(),
|
||||
};
|
||||
}));
|
||||
|
||||
return {
|
||||
raceId: outputPort.race.id,
|
||||
track: outputPort.race.track,
|
||||
results: resultsDTO,
|
||||
};
|
||||
}
|
||||
|
||||
async getRaceWithSOF(raceId: string): Promise<RaceWithSOFViewModel> {
|
||||
async getRaceWithSOF(raceId: string): Promise<RaceWithSOFDTO> {
|
||||
this.logger.debug('[RaceService] Fetching race with SOF:', { raceId });
|
||||
|
||||
const result = await this.getRaceWithSOFUseCase.execute({ raceId });
|
||||
@@ -159,10 +293,17 @@ export class RaceService {
|
||||
throw new Error('Failed to get race with SOF');
|
||||
}
|
||||
|
||||
return result.value;
|
||||
const outputPort = result.value;
|
||||
|
||||
// Map to DTO
|
||||
return {
|
||||
id: outputPort.id,
|
||||
track: outputPort.track,
|
||||
strengthOfField: outputPort.strengthOfField,
|
||||
};
|
||||
}
|
||||
|
||||
async getRaceProtests(raceId: string): Promise<RaceProtestsViewModel> {
|
||||
async getRaceProtests(raceId: string): Promise<RaceProtestsDTO> {
|
||||
this.logger.debug('[RaceService] Fetching race protests:', { raceId });
|
||||
|
||||
const result = await this.getRaceProtestsUseCase.execute({ raceId });
|
||||
@@ -171,10 +312,32 @@ export class RaceService {
|
||||
throw new Error('Failed to get race protests');
|
||||
}
|
||||
|
||||
return result.value;
|
||||
const outputPort = result.value;
|
||||
|
||||
const protestsDTO = outputPort.protests.map(protest => ({
|
||||
id: protest.id,
|
||||
protestingDriverId: protest.protestingDriverId,
|
||||
accusedDriverId: protest.accusedDriverId,
|
||||
incident: {
|
||||
lap: protest.incident.lap,
|
||||
description: protest.incident.description,
|
||||
},
|
||||
status: protest.status,
|
||||
filedAt: protest.filedAt.toISOString(),
|
||||
}));
|
||||
|
||||
const driverMap: Record<string, string> = {};
|
||||
outputPort.drivers.forEach(driver => {
|
||||
driverMap[driver.id] = driver.name.toString();
|
||||
});
|
||||
|
||||
return {
|
||||
protests: protestsDTO,
|
||||
driverMap,
|
||||
};
|
||||
}
|
||||
|
||||
async getRacePenalties(raceId: string): Promise<RacePenaltiesViewModel> {
|
||||
async getRacePenalties(raceId: string): Promise<RacePenaltiesDTO> {
|
||||
this.logger.debug('[RaceService] Fetching race penalties:', { raceId });
|
||||
|
||||
const result = await this.getRacePenaltiesUseCase.execute({ raceId });
|
||||
@@ -183,7 +346,28 @@ export class RaceService {
|
||||
throw new Error('Failed to get race penalties');
|
||||
}
|
||||
|
||||
return result.value;
|
||||
const outputPort = result.value;
|
||||
|
||||
const penaltiesDTO = outputPort.penalties.map(penalty => ({
|
||||
id: penalty.id,
|
||||
driverId: penalty.driverId,
|
||||
type: penalty.type,
|
||||
value: penalty.value ?? 0,
|
||||
reason: penalty.reason,
|
||||
issuedBy: penalty.issuedBy,
|
||||
issuedAt: penalty.issuedAt.toISOString(),
|
||||
notes: penalty.notes,
|
||||
}));
|
||||
|
||||
const driverMap: Record<string, string> = {};
|
||||
outputPort.drivers.forEach(driver => {
|
||||
driverMap[driver.id] = driver.name.toString();
|
||||
});
|
||||
|
||||
return {
|
||||
penalties: penaltiesDTO,
|
||||
driverMap,
|
||||
};
|
||||
}
|
||||
|
||||
async registerForRace(params: RegisterForRaceParamsDTO): Promise<void> {
|
||||
@@ -277,4 +461,10 @@ export class RaceService {
|
||||
throw new Error('Failed to review protest');
|
||||
}
|
||||
}
|
||||
|
||||
private calculateRatingChange(position: number): number {
|
||||
const baseChange = position <= 3 ? 25 : position <= 10 ? 10 : -5;
|
||||
const positionBonus = Math.max(0, (20 - position) * 2);
|
||||
return baseChange + positionBonus;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,45 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { RaceViewModel } from '@core/racing/application/presenters/IGetAllRacesPresenter';
|
||||
|
||||
export class AllRacesPageDTO {
|
||||
@ApiProperty({ type: [RaceViewModel] })
|
||||
races!: RaceViewModel[];
|
||||
export type AllRacesStatus = 'scheduled' | 'running' | 'completed' | 'cancelled' | 'all';
|
||||
|
||||
export class AllRacesListItemDTO {
|
||||
@ApiProperty()
|
||||
id!: string;
|
||||
|
||||
@ApiProperty()
|
||||
totalCount!: number;
|
||||
track!: string;
|
||||
|
||||
@ApiProperty()
|
||||
car!: string;
|
||||
|
||||
@ApiProperty()
|
||||
scheduledAt!: string;
|
||||
|
||||
@ApiProperty()
|
||||
status!: 'scheduled' | 'running' | 'completed' | 'cancelled';
|
||||
|
||||
@ApiProperty()
|
||||
leagueId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
leagueName!: string;
|
||||
|
||||
@ApiProperty({ nullable: true })
|
||||
strengthOfField!: number | null;
|
||||
}
|
||||
|
||||
export class AllRacesFilterOptionsDTO {
|
||||
@ApiProperty({ type: [{ value: String, label: String }] })
|
||||
statuses!: { value: AllRacesStatus; label: string }[];
|
||||
|
||||
@ApiProperty({ type: [{ id: String, name: String }] })
|
||||
leagues!: { id: string; name: string }[];
|
||||
}
|
||||
|
||||
export class AllRacesPageDTO {
|
||||
@ApiProperty({ type: [AllRacesListItemDTO] })
|
||||
races!: AllRacesListItemDTO[];
|
||||
|
||||
@ApiProperty({ type: AllRacesFilterOptionsDTO })
|
||||
filters!: AllRacesFilterOptionsDTO;
|
||||
}
|
||||
@@ -1,17 +1,39 @@
|
||||
import { IGetAllRacesPresenter, GetAllRacesResultDTO, AllRacesPageViewModel } from '@core/racing/application/presenters/IGetAllRacesPresenter';
|
||||
import { GetAllRacesOutputPort } from '@core/racing/application/ports/output/GetAllRacesOutputPort';
|
||||
import { AllRacesPageDTO } from '../dtos/AllRacesPageDTO';
|
||||
|
||||
export class GetAllRacesPresenter implements IGetAllRacesPresenter {
|
||||
private result: AllRacesPageViewModel | null = null;
|
||||
export class GetAllRacesPresenter {
|
||||
private result: AllRacesPageDTO | null = null;
|
||||
|
||||
reset() {
|
||||
this.result = null;
|
||||
}
|
||||
|
||||
present(dto: GetAllRacesResultDTO) {
|
||||
this.result = dto;
|
||||
async present(output: GetAllRacesOutputPort) {
|
||||
this.result = {
|
||||
races: output.races.map(race => ({
|
||||
id: race.id,
|
||||
track: race.track,
|
||||
car: race.car,
|
||||
scheduledAt: race.scheduledAt,
|
||||
status: race.status,
|
||||
leagueId: race.leagueId,
|
||||
leagueName: race.leagueName,
|
||||
strengthOfField: race.strengthOfField,
|
||||
})),
|
||||
filters: {
|
||||
statuses: [
|
||||
{ value: 'all', label: 'All' },
|
||||
{ value: 'scheduled', label: 'Scheduled' },
|
||||
{ value: 'running', label: 'Running' },
|
||||
{ value: 'completed', label: 'Completed' },
|
||||
{ value: 'cancelled', label: 'Cancelled' },
|
||||
],
|
||||
leagues: [], // TODO: populate if needed
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
getViewModel(): AllRacesPageViewModel | null {
|
||||
getViewModel(): AllRacesPageDTO | null {
|
||||
return this.result;
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,20 @@
|
||||
import { IGetTotalRacesPresenter, GetTotalRacesResultDTO, GetTotalRacesViewModel } from '@core/racing/application/presenters/IGetTotalRacesPresenter';
|
||||
import { GetTotalRacesOutputPort } from '@core/racing/application/ports/output/GetTotalRacesOutputPort';
|
||||
import { RaceStatsDTO } from '../dtos/RaceStatsDTO';
|
||||
|
||||
export class GetTotalRacesPresenter implements IGetTotalRacesPresenter {
|
||||
private result: GetTotalRacesViewModel | null = null;
|
||||
export class GetTotalRacesPresenter {
|
||||
private result: RaceStatsDTO | null = null;
|
||||
|
||||
reset() {
|
||||
this.result = null;
|
||||
}
|
||||
|
||||
present(dto: GetTotalRacesResultDTO) {
|
||||
present(output: GetTotalRacesOutputPort) {
|
||||
this.result = {
|
||||
totalRaces: dto.totalRaces,
|
||||
totalRaces: output.totalRaces,
|
||||
};
|
||||
}
|
||||
|
||||
getViewModel(): GetTotalRacesViewModel | null {
|
||||
getViewModel(): RaceStatsDTO | null {
|
||||
return this.result;
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,24 @@
|
||||
import { IImportRaceResultsApiPresenter, ImportRaceResultsApiResultDTO, ImportRaceResultsSummaryViewModel } from '@core/racing/application/presenters/IImportRaceResultsApiPresenter';
|
||||
import { ImportRaceResultsApiOutputPort } from '@core/racing/application/ports/output/ImportRaceResultsApiOutputPort';
|
||||
import { ImportRaceResultsSummaryDTO } from '../dtos/ImportRaceResultsSummaryDTO';
|
||||
|
||||
export class ImportRaceResultsApiPresenter implements IImportRaceResultsApiPresenter {
|
||||
private result: ImportRaceResultsSummaryViewModel | null = null;
|
||||
export class ImportRaceResultsApiPresenter {
|
||||
private result: ImportRaceResultsSummaryDTO | null = null;
|
||||
|
||||
reset() {
|
||||
this.result = null;
|
||||
}
|
||||
|
||||
present(dto: ImportRaceResultsApiResultDTO) {
|
||||
this.result = dto;
|
||||
present(output: ImportRaceResultsApiOutputPort) {
|
||||
this.result = {
|
||||
success: output.success,
|
||||
raceId: output.raceId,
|
||||
driversProcessed: output.driversProcessed,
|
||||
resultsRecorded: output.resultsRecorded,
|
||||
errors: output.errors,
|
||||
};
|
||||
}
|
||||
|
||||
getViewModel(): ImportRaceResultsSummaryViewModel | null {
|
||||
getViewModel(): ImportRaceResultsSummaryDTO | null {
|
||||
return this.result;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user