import type { DashboardPageDto } from '@/lib/page-queries/DashboardPageDto'; import type { DashboardViewData } from '@/templates/DashboardViewData'; import { formatDashboardDate, formatRating, formatRank, formatConsistency, formatRaceCount, formatFriendCount, formatLeaguePosition, formatPoints, formatTotalDrivers, } from '@/lib/display-objects/DashboardDisplay'; /** * DashboardPresenter - Client-side presenter for dashboard page * Transforms Page DTO into ViewData for the template * Deterministic; no hooks; no side effects */ export class DashboardPresenter { static createViewData(pageDto: DashboardPageDto): DashboardViewData { return { currentDriver: { name: pageDto.currentDriver?.name || '', avatarUrl: pageDto.currentDriver?.avatarUrl || '', country: pageDto.currentDriver?.country || '', rating: pageDto.currentDriver ? formatRating(pageDto.currentDriver.rating) : '0.0', rank: pageDto.currentDriver ? formatRank(pageDto.currentDriver.globalRank) : '0', totalRaces: pageDto.currentDriver ? formatRaceCount(pageDto.currentDriver.totalRaces) : '0', wins: pageDto.currentDriver ? formatRaceCount(pageDto.currentDriver.wins) : '0', podiums: pageDto.currentDriver ? formatRaceCount(pageDto.currentDriver.podiums) : '0', consistency: pageDto.currentDriver ? formatConsistency(pageDto.currentDriver.consistency) : '0%', }, nextRace: pageDto.nextRace ? (() => { const dateInfo = formatDashboardDate(new Date(pageDto.nextRace.scheduledAt)); return { id: pageDto.nextRace.id, track: pageDto.nextRace.track, car: pageDto.nextRace.car, scheduledAt: pageDto.nextRace.scheduledAt, formattedDate: dateInfo.date, formattedTime: dateInfo.time, timeUntil: dateInfo.relative, isMyLeague: pageDto.nextRace.isMyLeague, }; })() : null, upcomingRaces: pageDto.upcomingRaces.map((race) => { const dateInfo = formatDashboardDate(new Date(race.scheduledAt)); return { id: race.id, track: race.track, car: race.car, scheduledAt: race.scheduledAt, formattedDate: dateInfo.date, formattedTime: dateInfo.time, timeUntil: dateInfo.relative, isMyLeague: race.isMyLeague, }; }), leagueStandings: pageDto.leagueStandingsSummaries.map((standing) => ({ leagueId: standing.leagueId, leagueName: standing.leagueName, position: formatLeaguePosition(standing.position), points: formatPoints(standing.points), totalDrivers: formatTotalDrivers(standing.totalDrivers), })), feedItems: pageDto.feedSummary.items.map((item) => ({ id: item.id, type: item.type, headline: item.headline, body: item.body, timestamp: item.timestamp, formattedTime: formatDashboardDate(new Date(item.timestamp)).relative, ctaHref: item.ctaHref, ctaLabel: item.ctaLabel, })), friends: pageDto.friends.map((friend) => ({ id: friend.id, name: friend.name, avatarUrl: friend.avatarUrl, country: friend.country, })), activeLeaguesCount: formatRaceCount(pageDto.activeLeaguesCount), friendCount: formatFriendCount(pageDto.friends.length), hasUpcomingRaces: pageDto.upcomingRaces.length > 0, hasLeagueStandings: pageDto.leagueStandingsSummaries.length > 0, hasFeedItems: pageDto.feedSummary.items.length > 0, hasFriends: pageDto.friends.length > 0, }; } }