Files
gridpilot.gg/apps/website/lib/view-models/DashboardOverviewViewModel.ts
2026-01-11 13:04:33 +01:00

198 lines
5.1 KiB
TypeScript

import type { DashboardOverviewViewModelData } from './DashboardOverviewViewModelData';
import {
dashboardStatDisplay,
formatDashboardDate,
formatRating,
formatRank,
formatConsistency,
formatRaceCount,
formatFriendCount,
formatLeaguePosition,
formatPoints,
formatTotalDrivers,
} from '@/lib/display-objects/DashboardDisplay';
/**
* Dashboard Overview ViewModel
*
* Clean class that accepts DTO only and exposes derived values.
* This is client-only and instantiated after hydration.
*/
export class DashboardOverviewViewModel {
constructor(private readonly dto: DashboardOverviewViewModelData) {}
// Current Driver - Derived Values
get currentDriverName(): string {
return this.dto.currentDriver?.name || '';
}
get currentDriverAvatarUrl(): string {
return this.dto.currentDriver?.avatarUrl || '';
}
get currentDriverCountry(): string {
return this.dto.currentDriver?.country || '';
}
get currentDriverRating(): string {
return this.dto.currentDriver ? formatRating(this.dto.currentDriver.rating) : '0.0';
}
get currentDriverRank(): string {
return this.dto.currentDriver ? formatRank(this.dto.currentDriver.globalRank) : '0';
}
get currentDriverTotalRaces(): string {
return this.dto.currentDriver ? formatRaceCount(this.dto.currentDriver.totalRaces) : '0';
}
get currentDriverWins(): string {
return this.dto.currentDriver ? formatRaceCount(this.dto.currentDriver.wins) : '0';
}
get currentDriverPodiums(): string {
return this.dto.currentDriver ? formatRaceCount(this.dto.currentDriver.podiums) : '0';
}
get currentDriverConsistency(): string {
return this.dto.currentDriver ? formatConsistency(this.dto.currentDriver.consistency) : '0%';
}
// Next Race - Derived Values
get nextRace(): {
id: string;
track: string;
car: string;
scheduledAt: string;
status: string;
isMyLeague: boolean;
formattedDate: string;
formattedTime: string;
timeUntil: string;
} | null {
if (!this.dto.nextRace) return null;
const dateInfo = formatDashboardDate(new Date(this.dto.nextRace.scheduledAt));
return {
id: this.dto.nextRace.id,
track: this.dto.nextRace.track,
car: this.dto.nextRace.car,
scheduledAt: this.dto.nextRace.scheduledAt,
status: this.dto.nextRace.status,
isMyLeague: this.dto.nextRace.isMyLeague,
formattedDate: dateInfo.date,
formattedTime: dateInfo.time,
timeUntil: dateInfo.relative,
};
}
// Upcoming Races - Derived Values
get upcomingRaces(): Array<{
id: string;
track: string;
car: string;
scheduledAt: string;
status: string;
isMyLeague: boolean;
formattedDate: string;
formattedTime: string;
timeUntil: string;
}> {
return this.dto.upcomingRaces.map((race) => {
const dateInfo = formatDashboardDate(new Date(race.scheduledAt));
return {
id: race.id,
track: race.track,
car: race.car,
scheduledAt: race.scheduledAt,
status: race.status,
isMyLeague: race.isMyLeague,
formattedDate: dateInfo.date,
formattedTime: dateInfo.time,
timeUntil: dateInfo.relative,
};
});
}
// League Standings - Derived Values
get leagueStandings(): Array<{
leagueId: string;
leagueName: string;
position: string;
points: string;
totalDrivers: string;
}> {
return this.dto.leagueStandingsSummaries.map((standing) => ({
leagueId: standing.leagueId,
leagueName: standing.leagueName,
position: formatLeaguePosition(standing.position),
points: formatPoints(standing.points),
totalDrivers: formatTotalDrivers(standing.totalDrivers),
}));
}
// Feed Items - Derived Values
get feedItems(): Array<{
id: string;
type: string;
headline: string;
body?: string;
timestamp: string;
ctaHref?: string;
ctaLabel?: string;
formattedTime: string;
}> {
return this.dto.feedSummary.items.map((item) => ({
id: item.id,
type: item.type,
headline: item.headline,
body: item.body,
timestamp: item.timestamp,
ctaHref: item.ctaHref,
ctaLabel: item.ctaLabel,
formattedTime: formatDashboardDate(new Date(item.timestamp)).relative,
}));
}
// Friends - Derived Values
get friends(): Array<{
id: string;
name: string;
avatarUrl: string;
country: string;
}> {
// No additional formatting needed for friends
return this.dto.friends;
}
// Active Leagues Count
get activeLeaguesCount(): string {
return formatRaceCount(this.dto.activeLeaguesCount);
}
// Convenience getters for display
get hasNextRace(): boolean {
return this.dto.nextRace !== undefined;
}
get hasUpcomingRaces(): boolean {
return this.dto.upcomingRaces.length > 0;
}
get hasLeagueStandings(): boolean {
return this.dto.leagueStandingsSummaries.length > 0;
}
get hasFeedItems(): boolean {
return this.dto.feedSummary.items.length > 0;
}
get hasFriends(): boolean {
return this.dto.friends.length > 0;
}
get friendCount(): string {
return formatFriendCount(this.dto.friends.length);
}
}