Files
gridpilot.gg/apps/api/src/domain/driver/presenters/DriverPresenter.ts
2025-12-31 15:39:28 +01:00

80 lines
2.7 KiB
TypeScript

import { Result } from '@core/shared/application/Result';
import type { Driver } from '@core/racing/domain/entities/Driver';
import type { GetDriverOutputDTO } from '../dtos/GetDriverOutputDTO';
import type { IDriverStatsRepository } from '@core/racing/domain/repositories/IDriverStatsRepository';
import type { MediaResolverPort } from '@core/ports/media/MediaResolverPort';
import { MediaReference } from '@core/domain/media/MediaReference';
export class DriverPresenter {
private responseModel: GetDriverOutputDTO | null = null;
private mediaResolver: MediaResolverPort | undefined;
constructor(
private readonly driverStatsRepository: IDriverStatsRepository,
mediaResolver?: MediaResolverPort
) {
this.mediaResolver = mediaResolver;
}
setMediaResolver(resolver: MediaResolverPort | undefined): void {
this.mediaResolver = resolver;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async present(result: Result<Driver | null, any>): Promise<void> {
if (result.isErr()) {
const error = result.unwrapErr();
throw new Error(error.details?.message ?? 'Failed to get driver');
}
const driver = result.unwrap();
if (!driver) {
this.responseModel = null;
return;
}
// Get stats from repository (synchronously for now, could be async)
const stats = this.driverStatsRepository.getDriverStatsSync(driver.id);
// Resolve avatar URL using MediaResolverPort
let avatarUrl: string | null = null;
if (this.mediaResolver) {
const ref = driver.avatarRef ?? MediaReference.createNone();
const resolvedRef = ref instanceof MediaReference ? ref : MediaReference.fromJSON(ref);
const resolvedUrl = await this.mediaResolver.resolve(resolvedRef);
avatarUrl = resolvedUrl ?? null;
}
const dto: GetDriverOutputDTO = {
id: driver.id,
iracingId: driver.iracingId.toString(),
name: driver.name.toString(),
country: driver.country.toString(),
joinedAt: driver.joinedAt.toDate().toISOString(),
avatarUrl,
...(driver.bio ? { bio: driver.bio.toString() } : {}),
...(driver.category ? { category: driver.category } : {}),
// Add stats fields
...(stats ? {
rating: stats.rating,
wins: stats.wins,
podiums: stats.podiums,
totalRaces: stats.totalRaces,
experienceLevel: this.getExperienceLevel(stats.rating),
} : {}),
};
this.responseModel = dto;
}
getResponseModel(): GetDriverOutputDTO | null {
return this.responseModel;
}
private getExperienceLevel(rating: number): string {
if (rating >= 1700) return 'veteran';
if (rating >= 1300) return 'advanced';
if (rating >= 1000) return 'intermediate';
return 'beginner';
}
}