119 lines
5.2 KiB
TypeScript
119 lines
5.2 KiB
TypeScript
import type { GetDriverProfileOutputDTO } from '@/lib/types/generated/GetDriverProfileOutputDTO';
|
|
import type { DriverProfileViewData } from '@/lib/view-data/DriverProfileViewData';
|
|
import { DateDisplay } from '@/lib/display-objects/DateDisplay';
|
|
import { RatingDisplay } from '@/lib/display-objects/RatingDisplay';
|
|
import { NumberDisplay } from '@/lib/display-objects/NumberDisplay';
|
|
import { FinishDisplay } from '@/lib/display-objects/FinishDisplay';
|
|
import { PercentDisplay } from '@/lib/display-objects/PercentDisplay';
|
|
|
|
/**
|
|
* DriverProfileViewDataBuilder
|
|
*
|
|
* Transforms GetDriverProfileOutputDTO into ViewData for the driver profile page.
|
|
* Deterministic, side-effect free, no HTTP calls.
|
|
*/
|
|
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
|
|
|
export class DriverProfileViewDataBuilder implements ViewDataBuilder<any, any> {
|
|
build(input: any): any {
|
|
return DriverProfileViewDataBuilder.build(input);
|
|
}
|
|
|
|
static build(
|
|
static build(apiDto: GetDriverProfileOutputDTO): DriverProfileViewData {
|
|
return {
|
|
currentDriver: apiDto.currentDriver ? {
|
|
id: apiDto.currentDriver.id,
|
|
name: apiDto.currentDriver.name,
|
|
country: apiDto.currentDriver.country,
|
|
avatarUrl: apiDto.currentDriver.avatarUrl || '',
|
|
iracingId: typeof apiDto.currentDriver.iracingId === 'string' ? parseInt(apiDto.currentDriver.iracingId, 10) : (apiDto.currentDriver.iracingId ?? null),
|
|
joinedAt: apiDto.currentDriver.joinedAt,
|
|
joinedAtLabel: DateDisplay.formatMonthYear(apiDto.currentDriver.joinedAt),
|
|
rating: apiDto.currentDriver.rating ?? null,
|
|
ratingLabel: RatingDisplay.format(apiDto.currentDriver.rating),
|
|
globalRank: apiDto.currentDriver.globalRank ?? null,
|
|
globalRankLabel: apiDto.currentDriver.globalRank != null ? `#${apiDto.currentDriver.globalRank}` : '—',
|
|
consistency: apiDto.currentDriver.consistency ?? null,
|
|
bio: apiDto.currentDriver.bio ?? null,
|
|
totalDrivers: apiDto.currentDriver.totalDrivers ?? null,
|
|
} : null,
|
|
stats: apiDto.stats ? {
|
|
totalRaces: apiDto.stats.totalRaces,
|
|
totalRacesLabel: NumberDisplay.format(apiDto.stats.totalRaces),
|
|
wins: apiDto.stats.wins,
|
|
winsLabel: NumberDisplay.format(apiDto.stats.wins),
|
|
podiums: apiDto.stats.podiums,
|
|
podiumsLabel: NumberDisplay.format(apiDto.stats.podiums),
|
|
dnfs: apiDto.stats.dnfs,
|
|
dnfsLabel: NumberDisplay.format(apiDto.stats.dnfs),
|
|
avgFinish: apiDto.stats.avgFinish ?? null,
|
|
avgFinishLabel: FinishDisplay.formatAverage(apiDto.stats.avgFinish),
|
|
bestFinish: apiDto.stats.bestFinish ?? null,
|
|
bestFinishLabel: FinishDisplay.format(apiDto.stats.bestFinish),
|
|
worstFinish: apiDto.stats.worstFinish ?? null,
|
|
worstFinishLabel: FinishDisplay.format(apiDto.stats.worstFinish),
|
|
finishRate: apiDto.stats.finishRate ?? null,
|
|
winRate: apiDto.stats.winRate ?? null,
|
|
podiumRate: apiDto.stats.podiumRate ?? null,
|
|
percentile: apiDto.stats.percentile ?? null,
|
|
rating: apiDto.stats.rating ?? null,
|
|
ratingLabel: RatingDisplay.format(apiDto.stats.rating),
|
|
consistency: apiDto.stats.consistency ?? null,
|
|
consistencyLabel: PercentDisplay.formatWhole(apiDto.stats.consistency),
|
|
overallRank: apiDto.stats.overallRank ?? null,
|
|
} : null,
|
|
finishDistribution: apiDto.finishDistribution ? {
|
|
totalRaces: apiDto.finishDistribution.totalRaces,
|
|
wins: apiDto.finishDistribution.wins,
|
|
podiums: apiDto.finishDistribution.podiums,
|
|
topTen: apiDto.finishDistribution.topTen,
|
|
dnfs: apiDto.finishDistribution.dnfs,
|
|
other: apiDto.finishDistribution.other,
|
|
} : null,
|
|
teamMemberships: apiDto.teamMemberships.map(m => ({
|
|
teamId: m.teamId,
|
|
teamName: m.teamName,
|
|
teamTag: m.teamTag ?? null,
|
|
role: m.role,
|
|
joinedAt: m.joinedAt,
|
|
joinedAtLabel: DateDisplay.formatMonthYear(m.joinedAt),
|
|
isCurrent: m.isCurrent,
|
|
})),
|
|
socialSummary: {
|
|
friendsCount: apiDto.socialSummary.friendsCount,
|
|
friends: apiDto.socialSummary.friends.map(f => ({
|
|
id: f.id,
|
|
name: f.name,
|
|
country: f.country,
|
|
avatarUrl: f.avatarUrl || '',
|
|
})),
|
|
},
|
|
extendedProfile: apiDto.extendedProfile ? {
|
|
socialHandles: apiDto.extendedProfile.socialHandles.map(h => ({
|
|
platform: h.platform,
|
|
handle: h.handle,
|
|
url: h.url,
|
|
})),
|
|
achievements: apiDto.extendedProfile.achievements.map(a => ({
|
|
id: a.id,
|
|
title: a.title,
|
|
description: a.description,
|
|
icon: a.icon,
|
|
rarity: a.rarity,
|
|
rarityLabel: a.rarity,
|
|
earnedAt: a.earnedAt,
|
|
earnedAtLabel: DateDisplay.formatShort(a.earnedAt),
|
|
})),
|
|
racingStyle: apiDto.extendedProfile.racingStyle,
|
|
favoriteTrack: apiDto.extendedProfile.favoriteTrack,
|
|
favoriteCar: apiDto.extendedProfile.favoriteCar,
|
|
timezone: apiDto.extendedProfile.timezone,
|
|
availableHours: apiDto.extendedProfile.availableHours,
|
|
lookingForTeam: apiDto.extendedProfile.lookingForTeam,
|
|
openToRequests: apiDto.extendedProfile.openToRequests,
|
|
} : null,
|
|
};
|
|
}
|
|
}
|