58 lines
1.8 KiB
TypeScript
58 lines
1.8 KiB
TypeScript
import type { ILeagueRepository } from '../../domain/repositories/ILeagueRepository';
|
|
import type { ILeagueMembershipRepository } from '../../domain/repositories/ILeagueMembershipRepository';
|
|
import type { LeagueDTO } from '../dto/LeagueDTO';
|
|
|
|
export class GetAllLeaguesWithCapacityQuery {
|
|
constructor(
|
|
private readonly leagueRepository: ILeagueRepository,
|
|
private readonly leagueMembershipRepository: ILeagueMembershipRepository,
|
|
) {}
|
|
|
|
async execute(): Promise<LeagueDTO[]> {
|
|
const leagues = await this.leagueRepository.findAll();
|
|
|
|
const results: LeagueDTO[] = [];
|
|
|
|
for (const league of leagues) {
|
|
const members = await this.leagueMembershipRepository.getLeagueMembers(league.id);
|
|
|
|
const usedSlots = members.filter(
|
|
(m) =>
|
|
m.status === 'active' &&
|
|
(m.role === 'owner' ||
|
|
m.role === 'admin' ||
|
|
m.role === 'steward' ||
|
|
m.role === 'member'),
|
|
).length;
|
|
|
|
// Ensure we never expose an impossible state like 26/24:
|
|
// clamp maxDrivers to at least usedSlots at the application boundary.
|
|
const configuredMax = league.settings.maxDrivers ?? usedSlots;
|
|
const safeMaxDrivers = Math.max(configuredMax, usedSlots);
|
|
|
|
const dto: LeagueDTO = {
|
|
id: league.id,
|
|
name: league.name,
|
|
description: league.description,
|
|
ownerId: league.ownerId,
|
|
settings: {
|
|
...league.settings,
|
|
maxDrivers: safeMaxDrivers,
|
|
},
|
|
createdAt: league.createdAt.toISOString(),
|
|
socialLinks: league.socialLinks
|
|
? {
|
|
discordUrl: league.socialLinks.discordUrl,
|
|
youtubeUrl: league.socialLinks.youtubeUrl,
|
|
websiteUrl: league.socialLinks.websiteUrl,
|
|
}
|
|
: undefined,
|
|
usedSlots,
|
|
};
|
|
|
|
results.push(dto);
|
|
}
|
|
|
|
return results;
|
|
}
|
|
} |