website refactor
This commit is contained in:
@@ -1,15 +0,0 @@
|
||||
'use client';
|
||||
|
||||
import { AdminDashboardPageDto } from '@/lib/page-queries/AdminDashboardPageQuery';
|
||||
import { AdminDashboardViewModel } from '@/lib/view-models/AdminDashboardViewModel';
|
||||
|
||||
/**
|
||||
* AdminDashboardViewModelBuilder
|
||||
*
|
||||
* Transforms AdminDashboardPageDto into AdminDashboardViewModel
|
||||
*/
|
||||
export class AdminDashboardViewModelBuilder {
|
||||
static build(dto: AdminDashboardPageDto): AdminDashboardViewModel {
|
||||
return new AdminDashboardViewModel(dto);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
import type { GetDriverProfileOutputDTO } from '@/lib/types/generated/GetDriverProfileOutputDTO';
|
||||
import type { DriverProfileDriverSummaryDTO } from '@/lib/types/generated/DriverProfileDriverSummaryDTO';
|
||||
import type { DriverProfileStatsDTO } from '@/lib/types/generated/DriverProfileStatsDTO';
|
||||
import type { DriverProfileFinishDistributionDTO } from '@/lib/types/generated/DriverProfileFinishDistributionDTO';
|
||||
import type { DriverProfileTeamMembershipDTO } from '@/lib/types/generated/DriverProfileTeamMembershipDTO';
|
||||
import type { DriverProfileSocialSummaryDTO } from '@/lib/types/generated/DriverProfileSocialSummaryDTO';
|
||||
import type { DriverProfileExtendedProfileDTO } from '@/lib/types/generated/DriverProfileExtendedProfileDTO';
|
||||
import { DriverProfileViewModel } from '@/lib/view-models/DriverProfileViewModel';
|
||||
import type {
|
||||
DriverProfileDriverSummaryViewModel,
|
||||
DriverProfileStatsViewModel,
|
||||
DriverProfileFinishDistributionViewModel,
|
||||
DriverProfileTeamMembershipViewModel,
|
||||
DriverProfileSocialSummaryViewModel,
|
||||
DriverProfileExtendedProfileViewModel,
|
||||
} from '@/lib/view-models/DriverProfileViewModel';
|
||||
|
||||
/**
|
||||
* DriverProfileViewModelBuilder
|
||||
*
|
||||
* Transforms GetDriverProfileOutputDTO into DriverProfileViewModel.
|
||||
* Deterministic, side-effect free, no HTTP calls.
|
||||
*/
|
||||
export class DriverProfileViewModelBuilder {
|
||||
/**
|
||||
* Build ViewModel from API DTO
|
||||
*
|
||||
* @param apiDto - The API transport DTO
|
||||
* @returns ViewModel ready for template
|
||||
*/
|
||||
static build(apiDto: GetDriverProfileOutputDTO): DriverProfileViewModel {
|
||||
return new DriverProfileViewModel({
|
||||
currentDriver: apiDto.currentDriver ? this.transformCurrentDriver(apiDto.currentDriver) : null,
|
||||
stats: apiDto.stats ? this.transformStats(apiDto.stats) : null,
|
||||
finishDistribution: apiDto.finishDistribution ? this.transformFinishDistribution(apiDto.finishDistribution) : null,
|
||||
teamMemberships: apiDto.teamMemberships.map(m => this.transformTeamMembership(m)),
|
||||
socialSummary: this.transformSocialSummary(apiDto.socialSummary),
|
||||
extendedProfile: apiDto.extendedProfile ? this.transformExtendedProfile(apiDto.extendedProfile) : null,
|
||||
});
|
||||
}
|
||||
|
||||
private static transformCurrentDriver(dto: DriverProfileDriverSummaryDTO): DriverProfileDriverSummaryViewModel {
|
||||
return {
|
||||
id: dto.id,
|
||||
name: dto.name,
|
||||
country: dto.country,
|
||||
avatarUrl: dto.avatarUrl || '', // Handle undefined
|
||||
iracingId: dto.iracingId || null,
|
||||
joinedAt: dto.joinedAt,
|
||||
rating: dto.rating ?? null,
|
||||
globalRank: dto.globalRank ?? null,
|
||||
consistency: dto.consistency ?? null,
|
||||
bio: dto.bio || null,
|
||||
totalDrivers: dto.totalDrivers ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
private static transformStats(dto: DriverProfileStatsDTO): DriverProfileStatsViewModel {
|
||||
return {
|
||||
totalRaces: dto.totalRaces,
|
||||
wins: dto.wins,
|
||||
podiums: dto.podiums,
|
||||
dnfs: dto.dnfs,
|
||||
avgFinish: dto.avgFinish ?? null,
|
||||
bestFinish: dto.bestFinish ?? null,
|
||||
worstFinish: dto.worstFinish ?? null,
|
||||
finishRate: dto.finishRate ?? null,
|
||||
winRate: dto.winRate ?? null,
|
||||
podiumRate: dto.podiumRate ?? null,
|
||||
percentile: dto.percentile ?? null,
|
||||
rating: dto.rating ?? null,
|
||||
consistency: dto.consistency ?? null,
|
||||
overallRank: dto.overallRank ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
private static transformFinishDistribution(dto: DriverProfileFinishDistributionDTO): DriverProfileFinishDistributionViewModel {
|
||||
return {
|
||||
totalRaces: dto.totalRaces,
|
||||
wins: dto.wins,
|
||||
podiums: dto.podiums,
|
||||
topTen: dto.topTen,
|
||||
dnfs: dto.dnfs,
|
||||
other: dto.other,
|
||||
};
|
||||
}
|
||||
|
||||
private static transformTeamMembership(dto: DriverProfileTeamMembershipDTO): DriverProfileTeamMembershipViewModel {
|
||||
return {
|
||||
teamId: dto.teamId,
|
||||
teamName: dto.teamName,
|
||||
teamTag: dto.teamTag || null,
|
||||
role: dto.role,
|
||||
joinedAt: dto.joinedAt,
|
||||
isCurrent: dto.isCurrent,
|
||||
};
|
||||
}
|
||||
|
||||
private static transformSocialSummary(dto: DriverProfileSocialSummaryDTO): DriverProfileSocialSummaryViewModel {
|
||||
return {
|
||||
friendsCount: dto.friendsCount,
|
||||
friends: dto.friends.map(f => ({
|
||||
id: f.id,
|
||||
name: f.name,
|
||||
country: f.country,
|
||||
avatarUrl: f.avatarUrl || '', // Handle undefined
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
private static transformExtendedProfile(dto: DriverProfileExtendedProfileDTO): DriverProfileExtendedProfileViewModel {
|
||||
return {
|
||||
socialHandles: dto.socialHandles.map(h => ({
|
||||
platform: h.platform as any, // Type assertion - assuming valid platform
|
||||
handle: h.handle,
|
||||
url: h.url,
|
||||
})),
|
||||
achievements: dto.achievements.map(a => ({
|
||||
id: a.id,
|
||||
title: a.title,
|
||||
description: a.description,
|
||||
icon: a.icon as any, // Type assertion - assuming valid icon
|
||||
rarity: a.rarity as any, // Type assertion - assuming valid rarity
|
||||
earnedAt: a.earnedAt,
|
||||
})),
|
||||
racingStyle: dto.racingStyle,
|
||||
favoriteTrack: dto.favoriteTrack,
|
||||
favoriteCar: dto.favoriteCar,
|
||||
timezone: dto.timezone,
|
||||
availableHours: dto.availableHours,
|
||||
lookingForTeam: dto.lookingForTeam,
|
||||
openToRequests: dto.openToRequests,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Forgot Password ViewModel Builder
|
||||
*
|
||||
* Transforms API DTOs into ForgotPasswordViewModel for client-side state management.
|
||||
* Deterministic, side-effect free, no business logic.
|
||||
*/
|
||||
|
||||
import { ForgotPasswordViewData } from '@/lib/builders/view-data/ForgotPasswordViewDataBuilder';
|
||||
import { ForgotPasswordViewModel, ForgotPasswordFormState } from '@/lib/view-models/auth/ForgotPasswordViewModel';
|
||||
|
||||
export class ForgotPasswordViewModelBuilder {
|
||||
static build(viewData: ForgotPasswordViewData): ForgotPasswordViewModel {
|
||||
const formState: ForgotPasswordFormState = {
|
||||
fields: {
|
||||
email: { value: '', error: undefined, touched: false, validating: false },
|
||||
},
|
||||
isValid: true,
|
||||
isSubmitting: false,
|
||||
submitError: undefined,
|
||||
submitCount: 0,
|
||||
};
|
||||
|
||||
return new ForgotPasswordViewModel(
|
||||
viewData.returnTo,
|
||||
formState,
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
false,
|
||||
null
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Login ViewModel Builder
|
||||
*
|
||||
* Transforms API DTOs into LoginViewModel for client-side state management.
|
||||
* Deterministic, side-effect free, no business logic.
|
||||
*/
|
||||
|
||||
import { LoginViewData } from '@/lib/builders/view-data/LoginViewDataBuilder';
|
||||
import { LoginViewModel, LoginFormState, LoginUIState } from '@/lib/view-models/auth/LoginViewModel';
|
||||
|
||||
export class LoginViewModelBuilder {
|
||||
static build(viewData: LoginViewData): LoginViewModel {
|
||||
const formState: LoginFormState = {
|
||||
fields: {
|
||||
email: { value: '', error: undefined, touched: false, validating: false },
|
||||
password: { value: '', error: undefined, touched: false, validating: false },
|
||||
rememberMe: { value: false, error: undefined, touched: false, validating: false },
|
||||
},
|
||||
isValid: true,
|
||||
isSubmitting: false,
|
||||
submitError: undefined,
|
||||
submitCount: 0,
|
||||
};
|
||||
|
||||
const uiState: LoginUIState = {
|
||||
showPassword: false,
|
||||
showErrorDetails: false,
|
||||
};
|
||||
|
||||
return new LoginViewModel(
|
||||
viewData.returnTo,
|
||||
viewData.hasInsufficientPermissions,
|
||||
formState,
|
||||
uiState,
|
||||
false,
|
||||
null
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Onboarding ViewModel Builder
|
||||
*
|
||||
* Transforms API DTOs into ViewModels for client-side state management.
|
||||
* Deterministic, side-effect free.
|
||||
*/
|
||||
|
||||
import { Result } from '@/lib/contracts/Result';
|
||||
import { DomainError } from '@/lib/contracts/services/Service';
|
||||
import { OnboardingViewModel } from '@/lib/view-models/OnboardingViewModel';
|
||||
|
||||
export class OnboardingViewModelBuilder {
|
||||
static build(apiDto: { isAlreadyOnboarded: boolean }): Result<OnboardingViewModel, DomainError> {
|
||||
try {
|
||||
return Result.ok({
|
||||
isAlreadyOnboarded: apiDto.isAlreadyOnboarded || false,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : 'Failed to build ViewModel';
|
||||
return Result.err({ type: 'unknown', message: errorMessage });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Reset Password ViewModel Builder
|
||||
*
|
||||
* Transforms API DTOs into ResetPasswordViewModel for client-side state management.
|
||||
* Deterministic, side-effect free, no business logic.
|
||||
*/
|
||||
|
||||
import { ResetPasswordViewData } from '@/lib/builders/view-data/ResetPasswordViewDataBuilder';
|
||||
import { ResetPasswordViewModel, ResetPasswordFormState, ResetPasswordUIState } from '@/lib/view-models/auth/ResetPasswordViewModel';
|
||||
|
||||
export class ResetPasswordViewModelBuilder {
|
||||
static build(viewData: ResetPasswordViewData): ResetPasswordViewModel {
|
||||
const formState: ResetPasswordFormState = {
|
||||
fields: {
|
||||
newPassword: { value: '', error: undefined, touched: false, validating: false },
|
||||
confirmPassword: { value: '', error: undefined, touched: false, validating: false },
|
||||
},
|
||||
isValid: true,
|
||||
isSubmitting: false,
|
||||
submitError: undefined,
|
||||
submitCount: 0,
|
||||
};
|
||||
|
||||
const uiState: ResetPasswordUIState = {
|
||||
showPassword: false,
|
||||
showConfirmPassword: false,
|
||||
};
|
||||
|
||||
return new ResetPasswordViewModel(
|
||||
viewData.token,
|
||||
viewData.returnTo,
|
||||
formState,
|
||||
uiState,
|
||||
false,
|
||||
null,
|
||||
false,
|
||||
null
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Signup ViewModel Builder
|
||||
*
|
||||
* Transforms API DTOs into SignupViewModel for client-side state management.
|
||||
* Deterministic, side-effect free, no business logic.
|
||||
*/
|
||||
|
||||
import { SignupViewData } from '@/lib/builders/view-data/SignupViewDataBuilder';
|
||||
import { SignupViewModel, SignupFormState, SignupUIState } from '@/lib/view-models/auth/SignupViewModel';
|
||||
|
||||
export class SignupViewModelBuilder {
|
||||
static build(viewData: SignupViewData): SignupViewModel {
|
||||
const formState: SignupFormState = {
|
||||
fields: {
|
||||
firstName: { value: '', error: undefined, touched: false, validating: false },
|
||||
lastName: { value: '', error: undefined, touched: false, validating: false },
|
||||
email: { value: '', error: undefined, touched: false, validating: false },
|
||||
password: { value: '', error: undefined, touched: false, validating: false },
|
||||
confirmPassword: { value: '', error: undefined, touched: false, validating: false },
|
||||
},
|
||||
isValid: true,
|
||||
isSubmitting: false,
|
||||
submitError: undefined,
|
||||
submitCount: 0,
|
||||
};
|
||||
|
||||
const uiState: SignupUIState = {
|
||||
showPassword: false,
|
||||
showConfirmPassword: false,
|
||||
};
|
||||
|
||||
return new SignupViewModel(
|
||||
viewData.returnTo,
|
||||
formState,
|
||||
uiState,
|
||||
false,
|
||||
null
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user