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

@@ -9,6 +9,8 @@ import { CompleteOnboardingOutputDTO } from './dtos/CompleteOnboardingOutputDTO'
import { GetDriverRegistrationStatusQueryDTO } from './dtos/GetDriverRegistrationStatusQueryDTO';
import { DriverRegistrationStatusDTO } from './dtos/DriverRegistrationStatusDTO';
import { DriverDTO } from './dtos/DriverDTO';
import { GetDriverOutputDTO } from './dtos/GetDriverOutputDTO';
import { GetDriverProfileOutputDTO } from './dtos/GetDriverProfileOutputDTO';
@ApiTags('drivers')
@Controller('drivers')
@@ -31,9 +33,9 @@ export class DriverController {
@Get('current')
@ApiOperation({ summary: 'Get current authenticated driver' })
@ApiResponse({ status: 200, description: 'Current driver data', type: DriverDTO })
@ApiResponse({ status: 200, description: 'Current driver data', type: GetDriverOutputDTO })
@ApiResponse({ status: 404, description: 'Driver not found' })
async getCurrentDriver(@Req() req: Request): Promise<DriverDTO | null> {
async getCurrentDriver(@Req() req: Request): Promise<GetDriverOutputDTO | null> {
// Assuming userId is available from the request (e.g., via auth middleware)
const userId = req['user']?.userId;
if (!userId) {
@@ -64,13 +66,29 @@ export class DriverController {
return this.driverService.getDriverRegistrationStatus({ driverId, raceId });
}
@Get(':driverId')
@ApiOperation({ summary: 'Get driver by ID' })
@ApiResponse({ status: 200, description: 'Driver data', type: GetDriverOutputDTO })
@ApiResponse({ status: 404, description: 'Driver not found' })
async getDriver(@Param('driverId') driverId: string): Promise<GetDriverOutputDTO | null> {
return this.driverService.getDriver(driverId);
}
@Get(':driverId/profile')
@ApiOperation({ summary: 'Get driver profile with full details' })
@ApiResponse({ status: 200, description: 'Driver profile data', type: GetDriverProfileOutputDTO })
@ApiResponse({ status: 404, description: 'Driver not found' })
async getDriverProfile(@Param('driverId') driverId: string): Promise<GetDriverProfileOutputDTO> {
return this.driverService.getDriverProfile(driverId);
}
@Put(':driverId/profile')
@ApiOperation({ summary: 'Update driver profile' })
@ApiResponse({ status: 200, description: 'Driver profile updated', type: DriverDTO })
@ApiResponse({ status: 200, description: 'Driver profile updated', type: GetDriverOutputDTO })
async updateDriverProfile(
@Param('driverId') driverId: string,
@Body() body: { bio?: string; country?: string },
): Promise<DriverDTO | null> {
): Promise<GetDriverOutputDTO | null> {
return this.driverService.updateDriverProfile(driverId, body.bio, body.country);
}

View File

@@ -5,6 +5,8 @@ import { CompleteOnboardingInputDTO } from './dtos/CompleteOnboardingInputDTO';
import { CompleteOnboardingOutputDTO } from './dtos/CompleteOnboardingOutputDTO';
import { GetDriverRegistrationStatusQueryDTO } from './dtos/GetDriverRegistrationStatusQueryDTO';
import { DriverRegistrationStatusDTO } from './dtos/DriverRegistrationStatusDTO';
import { GetDriverOutputDTO } from './dtos/GetDriverOutputDTO';
import { GetDriverProfileOutputDTO } from './dtos/GetDriverProfileOutputDTO';
// Use cases
import { GetDriversLeaderboardUseCase } from '@core/racing/application/use-cases/GetDriversLeaderboardUseCase';
@@ -76,7 +78,7 @@ export class DriverService {
return presenter.viewModel;
}
async getCurrentDriver(userId: string): Promise<DriverDTO | null> {
async getCurrentDriver(userId: string): Promise<GetDriverOutputDTO | null> {
this.logger.debug(`[DriverService] Fetching current driver for userId: ${userId}`);
const driver = await this.driverRepository.findById(userId);
@@ -86,11 +88,15 @@ export class DriverService {
return {
id: driver.id,
iracingId: driver.iracingId.value,
name: driver.name.value,
country: driver.country.value,
bio: driver.bio?.value,
joinedAt: driver.joinedAt.toISOString(),
};
}
async updateDriverProfile(driverId: string, bio?: string, country?: string): Promise<DriverDTO | null> {
async updateDriverProfile(driverId: string, bio?: string, country?: string): Promise<GetDriverOutputDTO | null> {
this.logger.debug(`[DriverService] Updating driver profile for driverId: ${driverId}`);
const result = await this.updateDriverProfileUseCase.execute({ driverId, bio, country });
@@ -101,4 +107,40 @@ export class DriverService {
return result.value;
}
async getDriver(driverId: string): Promise<GetDriverOutputDTO | null> {
this.logger.debug(`[DriverService] Fetching driver for driverId: ${driverId}`);
const driver = await this.driverRepository.findById(driverId);
if (!driver) {
return null;
}
return {
id: driver.id,
iracingId: driver.iracingId.value,
name: driver.name.value,
country: driver.country.value,
bio: driver.bio?.value,
joinedAt: driver.joinedAt.toISOString(),
};
}
async getDriverProfile(driverId: string): Promise<GetDriverProfileOutputDTO> {
this.logger.debug(`[DriverService] Fetching driver profile for driverId: ${driverId}`);
// TODO: Implement proper driver profile fetching with all the detailed data
// For now, return a placeholder structure
return {
currentDriver: null,
stats: null,
finishDistribution: null,
teamMemberships: [],
socialSummary: {
friendsCount: 0,
friends: [],
},
extendedProfile: null,
};
}
}

View File

@@ -0,0 +1,21 @@
import { ApiProperty } from '@nestjs/swagger';
export class DriverDTO {
@ApiProperty()
id: string;
@ApiProperty()
iracingId: string;
@ApiProperty()
name: string;
@ApiProperty()
country: string;
@ApiProperty({ required: false })
bio?: string;
@ApiProperty()
joinedAt: string;
}

View File

@@ -0,0 +1,21 @@
import { ApiProperty } from '@nestjs/swagger';
export class GetDriverOutputDTO {
@ApiProperty()
id: string;
@ApiProperty()
iracingId: string;
@ApiProperty()
name: string;
@ApiProperty()
country: string;
@ApiProperty()
bio?: string;
@ApiProperty()
joinedAt: string;
}

View File

@@ -0,0 +1,226 @@
import { ApiProperty } from '@nestjs/swagger';
export class DriverProfileDriverSummaryDTO {
@ApiProperty()
id: string;
@ApiProperty()
name: string;
@ApiProperty()
country: string;
@ApiProperty()
avatarUrl: string;
@ApiProperty({ nullable: true })
iracingId: string | null;
@ApiProperty()
joinedAt: string;
@ApiProperty({ nullable: true })
rating: number | null;
@ApiProperty({ nullable: true })
globalRank: number | null;
@ApiProperty({ nullable: true })
consistency: number | null;
@ApiProperty({ nullable: true })
bio: string | null;
@ApiProperty({ nullable: true })
totalDrivers: number | null;
}
export class DriverProfileStatsDTO {
@ApiProperty()
totalRaces: number;
@ApiProperty()
wins: number;
@ApiProperty()
podiums: number;
@ApiProperty()
dnfs: number;
@ApiProperty({ nullable: true })
avgFinish: number | null;
@ApiProperty({ nullable: true })
bestFinish: number | null;
@ApiProperty({ nullable: true })
worstFinish: number | null;
@ApiProperty({ nullable: true })
finishRate: number | null;
@ApiProperty({ nullable: true })
winRate: number | null;
@ApiProperty({ nullable: true })
podiumRate: number | null;
@ApiProperty({ nullable: true })
percentile: number | null;
@ApiProperty({ nullable: true })
rating: number | null;
@ApiProperty({ nullable: true })
consistency: number | null;
@ApiProperty({ nullable: true })
overallRank: number | null;
}
export class DriverProfileFinishDistributionDTO {
@ApiProperty()
totalRaces: number;
@ApiProperty()
wins: number;
@ApiProperty()
podiums: number;
@ApiProperty()
topTen: number;
@ApiProperty()
dnfs: number;
@ApiProperty()
other: number;
}
export class DriverProfileTeamMembershipDTO {
@ApiProperty()
teamId: string;
@ApiProperty()
teamName: string;
@ApiProperty({ nullable: true })
teamTag: string | null;
@ApiProperty()
role: string;
@ApiProperty()
joinedAt: string;
@ApiProperty()
isCurrent: boolean;
}
export class DriverProfileSocialFriendSummaryDTO {
@ApiProperty()
id: string;
@ApiProperty()
name: string;
@ApiProperty()
country: string;
@ApiProperty()
avatarUrl: string;
}
export class DriverProfileSocialSummaryDTO {
@ApiProperty()
friendsCount: number;
@ApiProperty({ type: [DriverProfileSocialFriendSummaryDTO] })
friends: DriverProfileSocialFriendSummaryDTO[];
}
export type DriverProfileSocialPlatform = 'twitter' | 'youtube' | 'twitch' | 'discord';
export type DriverProfileAchievementRarity = 'common' | 'rare' | 'epic' | 'legendary';
export class DriverProfileAchievementDTO {
@ApiProperty()
id: string;
@ApiProperty()
title: string;
@ApiProperty()
description: string;
@ApiProperty({ enum: ['trophy', 'medal', 'star', 'crown', 'target', 'zap'] })
icon: 'trophy' | 'medal' | 'star' | 'crown' | 'target' | 'zap';
@ApiProperty({ enum: DriverProfileAchievementRarity })
rarity: DriverProfileAchievementRarity;
@ApiProperty()
earnedAt: string;
}
export class DriverProfileSocialHandleDTO {
@ApiProperty({ enum: DriverProfileSocialPlatform })
platform: DriverProfileSocialPlatform;
@ApiProperty()
handle: string;
@ApiProperty()
url: string;
}
export class DriverProfileExtendedProfileDTO {
@ApiProperty({ type: [DriverProfileSocialHandleDTO] })
socialHandles: DriverProfileSocialHandleDTO[];
@ApiProperty({ type: [DriverProfileAchievementDTO] })
achievements: DriverProfileAchievementDTO[];
@ApiProperty()
racingStyle: string;
@ApiProperty()
favoriteTrack: string;
@ApiProperty()
favoriteCar: string;
@ApiProperty()
timezone: string;
@ApiProperty()
availableHours: string;
@ApiProperty()
lookingForTeam: boolean;
@ApiProperty()
openToRequests: boolean;
}
export class GetDriverProfileOutputDTO {
@ApiProperty({ type: DriverProfileDriverSummaryDTO, nullable: true })
currentDriver: DriverProfileDriverSummaryDTO | null;
@ApiProperty({ type: DriverProfileStatsDTO, nullable: true })
stats: DriverProfileStatsDTO | null;
@ApiProperty({ type: DriverProfileFinishDistributionDTO, nullable: true })
finishDistribution: DriverProfileFinishDistributionDTO | null;
@ApiProperty({ type: [DriverProfileTeamMembershipDTO] })
teamMemberships: DriverProfileTeamMembershipDTO[];
@ApiProperty({ type: DriverProfileSocialSummaryDTO })
socialSummary: DriverProfileSocialSummaryDTO;
@ApiProperty({ type: DriverProfileExtendedProfileDTO, nullable: true })
extendedProfile: DriverProfileExtendedProfileDTO | null;
}