/** * Race Detail View Data Builder * * Transforms API DTO to ViewData for templates. */ import type { RaceDetailDTO } from '@/lib/types/generated/RaceDetailDTO'; import type { RaceDetailEntry, RaceDetailLeague, RaceDetailRace, RaceDetailRegistration, RaceDetailUserResult, RaceDetailViewData } from '@/lib/view-data/RaceDetailViewData'; import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder"; export class RaceDetailViewDataBuilder { /** * Transform API DTO to ViewData * * @param apiDto - The DTO from the service * @returns ViewData for the race detail page */ public static build(apiDto: RaceDetailDTO): RaceDetailViewData { if (!apiDto || !apiDto.race) { return { race: { id: '', track: '', car: '', scheduledAt: '', status: 'scheduled', sessionType: 'race', }, entryList: [], registration: { isUserRegistered: false, canRegister: false, }, canReopenRace: false, }; } const race: RaceDetailRace = { id: apiDto.race.id, track: apiDto.race.track || '', car: apiDto.race.car || '', scheduledAt: apiDto.race.scheduledAt, status: apiDto.race.status as 'scheduled' | 'running' | 'completed' | 'cancelled', sessionType: apiDto.race.sessionType || 'race', }; const league: RaceDetailLeague | undefined = apiDto.league ? { id: apiDto.league.id, name: apiDto.league.name, description: apiDto.league.description || undefined, settings: { maxDrivers: apiDto.league.maxDrivers ?? 32, qualifyingFormat: apiDto.league.qualifyingFormat ?? 'Open', }, } : undefined; const entryList: RaceDetailEntry[] = (apiDto.entryList || []).map((entry) => ({ id: entry.id, name: entry.name, avatarUrl: entry.avatarUrl || '', country: entry.country, rating: entry.rating, isCurrentUser: entry.isCurrentUser, })); const registration: RaceDetailRegistration = { isUserRegistered: apiDto.registration.isUserRegistered, canRegister: apiDto.registration.canRegister, }; const userResult: RaceDetailUserResult | undefined = apiDto.userResult ? { position: apiDto.userResult.position, startPosition: apiDto.userResult.startPosition, positionChange: apiDto.userResult.positionChange, incidents: apiDto.userResult.incidents, isClean: apiDto.userResult.isClean, isPodium: apiDto.userResult.isPodium, ratingChange: apiDto.userResult.ratingChange, } : undefined; return { race, league, entryList, registration, userResult, canReopenRace: (apiDto as any).canReopenRace || false, }; } } RaceDetailViewDataBuilder satisfies ViewDataBuilder;