Files
gridpilot.gg/apps/website/lib/presenters/AllLeaguesWithCapacityPresenter.ts
2025-12-11 21:06:25 +01:00

76 lines
2.2 KiB
TypeScript

import type { League } from '@gridpilot/racing/domain/entities/League';
import type {
IAllLeaguesWithCapacityPresenter,
LeagueWithCapacityViewModel,
AllLeaguesWithCapacityViewModel,
} from '@gridpilot/racing/application/presenters/IAllLeaguesWithCapacityPresenter';
export class AllLeaguesWithCapacityPresenter implements IAllLeaguesWithCapacityPresenter {
private viewModel: AllLeaguesWithCapacityViewModel | null = null;
present(
leagues: League[],
memberCounts: Map<string, number>
): AllLeaguesWithCapacityViewModel {
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<LeagueWithCapacityViewModel['socialLinks']> = {};
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,
};
return this.viewModel;
}
getViewModel(): AllLeaguesWithCapacityViewModel {
if (!this.viewModel) {
throw new Error('Presenter has not been called yet');
}
return this.viewModel;
}
}