107 lines
2.5 KiB
TypeScript
107 lines
2.5 KiB
TypeScript
import type { Race } from '@gridpilot/racing/domain/entities/Race';
|
|
import {
|
|
getRaceRepository,
|
|
getIsDriverRegisteredForRaceQuery,
|
|
getRegisterForRaceUseCase,
|
|
getWithdrawFromRaceUseCase,
|
|
} from '@/lib/di-container';
|
|
|
|
export interface LeagueScheduleRaceItemViewModel {
|
|
id: string;
|
|
leagueId: string;
|
|
track: string;
|
|
car: string;
|
|
sessionType: string;
|
|
scheduledAt: Date;
|
|
status: Race['status'];
|
|
isUpcoming: boolean;
|
|
isPast: boolean;
|
|
isRegistered: boolean;
|
|
}
|
|
|
|
export interface LeagueScheduleViewModel {
|
|
races: LeagueScheduleRaceItemViewModel[];
|
|
}
|
|
|
|
/**
|
|
* Load league schedule with registration status for a given driver.
|
|
*/
|
|
export async function loadLeagueSchedule(
|
|
leagueId: string,
|
|
driverId: string,
|
|
): Promise<LeagueScheduleViewModel> {
|
|
const raceRepo = getRaceRepository();
|
|
const isRegisteredQuery = getIsDriverRegisteredForRaceQuery();
|
|
|
|
const allRaces = await raceRepo.findAll();
|
|
const leagueRaces = allRaces
|
|
.filter((race) => race.leagueId === leagueId)
|
|
.sort(
|
|
(a, b) =>
|
|
new Date(a.scheduledAt).getTime() - new Date(b.scheduledAt).getTime(),
|
|
);
|
|
|
|
const now = new Date();
|
|
|
|
const registrationStates: Record<string, boolean> = {};
|
|
await Promise.all(
|
|
leagueRaces.map(async (race) => {
|
|
const registered = await isRegisteredQuery.execute({
|
|
raceId: race.id,
|
|
driverId,
|
|
});
|
|
registrationStates[race.id] = registered;
|
|
}),
|
|
);
|
|
|
|
const races: LeagueScheduleRaceItemViewModel[] = leagueRaces.map((race) => {
|
|
const raceDate = new Date(race.scheduledAt);
|
|
const isPast = race.status === 'completed' || raceDate <= now;
|
|
const isUpcoming = race.status === 'scheduled' && raceDate > now;
|
|
|
|
return {
|
|
id: race.id,
|
|
leagueId: race.leagueId,
|
|
track: race.track,
|
|
car: race.car,
|
|
sessionType: race.sessionType,
|
|
scheduledAt: raceDate,
|
|
status: race.status,
|
|
isUpcoming,
|
|
isPast,
|
|
isRegistered: registrationStates[race.id] ?? false,
|
|
};
|
|
});
|
|
|
|
return { races };
|
|
}
|
|
|
|
/**
|
|
* Register the driver for a race.
|
|
*/
|
|
export async function registerForRace(
|
|
raceId: string,
|
|
leagueId: string,
|
|
driverId: string,
|
|
): Promise<void> {
|
|
const useCase = getRegisterForRaceUseCase();
|
|
await useCase.execute({
|
|
raceId,
|
|
leagueId,
|
|
driverId,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Withdraw the driver from a race.
|
|
*/
|
|
export async function withdrawFromRace(
|
|
raceId: string,
|
|
driverId: string,
|
|
): Promise<void> {
|
|
const useCase = getWithdrawFromRaceUseCase();
|
|
await useCase.execute({
|
|
raceId,
|
|
driverId,
|
|
});
|
|
} |