view data fixes
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { ViewData } from '@/lib/contracts/view-data/ViewData';
|
||||
import type { DashboardStats } from '@/lib/types/admin';
|
||||
import type { AdminDashboardViewData } from '@/lib/view-data/AdminDashboardViewData';
|
||||
|
||||
@@ -7,7 +8,14 @@ import type { AdminDashboardViewData } from '@/lib/view-data/AdminDashboardViewD
|
||||
* Transforms DashboardStats API DTO into AdminDashboardViewData for server-side rendering.
|
||||
* Deterministic; side-effect free; no HTTP calls.
|
||||
*/
|
||||
export class AdminDashboardViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class AdminDashboardViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return AdminDashboardViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(apiDto: DashboardStats): AdminDashboardViewData {
|
||||
return {
|
||||
stats: {
|
||||
|
||||
@@ -1,27 +1,19 @@
|
||||
import { ViewData } from '@/lib/contracts/view-data/ViewData';
|
||||
import type { UserListResponse } from '@/lib/types/admin';
|
||||
import { AdminUsersViewData } from '@/lib/view-data/AdminUsersViewData';
|
||||
|
||||
/**
|
||||
* AdminUsersViewDataBuilder
|
||||
*
|
||||
* Server-side builder that transforms API DTO
|
||||
* into ViewData for the AdminUsersTemplate.
|
||||
*
|
||||
* Deterministic, side-effect free.
|
||||
*/
|
||||
export class AdminUsersViewDataBuilder {
|
||||
static build(apiDto: UserListResponse): AdminUsersViewData {
|
||||
const users = apiDto.users.map(user => ({
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
displayName: user.displayName,
|
||||
roles: user.roles,
|
||||
status: user.status,
|
||||
isSystemAdmin: user.isSystemAdmin,
|
||||
createdAt: typeof user.createdAt === 'string' ? user.createdAt : (user.createdAt as unknown as Date).toISOString(),
|
||||
updatedAt: typeof user.updatedAt === 'string' ? user.updatedAt : (user.updatedAt as unknown as Date).toISOString(),
|
||||
lastLoginAt: user.lastLoginAt ? (typeof user.lastLoginAt === 'string' ? user.lastLoginAt : (user.lastLoginAt as unknown as Date).toISOString()) : undefined,
|
||||
primaryDriverId: user.primaryDriverId,
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class AdminUsersViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return AdminUsersViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
public static build(apiDto: UserListResponse): AdminUsersViewData {
|
||||
const users = apiDto.users.map(u => ({
|
||||
...u,
|
||||
joinedAt: new Date(u.joinedAt),
|
||||
}));
|
||||
|
||||
return {
|
||||
@@ -35,4 +27,4 @@ export class AdminUsersViewDataBuilder {
|
||||
adminCount: users.filter(u => u.isSystemAdmin).length,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { AnalyticsDashboardViewDataBuilder } from './AnalyticsDashboardViewDataBuilder';
|
||||
import { AnalyticsDashboardInputViewData } from '@/lib/view-data/AnalyticsDashboardInputViewData';
|
||||
|
||||
describe('AnalyticsDashboardViewDataBuilder', () => {
|
||||
it('builds ViewData from AnalyticsDashboardInputViewData', () => {
|
||||
const inputViewData: AnalyticsDashboardInputViewData = {
|
||||
totalUsers: 100,
|
||||
activeUsers: 40,
|
||||
totalRaces: 10,
|
||||
totalLeagues: 5,
|
||||
};
|
||||
|
||||
const viewData = AnalyticsDashboardViewDataBuilder.build(inputViewData);
|
||||
|
||||
expect(viewData.metrics.totalUsers).toBe(100);
|
||||
expect(viewData.metrics.activeUsers).toBe(40);
|
||||
expect(viewData.metrics.totalRaces).toBe(10);
|
||||
expect(viewData.metrics.totalLeagues).toBe(5);
|
||||
expect(viewData.metrics.userEngagementRate).toBeCloseTo(40);
|
||||
expect(viewData.metrics.formattedEngagementRate).toBe('40.0%');
|
||||
expect(viewData.metrics.activityLevel).toBe('Low');
|
||||
});
|
||||
|
||||
it('computes engagement rate and formatted engagement rate', () => {
|
||||
const inputViewData: AnalyticsDashboardInputViewData = {
|
||||
totalUsers: 200,
|
||||
activeUsers: 50,
|
||||
totalRaces: 0,
|
||||
totalLeagues: 0,
|
||||
};
|
||||
|
||||
const viewData = AnalyticsDashboardViewDataBuilder.build(inputViewData);
|
||||
|
||||
expect(viewData.metrics.userEngagementRate).toBeCloseTo(25);
|
||||
expect(viewData.metrics.formattedEngagementRate).toBe('25.0%');
|
||||
});
|
||||
|
||||
it('handles zero users safely', () => {
|
||||
const inputViewData: AnalyticsDashboardInputViewData = {
|
||||
totalUsers: 0,
|
||||
activeUsers: 0,
|
||||
totalRaces: 0,
|
||||
totalLeagues: 0,
|
||||
};
|
||||
|
||||
const viewData = AnalyticsDashboardViewDataBuilder.build(inputViewData);
|
||||
|
||||
expect(viewData.metrics.userEngagementRate).toBe(0);
|
||||
expect(viewData.metrics.formattedEngagementRate).toBe('0.0%');
|
||||
expect(viewData.metrics.activityLevel).toBe('Low');
|
||||
});
|
||||
|
||||
it('derives activity level buckets from engagement rate', () => {
|
||||
const low = AnalyticsDashboardViewDataBuilder.build({
|
||||
totalUsers: 100,
|
||||
activeUsers: 30,
|
||||
totalRaces: 0,
|
||||
totalLeagues: 0,
|
||||
});
|
||||
const medium = AnalyticsDashboardViewDataBuilder.build({
|
||||
totalUsers: 100,
|
||||
activeUsers: 50,
|
||||
totalRaces: 0,
|
||||
totalLeagues: 0,
|
||||
});
|
||||
const high = AnalyticsDashboardViewDataBuilder.build({
|
||||
totalUsers: 100,
|
||||
activeUsers: 90,
|
||||
totalRaces: 0,
|
||||
totalLeagues: 0,
|
||||
});
|
||||
|
||||
expect(low.metrics.activityLevel).toBe('Low');
|
||||
expect(medium.metrics.activityLevel).toBe('Medium');
|
||||
expect(high.metrics.activityLevel).toBe('High');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,34 @@
|
||||
import { AnalyticsDashboardInputViewData } from '@/lib/view-data/AnalyticsDashboardInputViewData';
|
||||
import { AnalyticsDashboardViewData } from '@/lib/view-data/AnalyticsDashboardViewData';
|
||||
|
||||
/**
|
||||
* AnalyticsDashboardViewDataBuilder
|
||||
*
|
||||
* Transforms AnalyticsDashboardInputViewData into AnalyticsDashboardViewData for server-side rendering.
|
||||
* Deterministic; side-effect free; no HTTP calls.
|
||||
*/
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class AnalyticsDashboardViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return AnalyticsDashboardViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(viewData: AnalyticsDashboardInputViewData): AnalyticsDashboardViewData {
|
||||
const userEngagementRate = viewData.totalUsers > 0 ? (viewData.activeUsers / viewData.totalUsers) * 100 : 0;
|
||||
const formattedEngagementRate = `${userEngagementRate.toFixed(1)}%`;
|
||||
const activityLevel = userEngagementRate > 70 ? 'High' : userEngagementRate > 40 ? 'Medium' : 'Low';
|
||||
|
||||
return {
|
||||
metrics: {
|
||||
totalUsers: viewData.totalUsers,
|
||||
activeUsers: viewData.activeUsers,
|
||||
totalRaces: viewData.totalRaces,
|
||||
totalLeagues: viewData.totalLeagues,
|
||||
userEngagementRate,
|
||||
formattedEngagementRate,
|
||||
activityLevel,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,14 @@
|
||||
import { MediaBinaryDTO } from '@/lib/types/MediaBinaryDTO';
|
||||
import { AvatarViewData } from '@/lib/view-data/AvatarViewData';
|
||||
|
||||
export class AvatarViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class AvatarViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return AvatarViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(apiDto: MediaBinaryDTO): AvatarViewData {
|
||||
return {
|
||||
buffer: Buffer.from(apiDto.buffer).toString('base64'),
|
||||
|
||||
@@ -8,7 +8,14 @@
|
||||
import { MediaBinaryDTO } from '@/lib/types/MediaBinaryDTO';
|
||||
import { CategoryIconViewData } from '@/lib/view-data/CategoryIconViewData';
|
||||
|
||||
export class CategoryIconViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class CategoryIconViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return CategoryIconViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(apiDto: MediaBinaryDTO): CategoryIconViewData {
|
||||
return {
|
||||
buffer: Buffer.from(apiDto.buffer).toString('base64'),
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
export interface CompleteOnboardingViewData {
|
||||
import { ViewData } from "@/lib/contracts/view-data/ViewData";
|
||||
|
||||
export interface CompleteOnboardingViewData extends ViewData {
|
||||
success: boolean;
|
||||
driverId?: string;
|
||||
errorMessage?: string;
|
||||
|
||||
@@ -6,8 +6,16 @@
|
||||
|
||||
import { CompleteOnboardingOutputDTO } from '@/lib/types/generated/CompleteOnboardingOutputDTO';
|
||||
import { CompleteOnboardingViewData } from './CompleteOnboardingViewData';
|
||||
import { ViewData } from '@/lib/contracts/view-data/ViewData';
|
||||
|
||||
export class CompleteOnboardingViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class CompleteOnboardingViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return CompleteOnboardingViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
/**
|
||||
* Transform DTO into ViewData
|
||||
*
|
||||
|
||||
@@ -6,6 +6,8 @@ import { DashboardRankDisplay } from '@/lib/display-objects/DashboardRankDisplay
|
||||
import { DashboardConsistencyDisplay } from '@/lib/display-objects/DashboardConsistencyDisplay';
|
||||
import { DashboardCountDisplay } from '@/lib/display-objects/DashboardCountDisplay';
|
||||
import { DashboardLeaguePositionDisplay } from '@/lib/display-objects/DashboardLeaguePositionDisplay';
|
||||
import { ViewData } from '@/lib/contracts/view-data/ViewData';
|
||||
import { number } from 'zod';
|
||||
|
||||
/**
|
||||
* DashboardViewDataBuilder
|
||||
@@ -13,7 +15,14 @@ import { DashboardLeaguePositionDisplay } from '@/lib/display-objects/DashboardL
|
||||
* Transforms DashboardOverviewDTO (API DTO) into DashboardViewData for server-side rendering.
|
||||
* Deterministic; side-effect free; no HTTP calls.
|
||||
*/
|
||||
export class DashboardViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class DashboardViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return DashboardViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(apiDto: DashboardOverviewDTO): DashboardViewData {
|
||||
return {
|
||||
currentDriver: {
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
import { ViewData } from "@/lib/contracts/view-data/ViewData";
|
||||
|
||||
export interface DeleteMediaViewData extends ViewData {
|
||||
success: boolean;
|
||||
error?: string;
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { DeleteMediaViewDataBuilder } from './DeleteMediaViewDataBuilder';
|
||||
import type { DeleteMediaOutputDTO } from '@/lib/types/generated/DeleteMediaOutputDTO';
|
||||
|
||||
describe('DeleteMediaViewDataBuilder', () => {
|
||||
describe('happy paths', () => {
|
||||
it('should transform successful deletion DTO to ViewData correctly', () => {
|
||||
const apiDto: DeleteMediaOutputDTO = {
|
||||
success: true,
|
||||
};
|
||||
|
||||
const result = DeleteMediaViewDataBuilder.build(apiDto);
|
||||
|
||||
expect(result).toEqual({
|
||||
success: true,
|
||||
error: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle deletion with error message', () => {
|
||||
const apiDto: DeleteMediaOutputDTO = {
|
||||
success: false,
|
||||
error: 'Failed to delete media',
|
||||
};
|
||||
|
||||
const result = DeleteMediaViewDataBuilder.build(apiDto);
|
||||
|
||||
expect(result).toEqual({
|
||||
success: false,
|
||||
error: 'Failed to delete media',
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle deletion with only success field', () => {
|
||||
const apiDto: DeleteMediaOutputDTO = {
|
||||
success: true,
|
||||
};
|
||||
|
||||
const result = DeleteMediaViewDataBuilder.build(apiDto);
|
||||
|
||||
expect(result).toEqual({
|
||||
success: true,
|
||||
error: undefined,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('data transformation', () => {
|
||||
it('should preserve all DTO fields in the output', () => {
|
||||
const apiDto: DeleteMediaOutputDTO = {
|
||||
success: false,
|
||||
error: 'Something went wrong',
|
||||
};
|
||||
|
||||
const result = DeleteMediaViewDataBuilder.build(apiDto);
|
||||
|
||||
expect(result.success).toBe(apiDto.success);
|
||||
expect(result.error).toBe(apiDto.error);
|
||||
});
|
||||
|
||||
it('should not modify the input DTO', () => {
|
||||
const apiDto: DeleteMediaOutputDTO = {
|
||||
success: false,
|
||||
error: 'Error',
|
||||
};
|
||||
|
||||
const originalDto = { ...apiDto };
|
||||
DeleteMediaViewDataBuilder.build(apiDto);
|
||||
|
||||
expect(apiDto).toEqual(originalDto);
|
||||
});
|
||||
});
|
||||
|
||||
describe('edge cases', () => {
|
||||
it('should handle false success value', () => {
|
||||
const apiDto: DeleteMediaOutputDTO = {
|
||||
success: false,
|
||||
error: 'Error occurred',
|
||||
};
|
||||
|
||||
const result = DeleteMediaViewDataBuilder.build(apiDto);
|
||||
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toBe('Error occurred');
|
||||
});
|
||||
|
||||
it('should handle empty string error message', () => {
|
||||
const apiDto: DeleteMediaOutputDTO = {
|
||||
success: false,
|
||||
error: '',
|
||||
};
|
||||
|
||||
const result = DeleteMediaViewDataBuilder.build(apiDto);
|
||||
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toBe('');
|
||||
});
|
||||
|
||||
it('should handle very long error message', () => {
|
||||
const longError = 'Error: ' + 'a'.repeat(1000);
|
||||
const apiDto: DeleteMediaOutputDTO = {
|
||||
success: false,
|
||||
error: longError,
|
||||
};
|
||||
|
||||
const result = DeleteMediaViewDataBuilder.build(apiDto);
|
||||
|
||||
expect(result.error).toBe(longError);
|
||||
});
|
||||
|
||||
it('should handle special characters in error message', () => {
|
||||
const apiDto: DeleteMediaOutputDTO = {
|
||||
success: false,
|
||||
error: 'Error: "Failed to delete media" (code: 500)',
|
||||
};
|
||||
|
||||
const result = DeleteMediaViewDataBuilder.build(apiDto);
|
||||
|
||||
expect(result.error).toBe('Error: "Failed to delete media" (code: 500)');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* DeleteMedia ViewData Builder
|
||||
*
|
||||
* Transforms media deletion result into ViewData for templates.
|
||||
*/
|
||||
|
||||
import { DeleteMediaOutputDTO } from '@/lib/types/generated/DeleteMediaOutputDTO';
|
||||
import { DeleteMediaViewData } from './DeleteMediaViewData';
|
||||
import { ViewData } from '@/lib/contracts/view-data/ViewData';
|
||||
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class DeleteMediaViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return DeleteMediaViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform DTO into ViewData
|
||||
*
|
||||
* @param apiDto - The API DTO to transform
|
||||
* @returns ViewData for templates
|
||||
*/
|
||||
static build(apiDto: DeleteMediaOutputDTO): DeleteMediaViewData {
|
||||
return {
|
||||
success: apiDto.success,
|
||||
error: apiDto.error,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { GetDriverProfileOutputDTO } from '@/lib/types/generated/GetDriverProfileOutputDTO';
|
||||
import type { DriverProfileViewData } from '@/lib/types/view-data/DriverProfileViewData';
|
||||
import type { DriverProfileViewData } from '@/lib/view-data/DriverProfileViewData';
|
||||
import { DateDisplay } from '@/lib/display-objects/DateDisplay';
|
||||
import { RatingDisplay } from '@/lib/display-objects/RatingDisplay';
|
||||
import { NumberDisplay } from '@/lib/display-objects/NumberDisplay';
|
||||
@@ -12,7 +12,14 @@ import { PercentDisplay } from '@/lib/display-objects/PercentDisplay';
|
||||
* Transforms GetDriverProfileOutputDTO into ViewData for the driver profile page.
|
||||
* Deterministic, side-effect free, no HTTP calls.
|
||||
*/
|
||||
export class DriverProfileViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class DriverProfileViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return DriverProfileViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(apiDto: GetDriverProfileOutputDTO): DriverProfileViewData {
|
||||
return {
|
||||
currentDriver: apiDto.currentDriver ? {
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
import type { DriverLeaderboardItemDTO } from '@/lib/types/generated/DriverLeaderboardItemDTO';
|
||||
import type { DriverRankingsViewData } from '@/lib/view-data/DriverRankingsViewData';
|
||||
import { WinRateDisplay } from '@/lib/display-objects/WinRateDisplay';
|
||||
import { MedalDisplay } from '@/lib/display-objects/MedalDisplay';
|
||||
import { ViewData } from '@/lib/contracts/view-data/ViewData';
|
||||
|
||||
export class DriverRankingsViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class DriverRankingsViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return DriverRankingsViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(apiDto: DriverLeaderboardItemDTO[]): DriverRankingsViewData {
|
||||
if (!apiDto || apiDto.length === 0) {
|
||||
return {
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
import type { DriversLeaderboardDTO } from '@/lib/types/generated/DriversLeaderboardDTO';
|
||||
import type { DriversViewData } from '@/lib/types/view-data/DriversViewData';
|
||||
import type { DriversViewData } from '@/lib/view-data/DriversViewData';
|
||||
import { RatingDisplay } from '@/lib/display-objects/RatingDisplay';
|
||||
import { NumberDisplay } from '@/lib/display-objects/NumberDisplay';
|
||||
|
||||
export class DriversViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class DriversViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return DriversViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(dto: DriversLeaderboardDTO): DriversViewData {
|
||||
return {
|
||||
drivers: dto.drivers.map(driver => ({
|
||||
|
||||
@@ -6,9 +6,18 @@
|
||||
*/
|
||||
|
||||
import { ForgotPasswordPageDTO } from '@/lib/services/auth/types/ForgotPasswordPageDTO';
|
||||
import { ForgotPasswordViewData } from './types/ForgotPasswordViewData';
|
||||
import { ForgotPasswordViewData } from '../../view-data/ForgotPasswordViewData';
|
||||
import { ViewData } from '@/lib/contracts/view-data/ViewData';
|
||||
import { error } from 'console';
|
||||
|
||||
export class ForgotPasswordViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class ForgotPasswordViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return ForgotPasswordViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(apiDto: ForgotPasswordPageDTO): ForgotPasswordViewData {
|
||||
return {
|
||||
returnTo: apiDto.returnTo,
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
export interface GenerateAvatarsViewData {
|
||||
import { ViewData } from "@/lib/contracts/view-data/ViewData";
|
||||
|
||||
export interface GenerateAvatarsViewData extends ViewData {
|
||||
success: boolean;
|
||||
avatarUrls: string[];
|
||||
errorMessage?: string;
|
||||
|
||||
@@ -7,8 +7,16 @@
|
||||
|
||||
import { RequestAvatarGenerationOutputDTO } from '@/lib/types/generated/RequestAvatarGenerationOutputDTO';
|
||||
import { GenerateAvatarsViewData } from './GenerateAvatarsViewData';
|
||||
import { ViewData } from '@/lib/contracts/view-data/ViewData';
|
||||
|
||||
export class GenerateAvatarsViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class GenerateAvatarsViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return GenerateAvatarsViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
/**
|
||||
* Transform DTO into ViewData
|
||||
*
|
||||
|
||||
@@ -37,7 +37,14 @@ export interface HealthDTO {
|
||||
}>;
|
||||
}
|
||||
|
||||
export class HealthViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class HealthViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return HealthViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(dto: HealthDTO): HealthViewData {
|
||||
const now = new Date();
|
||||
const lastUpdated = dto.timestamp || now.toISOString();
|
||||
|
||||
@@ -1,12 +1,20 @@
|
||||
import type { HomeViewData } from '@/templates/HomeTemplate';
|
||||
import type { HomeDataDTO } from '@/lib/types/dtos/HomeDataDTO';
|
||||
import { ViewData } from '@/lib/contracts/view-data/ViewData';
|
||||
|
||||
/**
|
||||
* HomeViewDataBuilder
|
||||
*
|
||||
* Transforms HomeDataDTO to HomeViewData.
|
||||
*/
|
||||
export class HomeViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class HomeViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return HomeViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
/**
|
||||
* Build HomeViewData from HomeDataDTO
|
||||
*
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
import { ViewData } from '@/lib/contracts/view-data/ViewData';
|
||||
import type { DriverLeaderboardItemDTO } from '@/lib/types/generated/DriverLeaderboardItemDTO';
|
||||
import type { GetTeamsLeaderboardOutputDTO } from '@/lib/types/generated/GetTeamsLeaderboardOutputDTO';
|
||||
import type { LeaderboardsViewData } from '@/lib/view-data/LeaderboardsViewData';
|
||||
|
||||
export class LeaderboardsViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class LeaderboardsViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return LeaderboardsViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(
|
||||
apiDto: { drivers: { drivers: DriverLeaderboardItemDTO[] }; teams: GetTeamsLeaderboardOutputDTO }
|
||||
): LeaderboardsViewData {
|
||||
|
||||
@@ -8,7 +8,14 @@
|
||||
import { MediaBinaryDTO } from '@/lib/types/MediaBinaryDTO';
|
||||
import { LeagueCoverViewData } from '@/lib/view-data/LeagueCoverViewData';
|
||||
|
||||
export class LeagueCoverViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class LeagueCoverViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return LeagueCoverViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(apiDto: MediaBinaryDTO): LeagueCoverViewData {
|
||||
return {
|
||||
buffer: Buffer.from(apiDto.buffer).toString('base64'),
|
||||
|
||||
@@ -11,7 +11,14 @@ import type { LeagueDetailViewData, LeagueInfoData, LiveRaceData, DriverSummaryD
|
||||
* Transforms API DTOs into LeagueDetailViewData for server-side rendering.
|
||||
* Deterministic; side-effect free; no HTTP calls.
|
||||
*/
|
||||
export class LeagueDetailViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class LeagueDetailViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return LeagueDetailViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(input: {
|
||||
league: LeagueWithCapacityAndScoringDTO;
|
||||
owner: GetDriverOutputDTO | null;
|
||||
|
||||
@@ -8,7 +8,14 @@
|
||||
import { MediaBinaryDTO } from '@/lib/types/MediaBinaryDTO';
|
||||
import { LeagueLogoViewData } from '@/lib/view-data/LeagueLogoViewData';
|
||||
|
||||
export class LeagueLogoViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class LeagueLogoViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return LeagueLogoViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(apiDto: MediaBinaryDTO): LeagueLogoViewData {
|
||||
return {
|
||||
buffer: Buffer.from(apiDto.buffer).toString('base64'),
|
||||
|
||||
@@ -9,7 +9,14 @@ import { DateDisplay } from '@/lib/display-objects/DateDisplay';
|
||||
* Transforms API DTOs into LeagueRosterAdminViewData for server-side rendering.
|
||||
* Deterministic; side-effect free; no HTTP calls.
|
||||
*/
|
||||
export class LeagueRosterAdminViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class LeagueRosterAdminViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return LeagueRosterAdminViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(input: {
|
||||
leagueId: string;
|
||||
members: LeagueRosterMemberDTO[];
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
import { LeagueScheduleViewData } from '@/lib/view-data/leagues/LeagueScheduleViewData';
|
||||
import { LeagueScheduleApiDto } from '@/lib/types/tbd/LeagueScheduleApiDto';
|
||||
|
||||
export class LeagueScheduleViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class LeagueScheduleViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return LeagueScheduleViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(apiDto: LeagueScheduleApiDto, currentDriverId?: string, isAdmin: boolean = false): LeagueScheduleViewData {
|
||||
const now = new Date();
|
||||
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
import { LeagueSettingsViewData } from '@/lib/view-data/leagues/LeagueSettingsViewData';
|
||||
import { LeagueSettingsApiDto } from '@/lib/types/tbd/LeagueSettingsApiDto';
|
||||
import { LeagueSettingsViewData } from '@/lib/view-data/LeagueSettingsViewData';
|
||||
|
||||
export class LeagueSettingsViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class LeagueSettingsViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return LeagueSettingsViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(apiDto: LeagueSettingsApiDto): LeagueSettingsViewData {
|
||||
return {
|
||||
leagueId: apiDto.leagueId,
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
import { LeagueSponsorshipsViewData } from '@/lib/view-data/leagues/LeagueSponsorshipsViewData';
|
||||
import { LeagueSponsorshipsApiDto } from '@/lib/types/tbd/LeagueSponsorshipsApiDto';
|
||||
import { DateDisplay } from '@/lib/display-objects/DateDisplay';
|
||||
import { StatusDisplay } from '@/lib/display-objects/StatusDisplay';
|
||||
import { LeagueSponsorshipsApiDto } from '@/lib/types/tbd/LeagueSponsorshipsApiDto';
|
||||
import { LeagueSponsorshipsViewData } from '@/lib/view-data/LeagueSponsorshipsViewData';
|
||||
|
||||
export class LeagueSponsorshipsViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class LeagueSponsorshipsViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return LeagueSponsorshipsViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(apiDto: LeagueSponsorshipsApiDto): LeagueSponsorshipsViewData {
|
||||
return {
|
||||
leagueId: apiDto.leagueId,
|
||||
|
||||
@@ -16,7 +16,14 @@ interface LeagueMembershipsApiDto {
|
||||
* Transforms API DTOs into LeagueStandingsViewData for server-side rendering.
|
||||
* Deterministic; side-effect free; no HTTP calls.
|
||||
*/
|
||||
export class LeagueStandingsViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class LeagueStandingsViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return LeagueStandingsViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(
|
||||
standingsDto: LeagueStandingsApiDto,
|
||||
membershipsDto: LeagueMembershipsApiDto,
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
import { LeagueWalletViewData, LeagueWalletTransactionViewData } from '@/lib/view-data/leagues/LeagueWalletViewData';
|
||||
import { LeagueWalletApiDto } from '@/lib/types/tbd/LeagueWalletApiDto';
|
||||
import { CurrencyDisplay } from '@/lib/display-objects/CurrencyDisplay';
|
||||
import { DateDisplay } from '@/lib/display-objects/DateDisplay';
|
||||
import { LeagueWalletApiDto } from '@/lib/types/tbd/LeagueWalletApiDto';
|
||||
import { LeagueWalletTransactionViewData, LeagueWalletViewData } from '@/lib/view-data/LeagueWalletViewData';
|
||||
|
||||
export class LeagueWalletViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class LeagueWalletViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return LeagueWalletViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(apiDto: LeagueWalletApiDto): LeagueWalletViewData {
|
||||
const transactions: LeagueWalletTransactionViewData[] = apiDto.transactions.map(t => ({
|
||||
...t,
|
||||
|
||||
@@ -7,7 +7,14 @@ import type { LeaguesViewData } from '@/lib/view-data/LeaguesViewData';
|
||||
* Transforms AllLeaguesWithCapacityAndScoringDTO (API DTO) into LeaguesViewData for server-side rendering.
|
||||
* Deterministic; side-effect free; no HTTP calls.
|
||||
*/
|
||||
export class LeaguesViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class LeaguesViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return LeaguesViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(apiDto: AllLeaguesWithCapacityAndScoringDTO): LeaguesViewData {
|
||||
return {
|
||||
leagues: apiDto.leagues.map((league) => ({
|
||||
|
||||
@@ -6,9 +6,18 @@
|
||||
*/
|
||||
|
||||
import { LoginPageDTO } from '@/lib/services/auth/types/LoginPageDTO';
|
||||
import { LoginViewData } from './types/LoginViewData';
|
||||
import { LoginViewData } from '../../view-data/LoginViewData';
|
||||
import { ViewData } from '@/lib/contracts/view-data/ViewData';
|
||||
import { error } from 'console';
|
||||
|
||||
export class LoginViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class LoginViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return LoginViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(apiDto: LoginPageDTO): LoginViewData {
|
||||
return {
|
||||
returnTo: apiDto.returnTo,
|
||||
|
||||
@@ -6,7 +6,14 @@
|
||||
|
||||
import { OnboardingPageViewData } from '@/lib/view-data/OnboardingPageViewData';
|
||||
|
||||
export class OnboardingPageViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class OnboardingPageViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return OnboardingPageViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
/**
|
||||
* Transform driver data into ViewData
|
||||
*
|
||||
|
||||
@@ -9,7 +9,14 @@ import { Result } from '@/lib/contracts/Result';
|
||||
import { PresentationError } from '@/lib/contracts/page-queries/PresentationError';
|
||||
import { OnboardingPageViewData } from '@/lib/view-data/OnboardingPageViewData';
|
||||
|
||||
export class OnboardingViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class OnboardingViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return OnboardingViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(apiDto: Result<{ isAlreadyOnboarded: boolean }, PresentationError>): Result<OnboardingPageViewData, PresentationError> {
|
||||
if (apiDto.isErr()) {
|
||||
return Result.err(apiDto.getError());
|
||||
|
||||
@@ -19,7 +19,14 @@ interface ProfileLeaguesPageDto {
|
||||
* ViewData Builder for Profile Leagues page
|
||||
* Transforms Page DTO to ViewData for templates
|
||||
*/
|
||||
export class ProfileLeaguesViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class ProfileLeaguesViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return ProfileLeaguesViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(apiDto: ProfileLeaguesPageDto): ProfileLeaguesViewData {
|
||||
return {
|
||||
ownedLeagues: apiDto.ownedLeagues.map((league: { leagueId: string; name: string; description: string; membershipRole: 'owner' | 'admin' | 'steward' | 'member'; }) => ({
|
||||
|
||||
@@ -8,7 +8,14 @@ import { PercentDisplay } from '@/lib/display-objects/PercentDisplay';
|
||||
import { RatingDisplay } from '@/lib/display-objects/RatingDisplay';
|
||||
import { NumberDisplay } from '@/lib/display-objects/NumberDisplay';
|
||||
|
||||
export class ProfileViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class ProfileViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return ProfileViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(apiDto: GetDriverProfileOutputDTO): ProfileViewData {
|
||||
const driver = apiDto.currentDriver;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ProtestDetailViewData } from '@/lib/view-data/leagues/ProtestDetailViewData';
|
||||
import { ProtestDetailViewData } from '@/lib/view-data/ProtestDetailViewData';
|
||||
|
||||
interface ProtestDetailApiDto {
|
||||
id: string;
|
||||
@@ -29,7 +29,14 @@ interface ProtestDetailApiDto {
|
||||
}>;
|
||||
}
|
||||
|
||||
export class ProtestDetailViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class ProtestDetailViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return ProtestDetailViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(apiDto: ProtestDetailApiDto): ProtestDetailViewData {
|
||||
return {
|
||||
protestId: apiDto.id,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { RaceDetailViewData, RaceDetailRace, RaceDetailLeague, RaceDetailEntry, RaceDetailRegistration, RaceDetailUserResult } from '@/lib/view-data/races/RaceDetailViewData';
|
||||
import { RaceDetailEntry, RaceDetailLeague, RaceDetailRace, RaceDetailRegistration, RaceDetailUserResult, RaceDetailViewData } from '@/lib/view-data/RaceDetailViewData';
|
||||
|
||||
/**
|
||||
* Race Detail View Data Builder
|
||||
@@ -6,7 +6,14 @@ import { RaceDetailViewData, RaceDetailRace, RaceDetailLeague, RaceDetailEntry,
|
||||
* Transforms API DTO into ViewData for the race detail template.
|
||||
* Deterministic, side-effect free.
|
||||
*/
|
||||
export class RaceDetailViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class RaceDetailViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return RaceDetailViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(apiDto: any): RaceDetailViewData {
|
||||
if (!apiDto || !apiDto.race) {
|
||||
return {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { RaceResultsViewData, RaceResultsResult, RaceResultsPenalty } from '@/lib/view-data/races/RaceResultsViewData';
|
||||
import { RaceResultsPenalty, RaceResultsResult, RaceResultsViewData } from '@/lib/view-data/RaceResultsViewData';
|
||||
|
||||
/**
|
||||
* Race Results View Data Builder
|
||||
@@ -6,7 +6,14 @@ import { RaceResultsViewData, RaceResultsResult, RaceResultsPenalty } from '@/li
|
||||
* Transforms API DTO into ViewData for the race results template.
|
||||
* Deterministic, side-effect free.
|
||||
*/
|
||||
export class RaceResultsViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class RaceResultsViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return RaceResultsViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(apiDto: unknown): RaceResultsViewData {
|
||||
if (!apiDto) {
|
||||
return {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { RaceStewardingViewData, Protest, Penalty, Driver } from '@/lib/view-data/races/RaceStewardingViewData';
|
||||
import { Driver, Penalty, Protest, RaceStewardingViewData } from '@/lib/view-data/RaceStewardingViewData';
|
||||
|
||||
/**
|
||||
* Race Stewarding View Data Builder
|
||||
@@ -6,7 +6,14 @@ import { RaceStewardingViewData, Protest, Penalty, Driver } from '@/lib/view-dat
|
||||
* Transforms API DTO into ViewData for the race stewarding template.
|
||||
* Deterministic, side-effect free.
|
||||
*/
|
||||
export class RaceStewardingViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class RaceStewardingViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return RaceStewardingViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(apiDto: unknown): RaceStewardingViewData {
|
||||
if (!apiDto) {
|
||||
return {
|
||||
|
||||
@@ -4,7 +4,14 @@ import { DateDisplay } from '@/lib/display-objects/DateDisplay';
|
||||
import { RaceStatusDisplay } from '@/lib/display-objects/RaceStatusDisplay';
|
||||
import { RelativeTimeDisplay } from '@/lib/display-objects/RelativeTimeDisplay';
|
||||
|
||||
export class RacesViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class RacesViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return RacesViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(apiDto: RacesPageDataDTO): RacesViewData {
|
||||
const now = new Date();
|
||||
const races = apiDto.races.map((race): RaceViewData => {
|
||||
|
||||
@@ -6,9 +6,18 @@
|
||||
*/
|
||||
|
||||
import { ResetPasswordPageDTO } from '@/lib/services/auth/types/ResetPasswordPageDTO';
|
||||
import { ResetPasswordViewData } from './types/ResetPasswordViewData';
|
||||
import { ResetPasswordViewData } from '../../view-data/ResetPasswordViewData';
|
||||
import { ViewData } from '@/lib/contracts/view-data/ViewData';
|
||||
import { error } from 'console';
|
||||
|
||||
export class ResetPasswordViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class ResetPasswordViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return ResetPasswordViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(apiDto: ResetPasswordPageDTO): ResetPasswordViewData {
|
||||
return {
|
||||
token: apiDto.token,
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
import { RulebookViewData } from '@/lib/view-data/leagues/RulebookViewData';
|
||||
import { RulebookApiDto } from '@/lib/types/tbd/RulebookApiDto';
|
||||
import { RulebookViewData } from '@/lib/view-data/RulebookViewData';
|
||||
|
||||
export class RulebookViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class RulebookViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return RulebookViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(apiDto: RulebookApiDto): RulebookViewData {
|
||||
const primaryChampionship = apiDto.scoringConfig.championships.find(c => c.type === 'driver') ?? apiDto.scoringConfig.championships[0];
|
||||
const positionPoints: { position: number; points: number }[] = primaryChampionship?.pointsPreview
|
||||
|
||||
@@ -6,9 +6,14 @@
|
||||
*/
|
||||
|
||||
import { SignupPageDTO } from '@/lib/services/auth/types/SignupPageDTO';
|
||||
import { SignupViewData } from './types/SignupViewData';
|
||||
import { SignupViewData } from '../../view-data/SignupViewData';
|
||||
import { ViewDataBuilder } from '../../contracts/builders/ViewDataBuilder';
|
||||
|
||||
export class SignupViewDataBuilder implements ViewDataBuilder<SignupPageDTO, SignupViewData> {
|
||||
build(apiDto: SignupPageDTO): SignupViewData {
|
||||
return SignupViewDataBuilder.build(apiDto);
|
||||
}
|
||||
|
||||
export class SignupViewDataBuilder {
|
||||
static build(apiDto: SignupPageDTO): SignupViewData {
|
||||
return {
|
||||
returnTo: apiDto.returnTo,
|
||||
|
||||
@@ -9,7 +9,14 @@ import { NumberDisplay } from '@/lib/display-objects/NumberDisplay';
|
||||
* Transforms SponsorDashboardDTO into ViewData for templates.
|
||||
* Deterministic and side-effect free.
|
||||
*/
|
||||
export class SponsorDashboardViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class SponsorDashboardViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return SponsorDashboardViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(apiDto: SponsorDashboardDTO): SponsorDashboardViewData {
|
||||
const totalInvestmentValue = apiDto.investment.activeSponsorships * 1000;
|
||||
|
||||
|
||||
@@ -8,7 +8,14 @@
|
||||
import { MediaBinaryDTO } from '@/lib/types/MediaBinaryDTO';
|
||||
import { SponsorLogoViewData } from '@/lib/view-data/SponsorLogoViewData';
|
||||
|
||||
export class SponsorLogoViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class SponsorLogoViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return SponsorLogoViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(apiDto: MediaBinaryDTO): SponsorLogoViewData {
|
||||
return {
|
||||
buffer: Buffer.from(apiDto.buffer).toString('base64'),
|
||||
|
||||
@@ -5,7 +5,14 @@ import type { SponsorshipRequestsViewData } from '@/lib/view-data/SponsorshipReq
|
||||
* ViewData Builder for Sponsorship Requests page
|
||||
* Transforms API DTO to ViewData for templates
|
||||
*/
|
||||
export class SponsorshipRequestsPageViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class SponsorshipRequestsPageViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return SponsorshipRequestsPageViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(apiDto: GetPendingSponsorshipRequestsOutputDTO): SponsorshipRequestsViewData {
|
||||
return {
|
||||
sections: [{
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
import type { GetPendingSponsorshipRequestsOutputDTO } from '@/lib/types/generated/GetPendingSponsorshipRequestsOutputDTO';
|
||||
import type { SponsorshipRequestsViewData } from '@/lib/view-data/SponsorshipRequestsViewData';
|
||||
|
||||
export class SponsorshipRequestsViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class SponsorshipRequestsViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return SponsorshipRequestsViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(apiDto: GetPendingSponsorshipRequestsOutputDTO): SponsorshipRequestsViewData {
|
||||
return {
|
||||
sections: [
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
import { StewardingApiDto } from '@/lib/types/tbd/StewardingApiDto';
|
||||
import { StewardingViewData } from '@/lib/view-data/leagues/StewardingViewData';
|
||||
import { StewardingViewData } from '@/lib/view-data/StewardingViewData';
|
||||
|
||||
|
||||
export class StewardingViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class StewardingViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return StewardingViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(apiDto: StewardingApiDto): StewardingViewData {
|
||||
return {
|
||||
leagueId: apiDto.leagueId,
|
||||
|
||||
@@ -9,7 +9,14 @@ import { NumberDisplay } from '@/lib/display-objects/NumberDisplay';
|
||||
* TeamDetailViewDataBuilder - Transforms TeamDetailPageDto into ViewData
|
||||
* Deterministic; side-effect free; no HTTP calls
|
||||
*/
|
||||
export class TeamDetailViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class TeamDetailViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return TeamDetailViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(apiDto: TeamDetailPageDto): TeamDetailViewData {
|
||||
const team: TeamDetailData = {
|
||||
id: apiDto.team.id,
|
||||
|
||||
@@ -8,7 +8,14 @@
|
||||
import { MediaBinaryDTO } from '@/lib/types/MediaBinaryDTO';
|
||||
import { TeamLogoViewData } from '@/lib/view-data/TeamLogoViewData';
|
||||
|
||||
export class TeamLogoViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class TeamLogoViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return TeamLogoViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(apiDto: MediaBinaryDTO): TeamLogoViewData {
|
||||
return {
|
||||
buffer: Buffer.from(apiDto.buffer).toString('base64'),
|
||||
|
||||
@@ -1,21 +1,18 @@
|
||||
import { ViewData } from '@/lib/contracts/view-data/ViewData';
|
||||
import type { GetTeamsLeaderboardOutputDTO } from '@/lib/types/generated/GetTeamsLeaderboardOutputDTO';
|
||||
import type { TeamRankingsViewData } from '@/lib/view-data/TeamRankingsViewData';
|
||||
|
||||
export class TeamRankingsViewDataBuilder {
|
||||
static build(apiDto: GetTeamsLeaderboardOutputDTO): TeamRankingsViewData {
|
||||
const allTeams = apiDto.teams.map((team, index) => ({
|
||||
id: team.id,
|
||||
name: team.name,
|
||||
tag: team.tag,
|
||||
memberCount: team.memberCount,
|
||||
category: undefined,
|
||||
totalWins: team.totalWins || 0,
|
||||
logoUrl: team.logoUrl || '',
|
||||
position: index + 1,
|
||||
isRecruiting: team.isRecruiting,
|
||||
performanceLevel: team.performanceLevel || 'N/A',
|
||||
rating: team.rating || 0,
|
||||
totalRaces: team.totalRaces || 0,
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class TeamRankingsViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return TeamRankingsViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
public static build(apiDto: GetTeamsLeaderboardOutputDTO): TeamRankingsViewData {
|
||||
const allTeams = apiDto.teams.map(t => ({
|
||||
...t,
|
||||
}));
|
||||
|
||||
return {
|
||||
|
||||
@@ -8,7 +8,14 @@ import { NumberDisplay } from '@/lib/display-objects/NumberDisplay';
|
||||
* TeamsViewDataBuilder - Transforms TeamsPageDto into ViewData for TeamsTemplate
|
||||
* Deterministic; side-effect free; no HTTP calls
|
||||
*/
|
||||
export class TeamsViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class TeamsViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return TeamsViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(apiDto: TeamsPageDto): TeamsViewData {
|
||||
const teams: TeamSummaryData[] = apiDto.teams.map((team: TeamListItemDTO): TeamSummaryData => ({
|
||||
teamId: team.id,
|
||||
|
||||
@@ -8,7 +8,14 @@
|
||||
import { MediaBinaryDTO } from '@/lib/types/MediaBinaryDTO';
|
||||
import { TrackImageViewData } from '@/lib/view-data/TrackImageViewData';
|
||||
|
||||
export class TrackImageViewDataBuilder {
|
||||
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
|
||||
|
||||
export class TrackImageViewDataBuilder implements ViewDataBuilder<any, any> {
|
||||
build(input: any): any {
|
||||
return TrackImageViewDataBuilder.build(input);
|
||||
}
|
||||
|
||||
static build(
|
||||
static build(apiDto: MediaBinaryDTO): TrackImageViewData {
|
||||
return {
|
||||
buffer: Buffer.from(apiDto.buffer).toString('base64'),
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
/**
|
||||
* Forgot Password View Data
|
||||
*
|
||||
* ViewData for the forgot password template.
|
||||
*/
|
||||
|
||||
export interface ForgotPasswordViewData {
|
||||
returnTo: string;
|
||||
showSuccess: boolean;
|
||||
successMessage?: string;
|
||||
magicLink?: string;
|
||||
formState: any; // Will be managed by client component
|
||||
isSubmitting: boolean;
|
||||
submitError?: string;
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
/**
|
||||
* Login View Data
|
||||
*
|
||||
* ViewData for the login template.
|
||||
*/
|
||||
|
||||
import { FormState } from './FormState';
|
||||
|
||||
export interface LoginViewData {
|
||||
returnTo: string;
|
||||
hasInsufficientPermissions: boolean;
|
||||
showPassword: boolean;
|
||||
showErrorDetails: boolean;
|
||||
formState: FormState;
|
||||
isSubmitting: boolean;
|
||||
submitError?: string;
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
/**
|
||||
* Reset Password View Data
|
||||
*
|
||||
* ViewData for the reset password template.
|
||||
*/
|
||||
|
||||
export interface ResetPasswordViewData {
|
||||
token: string;
|
||||
returnTo: string;
|
||||
showSuccess: boolean;
|
||||
successMessage?: string;
|
||||
formState: any; // Will be managed by client component
|
||||
isSubmitting: boolean;
|
||||
submitError?: string;
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
/**
|
||||
* Signup View Data
|
||||
*
|
||||
* ViewData for the signup template.
|
||||
*/
|
||||
|
||||
export interface SignupViewData {
|
||||
returnTo: string;
|
||||
formState: any; // Will be managed by client component
|
||||
isSubmitting: boolean;
|
||||
submitError?: string;
|
||||
}
|
||||
Reference in New Issue
Block a user