149 lines
5.1 KiB
TypeScript
149 lines
5.1 KiB
TypeScript
import { DashboardApiClient } from '@/lib/api/dashboard/DashboardApiClient';
|
|
import { ConsoleErrorReporter } from '@/lib/infrastructure/logging/ConsoleErrorReporter';
|
|
import { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';
|
|
import type { DashboardOverviewDTO } from '@/lib/types/generated/DashboardOverviewDTO';
|
|
import type { PageQueryResult } from '@/lib/page-queries/page-query-result/PageQueryResult';
|
|
import type { DashboardPageDto } from '@/lib/page-queries/page-dtos/DashboardPageDto';
|
|
|
|
interface ErrorWithStatusCode extends Error {
|
|
statusCode?: number;
|
|
}
|
|
|
|
/**
|
|
* Transform DashboardOverviewDTO to DashboardPageDto
|
|
* Converts Date objects to ISO strings for JSON serialization
|
|
*/
|
|
function transformDtoToPageDto(dto: DashboardOverviewDTO): DashboardPageDto {
|
|
return {
|
|
currentDriver: dto.currentDriver ? {
|
|
id: dto.currentDriver.id,
|
|
name: dto.currentDriver.name,
|
|
avatarUrl: dto.currentDriver.avatarUrl || '',
|
|
country: dto.currentDriver.country,
|
|
totalRaces: dto.currentDriver.totalRaces,
|
|
wins: dto.currentDriver.wins,
|
|
podiums: dto.currentDriver.podiums,
|
|
rating: dto.currentDriver.rating ?? 0,
|
|
globalRank: dto.currentDriver.globalRank ?? 0,
|
|
consistency: dto.currentDriver.consistency ?? 0,
|
|
} : undefined,
|
|
myUpcomingRaces: dto.myUpcomingRaces.map(race => ({
|
|
id: race.id,
|
|
track: race.track,
|
|
car: race.car,
|
|
scheduledAt: new Date(race.scheduledAt).toISOString(),
|
|
status: race.status,
|
|
isMyLeague: race.isMyLeague,
|
|
})),
|
|
otherUpcomingRaces: dto.otherUpcomingRaces.map(race => ({
|
|
id: race.id,
|
|
track: race.track,
|
|
car: race.car,
|
|
scheduledAt: new Date(race.scheduledAt).toISOString(),
|
|
status: race.status,
|
|
isMyLeague: race.isMyLeague,
|
|
})),
|
|
upcomingRaces: dto.upcomingRaces.map(race => ({
|
|
id: race.id,
|
|
track: race.track,
|
|
car: race.car,
|
|
scheduledAt: new Date(race.scheduledAt).toISOString(),
|
|
status: race.status,
|
|
isMyLeague: race.isMyLeague,
|
|
})),
|
|
activeLeaguesCount: dto.activeLeaguesCount,
|
|
nextRace: dto.nextRace ? {
|
|
id: dto.nextRace.id,
|
|
track: dto.nextRace.track,
|
|
car: dto.nextRace.car,
|
|
scheduledAt: new Date(dto.nextRace.scheduledAt).toISOString(),
|
|
status: dto.nextRace.status,
|
|
isMyLeague: dto.nextRace.isMyLeague,
|
|
} : undefined,
|
|
recentResults: dto.recentResults.map(result => ({
|
|
id: result.raceId,
|
|
track: result.raceName,
|
|
car: '', // Not in DTO, will need to handle
|
|
position: result.position,
|
|
date: new Date(result.finishedAt).toISOString(),
|
|
})),
|
|
leagueStandingsSummaries: dto.leagueStandingsSummaries.map(standing => ({
|
|
leagueId: standing.leagueId,
|
|
leagueName: standing.leagueName,
|
|
position: standing.position,
|
|
points: standing.points,
|
|
totalDrivers: standing.totalDrivers,
|
|
})),
|
|
feedSummary: {
|
|
notificationCount: dto.feedSummary.notificationCount,
|
|
items: dto.feedSummary.items.map(item => ({
|
|
id: item.id,
|
|
type: item.type,
|
|
headline: item.headline,
|
|
body: item.body,
|
|
timestamp: new Date(item.timestamp).toISOString(),
|
|
ctaHref: item.ctaHref,
|
|
ctaLabel: item.ctaLabel,
|
|
})),
|
|
},
|
|
friends: dto.friends.map(friend => ({
|
|
id: friend.id,
|
|
name: friend.name,
|
|
avatarUrl: friend.avatarUrl || '',
|
|
country: friend.country,
|
|
})),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Dashboard page query with manual wiring
|
|
* Returns PageQueryResult<DashboardPageDto>
|
|
* No DI container usage - constructs dependencies explicitly
|
|
*/
|
|
export class DashboardPageQuery {
|
|
/**
|
|
* Execute the dashboard page query
|
|
* Constructs API client manually with required dependencies
|
|
*/
|
|
static async execute(): Promise<PageQueryResult<DashboardPageDto>> {
|
|
try {
|
|
// Manual wiring: construct dependencies explicitly
|
|
const errorReporter = new ConsoleErrorReporter();
|
|
const logger = new ConsoleLogger();
|
|
|
|
// Construct API client with required dependencies
|
|
// Using environment variable for base URL, fallback to empty string
|
|
const baseUrl = process.env.NEXT_PUBLIC_API_URL || '';
|
|
const apiClient = new DashboardApiClient(baseUrl, errorReporter, logger);
|
|
|
|
// Fetch data
|
|
const dto = await apiClient.getDashboardOverview();
|
|
|
|
if (!dto) {
|
|
return { status: 'notFound' };
|
|
}
|
|
|
|
// Transform to Page DTO
|
|
const pageDto = transformDtoToPageDto(dto);
|
|
return { status: 'ok', dto: pageDto };
|
|
} catch (error) {
|
|
// Handle specific error types
|
|
if (error instanceof Error) {
|
|
const errorWithStatus = error as ErrorWithStatusCode;
|
|
|
|
if (errorWithStatus.message?.includes('not found') || errorWithStatus.statusCode === 404) {
|
|
return { status: 'notFound' };
|
|
}
|
|
|
|
// Check if it's a redirect error
|
|
if (errorWithStatus.message?.includes('redirect') || errorWithStatus.statusCode === 302) {
|
|
return { status: 'redirect', to: '/' };
|
|
}
|
|
|
|
return { status: 'error', errorId: 'DASHBOARD_FETCH_FAILED' };
|
|
}
|
|
|
|
return { status: 'error', errorId: 'UNKNOWN_ERROR' };
|
|
}
|
|
}
|
|
} |