76 lines
2.2 KiB
TypeScript
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;
|
|
}
|
|
} |