import { ViewModel } from "../contracts/view-models/ViewModel"; import { DateFormatter } from "../formatters/DateFormatter"; import { RaceStatusFormatter } from "../formatters/RaceStatusFormatter"; import type { RaceListItemViewData } from "../view-data/RaceListItemViewData"; export class RaceListItemViewModel extends ViewModel { private readonly data: RaceListItemViewData; constructor(data: RaceListItemViewData) { super(); this.data = data; } get id(): string { return this.data.id; } get track(): string { return this.data.track; } get car(): string { return this.data.car; } get scheduledAt(): string { return this.data.scheduledAt; } get status(): string { return this.data.status; } get leagueId(): string { return this.data.leagueId; } get leagueName(): string { return this.data.leagueName; } get strengthOfField(): number | null { return this.data.strengthOfField; } get isUpcoming(): boolean { return this.data.isUpcoming; } get isLive(): boolean { return this.data.isLive; } get isPast(): boolean { return this.data.isPast; } get title(): string { return `${this.track} - ${this.car}`; } /** UI-specific: Formatted scheduled time */ get formattedScheduledTime(): string { return DateFormatter.formatDateTime(this.scheduledAt); } /** UI-specific: Badge variant for status */ get statusBadgeVariant(): string { return RaceStatusFormatter.getVariant(this.status); } /** UI-specific: Time until start in minutes */ get timeUntilStart(): number { const now = new Date(); const scheduled = new Date(this.scheduledAt); return Math.max(0, Math.floor((scheduled.getTime() - now.getTime()) / (1000 * 60))); } /** UI-specific: Display for time until start */ get timeUntilStartDisplay(): string { const minutes = this.timeUntilStart; if (minutes < 60) return `${minutes}m`; const hours = Math.floor(minutes / 60); return `${hours}h ${minutes % 60}m`; } }