Files
gridpilot.gg/apps/website/lib/view-models/UserProfileViewModel.ts
Marc Mintel d97f50ed72
Some checks failed
Contract Testing / contract-tests (pull_request) Failing after 6m4s
Contract Testing / contract-snapshot (pull_request) Has been skipped
view data fixes
2026-01-23 11:59:49 +01:00

50 lines
1.3 KiB
TypeScript

// Note: No generated DTO available for UserProfile yet
interface UserProfileDTO {
id: string;
name: string;
avatarUrl?: string;
iracingId?: string;
rating?: number;
}
import { ViewModel } from "../contracts/view-models/ViewModel";
export class UserProfileViewModel extends ViewModel {
id: string;
name: string;
avatarUrl?: string;
iracingId?: string;
rating?: number;
constructor(dto: UserProfileDTO) {
this.id = dto.id;
this.name = dto.name;
if (dto.avatarUrl !== undefined) this.avatarUrl = dto.avatarUrl;
if (dto.iracingId !== undefined) this.iracingId = dto.iracingId;
if (dto.rating !== undefined) this.rating = dto.rating;
}
/** UI-specific: Formatted rating */
get formattedRating(): string {
return this.rating ? this.rating.toFixed(0) : 'Unrated';
}
/** UI-specific: Whether has iRacing ID */
get hasIracingId(): boolean {
return !!this.iracingId;
}
/** UI-specific: Profile completeness percentage */
get profileCompleteness(): number {
let complete = 1; // id always there
if (this.avatarUrl) complete++;
if (this.iracingId) complete++;
if (this.rating) complete++;
return Math.round((complete / 4) * 100);
}
/** UI-specific: Avatar initials */
get avatarInitials(): string {
return this.name.split(' ').map(n => n[0]).join('').toUpperCase();
}
}