wip league admin tools

This commit is contained in:
2025-12-28 12:04:12 +01:00
parent 5dc8c2399c
commit 6edf12fda8
401 changed files with 15365 additions and 6047 deletions

View File

@@ -1,6 +1,6 @@
import { vi, describe, it, expect, beforeEach } from 'vitest';
import { InMemoryRaceRepository } from './InMemoryRaceRepository';
import { Race, RaceStatus } from '@core/racing/domain/entities/Race';
import { Race, type RaceStatusValue } from '@core/racing/domain/entities/Race';
import type { Logger } from '@core/shared/application';
describe('InMemoryRaceRepository', () => {
@@ -23,7 +23,7 @@ describe('InMemoryRaceRepository', () => {
track: string,
car: string,
scheduledAt: Date,
status: RaceStatus = 'scheduled'
status: RaceStatusValue = 'scheduled',
) => {
return Race.create({
id,
@@ -178,7 +178,7 @@ describe('InMemoryRaceRepository', () => {
const race = createTestRace('1', 'league1', 'Track1', 'Car1', new Date());
await repository.create(race);
const updatedRace = race.complete();
const updatedRace = race.start().complete();
const result = await repository.update(updatedRace);
expect(result).toEqual(updatedRace);
expect(mockLogger.info).toHaveBeenCalledWith('Race 1 updated successfully.');

View File

@@ -1,5 +1,5 @@
import { IRaceRepository } from '@core/racing/domain/repositories/IRaceRepository';
import { Race, RaceStatus } from '@core/racing/domain/entities/Race';
import { Race, type RaceStatusValue } from '@core/racing/domain/entities/Race';
import { Logger } from '@core/shared/application';
export class InMemoryRaceRepository implements IRaceRepository {
@@ -36,7 +36,7 @@ export class InMemoryRaceRepository implements IRaceRepository {
this.logger.debug(`[InMemoryRaceRepository] Finding upcoming races by league ID: ${leagueId}`);
const now = new Date();
const upcomingRaces = Array.from(this.races.values()).filter(race =>
race.leagueId === leagueId && race.status === 'scheduled' && race.scheduledAt > now
race.leagueId === leagueId && race.status.isScheduled() && race.scheduledAt > now
);
this.logger.info(`Found ${upcomingRaces.length} upcoming races for league ID: ${leagueId}.`);
return Promise.resolve(upcomingRaces);
@@ -45,15 +45,17 @@ export class InMemoryRaceRepository implements IRaceRepository {
async findCompletedByLeagueId(leagueId: string): Promise<Race[]> {
this.logger.debug(`[InMemoryRaceRepository] Finding completed races by league ID: ${leagueId}`);
const completedRaces = Array.from(this.races.values()).filter(race =>
race.leagueId === leagueId && race.status === 'completed'
race.leagueId === leagueId && race.status.isCompleted()
);
this.logger.info(`Found ${completedRaces.length} completed races for league ID: ${leagueId}.`);
return Promise.resolve(completedRaces);
}
async findByStatus(status: RaceStatus): Promise<Race[]> {
async findByStatus(status: RaceStatusValue): Promise<Race[]> {
this.logger.debug(`[InMemoryRaceRepository] Finding races by status: ${status}.`);
const races = Array.from(this.races.values()).filter(race => race.status === status);
const races = Array.from(this.races.values()).filter(
race => race.status.toString() === status,
);
this.logger.info(`Found ${races.length} races with status: ${status}.`);
return Promise.resolve(races);
}

View File

@@ -154,7 +154,7 @@ export class InMemorySeasonRepository implements ISeasonRepository {
this.logger.debug(`Listing active seasons by league id: ${leagueId}`);
try {
const seasons = this.seasons.filter(
(s) => s.leagueId === leagueId && s.status === 'active',
(s) => s.leagueId === leagueId && s.status.isActive(),
);
this.logger.info(`Found ${seasons.length} active seasons for league id: ${leagueId}.`);
return seasons;

View File

@@ -78,7 +78,9 @@ export class InMemorySeasonRepository implements ISeasonRepository {
async listActiveByLeague(leagueId: string): Promise<Season[]> {
this.logger.debug(`[InMemorySeasonRepository] Listing active seasons by league ID: ${leagueId}`);
const activeSeasons = Array.from(this.seasons.values()).filter(season => season.leagueId === leagueId && season.status === 'active');
const activeSeasons = Array.from(this.seasons.values()).filter(
season => season.leagueId === leagueId && season.status.isActive(),
);
return Promise.resolve(activeSeasons);
}
}

View File

@@ -52,8 +52,8 @@ export class InMemoryTrackRepository implements ITrackRepository {
this.logger.debug(`Finding tracks by game id: ${gameId}`);
try {
const tracks = Array.from(this.tracks.values())
.filter(track => track.gameId.props === gameId)
.sort((a, b) => a.name.props.localeCompare(b.name.props));
.filter(track => track.gameId.toString() === gameId)
.sort((a, b) => a.name.toString().localeCompare(b.name.toString()));
this.logger.info(`Found ${tracks.length} tracks for game id: ${gameId}.`);
return tracks;
} catch (error) {
@@ -67,7 +67,7 @@ export class InMemoryTrackRepository implements ITrackRepository {
try {
const tracks = Array.from(this.tracks.values())
.filter(track => track.category === category)
.sort((a, b) => a.name.props.localeCompare(b.name.props));
.sort((a, b) => a.name.toString().localeCompare(b.name.toString()));
this.logger.info(`Found ${tracks.length} tracks for category: ${category}.`);
return tracks;
} catch (error) {
@@ -80,8 +80,8 @@ export class InMemoryTrackRepository implements ITrackRepository {
this.logger.debug(`Finding tracks by country: ${country}`);
try {
const tracks = Array.from(this.tracks.values())
.filter(track => track.country.props.toLowerCase() === country.toLowerCase())
.sort((a, b) => a.name.props.localeCompare(b.name.props));
.filter(track => track.country.toString().toLowerCase() === country.toLowerCase())
.sort((a, b) => a.name.toString().localeCompare(b.name.toString()));
this.logger.info(`Found ${tracks.length} tracks for country: ${country}.`);
return tracks;
} catch (error) {
@@ -96,10 +96,10 @@ export class InMemoryTrackRepository implements ITrackRepository {
const lowerQuery = query.toLowerCase();
const tracks = Array.from(this.tracks.values())
.filter(track =>
track.name.props.toLowerCase().includes(lowerQuery) ||
track.shortName.props.toLowerCase().includes(lowerQuery)
track.name.toString().toLowerCase().includes(lowerQuery) ||
track.shortName.toString().toLowerCase().includes(lowerQuery)
)
.sort((a, b) => a.name.props.localeCompare(b.name.props));
.sort((a, b) => a.name.toString().localeCompare(b.name.toString()));
this.logger.info(`Found ${tracks.length} tracks matching search query: ${query}.`);
return tracks;
} catch (error) {