Files
gridpilot.gg/packages/racing/application/use-cases/GetRaceProtestsQuery.ts
2025-12-09 10:32:59 +01:00

77 lines
2.4 KiB
TypeScript

/**
* Application Query: GetRaceProtestsQuery
*
* Returns all protests filed for a specific race, with driver details.
*/
import type { IProtestRepository } from '../../domain/repositories/IProtestRepository';
import type { IDriverRepository } from '../../domain/repositories/IDriverRepository';
import type { ProtestStatus, ProtestIncident } from '../../domain/entities/Protest';
export interface RaceProtestDTO {
id: string;
raceId: string;
protestingDriverId: string;
protestingDriverName: string;
accusedDriverId: string;
accusedDriverName: string;
incident: ProtestIncident;
comment?: string;
proofVideoUrl?: string;
status: ProtestStatus;
reviewedBy?: string;
reviewedByName?: string;
decisionNotes?: string;
filedAt: string;
reviewedAt?: string;
}
export class GetRaceProtestsQuery {
constructor(
private readonly protestRepository: IProtestRepository,
private readonly driverRepository: IDriverRepository,
) {}
async execute(raceId: string): Promise<RaceProtestDTO[]> {
const protests = await this.protestRepository.findByRaceId(raceId);
// Load all driver details in parallel
const driverIds = new Set<string>();
protests.forEach(protest => {
driverIds.add(protest.protestingDriverId);
driverIds.add(protest.accusedDriverId);
if (protest.reviewedBy) {
driverIds.add(protest.reviewedBy);
}
});
const drivers = await Promise.all(
Array.from(driverIds).map(id => this.driverRepository.findById(id))
);
const driverMap = new Map<string, string>();
drivers.forEach(driver => {
if (driver) {
driverMap.set(driver.id, driver.name);
}
});
return protests.map(protest => ({
id: protest.id,
raceId: protest.raceId,
protestingDriverId: protest.protestingDriverId,
protestingDriverName: driverMap.get(protest.protestingDriverId) || 'Unknown',
accusedDriverId: protest.accusedDriverId,
accusedDriverName: driverMap.get(protest.accusedDriverId) || 'Unknown',
incident: protest.incident,
comment: protest.comment,
proofVideoUrl: protest.proofVideoUrl,
status: protest.status,
reviewedBy: protest.reviewedBy,
reviewedByName: protest.reviewedBy ? driverMap.get(protest.reviewedBy) : undefined,
decisionNotes: protest.decisionNotes,
filedAt: protest.filedAt.toISOString(),
reviewedAt: protest.reviewedAt?.toISOString(),
}));
}
}