resolve manual DTOs

This commit is contained in:
2025-12-18 22:19:40 +01:00
parent 4a3087ae35
commit d617654928
179 changed files with 3716 additions and 1257 deletions

View File

@@ -0,0 +1,18 @@
import { Controller, Get, Query } from '@nestjs/common';
import { ApiTags, ApiResponse, ApiOperation, ApiQuery } from '@nestjs/swagger';
import { DashboardService } from './DashboardService';
import { DashboardOverviewDTO } from './dtos/DashboardOverviewDTO';
@ApiTags('dashboard')
@Controller('dashboard')
export class DashboardController {
constructor(private readonly dashboardService: DashboardService) {}
@Get('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.dashboardService.getDashboardOverview(driverId);
}
}

View File

@@ -0,0 +1,11 @@
import { Module } from '@nestjs/common';
import { DashboardService } from './DashboardService';
import { DashboardController } from './DashboardController';
import { DashboardProviders } from './DashboardProviders';
@Module({
controllers: [DashboardController],
providers: DashboardProviders,
exports: [DashboardService],
})
export class DashboardModule {}

View File

@@ -0,0 +1,23 @@
import { Provider } from '@nestjs/common';
import { DashboardService } from './DashboardService';
// Import core interfaces
import type { Logger } from '@core/shared/application/Logger';
// Import concrete implementations
import { ConsoleLogger } from '@adapters/logging/ConsoleLogger';
// Import use cases
import { DashboardOverviewUseCase } from '@core/racing/application/use-cases/DashboardOverviewUseCase';
// Define injection tokens
export const LOGGER_TOKEN = 'Logger';
export const DashboardProviders: Provider[] = [
DashboardService,
{
provide: LOGGER_TOKEN,
useClass: ConsoleLogger,
},
DashboardOverviewUseCase,
];

View File

@@ -0,0 +1,28 @@
import { Injectable, Inject } from '@nestjs/common';
import { DashboardOverviewUseCase } from '@core/racing/application/use-cases/DashboardOverviewUseCase';
// Core imports
import type { Logger } from '@core/shared/application/Logger';
// Tokens
import { LOGGER_TOKEN } from './DashboardProviders';
@Injectable()
export class DashboardService {
constructor(
private readonly dashboardOverviewUseCase: DashboardOverviewUseCase,
@Inject(LOGGER_TOKEN) private readonly logger: Logger,
) {}
async getDashboardOverview(driverId: string): Promise<any> {
this.logger.debug('[DashboardService] 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;
}
}

View 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;
}

View 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;
}

View 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[];
}

View 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;
}

View File

@@ -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;
}

View File

@@ -0,0 +1,41 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsNumber, IsOptional } from 'class-validator';
import { DashboardDriverSummaryDTO } from '../../../race/dtos/DashboardDriverSummaryDTO';
import { DashboardRaceSummaryDTO } from '../../../race/dtos/DashboardRaceSummaryDTO';
import { DashboardRecentResultDTO } from '../../../race/dtos/DashboardRecentResultDTO';
import { DashboardLeagueStandingSummaryDTO } from '../../../race/dtos/DashboardLeagueStandingSummaryDTO';
import { DashboardFeedSummaryDTO } from '../../../race/dtos/DashboardFeedSummaryDTO';
import { DashboardFriendSummaryDTO } from '../../../race/dtos/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[];
}

View 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;
}

View 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;
}