90 lines
2.7 KiB
TypeScript
90 lines
2.7 KiB
TypeScript
import { RaceListItemViewModel } from './RaceListItemViewModel';
|
|
import type { RacesPageDataRaceDTO } from '@/lib/types/generated/RacesPageDataRaceDTO';
|
|
|
|
// DTO matching the backend RacesPageDataDTO
|
|
interface RacesPageDTO {
|
|
races: RacesPageDataRaceDTO[];
|
|
}
|
|
|
|
/**
|
|
* Races page view model
|
|
* Represents the races page data with all races in a single list
|
|
*/
|
|
import { ViewModel } from "../contracts/view-models/ViewModel";
|
|
|
|
export class RacesPageViewModel extends ViewModel {
|
|
races: RaceListItemViewModel[];
|
|
|
|
constructor(dto: RacesPageDTO) {
|
|
this.races = dto.races.map((r) => {
|
|
const status = 'status' in r ? r.status : 'unknown';
|
|
|
|
const isUpcoming =
|
|
'isUpcoming' in r ? r.isUpcoming :
|
|
(status === 'upcoming' || status === 'scheduled');
|
|
|
|
const isLive =
|
|
'isLive' in r ? r.isLive :
|
|
(status === 'live' || status === 'running');
|
|
|
|
const isPast =
|
|
'isPast' in r ? r.isPast :
|
|
(status === 'completed' || status === 'finished' || status === 'cancelled');
|
|
|
|
// Build the RaceListItemDTO from the input with proper type checking
|
|
const scheduledAt = 'scheduledAt' in r ? r.scheduledAt :
|
|
('date' in r ? (r as { date?: string }).date : '');
|
|
|
|
const normalized = {
|
|
id: r.id,
|
|
track: 'track' in r ? r.track : '',
|
|
car: 'car' in r ? r.car : '',
|
|
scheduledAt: scheduledAt || '',
|
|
status: status,
|
|
leagueId: 'leagueId' in r ? r.leagueId : '',
|
|
leagueName: 'leagueName' in r ? r.leagueName : '',
|
|
strengthOfField: 'strengthOfField' in r ? (r as { strengthOfField?: number }).strengthOfField ?? null : null,
|
|
isUpcoming: Boolean(isUpcoming),
|
|
isLive: Boolean(isLive),
|
|
isPast: Boolean(isPast),
|
|
};
|
|
|
|
return new RaceListItemViewModel(normalized);
|
|
});
|
|
}
|
|
|
|
/** UI-specific: Total races */
|
|
get totalCount(): number {
|
|
return this.races.length;
|
|
}
|
|
|
|
/** UI-specific: Upcoming races */
|
|
get upcomingRaces(): RaceListItemViewModel[] {
|
|
return this.races.filter(r => r.isUpcoming);
|
|
}
|
|
|
|
/** UI-specific: Live races */
|
|
get liveRaces(): RaceListItemViewModel[] {
|
|
return this.races.filter(r => r.isLive);
|
|
}
|
|
|
|
/** UI-specific: Past races */
|
|
get pastRaces(): RaceListItemViewModel[] {
|
|
return this.races.filter(r => r.isPast);
|
|
}
|
|
|
|
/** UI-specific: Scheduled races */
|
|
get scheduledRaces(): RaceListItemViewModel[] {
|
|
return this.races.filter(r => r.status === 'scheduled');
|
|
}
|
|
|
|
/** UI-specific: Running races */
|
|
get runningRaces(): RaceListItemViewModel[] {
|
|
return this.races.filter(r => r.status === 'running');
|
|
}
|
|
|
|
/** UI-specific: Completed races */
|
|
get completedRaces(): RaceListItemViewModel[] {
|
|
return this.races.filter(r => r.status === 'completed');
|
|
}
|
|
} |