import type { LeagueWithCapacityAndScoringDTO } from '@/lib/types/generated/LeagueWithCapacityAndScoringDTO'; import type { LeagueMembershipsDTO } from '@/lib/types/generated/LeagueMembershipsDTO'; import type { RaceDTO } from '@/lib/types/generated/RaceDTO'; import type { GetDriverOutputDTO } from '@/lib/types/generated/GetDriverOutputDTO'; import type { LeagueScoringConfigDTO } from '@/lib/types/generated/LeagueScoringConfigDTO'; import type { LeagueDetailViewData, LeagueInfoData, LiveRaceData, DriverSummaryData, SponsorInfo } from '@/lib/view-data/LeagueDetailViewData'; /** * LeagueDetailViewDataBuilder * * Transforms API DTOs into LeagueDetailViewData for server-side rendering. * Deterministic; side-effect free; no HTTP calls. */ export class LeagueDetailViewDataBuilder { static build(input: { league: LeagueWithCapacityAndScoringDTO; owner: GetDriverOutputDTO | null; scoringConfig: LeagueScoringConfigDTO | null; memberships: LeagueMembershipsDTO; races: RaceDTO[]; sponsors: any[]; }): LeagueDetailViewData { const { league, owner, scoringConfig, memberships, races, sponsors } = input; // Calculate running races - using available fields from RaceDTO const runningRaces: LiveRaceData[] = races .filter(r => r.name.includes('Running')) // Placeholder filter .map(r => ({ id: r.id, name: r.name, date: r.date, registeredCount: 0, strengthOfField: 0, })); // Calculate info data const membersCount = Array.isArray(memberships.members) ? memberships.members.length : 0; const completedRacesCount = races.filter(r => r.name.includes('Completed')).length; // Placeholder const avgSOF = races.length > 0 ? Math.round(races.reduce((sum, r) => sum + 0, 0) / races.length) : null; const info: LeagueInfoData = { name: league.name, description: league.description || '', membersCount, racesCount: completedRacesCount, avgSOF, structure: `Solo • ${league.settings?.maxDrivers ?? 32} max`, scoring: scoringConfig?.scoringPresetId || 'Standard', createdAt: league.createdAt, discordUrl: league.socialLinks?.discordUrl, youtubeUrl: league.socialLinks?.youtubeUrl, websiteUrl: league.socialLinks?.websiteUrl, }; // Convert owner to driver summary const ownerSummary: DriverSummaryData | null = owner ? { driverId: owner.id, driverName: owner.name, avatarUrl: owner.avatarUrl || null, rating: null, rank: null, roleBadgeText: 'Owner', roleBadgeClasses: 'bg-yellow-500/10 text-yellow-500 border-yellow-500/30', profileUrl: `/drivers/${owner.id}`, } : null; // Convert sponsors const sponsorInfo: SponsorInfo[] = sponsors.map(s => ({ id: s.id, name: s.name, tier: s.tier, logoUrl: s.logoUrl, websiteUrl: s.websiteUrl, tagline: s.tagline, })); return { leagueId: league.id, name: league.name, description: league.description || '', info, runningRaces, sponsors: sponsorInfo, ownerSummary, adminSummaries: [], // Would need additional data stewardSummaries: [], // Would need additional data sponsorInsights: null, // Only for sponsor mode }; } }