website refactor

This commit is contained in:
2026-01-14 23:46:04 +01:00
parent c1a86348d7
commit 4a2d7d15a5
294 changed files with 5637 additions and 3418 deletions

View File

@@ -27,12 +27,7 @@ export class ProfilePageQuery implements PageQuery<ProfileViewData, void, Presen
}
const dto = profileResult.unwrap();
const output = ProfileViewDataBuilder.build(dto);
return Result.ok(output);
const viewData = ProfileViewDataBuilder.build(dto);
return Result.ok(viewData);
}
static async execute(): Promise<Result<ProfileViewData, PresentationError>> {
const query = new ProfilePageQuery();
return query.execute();
}
}
}

View File

@@ -1,39 +1,16 @@
import type { PageQueryResult } from '@/lib/contracts/page-queries/PageQueryResult';
import { Result } from '@/lib/contracts/Result';
import { PageQuery } from '@/lib/contracts/page-queries/PageQuery';
import { PresentationError, mapToPresentationError } from '@/lib/contracts/page-queries/PresentationError';
import { TeamService } from '@/lib/services/teams/TeamService';
import type { TeamSummaryViewModel } from '@/lib/view-models/TeamSummaryViewModel';
/**
* TeamsPageDto - Raw serializable data for teams page
* Contains only raw data, no derived/computed properties
*/
export interface TeamsPageDto {
teams: Array<{
id: string;
name: string;
tag: string;
memberCount: number;
description?: string;
totalWins: number;
totalRaces: number;
performanceLevel: 'beginner' | 'intermediate' | 'advanced' | 'pro';
isRecruiting: boolean;
specialization?: 'endurance' | 'sprint' | 'mixed';
region?: string;
languages: string[];
leagues: string[];
logoUrl?: string;
rating?: number;
category?: string;
}>;
}
import type { TeamsViewData } from '@/lib/view-data/TeamsViewData';
import { TeamsViewDataBuilder } from '@/lib/builders/view-data/TeamsViewDataBuilder';
/**
* TeamsPageQuery - Server-side composition for teams list page
* Manual wiring only; no ContainerManager; no PageDataFetcher
* Returns raw serializable DTO
*/
export class TeamsPageQuery {
static async execute(): Promise<PageQueryResult<TeamsPageDto>> {
export class TeamsPageQuery implements PageQuery<TeamsViewData, void> {
async execute(): Promise<Result<TeamsViewData, PresentationError>> {
try {
// Manual dependency creation
const service = new TeamService();
@@ -42,51 +19,17 @@ export class TeamsPageQuery {
const result = await service.getAllTeams();
if (result.isErr()) {
return { status: 'error', errorId: 'TEAMS_FETCH_FAILED' };
return Result.err(mapToPresentationError(result.getError()));
}
const teams = result.unwrap();
if (!teams || teams.length === 0) {
return { status: 'notFound' };
}
// Transform to ViewData using builder
const viewData = TeamsViewDataBuilder.build({ teams });
// Transform to raw serializable DTO
const dto: TeamsPageDto = {
teams: teams.map((team: TeamSummaryViewModel) => ({
id: team.id,
name: team.name,
tag: team.tag,
memberCount: team.memberCount,
description: team.description,
totalWins: team.totalWins,
totalRaces: team.totalRaces,
performanceLevel: team.performanceLevel,
isRecruiting: team.isRecruiting,
specialization: team.specialization,
region: team.region,
languages: team.languages,
leagues: team.leagues,
logoUrl: team.logoUrl,
rating: team.rating,
category: team.category,
})),
};
return { status: 'ok', dto };
return Result.ok(viewData);
} catch (error) {
// Handle specific error types
if (error instanceof Error) {
const errorAny = error as { statusCode?: number; message?: string };
if (errorAny.message?.includes('not found') || errorAny.statusCode === 404) {
return { status: 'notFound' };
}
if (errorAny.message?.includes('redirect') || errorAny.statusCode === 302) {
return { status: 'redirect', to: '/' };
}
return { status: 'error', errorId: 'TEAMS_FETCH_FAILED' };
}
return { status: 'error', errorId: 'UNKNOWN_ERROR' };
return Result.err('unknown');
}
}
}
}

View File

@@ -1,7 +1,7 @@
import { Result } from '@/lib/contracts/Result';
import { PageQuery } from '@/lib/contracts/page-queries/PageQuery';
import { PresentationError, mapToPresentationError } from '@/lib/contracts/page-queries/PresentationError';
import { RacesViewData } from '@/lib/view-data/races/RacesViewData';
import { RacesViewData } from '@/lib/view-data/RacesViewData';
import { RacesService } from '@/lib/services/races/RacesService';
import { RacesViewDataBuilder } from '@/lib/builders/view-data/RacesViewDataBuilder';
@@ -27,10 +27,4 @@ export class RacesPageQuery implements PageQuery<RacesViewData, void> {
const viewData = RacesViewDataBuilder.build(result.unwrap());
return Result.ok(viewData);
}
// Static method to avoid object construction in server code
static async execute(): Promise<Result<RacesViewData, PresentationError>> {
const query = new RacesPageQuery();
return await query.execute();
}
}
}