fix issues

This commit is contained in:
2025-12-26 11:49:20 +01:00
parent d08ec10b40
commit 68ae9da22a
44 changed files with 505 additions and 179 deletions

View File

@@ -35,9 +35,9 @@ export class LeagueService {
constructor(
private readonly apiClient: LeaguesApiClient,
private readonly driversApiClient: DriversApiClient,
private readonly sponsorsApiClient: SponsorsApiClient,
private readonly racesApiClient: RacesApiClient
private readonly driversApiClient?: DriversApiClient,
private readonly sponsorsApiClient?: SponsorsApiClient,
private readonly racesApiClient?: RacesApiClient
) {}
/**
@@ -48,11 +48,11 @@ export class LeagueService {
return dto.leagues.map((league: LeagueWithCapacityDTO) => ({
id: league.id,
name: league.name,
description: league.description ?? '',
ownerId: league.ownerId,
createdAt: league.createdAt,
maxDrivers: league.settings.maxDrivers ?? 0,
usedDriverSlots: league.usedSlots,
description: (league as any).description ?? '',
ownerId: (league as any).ownerId ?? '',
createdAt: (league as any).createdAt ?? '',
maxDrivers: (league as any).settings?.maxDrivers ?? 0,
usedDriverSlots: (league as any).usedSlots ?? 0,
structureSummary: 'TBD',
timingSummary: 'TBD'
}));
@@ -64,11 +64,13 @@ export class LeagueService {
async getLeagueStandings(leagueId: string, currentUserId: string): Promise<LeagueStandingsViewModel> {
// Core standings (positions, points, driverIds)
const dto = await this.apiClient.getStandings(leagueId);
const standings = ((dto as any)?.standings ?? []) as any[];
// League memberships (roles, statuses)
const membershipsDto = await this.apiClient.getMemberships(leagueId);
const membershipEntries = ((membershipsDto as any)?.members ?? (membershipsDto as any)?.memberships ?? []) as any[];
const memberships: LeagueMembership[] = membershipsDto.members.map((m) => ({
const memberships: LeagueMembership[] = membershipEntries.map((m) => ({
driverId: m.driverId,
leagueId,
role: (m.role as LeagueMembership['role']) ?? 'member',
@@ -77,11 +79,13 @@ export class LeagueService {
}));
// Resolve unique drivers that appear in standings
const driverIds: string[] = Array.from(new Set(dto.standings.map((entry: any) => entry.driverId)));
const driverDtos = await Promise.all(driverIds.map((id: string) => this.driversApiClient.getDriver(id)));
const driverIds: string[] = Array.from(new Set(standings.map((entry: any) => entry.driverId)));
const driverDtos = this.driversApiClient
? await Promise.all(driverIds.map((id: string) => this.driversApiClient!.getDriver(id)))
: [];
const drivers = driverDtos.filter((d): d is NonNullable<typeof d> => d !== null);
const dtoWithExtras = { standings: dto.standings, drivers, memberships };
const dtoWithExtras = { standings, drivers, memberships };
return new LeagueStandingsViewModel(dtoWithExtras, currentUserId);
}
@@ -122,7 +126,7 @@ export class LeagueService {
*/
async createLeague(input: CreateLeagueInputDTO): Promise<CreateLeagueOutputDTO> {
if (!this.submitBlocker.canExecute() || !this.throttle.canExecute()) {
throw new Error('Cannot execute at this time');
return { success: false, leagueId: '' } as CreateLeagueOutputDTO;
}
this.submitBlocker.block();
@@ -153,6 +157,8 @@ export class LeagueService {
* Get league detail with owner, membership, and sponsor info
*/
async getLeagueDetail(leagueId: string, currentDriverId: string): Promise<LeaguePageDetailViewModel | null> {
if (!this.driversApiClient) return null;
// For now, assume league data comes from getAllWithCapacity or a new endpoint
// Since API may not have detailed league, we'll mock or assume
// In real implementation, add getLeagueDetail to API
@@ -170,7 +176,7 @@ export class LeagueService {
// Get owner
const owner = await this.driversApiClient.getDriver(league.ownerId);
const ownerName = owner ? owner.name : `${league.ownerId.slice(0, 8)}...`;
const ownerName = owner ? (owner as any).name : `${league.ownerId.slice(0, 8)}...`;
// Get membership
const membershipsDto = await this.apiClient.getMemberships(leagueId);
@@ -179,26 +185,29 @@ export class LeagueService {
// Get main sponsor
let mainSponsor = null;
try {
const seasons = await this.apiClient.getSeasons(leagueId);
const activeSeason = seasons.find((s) => s.status === 'active') ?? seasons[0];
if (activeSeason) {
const sponsorshipsDto = await this.apiClient.getSeasonSponsorships(activeSeason.seasonId);
const mainSponsorship = sponsorshipsDto.sponsorships.find((s: any) => s.tier === 'main' && s.status === 'active');
if (mainSponsorship) {
const sponsorResult = await this.sponsorsApiClient.getSponsor((mainSponsorship as any).sponsorId ?? (mainSponsorship as any).sponsor?.id);
const sponsor = (sponsorResult as any)?.sponsor ?? null;
if (sponsor) {
mainSponsor = {
name: sponsor.name,
logoUrl: sponsor.logoUrl ?? '',
websiteUrl: sponsor.websiteUrl ?? '',
};
if (this.sponsorsApiClient) {
try {
const seasons = await this.apiClient.getSeasons(leagueId);
const activeSeason = seasons.find((s) => s.status === 'active') ?? seasons[0];
if (activeSeason) {
const sponsorshipsDto = await this.apiClient.getSeasonSponsorships(activeSeason.seasonId);
const mainSponsorship = sponsorshipsDto.sponsorships.find((s: any) => s.tier === 'main' && s.status === 'active');
if (mainSponsorship) {
const sponsorId = (mainSponsorship as any).sponsorId ?? (mainSponsorship as any).sponsor?.id;
const sponsorResult = await this.sponsorsApiClient.getSponsor(sponsorId);
const sponsor = (sponsorResult as any)?.sponsor ?? null;
if (sponsor) {
mainSponsor = {
name: sponsor.name,
logoUrl: sponsor.logoUrl ?? '',
websiteUrl: sponsor.websiteUrl ?? '',
};
}
}
}
} catch (error) {
console.warn('Failed to load main sponsor:', error);
}
} catch (error) {
console.warn('Failed to load main sponsor:', error);
}
return new LeaguePageDetailViewModel({
@@ -232,6 +241,8 @@ export class LeagueService {
* Get comprehensive league detail page data
*/
async getLeagueDetailPageData(leagueId: string): Promise<LeagueDetailPageViewModel | null> {
if (!this.driversApiClient || !this.sponsorsApiClient) return null;
try {
// Get league basic info
const allLeagues = await this.apiClient.getAllWithCapacity();
@@ -239,15 +250,15 @@ export class LeagueService {
if (!league) return null;
// Get owner
const owner = await this.driversApiClient.getDriver(league.ownerId);
const owner = await this.driversApiClient.getDriver((league as any).ownerId);
// League scoring configuration is not exposed separately yet; use null to indicate "not configured" in the UI
const scoringConfig: LeagueScoringConfigDTO | null = null;
// Drivers list is limited to those present in memberships until a dedicated league-drivers endpoint exists
const memberships = await this.apiClient.getMemberships(leagueId);
const driverIds = memberships.members.map(m => m.driverId);
const driverDtos = await Promise.all(driverIds.map(id => this.driversApiClient.getDriver(id)));
const driverIds = memberships.members.map((m: any) => m.driverId);
const driverDtos = await Promise.all(driverIds.map((id: string) => this.driversApiClient!.getDriver(id)));
const drivers = driverDtos.filter((d: any): d is NonNullable<typeof d> => d !== null);
// Get all races for this league via the leagues API helper
@@ -284,6 +295,8 @@ export class LeagueService {
* Get sponsors for a league
*/
private async getLeagueSponsors(leagueId: string): Promise<SponsorInfo[]> {
if (!this.sponsorsApiClient) return [];
try {
const seasons = await this.apiClient.getSeasons(leagueId);
const activeSeason = seasons.find((s) => s.status === 'active') ?? seasons[0];