80 lines
2.7 KiB
TypeScript
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';
|
|
}
|
|
} |