refactor core presenters

This commit is contained in:
2025-12-19 19:42:19 +01:00
parent 8116fe888f
commit 94fc538f44
228 changed files with 2817 additions and 3097 deletions

View File

@@ -5,14 +5,7 @@ import type { IImageServicePort } from '../ports/IImageServicePort';
import type { ISocialGraphRepository } from '@core/social/domain/repositories/ISocialGraphRepository';
import type { Driver } from '../../domain/entities/Driver';
import type { Team } from '../../domain/entities/Team';
import type {
ProfileOverviewViewModel,
ProfileOverviewDriverSummaryViewModel,
ProfileOverviewStatsViewModel,
ProfileOverviewFinishDistributionViewModel,
ProfileOverviewTeamMembershipViewModel,
ProfileOverviewSocialSummaryViewModel,
} from '../presenters/IProfileOverviewPresenter';
import type { ProfileOverviewOutputPort } from '../ports/output/ProfileOverviewOutputPort';
import { Result } from '@core/shared/application/Result';
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
@@ -51,7 +44,7 @@ export class GetProfileOverviewUseCase {
private readonly getAllDriverRankings: () => DriverRankingEntry[],
) {}
async execute(params: GetProfileOverviewParams): Promise<Result<ProfileOverviewViewModel, ApplicationErrorCode<'DRIVER_NOT_FOUND' | 'REPOSITORY_ERROR'>>> {
async execute(params: GetProfileOverviewParams): Promise<Result<ProfileOverviewOutputPort, ApplicationErrorCode<'DRIVER_NOT_FOUND' | 'REPOSITORY_ERROR'>>> {
try {
const { driverId } = params;
@@ -73,8 +66,8 @@ export class GetProfileOverviewUseCase {
const teamMemberships = await this.buildTeamMemberships(driver.id, teams as Team[]);
const socialSummary = this.buildSocialSummary(friends as Driver[]);
const viewModel: ProfileOverviewViewModel = {
currentDriver: driverSummary,
const outputPort: ProfileOverviewOutputPort = {
driver: driverSummary,
stats,
finishDistribution,
teamMemberships,
@@ -82,7 +75,7 @@ export class GetProfileOverviewUseCase {
extendedProfile: null,
};
return Result.ok(viewModel);
return Result.ok(outputPort);
} catch {
return Result.err({ code: 'REPOSITORY_ERROR', message: 'Failed to fetch profile overview' });
}
@@ -91,25 +84,25 @@ export class GetProfileOverviewUseCase {
private buildDriverSummary(
driver: Driver,
stats: ProfileDriverStatsAdapter | null,
): ProfileOverviewDriverSummaryViewModel {
): ProfileOverviewOutputPort['driver'] {
const rankings = this.getAllDriverRankings();
const fallbackRank = this.computeFallbackRank(driver.id, rankings);
const totalDrivers = rankings.length;
return {
id: driver.id,
name: driver.name,
country: driver.country,
name: driver.name.value,
country: driver.country.value,
avatarUrl: this.imageService.getDriverAvatar(driver.id),
iracingId: driver.iracingId ?? null,
iracingId: driver.iracingId?.value ?? null,
joinedAt:
driver.joinedAt instanceof Date
? driver.joinedAt.toISOString()
: new Date(driver.joinedAt).toISOString(),
? driver.joinedAt
: new Date(driver.joinedAt.value),
rating: stats?.rating ?? null,
globalRank: stats?.overallRank ?? fallbackRank,
consistency: stats?.consistency ?? null,
bio: driver.bio ?? null,
bio: driver.bio?.value ?? null,
totalDrivers,
};
}
@@ -193,8 +186,8 @@ export class GetProfileOverviewUseCase {
private async buildTeamMemberships(
driverId: string,
teams: Team[],
): Promise<ProfileOverviewTeamMembershipViewModel[]> {
const memberships: ProfileOverviewTeamMembershipViewModel[] = [];
): Promise<ProfileOverviewOutputPort['teamMemberships']> {
const memberships: ProfileOverviewOutputPort['teamMemberships'] = [];
for (const team of teams) {
const membership = await this.teamMembershipRepository.getMembership(
@@ -205,29 +198,29 @@ export class GetProfileOverviewUseCase {
memberships.push({
teamId: team.id,
teamName: team.name,
teamTag: team.tag ?? null,
teamName: team.name.value,
teamTag: team.tag?.value ?? null,
role: membership.role,
joinedAt:
membership.joinedAt instanceof Date
? membership.joinedAt.toISOString()
: new Date(membership.joinedAt).toISOString(),
? membership.joinedAt
: new Date(membership.joinedAt),
isCurrent: membership.status === 'active',
});
}
memberships.sort((a, b) => a.joinedAt.localeCompare(b.joinedAt));
memberships.sort((a, b) => a.joinedAt.getTime() - b.joinedAt.getTime());
return memberships;
}
private buildSocialSummary(friends: Driver[]): ProfileOverviewSocialSummaryViewModel {
private buildSocialSummary(friends: Driver[]): ProfileOverviewOutputPort['socialSummary'] {
return {
friendsCount: friends.length,
friends: friends.map(friend => ({
id: friend.id,
name: friend.name,
country: friend.country,
name: friend.name.value,
country: friend.country.value,
avatarUrl: this.imageService.getDriverAvatar(friend.id),
})),
};