Files
gridpilot.gg/apps/website/lib/view-models/RaceListItemViewModel.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

80 lines
2.1 KiB
TypeScript

// DTO matching the backend RacesPageDataRaceDTO
export interface RaceListItemDTO {
id: string;
track: string;
car: string;
scheduledAt: string;
status: string;
leagueId: string;
leagueName: string;
strengthOfField?: number | null;
isUpcoming: boolean;
isLive: boolean;
isPast: boolean;
}
import { ViewModel } from "../contracts/view-models/ViewModel";
export class RaceListItemViewModel extends ViewModel {
id: string;
track: string;
car: string;
scheduledAt: string;
status: string;
leagueId: string;
leagueName: string;
strengthOfField: number | null;
isUpcoming: boolean;
isLive: boolean;
isPast: boolean;
constructor(dto: RaceListItemDTO) {
this.id = dto.id;
this.track = dto.track;
this.car = dto.car;
this.scheduledAt = dto.scheduledAt;
this.status = dto.status;
this.leagueId = dto.leagueId;
this.leagueName = dto.leagueName;
this.strengthOfField = dto.strengthOfField ?? null;
this.isUpcoming = dto.isUpcoming;
this.isLive = dto.isLive;
this.isPast = dto.isPast;
}
get title(): string {
return `${this.track} - ${this.car}`;
}
/** UI-specific: Formatted scheduled time */
get formattedScheduledTime(): string {
return new Date(this.scheduledAt).toLocaleString();
}
/** UI-specific: Badge variant for status */
get statusBadgeVariant(): string {
switch (this.status) {
case 'scheduled': return 'info';
case 'running': return 'success';
case 'completed': return 'secondary';
case 'cancelled': return 'danger';
default: return 'default';
}
}
/** 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`;
}
}