Files
gridpilot.gg/apps/website/lib/builders/view-data/ProfileViewDataBuilder.ts
2026-01-24 01:07:43 +01:00

112 lines
4.5 KiB
TypeScript

import { mediaConfig } from '@/lib/config/mediaConfig';
import { CountryFlagFormatter } from '@/lib/formatters/CountryFlagFormatter';
import { DateFormatter } from '@/lib/formatters/DateFormatter';
import { FinishFormatter } from '@/lib/formatters/FinishFormatter';
import { NumberFormatter } from '@/lib/formatters/NumberFormatter';
import { PercentFormatter } from '@/lib/formatters/PercentFormatter';
import { RatingFormatter } from '@/lib/formatters/RatingFormatter';
import type { GetDriverProfileOutputDTO } from '@/lib/types/generated/GetDriverProfileOutputDTO';
import type { ProfileViewData } from '@/lib/view-data/ProfileViewData';
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
export class ProfileViewDataBuilder implements ViewDataBuilder<any, any> {
build(input: any): any {
return ProfileViewDataBuilder.build(input);
}
static build(apiDto: GetDriverProfileOutputDTO): ProfileViewData {
const driver = apiDto.currentDriver;
if (!driver) {
return {
driver: {
id: '',
name: '',
countryCode: '',
countryFlag: CountryFlagFormatter.fromCountryCode(null).toString(),
avatarUrl: mediaConfig.avatars.defaultFallback,
bio: null,
iracingId: null,
joinedAtLabel: '',
},
stats: null,
teamMemberships: [],
extendedProfile: null,
};
}
const stats = apiDto.stats ?? null;
const socialSummary = apiDto.socialSummary;
const extended = apiDto.extendedProfile ?? null;
return {
driver: {
id: driver.id,
name: driver.name,
countryCode: driver.country,
countryFlag: CountryFlagFormatter.fromCountryCode(driver.country).toString(),
avatarUrl: driver.avatarUrl || mediaConfig.avatars.defaultFallback,
bio: driver.bio || null,
iracingId: driver.iracingId ? String(driver.iracingId) : null,
joinedAtLabel: DateFormatter.formatMonthYear(driver.joinedAt),
},
stats: stats
? {
ratingLabel: RatingFormatter.format(stats.rating),
globalRankLabel: driver.globalRank != null ? `#${driver.globalRank}` : '—',
totalRacesLabel: NumberFormatter.format(stats.totalRaces),
winsLabel: NumberFormatter.format(stats.wins),
podiumsLabel: NumberFormatter.format(stats.podiums),
dnfsLabel: NumberFormatter.format(stats.dnfs),
bestFinishLabel: FinishFormatter.format(stats.bestFinish),
worstFinishLabel: FinishFormatter.format(stats.worstFinish),
avgFinishLabel: FinishFormatter.formatAverage(stats.avgFinish),
consistencyLabel: PercentFormatter.formatWhole(stats.consistency),
percentileLabel: PercentFormatter.format(stats.percentile),
}
: null,
teamMemberships: apiDto.teamMemberships.map((m) => ({
teamId: m.teamId,
teamName: m.teamName,
teamTag: m.teamTag || null,
roleLabel: m.role,
joinedAtLabel: DateFormatter.formatMonthYear(m.joinedAt),
href: `/teams/${m.teamId}`,
})),
extendedProfile: extended
? {
timezone: extended.timezone,
racingStyle: extended.racingStyle,
favoriteTrack: extended.favoriteTrack,
favoriteCar: extended.favoriteCar,
availableHours: extended.availableHours,
lookingForTeamLabel: extended.lookingForTeam ? 'Looking for Team' : '',
openToRequestsLabel: extended.openToRequests ? 'Open to Requests' : '',
socialHandles: extended.socialHandles.map((h) => ({
platformLabel: h.platform,
handle: h.handle,
url: h.url,
})),
achievements: extended.achievements.map((a) => ({
id: a.id,
title: a.title,
description: a.description,
earnedAtLabel: DateFormatter.formatShort(a.earnedAt),
icon: a.icon as any,
rarityLabel: a.rarity,
})),
friends: socialSummary.friends.slice(0, 8).map((f) => ({
id: f.id,
name: f.name,
countryFlag: CountryFlagFormatter.fromCountryCode(f.country).toString(),
avatarUrl: f.avatarUrl || mediaConfig.avatars.defaultFallback,
href: `/drivers/${f.id}`,
})),
friendsCountLabel: NumberFormatter.format(socialSummary.friendsCount),
}
: null,
};
}
}