Files
gridpilot.gg/apps/website/lib/view-models/RaceListItemViewModel.ts
2026-01-23 15:30:23 +01:00

55 lines
1.9 KiB
TypeScript

import { ViewModel } from "../contracts/view-models/ViewModel";
import { RaceStatusDisplay } from "../display-objects/RaceStatusDisplay";
import { DateDisplay } from "../display-objects/DateDisplay";
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 DateDisplay.formatDateTime(this.scheduledAt);
}
/** UI-specific: Badge variant for status */
get statusBadgeVariant(): string {
return RaceStatusDisplay.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`;
}
}