'use client'; import React, { useState, useEffect } from 'react'; import type { DashboardViewData } from './DashboardViewData'; import type { DashboardOverviewViewModelData } from '@/lib/view-models/DashboardOverviewViewModelData'; import { DashboardOverviewViewModel } from '@/lib/view-models/DashboardOverviewViewModel'; import { DashboardTemplate } from '@/templates/DashboardTemplate'; interface DashboardPageClientProps { initialViewData: DashboardViewData; dto: DashboardOverviewViewModelData; } /** * Dashboard Page Client Component * * Two-phase render: * 1. Initial SSR: Uses ViewData built directly from DTO (no ViewModel) * 2. Post-hydration: Instantiates ViewModel and re-renders with enhanced data */ export function DashboardPageClient({ initialViewData, dto }: DashboardPageClientProps) { const [viewData, setViewData] = useState(initialViewData); useEffect(() => { // Phase 2: After hydration, instantiate ViewModel and enhance data const viewModel = new DashboardOverviewViewModel(dto); const enhancedViewData: DashboardViewData = { currentDriver: { name: viewModel.currentDriverName, avatarUrl: viewModel.currentDriverAvatarUrl, country: viewModel.currentDriverCountry, rating: viewModel.currentDriverRating, rank: viewModel.currentDriverRank, totalRaces: viewModel.currentDriverTotalRaces, wins: viewModel.currentDriverWins, podiums: viewModel.currentDriverPodiums, consistency: viewModel.currentDriverConsistency, }, nextRace: viewModel.nextRace ? { id: viewModel.nextRace.id, track: viewModel.nextRace.track, car: viewModel.nextRace.car, scheduledAt: viewModel.nextRace.scheduledAt, formattedDate: viewModel.nextRace.formattedDate, formattedTime: viewModel.nextRace.formattedTime, timeUntil: viewModel.nextRace.timeUntil, isMyLeague: viewModel.nextRace.isMyLeague, } : null, upcomingRaces: viewModel.upcomingRaces.map((race) => ({ id: race.id, track: race.track, car: race.car, scheduledAt: race.scheduledAt, formattedDate: race.formattedDate, formattedTime: race.formattedTime, timeUntil: race.timeUntil, isMyLeague: race.isMyLeague, })), leagueStandings: viewModel.leagueStandings.map((standing) => ({ leagueId: standing.leagueId, leagueName: standing.leagueName, position: standing.position, points: standing.points, totalDrivers: standing.totalDrivers, })), feedItems: viewModel.feedItems.map((item) => ({ id: item.id, type: item.type, headline: item.headline, body: item.body, timestamp: item.timestamp, formattedTime: item.formattedTime, ctaHref: item.ctaHref, ctaLabel: item.ctaLabel, })), friends: viewModel.friends.map((friend) => ({ id: friend.id, name: friend.name, avatarUrl: friend.avatarUrl, country: friend.country, })), activeLeaguesCount: viewModel.activeLeaguesCount, friendCount: viewModel.friendCount, hasUpcomingRaces: viewModel.hasUpcomingRaces, hasLeagueStandings: viewModel.hasLeagueStandings, hasFeedItems: viewModel.hasFeedItems, hasFriends: viewModel.hasFriends, }; setViewData(enhancedViewData); }, [dto]); return ; }