Files
gridpilot.gg/apps/website/lib/view-models/DriverLeaderboardItemViewModel.ts
2025-12-17 18:01:47 +01:00

76 lines
2.0 KiB
TypeScript

import { DriverLeaderboardItemDto } from '../dtos';
export class DriverLeaderboardItemViewModel implements DriverLeaderboardItemDto {
id: string;
name: string;
avatarUrl?: string;
rating: number;
wins: number;
races: number;
skillLevel: string;
isActive: boolean;
nationality: string;
podiums: number;
position: number;
private previousRating?: number;
constructor(dto: DriverLeaderboardItemDto, position: number, previousRating?: number) {
Object.assign(this, dto);
this.position = position;
this.previousRating = previousRating;
}
/** UI-specific: Skill level color */
get skillLevelColor(): string {
switch (this.skillLevel) {
case 'beginner': return 'green';
case 'intermediate': return 'yellow';
case 'advanced': return 'orange';
case 'expert': return 'red';
default: return 'gray';
}
}
/** UI-specific: Skill level icon */
get skillLevelIcon(): string {
switch (this.skillLevel) {
case 'beginner': return '🥉';
case 'intermediate': return '🥈';
case 'advanced': return '🥇';
case 'expert': return '👑';
default: return '🏁';
}
}
/** UI-specific: Win rate */
get winRate(): number {
return this.races > 0 ? (this.wins / this.races) * 100 : 0;
}
/** UI-specific: Formatted win rate */
get winRateFormatted(): string {
return `${this.winRate.toFixed(1)}%`;
}
/** UI-specific: Rating trend */
get ratingTrend(): 'up' | 'down' | 'same' {
if (!this.previousRating) return 'same';
if (this.rating > this.previousRating) return 'up';
if (this.rating < this.previousRating) return 'down';
return 'same';
}
/** UI-specific: Rating change indicator */
get ratingChangeIndicator(): string {
const change = this.previousRating ? this.rating - this.previousRating : 0;
if (change > 0) return `+${change}`;
if (change < 0) return `${change}`;
return '0';
}
/** UI-specific: Position badge */
get positionBadge(): string {
return this.position.toString();
}
}