165 lines
4.9 KiB
TypeScript
165 lines
4.9 KiB
TypeScript
import { DriverProfileDriverSummaryViewModel } from "./DriverProfileDriverSummaryViewModel";
|
|
import { ProfileViewData } from "../view-data/ProfileViewData";
|
|
import { ViewModel } from "../contracts/view-models/ViewModel";
|
|
|
|
export interface DriverProfileStatsViewModel extends ViewModel {
|
|
totalRaces: number;
|
|
wins: number;
|
|
podiums: number;
|
|
dnfs: number;
|
|
avgFinish: number | null;
|
|
bestFinish: number | null;
|
|
worstFinish: number | null;
|
|
finishRate: number | null;
|
|
winRate: number | null;
|
|
podiumRate: number | null;
|
|
percentile: number | null;
|
|
rating: number | null;
|
|
consistency: number | null;
|
|
overallRank: number | null;
|
|
}
|
|
|
|
export interface DriverProfileFinishDistributionViewModel extends ViewModel {
|
|
totalRaces: number;
|
|
wins: number;
|
|
podiums: number;
|
|
topTen: number;
|
|
dnfs: number;
|
|
other: number;
|
|
}
|
|
|
|
export interface DriverProfileTeamMembershipViewModel extends ViewModel {
|
|
teamId: string;
|
|
teamName: string;
|
|
teamTag: string | null;
|
|
role: string;
|
|
joinedAt: string;
|
|
isCurrent: boolean;
|
|
}
|
|
|
|
export interface DriverProfileSocialFriendSummaryViewModel extends ViewModel {
|
|
id: string;
|
|
name: string;
|
|
country: string;
|
|
avatarUrl: string;
|
|
}
|
|
|
|
export interface DriverProfileSocialSummaryViewModel extends ViewModel {
|
|
friendsCount: number;
|
|
friends: DriverProfileSocialFriendSummaryViewModel[];
|
|
}
|
|
|
|
export type DriverProfileSocialPlatform = 'twitter' | 'youtube' | 'twitch' | 'discord';
|
|
|
|
export type DriverProfileAchievementRarity = 'common' | 'rare' | 'epic' | 'legendary';
|
|
|
|
export interface DriverProfileAchievementViewModel extends ViewModel {
|
|
id: string;
|
|
title: string;
|
|
description: string;
|
|
icon: 'trophy' | 'medal' | 'star' | 'crown' | 'target' | 'zap';
|
|
rarity: DriverProfileAchievementRarity;
|
|
earnedAt: string;
|
|
}
|
|
|
|
export interface DriverProfileSocialHandleViewModel extends ViewModel {
|
|
platform: DriverProfileSocialPlatform;
|
|
handle: string;
|
|
url: string;
|
|
}
|
|
|
|
export interface DriverProfileExtendedProfileViewModel extends ViewModel {
|
|
socialHandles: DriverProfileSocialHandleViewModel[];
|
|
achievements: DriverProfileAchievementViewModel[];
|
|
racingStyle: string;
|
|
favoriteTrack: string;
|
|
favoriteCar: string;
|
|
timezone: string;
|
|
availableHours: string;
|
|
lookingForTeam: boolean;
|
|
openToRequests: boolean;
|
|
}
|
|
|
|
export interface DriverProfileViewModelData {
|
|
currentDriver: DriverProfileDriverSummaryViewModel | null;
|
|
stats: DriverProfileStatsViewModel | null;
|
|
finishDistribution: DriverProfileFinishDistributionViewModel | null;
|
|
teamMemberships: DriverProfileTeamMembershipViewModel[];
|
|
socialSummary: DriverProfileSocialSummaryViewModel;
|
|
extendedProfile: DriverProfileExtendedProfileViewModel | null;
|
|
}
|
|
|
|
/**
|
|
* Driver Profile View Model
|
|
*
|
|
* Represents a fully prepared UI state for driver profile display.
|
|
* Transforms ViewData into UI-ready data structures.
|
|
*/
|
|
export class DriverProfileViewModel extends ViewModel {
|
|
constructor(private readonly viewData: ProfileViewData) {
|
|
super();
|
|
}
|
|
|
|
get currentDriver(): DriverProfileDriverSummaryViewModel | null {
|
|
if (!this.viewData.driver) return null;
|
|
return new DriverProfileDriverSummaryViewModel(this.viewData);
|
|
}
|
|
|
|
get stats(): DriverProfileStatsViewModel | null {
|
|
if (!this.viewData.stats) return null;
|
|
return {
|
|
totalRaces: 0,
|
|
wins: 0,
|
|
podiums: 0,
|
|
dnfs: 0,
|
|
avgFinish: null,
|
|
bestFinish: null,
|
|
worstFinish: null,
|
|
finishRate: null,
|
|
winRate: null,
|
|
podiumRate: null,
|
|
percentile: null,
|
|
rating: null,
|
|
consistency: null,
|
|
overallRank: null,
|
|
};
|
|
}
|
|
|
|
get teamMemberships(): DriverProfileTeamMembershipViewModel[] {
|
|
return this.viewData.teamMemberships.map((m) => ({
|
|
teamId: m.teamId,
|
|
teamName: m.teamName,
|
|
teamTag: m.teamTag,
|
|
role: m.roleLabel,
|
|
joinedAt: m.joinedAtLabel,
|
|
isCurrent: true,
|
|
}));
|
|
}
|
|
|
|
get extendedProfile(): DriverProfileExtendedProfileViewModel | null {
|
|
if (!this.viewData.extendedProfile) return null;
|
|
return {
|
|
socialHandles: this.viewData.extendedProfile.socialHandles.map((h) => ({
|
|
platform: h.platformLabel.toLowerCase() as any,
|
|
handle: h.handle,
|
|
url: h.url,
|
|
})),
|
|
achievements: this.viewData.extendedProfile.achievements.map((a) => ({
|
|
id: a.id,
|
|
title: a.title,
|
|
description: a.description,
|
|
icon: a.icon,
|
|
rarity: a.rarityLabel.toLowerCase() as any,
|
|
earnedAt: a.earnedAtLabel,
|
|
})),
|
|
racingStyle: this.viewData.extendedProfile.racingStyle,
|
|
favoriteTrack: this.viewData.extendedProfile.favoriteTrack,
|
|
favoriteCar: this.viewData.extendedProfile.favoriteCar,
|
|
timezone: this.viewData.extendedProfile.timezone,
|
|
availableHours: this.viewData.extendedProfile.availableHours,
|
|
lookingForTeam: this.viewData.extendedProfile.lookingForTeamLabel === 'Yes',
|
|
openToRequests: this.viewData.extendedProfile.openToRequestsLabel === 'Yes',
|
|
};
|
|
}
|
|
}
|