website cleanup

This commit is contained in:
2025-12-25 00:19:36 +01:00
parent d78854a4c6
commit 9486455b9e
82 changed files with 1223 additions and 363 deletions

View File

@@ -1,5 +1,5 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsArray, ValidateNested } from 'class-validator';
import { IsArray, ValidateNested, IsObject } from 'class-validator';
import { Type } from 'class-transformer';
import { DriverDTO } from '../../driver/dtos/DriverDTO';
import { RaceDTO } from '../../race/dtos/RaceDTO';
@@ -12,13 +12,15 @@ export class LeagueAdminProtestsDTO {
@Type(() => ProtestDTO)
protests!: ProtestDTO[];
@ApiProperty({ type: () => RaceDTO })
@ApiProperty({ type: Object })
@IsObject()
@ValidateNested()
@Type(() => RaceDTO)
racesById!: { [raceId: string]: RaceDTO };
racesById!: Record<string, RaceDTO>;
@ApiProperty({ type: () => DriverDTO })
@ApiProperty({ type: Object })
@IsObject()
@ValidateNested()
@Type(() => DriverDTO)
driversById!: { [driverId: string]: DriverDTO };
driversById!: Record<string, DriverDTO>;
}

View File

@@ -12,6 +12,8 @@ import { DeleteMediaOutputDTO } from './dtos/DeleteMediaOutputDTO';
import { GetAvatarOutputDTO } from './dtos/GetAvatarOutputDTO';
import { UpdateAvatarInputDTO } from './dtos/UpdateAvatarInputDTO';
import { UpdateAvatarOutputDTO } from './dtos/UpdateAvatarOutputDTO';
import { ValidateFaceInputDTO } from './dtos/ValidateFaceInputDTO';
import { ValidateFaceOutputDTO } from './dtos/ValidateFaceOutputDTO';
import type { MulterFile } from './types/MulterFile';
type RequestAvatarGenerationInput = RequestAvatarGenerationInputDTO;
@@ -118,4 +120,20 @@ export class MediaController {
res.status(HttpStatus.OK).json(dto);
}
@Post('avatar/validate-face')
@ApiOperation({ summary: 'Validate face photo for avatar generation' })
@ApiResponse({ status: 200, description: 'Face validation result', type: ValidateFaceOutputDTO })
async validateFacePhoto(
@Body() input: ValidateFaceInputDTO,
@Res() res: Response,
): Promise<void> {
const dto: ValidateFaceOutputDTO = await this.mediaService.validateFacePhoto(input);
if (dto.isValid) {
res.status(HttpStatus.OK).json(dto);
} else {
res.status(HttpStatus.BAD_REQUEST).json(dto);
}
}
}

View File

@@ -8,6 +8,8 @@ import type { GetMediaOutputDTO } from './dtos/GetMediaOutputDTO';
import type { DeleteMediaOutputDTO } from './dtos/DeleteMediaOutputDTO';
import type { GetAvatarOutputDTO } from './dtos/GetAvatarOutputDTO';
import type { UpdateAvatarOutputDTO } from './dtos/UpdateAvatarOutputDTO';
import type { ValidateFaceInputDTO } from './dtos/ValidateFaceInputDTO';
import type { ValidateFaceOutputDTO } from './dtos/ValidateFaceOutputDTO';
import type { RacingSuitColor } from '@core/media/domain/types/AvatarGenerationRequest';
import type { MulterFile } from './types/MulterFile';
@@ -179,4 +181,24 @@ export class MediaService {
return this.updateAvatarPresenter.responseModel;
}
async validateFacePhoto(input: ValidateFaceInputDTO): Promise<ValidateFaceOutputDTO> {
this.logger.debug('[MediaService] Validating face photo.');
// Simple validation: check if it's a valid base64 image
if (!input.imageData || !input.imageData.startsWith('data:image/')) {
return { isValid: false, errorMessage: 'Invalid image data' };
}
// Check file size (rough estimate from base64 length)
const base64Length = input.imageData.length;
const fileSizeInBytes = (base64Length * 3) / 4; // Rough estimate
const maxSize = 5 * 1024 * 1024; // 5MB
if (fileSizeInBytes > maxSize) {
return { isValid: false, errorMessage: 'Image too large (max 5MB)' };
}
return { isValid: true };
}
}

View File

@@ -0,0 +1,13 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsString, IsOptional } from 'class-validator';
export class AvatarDTO {
@ApiProperty()
@IsString()
driverId!: string;
@ApiProperty({ required: false })
@IsOptional()
@IsString()
avatarUrl?: string;
}

View File

@@ -0,0 +1,9 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsString, IsNotEmpty } from 'class-validator';
export class ValidateFaceInputDTO {
@ApiProperty()
@IsString()
@IsNotEmpty()
imageData: string = '';
}

View File

@@ -0,0 +1,9 @@
import { ApiProperty } from '@nestjs/swagger';
export class ValidateFaceOutputDTO {
@ApiProperty()
isValid: boolean = false;
@ApiProperty({ required: false })
errorMessage?: string;
}

View File

@@ -0,0 +1,54 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsString, IsNumber, IsEnum, IsOptional, IsDate } from 'class-validator';
import { TransactionType, ReferenceType } from './PaymentsDto';
export class FullTransactionDto {
@ApiProperty()
@IsString()
id!: string;
@ApiProperty()
@IsString()
walletId!: string;
@ApiProperty({ enum: TransactionType })
@IsEnum(TransactionType)
type!: TransactionType;
@ApiProperty()
@IsNumber()
amount!: number;
@ApiProperty()
@IsString()
description!: string;
@ApiProperty({ required: false })
@IsOptional()
@IsString()
referenceId?: string;
@ApiProperty({ required: false, enum: ReferenceType })
@IsOptional()
@IsEnum(ReferenceType)
referenceType?: ReferenceType;
@ApiProperty()
@IsDate()
createdAt!: Date;
@ApiProperty({ required: false })
@IsOptional()
@IsString()
leagueId?: string;
@ApiProperty({ required: false })
@IsOptional()
@IsString()
driverId?: string;
@ApiProperty({ required: false })
@IsOptional()
@IsString()
sponsorId?: string;
}

View File

@@ -0,0 +1,52 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsString, IsNumber, IsOptional } from 'class-validator';
export class DriverSummaryDTO {
@ApiProperty()
@IsString()
id!: string;
@ApiProperty()
@IsString()
name!: string;
@ApiProperty({ required: false })
@IsOptional()
@IsString()
country?: string;
@ApiProperty({ required: false })
@IsOptional()
@IsString()
avatarUrl?: string;
@ApiProperty({ required: false, nullable: true })
@IsOptional()
@IsNumber()
rating?: number | null;
@ApiProperty({ required: false, nullable: true })
@IsOptional()
@IsNumber()
globalRank?: number | null;
@ApiProperty({ required: false })
@IsOptional()
@IsNumber()
totalRaces?: number;
@ApiProperty({ required: false })
@IsOptional()
@IsNumber()
wins?: number;
@ApiProperty({ required: false })
@IsOptional()
@IsNumber()
podiums?: number;
@ApiProperty({ required: false, nullable: true })
@IsOptional()
@IsNumber()
consistency?: number | null;
}