import type { IAllLeaguesWithCapacityPresenter, LeagueWithCapacityViewModel, AllLeaguesWithCapacityViewModel, AllLeaguesWithCapacityResultDTO, } from '@core/racing/application/presenters/IAllLeaguesWithCapacityPresenter'; export class AllLeaguesWithCapacityPresenter implements IAllLeaguesWithCapacityPresenter { private viewModel: AllLeaguesWithCapacityViewModel | null = null; reset(): void { this.viewModel = null; } present(input: AllLeaguesWithCapacityResultDTO): void { const { leagues, memberCounts } = input; const leagueItems: LeagueWithCapacityViewModel[] = leagues.map((league) => { const usedSlots = memberCounts.get(league.id) ?? 0; // 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 base: LeagueWithCapacityViewModel = { id: league.id, name: league.name, description: league.description, ownerId: league.ownerId, settings: { ...league.settings, maxDrivers: safeMaxDrivers, }, createdAt: league.createdAt.toISOString(), usedSlots, }; if (!league.socialLinks) { return base; } const socialLinks: NonNullable = {}; if (league.socialLinks.discordUrl) { socialLinks.discordUrl = league.socialLinks.discordUrl; } if (league.socialLinks.youtubeUrl) { socialLinks.youtubeUrl = league.socialLinks.youtubeUrl; } if (league.socialLinks.websiteUrl) { socialLinks.websiteUrl = league.socialLinks.websiteUrl; } if (Object.keys(socialLinks).length === 0) { return base; } return { ...base, socialLinks, }; }); this.viewModel = { leagues: leagueItems, totalCount: leagueItems.length, }; } getViewModel(): AllLeaguesWithCapacityViewModel | null { return this.viewModel; } }