refactor
This commit is contained in:
@@ -1,7 +1,25 @@
|
||||
import { Controller, Get, Post, Body, HttpCode, HttpStatus } from '@nestjs/common';
|
||||
import { ApiTags, ApiResponse, ApiOperation } from '@nestjs/swagger';
|
||||
import { Controller, Get, Post, Body, HttpCode, HttpStatus, Param, Query } from '@nestjs/common';
|
||||
import { ApiTags, ApiResponse, ApiOperation, ApiParam, ApiQuery } from '@nestjs/swagger';
|
||||
import { RaceService } from './RaceService';
|
||||
import { AllRacesPageViewModel, RaceStatsDto } from './dto/RaceDto';
|
||||
import { AllRacesPageDTO } from './dtos/AllRacesPageDTO';
|
||||
import { RaceStatsDTO } from './dtos/RaceStatsDTO';
|
||||
import { RaceDetailDTO } from './dtos/RaceDetailDTO';
|
||||
import { RacesPageDataDTO } from './dtos/RacesPageDataDTO';
|
||||
import { RaceResultsDetailDTO } from './dtos/RaceResultsDetailDTO';
|
||||
import { RaceWithSOFDTO } from './dtos/RaceWithSOFDTO';
|
||||
import { RaceProtestsDTO } from './dtos/RaceProtestsDTO';
|
||||
import { RacePenaltiesDTO } from './dtos/RacePenaltiesDTO';
|
||||
import { GetRaceDetailParamsDTO } from './dtos/GetRaceDetailParamsDTO';
|
||||
import { RegisterForRaceParamsDTO } from './dtos/RegisterForRaceParamsDTO';
|
||||
import { WithdrawFromRaceParamsDTO } from './dtos/WithdrawFromRaceParamsDTO';
|
||||
import { RaceActionParamsDTO } from './dtos/RaceActionParamsDTO';
|
||||
import { ImportRaceResultsDTO } from './dtos/ImportRaceResultsDTO';
|
||||
import { ImportRaceResultsSummaryDTO } from './dtos/ImportRaceResultsSummaryDTO';
|
||||
import { DashboardOverviewDTO } from './dtos/DashboardOverviewDTO';
|
||||
import { FileProtestCommandDTO } from './dtos/FileProtestCommandDTO';
|
||||
import { QuickPenaltyCommandDTO } from './dtos/QuickPenaltyCommandDTO';
|
||||
import { ApplyPenaltyCommandDTO } from './dtos/ApplyPenaltyCommandDTO';
|
||||
import { RequestProtestDefenseCommandDTO } from './dtos/RequestProtestDefenseCommandDTO';
|
||||
|
||||
@ApiTags('races')
|
||||
@Controller('races')
|
||||
@@ -10,17 +28,167 @@ export class RaceController {
|
||||
|
||||
@Get('all')
|
||||
@ApiOperation({ summary: 'Get all races' })
|
||||
@ApiResponse({ status: 200, description: 'List of all races', type: AllRacesPageViewModel })
|
||||
async getAllRaces(): Promise<AllRacesPageViewModel> {
|
||||
@ApiResponse({ status: 200, description: 'List of all races', type: AllRacesPageDTO })
|
||||
async getAllRaces(): Promise<AllRacesPageDTO> {
|
||||
return this.raceService.getAllRaces();
|
||||
}
|
||||
|
||||
@Get('total-races')
|
||||
@ApiOperation({ summary: 'Get the total number of races' })
|
||||
@ApiResponse({ status: 200, description: 'Total number of races', type: RaceStatsDto })
|
||||
async getTotalRaces(): Promise<RaceStatsDto> {
|
||||
@ApiResponse({ status: 200, description: 'Total number of races', type: RaceStatsDTO })
|
||||
async getTotalRaces(): Promise<RaceStatsDTO> {
|
||||
return this.raceService.getTotalRaces();
|
||||
}
|
||||
|
||||
// Add other Race endpoints here based on other presenters
|
||||
@Get('page-data')
|
||||
@ApiOperation({ summary: 'Get races page data' })
|
||||
@ApiResponse({ status: 200, description: 'Races page data', type: RacesPageDataDTO })
|
||||
async getRacesPageData(): Promise<RacesPageDataDTO> {
|
||||
return this.raceService.getRacesPageData();
|
||||
}
|
||||
|
||||
@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> {
|
||||
return this.raceService.getAllRacesPageData();
|
||||
}
|
||||
|
||||
@Get(':raceId')
|
||||
@ApiOperation({ summary: 'Get race detail' })
|
||||
@ApiParam({ name: 'raceId', description: 'Race ID' })
|
||||
@ApiQuery({ name: 'driverId', description: 'Driver ID' })
|
||||
@ApiResponse({ status: 200, description: 'Race detail', type: RaceDetailDTO })
|
||||
async getRaceDetail(
|
||||
@Param('raceId') raceId: string,
|
||||
@Query('driverId') driverId: string,
|
||||
): Promise<RaceDetailDTO> {
|
||||
return this.raceService.getRaceDetail({ raceId, driverId });
|
||||
}
|
||||
|
||||
@Get(':raceId/results')
|
||||
@ApiOperation({ summary: 'Get race results detail' })
|
||||
@ApiParam({ name: 'raceId', description: 'Race ID' })
|
||||
@ApiResponse({ status: 200, description: 'Race results detail', type: RaceResultsDetailDTO })
|
||||
async getRaceResultsDetail(@Param('raceId') raceId: string): Promise<RaceResultsDetailDTO> {
|
||||
return this.raceService.getRaceResultsDetail(raceId);
|
||||
}
|
||||
|
||||
@Get(':raceId/sof')
|
||||
@ApiOperation({ summary: 'Get race with strength of field' })
|
||||
@ApiParam({ name: 'raceId', description: 'Race ID' })
|
||||
@ApiResponse({ status: 200, description: 'Race with SOF', type: RaceWithSOFDTO })
|
||||
async getRaceWithSOF(@Param('raceId') raceId: string): Promise<RaceWithSOFDTO> {
|
||||
return this.raceService.getRaceWithSOF(raceId);
|
||||
}
|
||||
|
||||
@Get(':raceId/protests')
|
||||
@ApiOperation({ summary: 'Get race protests' })
|
||||
@ApiParam({ name: 'raceId', description: 'Race ID' })
|
||||
@ApiResponse({ status: 200, description: 'Race protests', type: RaceProtestsDTO })
|
||||
async getRaceProtests(@Param('raceId') raceId: string): Promise<RaceProtestsDTO> {
|
||||
return this.raceService.getRaceProtests(raceId);
|
||||
}
|
||||
|
||||
@Get(':raceId/penalties')
|
||||
@ApiOperation({ summary: 'Get race penalties' })
|
||||
@ApiParam({ name: 'raceId', description: 'Race ID' })
|
||||
@ApiResponse({ status: 200, description: 'Race penalties', type: RacePenaltiesDTO })
|
||||
async getRacePenalties(@Param('raceId') raceId: string): Promise<RacePenaltiesDTO> {
|
||||
return this.raceService.getRacePenalties(raceId);
|
||||
}
|
||||
|
||||
@Post(':raceId/register')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@ApiOperation({ summary: 'Register for race' })
|
||||
@ApiParam({ name: 'raceId', description: 'Race ID' })
|
||||
@ApiResponse({ status: 200, description: 'Successfully registered for race' })
|
||||
async registerForRace(
|
||||
@Param('raceId') raceId: string,
|
||||
@Body() body: Omit<RegisterForRaceParamsDTO, 'raceId'>,
|
||||
): Promise<void> {
|
||||
return this.raceService.registerForRace({ raceId, ...body });
|
||||
}
|
||||
|
||||
@Post(':raceId/withdraw')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@ApiOperation({ summary: 'Withdraw from race' })
|
||||
@ApiParam({ name: 'raceId', description: 'Race ID' })
|
||||
@ApiResponse({ status: 200, description: 'Successfully withdrew from race' })
|
||||
async withdrawFromRace(
|
||||
@Param('raceId') raceId: string,
|
||||
@Body() body: Omit<WithdrawFromRaceParamsDTO, 'raceId'>,
|
||||
): Promise<void> {
|
||||
return this.raceService.withdrawFromRace({ raceId, ...body });
|
||||
}
|
||||
|
||||
@Post(':raceId/cancel')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@ApiOperation({ summary: 'Cancel race' })
|
||||
@ApiParam({ name: 'raceId', description: 'Race ID' })
|
||||
@ApiResponse({ status: 200, description: 'Successfully cancelled race' })
|
||||
async cancelRace(@Param('raceId') raceId: string): Promise<void> {
|
||||
return this.raceService.cancelRace({ raceId });
|
||||
}
|
||||
|
||||
@Post(':raceId/complete')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@ApiOperation({ summary: 'Complete race' })
|
||||
@ApiParam({ name: 'raceId', description: 'Race ID' })
|
||||
@ApiResponse({ status: 200, description: 'Successfully completed race' })
|
||||
async completeRace(@Param('raceId') raceId: string): Promise<void> {
|
||||
return this.raceService.completeRace({ raceId });
|
||||
}
|
||||
|
||||
@Post(':raceId/import-results')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@ApiOperation({ summary: 'Import race results' })
|
||||
@ApiParam({ name: 'raceId', description: 'Race ID' })
|
||||
@ApiResponse({ status: 200, description: 'Successfully imported race results', type: ImportRaceResultsSummaryDTO })
|
||||
async importRaceResults(
|
||||
@Param('raceId') raceId: string,
|
||||
@Body() body: Omit<ImportRaceResultsDTO, 'raceId'>,
|
||||
): Promise<ImportRaceResultsSummaryDTO> {
|
||||
return this.raceService.importRaceResults({ raceId, ...body });
|
||||
}
|
||||
|
||||
@Get('dashboard/overview')
|
||||
@ApiOperation({ summary: 'Get dashboard overview' })
|
||||
@ApiQuery({ name: 'driverId', description: 'Driver ID' })
|
||||
@ApiResponse({ status: 200, description: 'Dashboard overview', type: DashboardOverviewDTO })
|
||||
async getDashboardOverview(@Query('driverId') driverId: string): Promise<DashboardOverviewDTO> {
|
||||
return this.raceService.getDashboardOverview(driverId);
|
||||
}
|
||||
|
||||
@Post('protests/file')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@ApiOperation({ summary: 'File a protest' })
|
||||
@ApiResponse({ status: 200, description: 'Protest filed successfully' })
|
||||
async fileProtest(@Body() body: FileProtestCommandDTO): Promise<any> {
|
||||
return this.raceService.fileProtest(body);
|
||||
}
|
||||
|
||||
@Post('penalties/quick')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@ApiOperation({ summary: 'Apply a quick penalty' })
|
||||
@ApiResponse({ status: 200, description: 'Penalty applied successfully' })
|
||||
async applyQuickPenalty(@Body() body: QuickPenaltyCommandDTO): Promise<any> {
|
||||
return this.raceService.applyQuickPenalty(body);
|
||||
}
|
||||
|
||||
@Post('penalties/apply')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@ApiOperation({ summary: 'Apply a penalty' })
|
||||
@ApiResponse({ status: 200, description: 'Penalty applied successfully' })
|
||||
async applyPenalty(@Body() body: ApplyPenaltyCommandDTO): Promise<any> {
|
||||
return this.raceService.applyPenalty(body);
|
||||
}
|
||||
|
||||
@Post('protests/defense/request')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@ApiOperation({ summary: 'Request protest defense' })
|
||||
@ApiResponse({ status: 200, description: 'Defense requested successfully' })
|
||||
async requestProtestDefense(@Body() body: RequestProtestDefenseCommandDTO): Promise<any> {
|
||||
return this.raceService.requestProtestDefense(body);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,20 +5,61 @@ import { RaceService } from './RaceService';
|
||||
import type { Logger } from '@core/shared/application/Logger';
|
||||
import { IRaceRepository } from '@core/racing/domain/repositories/IRaceRepository';
|
||||
import { ILeagueRepository } from '@core/racing/domain/repositories/ILeagueRepository';
|
||||
import { IDriverRepository } from '@core/racing/domain/repositories/IDriverRepository';
|
||||
import { IRaceRegistrationRepository } from '@core/racing/domain/repositories/IRaceRegistrationRepository';
|
||||
import { IResultRepository } from '@core/racing/domain/repositories/IResultRepository';
|
||||
import { ILeagueMembershipRepository } from '@core/racing/domain/repositories/ILeagueMembershipRepository';
|
||||
import { IPenaltyRepository } from '@core/racing/domain/repositories/IPenaltyRepository';
|
||||
import { IProtestRepository } from '@core/racing/domain/repositories/IProtestRepository';
|
||||
import { DriverRatingProvider } from '@core/racing/application/ports/DriverRatingProvider';
|
||||
import { IImageServicePort } from '@core/racing/application/ports/IImageServicePort';
|
||||
|
||||
// Import concrete in-memory implementations
|
||||
import { InMemoryRaceRepository } from '@adapters/racing/persistence/inmemory/InMemoryRaceRepository';
|
||||
import { InMemoryLeagueRepository } from '@adapters/racing/persistence/inmemory/InMemoryLeagueRepository';
|
||||
import { InMemoryDriverRepository } from '@adapters/racing/persistence/inmemory/InMemoryDriverRepository';
|
||||
import { InMemoryRaceRegistrationRepository } from '@adapters/racing/persistence/inmemory/InMemoryRaceRegistrationRepository';
|
||||
import { InMemoryResultRepository } from '@adapters/racing/persistence/inmemory/InMemoryResultRepository';
|
||||
import { InMemoryLeagueMembershipRepository } from '@adapters/racing/persistence/inmemory/InMemoryLeagueMembershipRepository';
|
||||
import { InMemoryPenaltyRepository } from '@adapters/racing/persistence/inmemory/InMemoryPenaltyRepository';
|
||||
import { InMemoryProtestRepository } from '@adapters/racing/persistence/inmemory/InMemoryProtestRepository';
|
||||
import { InMemoryDriverRatingProvider } from '@adapters/racing/ports/InMemoryDriverRatingProvider';
|
||||
import { InMemoryImageServiceAdapter } from '@adapters/media/ports/InMemoryImageServiceAdapter';
|
||||
import { ConsoleLogger } from '@adapters/logging/ConsoleLogger';
|
||||
|
||||
// Import use cases
|
||||
import { GetAllRacesUseCase } from '@core/racing/application/use-cases/GetAllRacesUseCase';
|
||||
import { GetTotalRacesUseCase } from '@core/racing/application/use-cases/GetTotalRacesUseCase';
|
||||
import { ImportRaceResultsApiUseCase } from '@core/racing/application/use-cases/ImportRaceResultsApiUseCase';
|
||||
import { GetRaceDetailUseCase } from '@core/racing/application/use-cases/GetRaceDetailUseCase';
|
||||
import { GetRacesPageDataUseCase } from '@core/racing/application/use-cases/GetRacesPageDataUseCase';
|
||||
import { GetAllRacesPageDataUseCase } from '@core/racing/application/use-cases/GetAllRacesPageDataUseCase';
|
||||
import { GetRaceResultsDetailUseCase } from '@core/racing/application/use-cases/GetRaceResultsDetailUseCase';
|
||||
import { GetRaceWithSOFUseCase } from '@core/racing/application/use-cases/GetRaceWithSOFUseCase';
|
||||
import { GetRaceProtestsUseCase } from '@core/racing/application/use-cases/GetRaceProtestsUseCase';
|
||||
import { GetRacePenaltiesUseCase } from '@core/racing/application/use-cases/GetRacePenaltiesUseCase';
|
||||
import { RegisterForRaceUseCase } from '@core/racing/application/use-cases/RegisterForRaceUseCase';
|
||||
import { WithdrawFromRaceUseCase } from '@core/racing/application/use-cases/WithdrawFromRaceUseCase';
|
||||
import { CancelRaceUseCase } from '@core/racing/application/use-cases/CancelRaceUseCase';
|
||||
import { CompleteRaceUseCase } from '@core/racing/application/use-cases/CompleteRaceUseCase';
|
||||
import { ImportRaceResultsUseCase } from '@core/racing/application/use-cases/ImportRaceResultsUseCase';
|
||||
import { DashboardOverviewUseCase } from '@core/racing/application/use-cases/DashboardOverviewUseCase';
|
||||
import { FileProtestUseCase } from '@core/racing/application/use-cases/FileProtestUseCase';
|
||||
import { QuickPenaltyUseCase } from '@core/racing/application/use-cases/QuickPenaltyUseCase';
|
||||
import { ApplyPenaltyUseCase } from '@core/racing/application/use-cases/ApplyPenaltyUseCase';
|
||||
import { RequestProtestDefenseUseCase } from '@core/racing/application/use-cases/RequestProtestDefenseUseCase';
|
||||
|
||||
// Define injection tokens
|
||||
export const RACE_REPOSITORY_TOKEN = 'IRaceRepository';
|
||||
export const LEAGUE_REPOSITORY_TOKEN = 'ILeagueRepository';
|
||||
export const DRIVER_REPOSITORY_TOKEN = 'IDriverRepository';
|
||||
export const RACE_REGISTRATION_REPOSITORY_TOKEN = 'IRaceRegistrationRepository';
|
||||
export const RESULT_REPOSITORY_TOKEN = 'IResultRepository';
|
||||
export const LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN = 'ILeagueMembershipRepository';
|
||||
export const PENALTY_REPOSITORY_TOKEN = 'IPenaltyRepository';
|
||||
export const PROTEST_REPOSITORY_TOKEN = 'IProtestRepository';
|
||||
export const DRIVER_RATING_PROVIDER_TOKEN = 'DriverRatingProvider';
|
||||
export const IMAGE_SERVICE_TOKEN = 'IImageServicePort';
|
||||
export const LOGGER_TOKEN = 'Logger';
|
||||
|
||||
export const RaceProviders: Provider[] = [
|
||||
@@ -33,6 +74,46 @@ export const RaceProviders: Provider[] = [
|
||||
useFactory: (logger: Logger) => new InMemoryLeagueRepository(logger),
|
||||
inject: [LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: DRIVER_REPOSITORY_TOKEN,
|
||||
useFactory: (logger: Logger) => new InMemoryDriverRepository(logger),
|
||||
inject: [LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: RACE_REGISTRATION_REPOSITORY_TOKEN,
|
||||
useFactory: (logger: Logger) => new InMemoryRaceRegistrationRepository(logger),
|
||||
inject: [LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: RESULT_REPOSITORY_TOKEN,
|
||||
useFactory: (logger: Logger) => new InMemoryResultRepository(logger),
|
||||
inject: [LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN,
|
||||
useFactory: (logger: Logger) => new InMemoryLeagueMembershipRepository(logger),
|
||||
inject: [LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: PENALTY_REPOSITORY_TOKEN,
|
||||
useFactory: (logger: Logger) => new InMemoryPenaltyRepository(logger),
|
||||
inject: [LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: PROTEST_REPOSITORY_TOKEN,
|
||||
useFactory: (logger: Logger) => new InMemoryProtestRepository(logger),
|
||||
inject: [LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: DRIVER_RATING_PROVIDER_TOKEN,
|
||||
useFactory: (logger: Logger) => new InMemoryDriverRatingProvider(logger),
|
||||
inject: [LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: IMAGE_SERVICE_TOKEN,
|
||||
useFactory: (logger: Logger) => new InMemoryImageServiceAdapter(logger),
|
||||
inject: [LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: LOGGER_TOKEN,
|
||||
useClass: ConsoleLogger,
|
||||
@@ -48,5 +129,114 @@ export const RaceProviders: Provider[] = [
|
||||
useFactory: (raceRepo: IRaceRepository) => new GetTotalRacesUseCase(raceRepo),
|
||||
inject: [RACE_REPOSITORY_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: GetRaceDetailUseCase,
|
||||
useFactory: (
|
||||
raceRepo: IRaceRepository,
|
||||
leagueRepo: ILeagueRepository,
|
||||
driverRepo: IDriverRepository,
|
||||
raceRegRepo: IRaceRegistrationRepository,
|
||||
resultRepo: IResultRepository,
|
||||
leagueMembershipRepo: ILeagueMembershipRepository,
|
||||
driverRatingProvider: DriverRatingProvider,
|
||||
imageService: IImageServicePort,
|
||||
) => new GetRaceDetailUseCase(
|
||||
raceRepo,
|
||||
leagueRepo,
|
||||
driverRepo,
|
||||
raceRegRepo,
|
||||
resultRepo,
|
||||
leagueMembershipRepo,
|
||||
driverRatingProvider,
|
||||
imageService,
|
||||
),
|
||||
inject: [
|
||||
RACE_REPOSITORY_TOKEN,
|
||||
LEAGUE_REPOSITORY_TOKEN,
|
||||
DRIVER_REPOSITORY_TOKEN,
|
||||
RACE_REGISTRATION_REPOSITORY_TOKEN,
|
||||
RESULT_REPOSITORY_TOKEN,
|
||||
LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN,
|
||||
DRIVER_RATING_PROVIDER_TOKEN,
|
||||
IMAGE_SERVICE_TOKEN,
|
||||
],
|
||||
},
|
||||
{
|
||||
provide: GetRacesPageDataUseCase,
|
||||
useFactory: (raceRepo: IRaceRepository, leagueRepo: ILeagueRepository) => new GetRacesPageDataUseCase(raceRepo, leagueRepo),
|
||||
inject: [RACE_REPOSITORY_TOKEN, LEAGUE_REPOSITORY_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: GetAllRacesPageDataUseCase,
|
||||
useFactory: (raceRepo: IRaceRepository, leagueRepo: ILeagueRepository) => new GetAllRacesPageDataUseCase(raceRepo, leagueRepo),
|
||||
inject: [RACE_REPOSITORY_TOKEN, LEAGUE_REPOSITORY_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: GetRaceResultsDetailUseCase,
|
||||
useFactory: (resultRepo: IResultRepository, driverRepo: IDriverRepository, imageService: IImageServicePort) =>
|
||||
new GetRaceResultsDetailUseCase(resultRepo, driverRepo, imageService),
|
||||
inject: [RESULT_REPOSITORY_TOKEN, DRIVER_REPOSITORY_TOKEN, IMAGE_SERVICE_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: GetRaceWithSOFUseCase,
|
||||
useFactory: (raceRepo: IRaceRepository) => new GetRaceWithSOFUseCase(raceRepo),
|
||||
inject: [RACE_REPOSITORY_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: GetRaceProtestsUseCase,
|
||||
useFactory: (protestRepo: IProtestRepository, driverRepo: IDriverRepository) => new GetRaceProtestsUseCase(protestRepo, driverRepo),
|
||||
inject: [PROTEST_REPOSITORY_TOKEN, DRIVER_REPOSITORY_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: GetRacePenaltiesUseCase,
|
||||
useFactory: (penaltyRepo: IPenaltyRepository, driverRepo: IDriverRepository) => new GetRacePenaltiesUseCase(penaltyRepo, driverRepo),
|
||||
inject: [PENALTY_REPOSITORY_TOKEN, DRIVER_REPOSITORY_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: RegisterForRaceUseCase,
|
||||
useFactory: (raceRegRepo: IRaceRegistrationRepository, leagueMembershipRepo: ILeagueMembershipRepository, logger: Logger) =>
|
||||
new RegisterForRaceUseCase(raceRegRepo, leagueMembershipRepo, logger),
|
||||
inject: [RACE_REGISTRATION_REPOSITORY_TOKEN, LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN, LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: WithdrawFromRaceUseCase,
|
||||
useFactory: (raceRegRepo: IRaceRegistrationRepository, logger: Logger) => new WithdrawFromRaceUseCase(raceRegRepo, logger),
|
||||
inject: [RACE_REGISTRATION_REPOSITORY_TOKEN, LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: CancelRaceUseCase,
|
||||
useFactory: (raceRepo: IRaceRepository, logger: Logger) => new CancelRaceUseCase(raceRepo, logger),
|
||||
inject: [RACE_REPOSITORY_TOKEN, LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: CompleteRaceUseCase,
|
||||
useFactory: (raceRepo: IRaceRepository, logger: Logger) => new CompleteRaceUseCase(raceRepo, logger),
|
||||
inject: [RACE_REPOSITORY_TOKEN, LOGGER_TOKEN],
|
||||
},
|
||||
ImportRaceResultsApiUseCase,
|
||||
ImportRaceResultsUseCase,
|
||||
{
|
||||
provide: FileProtestUseCase,
|
||||
useFactory: (protestRepo: IProtestRepository, raceRepo: IRaceRepository, driverRepo: IDriverRepository, logger: Logger) =>
|
||||
new FileProtestUseCase(protestRepo, raceRepo, driverRepo, logger),
|
||||
inject: [PROTEST_REPOSITORY_TOKEN, RACE_REPOSITORY_TOKEN, DRIVER_REPOSITORY_TOKEN, LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: QuickPenaltyUseCase,
|
||||
useFactory: (penaltyRepo: IPenaltyRepository, raceRepo: IRaceRepository, leagueMembershipRepo: ILeagueMembershipRepository, logger: Logger) =>
|
||||
new QuickPenaltyUseCase(penaltyRepo, raceRepo, leagueMembershipRepo, logger),
|
||||
inject: [PENALTY_REPOSITORY_TOKEN, RACE_REPOSITORY_TOKEN, LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN, LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: ApplyPenaltyUseCase,
|
||||
useFactory: (penaltyRepo: IPenaltyRepository, protestRepo: IProtestRepository, raceRepo: IRaceRepository, leagueMembershipRepo: ILeagueMembershipRepository, logger: Logger) =>
|
||||
new ApplyPenaltyUseCase(penaltyRepo, protestRepo, raceRepo, leagueMembershipRepo, logger),
|
||||
inject: [PENALTY_REPOSITORY_TOKEN, PROTEST_REPOSITORY_TOKEN, RACE_REPOSITORY_TOKEN, LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN, LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: RequestProtestDefenseUseCase,
|
||||
useFactory: (protestRepo: IProtestRepository, raceRepo: IRaceRepository, leagueMembershipRepo: ILeagueMembershipRepository) =>
|
||||
new RequestProtestDefenseUseCase(protestRepo, raceRepo, leagueMembershipRepo),
|
||||
inject: [PROTEST_REPOSITORY_TOKEN, RACE_REPOSITORY_TOKEN, LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN],
|
||||
},
|
||||
];
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
import { Injectable, Inject } from '@nestjs/common';
|
||||
import { AllRacesPageViewModel, RaceStatsDto, ImportRaceResultsInput, ImportRaceResultsSummaryViewModel } from './dto/RaceDto';
|
||||
import {
|
||||
AllRacesPageViewModel,
|
||||
RaceStatsDto,
|
||||
ImportRaceResultsInput,
|
||||
ImportRaceResultsSummaryViewModel,
|
||||
RaceDetailViewModelDto,
|
||||
RacesPageDataViewModelDto,
|
||||
RaceResultsDetailViewModelDto,
|
||||
RaceWithSOFViewModelDto,
|
||||
RaceProtestsViewModelDto,
|
||||
RacePenaltiesViewModelDto,
|
||||
GetRaceDetailParamsDto,
|
||||
RegisterForRaceParamsDto,
|
||||
WithdrawFromRaceParamsDto,
|
||||
RaceActionParamsDto,
|
||||
} from './dtos/RaceDTO';
|
||||
|
||||
// Core imports
|
||||
import type { Logger } from '@core/shared/application/Logger';
|
||||
@@ -8,6 +23,23 @@ import type { Logger } from '@core/shared/application/Logger';
|
||||
import { GetAllRacesUseCase } from '@core/racing/application/use-cases/GetAllRacesUseCase';
|
||||
import { GetTotalRacesUseCase } from '@core/racing/application/use-cases/GetTotalRacesUseCase';
|
||||
import { ImportRaceResultsApiUseCase } from '@core/racing/application/use-cases/ImportRaceResultsApiUseCase';
|
||||
import { GetRaceDetailUseCase } from '@core/racing/application/use-cases/GetRaceDetailUseCase';
|
||||
import { GetRacesPageDataUseCase } from '@core/racing/application/use-cases/GetRacesPageDataUseCase';
|
||||
import { GetAllRacesPageDataUseCase } from '@core/racing/application/use-cases/GetAllRacesPageDataUseCase';
|
||||
import { GetRaceResultsDetailUseCase } from '@core/racing/application/use-cases/GetRaceResultsDetailUseCase';
|
||||
import { GetRaceWithSOFUseCase } from '@core/racing/application/use-cases/GetRaceWithSOFUseCase';
|
||||
import { GetRaceProtestsUseCase } from '@core/racing/application/use-cases/GetRaceProtestsUseCase';
|
||||
import { GetRacePenaltiesUseCase } from '@core/racing/application/use-cases/GetRacePenaltiesUseCase';
|
||||
import { RegisterForRaceUseCase } from '@core/racing/application/use-cases/RegisterForRaceUseCase';
|
||||
import { WithdrawFromRaceUseCase } from '@core/racing/application/use-cases/WithdrawFromRaceUseCase';
|
||||
import { CancelRaceUseCase } from '@core/racing/application/use-cases/CancelRaceUseCase';
|
||||
import { CompleteRaceUseCase } from '@core/racing/application/use-cases/CompleteRaceUseCase';
|
||||
import { ImportRaceResultsUseCase } from '@core/racing/application/use-cases/ImportRaceResultsUseCase';
|
||||
import { DashboardOverviewUseCase } from '@core/racing/application/use-cases/DashboardOverviewUseCase';
|
||||
import { FileProtestUseCase } from '@core/racing/application/use-cases/FileProtestUseCase';
|
||||
import { QuickPenaltyUseCase } from '@core/racing/application/use-cases/QuickPenaltyUseCase';
|
||||
import { ApplyPenaltyUseCase } from '@core/racing/application/use-cases/ApplyPenaltyUseCase';
|
||||
import { RequestProtestDefenseUseCase } from '@core/racing/application/use-cases/RequestProtestDefenseUseCase';
|
||||
|
||||
// Presenters
|
||||
import { GetAllRacesPresenter } from './presenters/GetAllRacesPresenter';
|
||||
@@ -23,6 +55,23 @@ export class RaceService {
|
||||
private readonly getAllRacesUseCase: GetAllRacesUseCase,
|
||||
private readonly getTotalRacesUseCase: GetTotalRacesUseCase,
|
||||
private readonly importRaceResultsApiUseCase: ImportRaceResultsApiUseCase,
|
||||
private readonly getRaceDetailUseCase: GetRaceDetailUseCase,
|
||||
private readonly getRacesPageDataUseCase: GetRacesPageDataUseCase,
|
||||
private readonly getAllRacesPageDataUseCase: GetAllRacesPageDataUseCase,
|
||||
private readonly getRaceResultsDetailUseCase: GetRaceResultsDetailUseCase,
|
||||
private readonly getRaceWithSOFUseCase: GetRaceWithSOFUseCase,
|
||||
private readonly getRaceProtestsUseCase: GetRaceProtestsUseCase,
|
||||
private readonly getRacePenaltiesUseCase: GetRacePenaltiesUseCase,
|
||||
private readonly registerForRaceUseCase: RegisterForRaceUseCase,
|
||||
private readonly withdrawFromRaceUseCase: WithdrawFromRaceUseCase,
|
||||
private readonly cancelRaceUseCase: CancelRaceUseCase,
|
||||
private readonly completeRaceUseCase: CompleteRaceUseCase,
|
||||
private readonly importRaceResultsUseCase: ImportRaceResultsUseCase,
|
||||
private readonly dashboardOverviewUseCase: DashboardOverviewUseCase,
|
||||
private readonly fileProtestUseCase: FileProtestUseCase,
|
||||
private readonly quickPenaltyUseCase: QuickPenaltyUseCase,
|
||||
private readonly applyPenaltyUseCase: ApplyPenaltyUseCase,
|
||||
private readonly requestProtestDefenseUseCase: RequestProtestDefenseUseCase,
|
||||
@Inject(LOGGER_TOKEN) private readonly logger: Logger,
|
||||
) {}
|
||||
|
||||
@@ -47,4 +96,202 @@ export class RaceService {
|
||||
await this.importRaceResultsApiUseCase.execute({ raceId: input.raceId, resultsFileContent: input.resultsFileContent }, presenter);
|
||||
return presenter.getViewModel()!;
|
||||
}
|
||||
|
||||
async getRaceDetail(params: GetRaceDetailParamsDto): Promise<RaceDetailViewModelDto> {
|
||||
this.logger.debug('[RaceService] Fetching race detail:', params);
|
||||
|
||||
const presenter = new RaceDetailPresenter();
|
||||
const result = await this.getRaceDetailUseCase.execute(params);
|
||||
|
||||
if (result.isErr()) {
|
||||
throw new Error(result.error.details.message || 'Failed to get race detail');
|
||||
}
|
||||
|
||||
return result.value;
|
||||
}
|
||||
|
||||
async getRacesPageData(): Promise<RacesPageDataViewModelDto> {
|
||||
this.logger.debug('[RaceService] Fetching races page data.');
|
||||
|
||||
const result = await this.getRacesPageDataUseCase.execute();
|
||||
|
||||
if (result.isErr()) {
|
||||
throw new Error('Failed to get races page data');
|
||||
}
|
||||
|
||||
return result.value;
|
||||
}
|
||||
|
||||
async getAllRacesPageData(): Promise<RacesPageDataViewModelDto> {
|
||||
this.logger.debug('[RaceService] Fetching all races page data.');
|
||||
|
||||
const result = await this.getAllRacesPageDataUseCase.execute();
|
||||
|
||||
if (result.isErr()) {
|
||||
throw new Error('Failed to get all races page data');
|
||||
}
|
||||
|
||||
return result.value;
|
||||
}
|
||||
|
||||
async getRaceResultsDetail(raceId: string): Promise<RaceResultsDetailViewModelDto> {
|
||||
this.logger.debug('[RaceService] Fetching race results detail:', { raceId });
|
||||
|
||||
const result = await this.getRaceResultsDetailUseCase.execute({ raceId });
|
||||
|
||||
if (result.isErr()) {
|
||||
throw new Error(result.error.details.message || 'Failed to get race results detail');
|
||||
}
|
||||
|
||||
return result.value;
|
||||
}
|
||||
|
||||
async getRaceWithSOF(raceId: string): Promise<RaceWithSOFViewModelDto> {
|
||||
this.logger.debug('[RaceService] Fetching race with SOF:', { raceId });
|
||||
|
||||
const result = await this.getRaceWithSOFUseCase.execute({ raceId });
|
||||
|
||||
if (result.isErr()) {
|
||||
throw new Error(result.error.details.message || 'Failed to get race with SOF');
|
||||
}
|
||||
|
||||
return result.value;
|
||||
}
|
||||
|
||||
async getRaceProtests(raceId: string): Promise<RaceProtestsViewModelDto> {
|
||||
this.logger.debug('[RaceService] Fetching race protests:', { raceId });
|
||||
|
||||
const result = await this.getRaceProtestsUseCase.execute({ raceId });
|
||||
|
||||
if (result.isErr()) {
|
||||
throw new Error(result.error.details.message || 'Failed to get race protests');
|
||||
}
|
||||
|
||||
return result.value;
|
||||
}
|
||||
|
||||
async getRacePenalties(raceId: string): Promise<RacePenaltiesViewModelDto> {
|
||||
this.logger.debug('[RaceService] Fetching race penalties:', { raceId });
|
||||
|
||||
const result = await this.getRacePenaltiesUseCase.execute({ raceId });
|
||||
|
||||
if (result.isErr()) {
|
||||
throw new Error(result.error.details.message || 'Failed to get race penalties');
|
||||
}
|
||||
|
||||
return result.value;
|
||||
}
|
||||
|
||||
async registerForRace(params: RegisterForRaceParamsDto): Promise<void> {
|
||||
this.logger.debug('[RaceService] Registering for race:', params);
|
||||
|
||||
const result = await this.registerForRaceUseCase.execute(params);
|
||||
|
||||
if (result.isErr()) {
|
||||
throw new Error(result.error.details.message || 'Failed to register for race');
|
||||
}
|
||||
}
|
||||
|
||||
async withdrawFromRace(params: WithdrawFromRaceParamsDto): Promise<void> {
|
||||
this.logger.debug('[RaceService] Withdrawing from race:', params);
|
||||
|
||||
const result = await this.withdrawFromRaceUseCase.execute(params);
|
||||
|
||||
if (result.isErr()) {
|
||||
throw new Error(result.error.details.message || 'Failed to withdraw from race');
|
||||
}
|
||||
}
|
||||
|
||||
async cancelRace(params: RaceActionParamsDto): Promise<void> {
|
||||
this.logger.debug('[RaceService] Cancelling race:', params);
|
||||
|
||||
const result = await this.cancelRaceUseCase.execute({ raceId: params.raceId });
|
||||
|
||||
if (result.isErr()) {
|
||||
throw new Error(result.error.details.message || 'Failed to cancel race');
|
||||
}
|
||||
}
|
||||
|
||||
async completeRace(params: RaceActionParamsDto): Promise<void> {
|
||||
this.logger.debug('[RaceService] Completing race:', params);
|
||||
|
||||
const result = await this.completeRaceUseCase.execute({ raceId: params.raceId });
|
||||
|
||||
if (result.isErr()) {
|
||||
throw new Error(result.error.details.message || 'Failed to complete race');
|
||||
}
|
||||
}
|
||||
|
||||
async importRaceResultsAlt(params: { raceId: string; resultsFileContent: string }): Promise<void> {
|
||||
this.logger.debug('[RaceService] Importing race results (alt):', params);
|
||||
|
||||
const result = await this.importRaceResultsUseCase.execute({
|
||||
raceId: params.raceId,
|
||||
resultsFileContent: params.resultsFileContent,
|
||||
});
|
||||
|
||||
if (result.isErr()) {
|
||||
throw new Error(result.error.details.message || 'Failed to import race results');
|
||||
}
|
||||
}
|
||||
|
||||
async getDashboardOverview(driverId: string): Promise<any> {
|
||||
this.logger.debug('[RaceService] Getting dashboard overview:', { driverId });
|
||||
|
||||
const result = await this.dashboardOverviewUseCase.execute({ driverId });
|
||||
|
||||
if (result.isErr()) {
|
||||
throw new Error(result.error.details.message || 'Failed to get dashboard overview');
|
||||
}
|
||||
|
||||
return result.value;
|
||||
}
|
||||
|
||||
async fileProtest(command: any): Promise<any> {
|
||||
this.logger.debug('[RaceService] Filing protest:', command);
|
||||
|
||||
const result = await this.fileProtestUseCase.execute(command);
|
||||
|
||||
if (result.isErr()) {
|
||||
throw new Error(result.error.details.message || 'Failed to file protest');
|
||||
}
|
||||
|
||||
return result.value;
|
||||
}
|
||||
|
||||
async applyQuickPenalty(command: any): Promise<any> {
|
||||
this.logger.debug('[RaceService] Applying quick penalty:', command);
|
||||
|
||||
const result = await this.quickPenaltyUseCase.execute(command);
|
||||
|
||||
if (result.isErr()) {
|
||||
throw new Error(result.error.details.message || 'Failed to apply quick penalty');
|
||||
}
|
||||
|
||||
return result.value;
|
||||
}
|
||||
|
||||
async applyPenalty(command: any): Promise<any> {
|
||||
this.logger.debug('[RaceService] Applying penalty:', command);
|
||||
|
||||
const result = await this.applyPenaltyUseCase.execute(command);
|
||||
|
||||
if (result.isErr()) {
|
||||
throw new Error(result.error.details.message || 'Failed to apply penalty');
|
||||
}
|
||||
|
||||
return result.value;
|
||||
}
|
||||
|
||||
async requestProtestDefense(command: any): Promise<any> {
|
||||
this.logger.debug('[RaceService] Requesting protest defense:', command);
|
||||
|
||||
const result = await this.requestProtestDefenseUseCase.execute(command);
|
||||
|
||||
if (result.isErr()) {
|
||||
throw new Error(result.error.details.message || 'Failed to request protest defense');
|
||||
}
|
||||
|
||||
return result.value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString, IsNotEmpty, IsBoolean, IsNumber } from 'class-validator';
|
||||
|
||||
export class RaceViewModel {
|
||||
@ApiProperty()
|
||||
id: string; // Assuming a race has an ID
|
||||
|
||||
@ApiProperty()
|
||||
name: string; // Assuming a race has a name
|
||||
|
||||
@ApiProperty()
|
||||
date: string; // Assuming a race has a date
|
||||
|
||||
@ApiProperty({ nullable: true })
|
||||
leagueName?: string; // Assuming a race might belong to a league
|
||||
|
||||
// Add more race-related properties as needed based on the DTO from the application layer
|
||||
}
|
||||
|
||||
export class AllRacesPageViewModel {
|
||||
@ApiProperty({ type: [RaceViewModel] })
|
||||
races: RaceViewModel[];
|
||||
|
||||
@ApiProperty()
|
||||
totalCount: number;
|
||||
}
|
||||
|
||||
export class RaceStatsDto {
|
||||
@ApiProperty()
|
||||
totalRaces: number;
|
||||
}
|
||||
|
||||
export class ImportRaceResultsInput {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
raceId: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
resultsFileContent: string;
|
||||
}
|
||||
|
||||
export class ImportRaceResultsSummaryViewModel {
|
||||
@ApiProperty()
|
||||
@IsBoolean()
|
||||
success: boolean;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
raceId: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
driversProcessed: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
resultsRecorded: number;
|
||||
|
||||
@ApiProperty({ type: [String], required: false })
|
||||
errors?: string[];
|
||||
}
|
||||
|
||||
export class RaceDto {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
id: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
name: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
date: string;
|
||||
}
|
||||
10
apps/api/src/domain/race/dtos/AllRacesPageDTO.ts
Normal file
10
apps/api/src/domain/race/dtos/AllRacesPageDTO.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { RaceViewModel } from './RaceViewModel';
|
||||
|
||||
export class AllRacesPageDTO {
|
||||
@ApiProperty({ type: [RaceViewModel] })
|
||||
races!: RaceViewModel[];
|
||||
|
||||
@ApiProperty()
|
||||
totalCount!: number;
|
||||
}
|
||||
65
apps/api/src/domain/race/dtos/ApplyPenaltyCommandDTO.ts
Normal file
65
apps/api/src/domain/race/dtos/ApplyPenaltyCommandDTO.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString, IsNotEmpty, IsOptional, IsNumber, IsEnum } from 'class-validator';
|
||||
|
||||
export class ApplyPenaltyCommandDTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
raceId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
driverId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
stewardId!: string;
|
||||
|
||||
@ApiProperty({
|
||||
enum: [
|
||||
'time_penalty',
|
||||
'grid_penalty',
|
||||
'points_deduction',
|
||||
'disqualification',
|
||||
'warning',
|
||||
'license_points',
|
||||
'probation',
|
||||
'fine',
|
||||
'race_ban',
|
||||
],
|
||||
})
|
||||
@IsEnum([
|
||||
'time_penalty',
|
||||
'grid_penalty',
|
||||
'points_deduction',
|
||||
'disqualification',
|
||||
'warning',
|
||||
'license_points',
|
||||
'probation',
|
||||
'fine',
|
||||
'race_ban',
|
||||
])
|
||||
type!: string;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
value?: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
reason!: string;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
protestId?: string;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
notes?: string;
|
||||
}
|
||||
47
apps/api/src/domain/race/dtos/DashboardDriverSummaryDTO.ts
Normal file
47
apps/api/src/domain/race/dtos/DashboardDriverSummaryDTO.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString, IsNumber, IsOptional } from 'class-validator';
|
||||
|
||||
export class DashboardDriverSummaryDTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
id!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
name!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
country!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
avatarUrl!: string;
|
||||
|
||||
@ApiProperty({ nullable: true })
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
rating?: number | null;
|
||||
|
||||
@ApiProperty({ nullable: true })
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
globalRank?: number | null;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
totalRaces!: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
wins!: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
podiums!: number;
|
||||
|
||||
@ApiProperty({ nullable: true })
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
consistency?: number | null;
|
||||
}
|
||||
53
apps/api/src/domain/race/dtos/DashboardFeedItemSummaryDTO.ts
Normal file
53
apps/api/src/domain/race/dtos/DashboardFeedItemSummaryDTO.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString, IsOptional } from 'class-validator';
|
||||
|
||||
export type DashboardFeedItemType =
|
||||
| 'friend-joined-league'
|
||||
| 'friend-joined-team'
|
||||
| 'friend-finished-race'
|
||||
| 'friend-new-personal-best'
|
||||
| 'new-race-scheduled'
|
||||
| 'new-result-posted'
|
||||
| 'league-highlight';
|
||||
|
||||
export class DashboardFeedItemSummaryDTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
id!: string;
|
||||
|
||||
@ApiProperty({
|
||||
enum: [
|
||||
'friend-joined-league',
|
||||
'friend-joined-team',
|
||||
'friend-finished-race',
|
||||
'friend-new-personal-best',
|
||||
'new-race-scheduled',
|
||||
'new-result-posted',
|
||||
'league-highlight',
|
||||
],
|
||||
})
|
||||
type!: DashboardFeedItemType;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
headline!: string;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
body?: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
timestamp!: string;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
ctaLabel?: string;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
ctaHref?: string;
|
||||
}
|
||||
12
apps/api/src/domain/race/dtos/DashboardFeedSummaryDTO.ts
Normal file
12
apps/api/src/domain/race/dtos/DashboardFeedSummaryDTO.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsNumber } from 'class-validator';
|
||||
import { DashboardFeedItemSummaryDTO } from './DashboardFeedItemSummaryDTO';
|
||||
|
||||
export class DashboardFeedSummaryDTO {
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
notificationCount!: number;
|
||||
|
||||
@ApiProperty({ type: [DashboardFeedItemSummaryDTO] })
|
||||
items!: DashboardFeedItemSummaryDTO[];
|
||||
}
|
||||
20
apps/api/src/domain/race/dtos/DashboardFriendSummaryDTO.ts
Normal file
20
apps/api/src/domain/race/dtos/DashboardFriendSummaryDTO.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString } from 'class-validator';
|
||||
|
||||
export class DashboardFriendSummaryDTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
id!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
name!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
country!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
avatarUrl!: string;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString, IsNumber } from 'class-validator';
|
||||
|
||||
export class DashboardLeagueStandingSummaryDTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
leagueId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
leagueName!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
position!: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
totalDrivers!: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
points!: number;
|
||||
}
|
||||
41
apps/api/src/domain/race/dtos/DashboardOverviewDTO.ts
Normal file
41
apps/api/src/domain/race/dtos/DashboardOverviewDTO.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsNumber, IsOptional } from 'class-validator';
|
||||
import { DashboardDriverSummaryDTO } from './DashboardDriverSummaryDTO';
|
||||
import { DashboardRaceSummaryDTO } from './DashboardRaceSummaryDTO';
|
||||
import { DashboardRecentResultDTO } from './DashboardRecentResultDTO';
|
||||
import { DashboardLeagueStandingSummaryDTO } from './DashboardLeagueStandingSummaryDTO';
|
||||
import { DashboardFeedSummaryDTO } from './DashboardFeedSummaryDTO';
|
||||
import { DashboardFriendSummaryDTO } from './DashboardFriendSummaryDTO';
|
||||
|
||||
export class DashboardOverviewDTO {
|
||||
@ApiProperty({ nullable: true })
|
||||
currentDriver!: DashboardDriverSummaryDTO | null;
|
||||
|
||||
@ApiProperty({ type: [DashboardRaceSummaryDTO] })
|
||||
myUpcomingRaces!: DashboardRaceSummaryDTO[];
|
||||
|
||||
@ApiProperty({ type: [DashboardRaceSummaryDTO] })
|
||||
otherUpcomingRaces!: DashboardRaceSummaryDTO[];
|
||||
|
||||
@ApiProperty({ type: [DashboardRaceSummaryDTO] })
|
||||
upcomingRaces!: DashboardRaceSummaryDTO[];
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
activeLeaguesCount!: number;
|
||||
|
||||
@ApiProperty({ nullable: true })
|
||||
nextRace!: DashboardRaceSummaryDTO | null;
|
||||
|
||||
@ApiProperty({ type: [DashboardRecentResultDTO] })
|
||||
recentResults!: DashboardRecentResultDTO[];
|
||||
|
||||
@ApiProperty({ type: [DashboardLeagueStandingSummaryDTO] })
|
||||
leagueStandingsSummaries!: DashboardLeagueStandingSummaryDTO[];
|
||||
|
||||
@ApiProperty()
|
||||
feedSummary!: DashboardFeedSummaryDTO;
|
||||
|
||||
@ApiProperty({ type: [DashboardFriendSummaryDTO] })
|
||||
friends!: DashboardFriendSummaryDTO[];
|
||||
}
|
||||
36
apps/api/src/domain/race/dtos/DashboardRaceSummaryDTO.ts
Normal file
36
apps/api/src/domain/race/dtos/DashboardRaceSummaryDTO.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString, IsBoolean } from 'class-validator';
|
||||
|
||||
export class DashboardRaceSummaryDTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
id!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
leagueId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
leagueName!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
track!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
car!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
scheduledAt!: string;
|
||||
|
||||
@ApiProperty({ enum: ['scheduled', 'running', 'completed', 'cancelled'] })
|
||||
@IsString()
|
||||
status!: 'scheduled' | 'running' | 'completed' | 'cancelled';
|
||||
|
||||
@ApiProperty()
|
||||
@IsBoolean()
|
||||
isMyLeague!: boolean;
|
||||
}
|
||||
32
apps/api/src/domain/race/dtos/DashboardRecentResultDTO.ts
Normal file
32
apps/api/src/domain/race/dtos/DashboardRecentResultDTO.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString, IsNumber } from 'class-validator';
|
||||
|
||||
export class DashboardRecentResultDTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
raceId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
raceName!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
leagueId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
leagueName!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
finishedAt!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
position!: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
incidents!: number;
|
||||
}
|
||||
37
apps/api/src/domain/race/dtos/FileProtestCommandDTO.ts
Normal file
37
apps/api/src/domain/race/dtos/FileProtestCommandDTO.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString, IsNotEmpty, IsOptional, IsNumber, IsUrl } from 'class-validator';
|
||||
|
||||
export class FileProtestCommandDTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
raceId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
protestingDriverId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
accusedDriverId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
incident!: {
|
||||
lap: number;
|
||||
description: string;
|
||||
timeInRace?: number;
|
||||
};
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
comment?: string;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@IsUrl()
|
||||
proofVideoUrl?: string;
|
||||
}
|
||||
14
apps/api/src/domain/race/dtos/GetRaceDetailParamsDTO.ts
Normal file
14
apps/api/src/domain/race/dtos/GetRaceDetailParamsDTO.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString, IsNotEmpty } from 'class-validator';
|
||||
|
||||
export class GetRaceDetailParamsDTODTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
raceId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
driverId!: string;
|
||||
}
|
||||
14
apps/api/src/domain/race/dtos/ImportRaceResultsDTO.ts
Normal file
14
apps/api/src/domain/race/dtos/ImportRaceResultsDTO.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString, IsNotEmpty } from 'class-validator';
|
||||
|
||||
export class ImportRaceResultsDTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
raceId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
resultsFileContent!: string;
|
||||
}
|
||||
23
apps/api/src/domain/race/dtos/ImportRaceResultsSummaryDTO.ts
Normal file
23
apps/api/src/domain/race/dtos/ImportRaceResultsSummaryDTO.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsBoolean, IsString, IsNumber } from 'class-validator';
|
||||
|
||||
export class ImportRaceResultsSummaryDTOViewModel {
|
||||
@ApiProperty()
|
||||
@IsBoolean()
|
||||
success!: boolean;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
raceId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
driversProcessed!: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
resultsRecorded!: number;
|
||||
|
||||
@ApiProperty({ type: [String], required: false })
|
||||
errors?: string[];
|
||||
}
|
||||
32
apps/api/src/domain/race/dtos/QuickPenaltyCommandDTO.ts
Normal file
32
apps/api/src/domain/race/dtos/QuickPenaltyCommandDTO.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString, IsNotEmpty, IsOptional, IsEnum } from 'class-validator';
|
||||
|
||||
export class QuickPenaltyCommandDTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
raceId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
driverId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
adminId!: string;
|
||||
|
||||
@ApiProperty({ enum: ['track_limits', 'unsafe_rejoin', 'aggressive_driving', 'false_start', 'other'] })
|
||||
@IsEnum(['track_limits', 'unsafe_rejoin', 'aggressive_driving', 'false_start', 'other'])
|
||||
infractionType!: 'track_limits' | 'unsafe_rejoin' | 'aggressive_driving' | 'false_start' | 'other';
|
||||
|
||||
@ApiProperty({ enum: ['warning', 'minor', 'major', 'severe'] })
|
||||
@IsEnum(['warning', 'minor', 'major', 'severe'])
|
||||
severity!: 'warning' | 'minor' | 'major' | 'severe';
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
notes?: string;
|
||||
}
|
||||
9
apps/api/src/domain/race/dtos/RaceActionParamsDTO.ts
Normal file
9
apps/api/src/domain/race/dtos/RaceActionParamsDTO.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString, IsNotEmpty } from 'class-validator';
|
||||
|
||||
export class RaceActionParamsDTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
raceId!: string;
|
||||
}
|
||||
15
apps/api/src/domain/race/dtos/RaceDTO.ts
Normal file
15
apps/api/src/domain/race/dtos/RaceDTO.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
|
||||
export class RaceDTO {
|
||||
@ApiProperty()
|
||||
id!: string;
|
||||
|
||||
@ApiProperty()
|
||||
name!: string;
|
||||
|
||||
@ApiProperty()
|
||||
date!: string;
|
||||
|
||||
@ApiProperty({ nullable: true })
|
||||
leagueName?: string;
|
||||
}
|
||||
29
apps/api/src/domain/race/dtos/RaceDetailDTO.ts
Normal file
29
apps/api/src/domain/race/dtos/RaceDetailDTO.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsOptional, IsString } from 'class-validator';
|
||||
import { RaceDetailRaceDTO } from './RaceDetailRaceDTO';
|
||||
import { RaceDetailLeagueDTO } from './RaceDetailLeagueDTO';
|
||||
import { RaceDetailEntryDTO } from './RaceDetailEntryDTO';
|
||||
import { RaceDetailRegistrationDTO } from './RaceDetailRegistrationDTO';
|
||||
import { RaceDetailUserResultDTO } from './RaceDetailUserResultDTO';
|
||||
|
||||
export class RaceDetailDTO {
|
||||
@ApiProperty({ nullable: true })
|
||||
race!: RaceDetailRaceDTO | null;
|
||||
|
||||
@ApiProperty({ nullable: true })
|
||||
league!: RaceDetailLeagueDTO | null;
|
||||
|
||||
@ApiProperty({ type: [RaceDetailEntryDTO] })
|
||||
entryList!: RaceDetailEntryDTO[];
|
||||
|
||||
@ApiProperty()
|
||||
registration!: RaceDetailRegistrationDTO;
|
||||
|
||||
@ApiProperty({ nullable: true })
|
||||
userResult!: RaceDetailUserResultDTO | null;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
error?: string;
|
||||
}
|
||||
27
apps/api/src/domain/race/dtos/RaceDetailEntryDTO.ts
Normal file
27
apps/api/src/domain/race/dtos/RaceDetailEntryDTO.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString, IsBoolean, IsNumber } from 'class-validator';
|
||||
|
||||
export class RaceDetailEntryDTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
id!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
name!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
country!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
avatarUrl!: string;
|
||||
|
||||
@ApiProperty({ nullable: true })
|
||||
rating!: number | null;
|
||||
|
||||
@ApiProperty()
|
||||
@IsBoolean()
|
||||
isCurrentUser!: boolean;
|
||||
}
|
||||
22
apps/api/src/domain/race/dtos/RaceDetailLeagueDTO.ts
Normal file
22
apps/api/src/domain/race/dtos/RaceDetailLeagueDTO.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString } from 'class-validator';
|
||||
|
||||
export class RaceDetailLeagueDTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
id!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
name!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
description!: string;
|
||||
|
||||
@ApiProperty()
|
||||
settings!: {
|
||||
maxDrivers?: number;
|
||||
qualifyingFormat?: string;
|
||||
};
|
||||
}
|
||||
45
apps/api/src/domain/race/dtos/RaceDetailRaceDTO.ts
Normal file
45
apps/api/src/domain/race/dtos/RaceDetailRaceDTO.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString, IsOptional, IsNumber } from 'class-validator';
|
||||
|
||||
export class RaceDetailRaceDTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
id!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
leagueId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
track!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
car!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
scheduledAt!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
sessionType!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
status!: string;
|
||||
|
||||
@ApiProperty({ nullable: true })
|
||||
strengthOfField!: number | null;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
registeredCount?: number;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
maxParticipants?: number;
|
||||
}
|
||||
12
apps/api/src/domain/race/dtos/RaceDetailRegistrationDTO.ts
Normal file
12
apps/api/src/domain/race/dtos/RaceDetailRegistrationDTO.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsBoolean } from 'class-validator';
|
||||
|
||||
export class RaceDetailRegistrationDTO {
|
||||
@ApiProperty()
|
||||
@IsBoolean()
|
||||
isUserRegistered!: boolean;
|
||||
|
||||
@ApiProperty()
|
||||
@IsBoolean()
|
||||
canRegister!: boolean;
|
||||
}
|
||||
35
apps/api/src/domain/race/dtos/RaceDetailUserResultDTO.ts
Normal file
35
apps/api/src/domain/race/dtos/RaceDetailUserResultDTO.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsNumber, IsBoolean } from 'class-validator';
|
||||
|
||||
export class RaceDetailUserResultDTO {
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
position!: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
startPosition!: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
incidents!: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
fastestLap!: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
positionChange!: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsBoolean()
|
||||
isPodium!: boolean;
|
||||
|
||||
@ApiProperty()
|
||||
@IsBoolean()
|
||||
isClean!: boolean;
|
||||
|
||||
@ApiProperty({ nullable: true })
|
||||
ratingChange!: number | null;
|
||||
}
|
||||
10
apps/api/src/domain/race/dtos/RacePenaltiesDTO.ts
Normal file
10
apps/api/src/domain/race/dtos/RacePenaltiesDTO.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { RacePenaltyDTO } from './RacePenaltyDTO';
|
||||
|
||||
export class RacePenaltiesDTO {
|
||||
@ApiProperty({ type: [RacePenaltyDTO] })
|
||||
penalties!: RacePenaltyDTO[];
|
||||
|
||||
@ApiProperty()
|
||||
driverMap!: Record<string, string>;
|
||||
}
|
||||
35
apps/api/src/domain/race/dtos/RacePenaltyDTO.ts
Normal file
35
apps/api/src/domain/race/dtos/RacePenaltyDTO.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString, IsNumber } from 'class-validator';
|
||||
|
||||
export class RacePenaltyDTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
id!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
driverId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
type!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
value!: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
reason!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
issuedBy!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
issuedAt!: string;
|
||||
|
||||
@ApiProperty({ nullable: true })
|
||||
notes?: string;
|
||||
}
|
||||
30
apps/api/src/domain/race/dtos/RaceProtestDTO.ts
Normal file
30
apps/api/src/domain/race/dtos/RaceProtestDTO.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString } from 'class-validator';
|
||||
|
||||
export class RaceProtestDTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
id!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
protestingDriverId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
accusedDriverId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
incident!: {
|
||||
lap: number;
|
||||
description: string;
|
||||
};
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
status!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
filedAt!: string;
|
||||
}
|
||||
10
apps/api/src/domain/race/dtos/RaceProtestsDTO.ts
Normal file
10
apps/api/src/domain/race/dtos/RaceProtestsDTO.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { RaceProtestDto } from './RaceProtestDto';
|
||||
|
||||
export class RaceProtestsDTO {
|
||||
@ApiProperty({ type: [RaceProtestDto] })
|
||||
protests!: RaceProtestDto[];
|
||||
|
||||
@ApiProperty()
|
||||
driverMap!: Record<string, string>;
|
||||
}
|
||||
44
apps/api/src/domain/race/dtos/RaceResultDTO.ts
Normal file
44
apps/api/src/domain/race/dtos/RaceResultDTO.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString, IsNumber, IsBoolean } from 'class-validator';
|
||||
|
||||
export class RaceResultDTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
driverId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
driverName!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
avatarUrl!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
position!: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
startPosition!: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
incidents!: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
fastestLap!: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
positionChange!: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsBoolean()
|
||||
isPodium!: boolean;
|
||||
|
||||
@ApiProperty()
|
||||
@IsBoolean()
|
||||
isClean!: boolean;
|
||||
}
|
||||
16
apps/api/src/domain/race/dtos/RaceResultsDetailDTO.ts
Normal file
16
apps/api/src/domain/race/dtos/RaceResultsDetailDTO.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString } from 'class-validator';
|
||||
import { RaceResultDto } from './RaceResultDto';
|
||||
|
||||
export class RaceResultsDetailDTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
raceId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
track!: string;
|
||||
|
||||
@ApiProperty({ type: [RaceResultDto] })
|
||||
results!: RaceResultDto[];
|
||||
}
|
||||
6
apps/api/src/domain/race/dtos/RaceStatsDTO.ts
Normal file
6
apps/api/src/domain/race/dtos/RaceStatsDTO.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
|
||||
export class RaceStatsDTO {
|
||||
@ApiProperty()
|
||||
totalRaces!: number;
|
||||
}
|
||||
15
apps/api/src/domain/race/dtos/RaceWithSOFDTO.ts
Normal file
15
apps/api/src/domain/race/dtos/RaceWithSOFDTO.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString } from 'class-validator';
|
||||
|
||||
export class RaceWithSOFDTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
id!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
track!: string;
|
||||
|
||||
@ApiProperty({ nullable: true })
|
||||
strengthOfField!: number | null;
|
||||
}
|
||||
7
apps/api/src/domain/race/dtos/RacesPageDataDTO.ts
Normal file
7
apps/api/src/domain/race/dtos/RacesPageDataDTO.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { RacesPageDataRaceDto } from './RacesPageDataRaceDto';
|
||||
|
||||
export class RacesPageDataDTO {
|
||||
@ApiProperty({ type: [RacesPageDataRaceDto] })
|
||||
races!: RacesPageDataRaceDto[];
|
||||
}
|
||||
47
apps/api/src/domain/race/dtos/RacesPageDataRaceDTO.ts
Normal file
47
apps/api/src/domain/race/dtos/RacesPageDataRaceDTO.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString, IsBoolean } from 'class-validator';
|
||||
|
||||
export class RacesPageDataRaceDTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
id!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
track!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
car!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
scheduledAt!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
status!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
leagueId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
leagueName!: string;
|
||||
|
||||
@ApiProperty({ nullable: true })
|
||||
strengthOfField!: number | null;
|
||||
|
||||
@ApiProperty()
|
||||
@IsBoolean()
|
||||
isUpcoming!: boolean;
|
||||
|
||||
@ApiProperty()
|
||||
@IsBoolean()
|
||||
isLive!: boolean;
|
||||
|
||||
@ApiProperty()
|
||||
@IsBoolean()
|
||||
isPast!: boolean;
|
||||
}
|
||||
19
apps/api/src/domain/race/dtos/RegisterForRaceParamsDTO.ts
Normal file
19
apps/api/src/domain/race/dtos/RegisterForRaceParamsDTO.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString, IsNotEmpty } from 'class-validator';
|
||||
|
||||
export class RegisterForRaceParamsDTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
raceId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
leagueId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
driverId!: string;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString, IsNotEmpty } from 'class-validator';
|
||||
|
||||
export class RequestProtestDefenseCommandDTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
protestId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
stewardId!: string;
|
||||
}
|
||||
14
apps/api/src/domain/race/dtos/WithdrawFromRaceParamsDTO.ts
Normal file
14
apps/api/src/domain/race/dtos/WithdrawFromRaceParamsDTO.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString, IsNotEmpty } from 'class-validator';
|
||||
|
||||
export class WithdrawFromRaceParamsDTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
raceId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
driverId!: string;
|
||||
}
|
||||
Reference in New Issue
Block a user