services refactor
This commit is contained in:
10
apps/website/lib/view-models/AvatarViewModel.ts
Normal file
10
apps/website/lib/view-models/AvatarViewModel.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Avatar View Model
|
||||
*
|
||||
* Represents avatar information for the UI layer
|
||||
*/
|
||||
export interface AvatarViewModel {
|
||||
driverId: string;
|
||||
avatarUrl?: string;
|
||||
hasAvatar: boolean;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Complete onboarding view model
|
||||
* UI representation of onboarding completion result
|
||||
*/
|
||||
export interface CompleteOnboardingViewModel {
|
||||
driverId: string;
|
||||
success: boolean;
|
||||
}
|
||||
9
apps/website/lib/view-models/DeleteMediaViewModel.ts
Normal file
9
apps/website/lib/view-models/DeleteMediaViewModel.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Delete Media View Model
|
||||
*
|
||||
* Represents the result of a media deletion operation
|
||||
*/
|
||||
export interface DeleteMediaViewModel {
|
||||
success: boolean;
|
||||
error?: string;
|
||||
}
|
||||
11
apps/website/lib/view-models/DriverViewModel.ts
Normal file
11
apps/website/lib/view-models/DriverViewModel.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Driver view model
|
||||
* UI representation of a driver
|
||||
*/
|
||||
export interface DriverViewModel {
|
||||
id: string;
|
||||
name: string;
|
||||
avatarUrl?: string;
|
||||
iracingId?: string;
|
||||
rating?: number;
|
||||
}
|
||||
13
apps/website/lib/view-models/MediaViewModel.ts
Normal file
13
apps/website/lib/view-models/MediaViewModel.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Media View Model
|
||||
*
|
||||
* Represents media information for the UI layer
|
||||
*/
|
||||
export interface MediaViewModel {
|
||||
id: string;
|
||||
url: string;
|
||||
type: 'image' | 'video' | 'document';
|
||||
category?: 'avatar' | 'team-logo' | 'league-cover' | 'race-result';
|
||||
uploadedAt: Date;
|
||||
size?: number;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Request Avatar Generation View Model
|
||||
*
|
||||
* Represents the result of an avatar generation request
|
||||
*/
|
||||
export interface RequestAvatarGenerationViewModel {
|
||||
success: boolean;
|
||||
avatarUrl?: string;
|
||||
error?: string;
|
||||
}
|
||||
41
apps/website/lib/view-models/SponsorDashboardViewModel.ts
Normal file
41
apps/website/lib/view-models/SponsorDashboardViewModel.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import type { SponsorDashboardDto } from '../dtos';
|
||||
|
||||
/**
|
||||
* Sponsor Dashboard View Model
|
||||
*
|
||||
* View model for sponsor dashboard data with UI-specific transformations.
|
||||
*/
|
||||
export class SponsorDashboardViewModel implements SponsorDashboardDto {
|
||||
sponsorId: string;
|
||||
sponsorName: string;
|
||||
totalSponsorships: number;
|
||||
activeSponsorships: number;
|
||||
totalInvestment: number;
|
||||
|
||||
constructor(dto: SponsorDashboardDto) {
|
||||
Object.assign(this, dto);
|
||||
}
|
||||
|
||||
/** UI-specific: Formatted total investment */
|
||||
get formattedTotalInvestment(): string {
|
||||
return `$${this.totalInvestment.toLocaleString()}`;
|
||||
}
|
||||
|
||||
/** UI-specific: Active percentage */
|
||||
get activePercentage(): number {
|
||||
if (this.totalSponsorships === 0) return 0;
|
||||
return Math.round((this.activeSponsorships / this.totalSponsorships) * 100);
|
||||
}
|
||||
|
||||
/** UI-specific: Has sponsorships */
|
||||
get hasSponsorships(): boolean {
|
||||
return this.totalSponsorships > 0;
|
||||
}
|
||||
|
||||
/** UI-specific: Status text */
|
||||
get statusText(): string {
|
||||
if (this.activeSponsorships === 0) return 'No active sponsorships';
|
||||
if (this.activeSponsorships === this.totalSponsorships) return 'All sponsorships active';
|
||||
return `${this.activeSponsorships} of ${this.totalSponsorships} active`;
|
||||
}
|
||||
}
|
||||
50
apps/website/lib/view-models/SponsorSponsorshipsViewModel.ts
Normal file
50
apps/website/lib/view-models/SponsorSponsorshipsViewModel.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import type { SponsorSponsorshipsDto } from '../dtos';
|
||||
import { SponsorshipDetailViewModel } from './SponsorshipDetailViewModel';
|
||||
|
||||
/**
|
||||
* Sponsor Sponsorships View Model
|
||||
*
|
||||
* View model for sponsor sponsorships data with UI-specific transformations.
|
||||
*/
|
||||
export class SponsorSponsorshipsViewModel {
|
||||
sponsorId: string;
|
||||
sponsorName: string;
|
||||
sponsorships: SponsorshipDetailViewModel[];
|
||||
|
||||
constructor(dto: SponsorSponsorshipsDto) {
|
||||
this.sponsorId = dto.sponsorId;
|
||||
this.sponsorName = dto.sponsorName;
|
||||
this.sponsorships = dto.sponsorships.map(s => new SponsorshipDetailViewModel(s));
|
||||
}
|
||||
|
||||
/** UI-specific: Total sponsorships count */
|
||||
get totalCount(): number {
|
||||
return this.sponsorships.length;
|
||||
}
|
||||
|
||||
/** UI-specific: Active sponsorships */
|
||||
get activeSponsorships(): SponsorshipDetailViewModel[] {
|
||||
return this.sponsorships.filter(s => s.status === 'active');
|
||||
}
|
||||
|
||||
/** UI-specific: Active count */
|
||||
get activeCount(): number {
|
||||
return this.activeSponsorships.length;
|
||||
}
|
||||
|
||||
/** UI-specific: Has sponsorships */
|
||||
get hasSponsorships(): boolean {
|
||||
return this.sponsorships.length > 0;
|
||||
}
|
||||
|
||||
/** UI-specific: Total investment */
|
||||
get totalInvestment(): number {
|
||||
return this.sponsorships.reduce((sum, s) => sum + s.amount, 0);
|
||||
}
|
||||
|
||||
/** UI-specific: Formatted total investment */
|
||||
get formattedTotalInvestment(): string {
|
||||
const firstCurrency = this.sponsorships[0]?.currency || 'USD';
|
||||
return `${firstCurrency} ${this.totalInvestment.toLocaleString()}`;
|
||||
}
|
||||
}
|
||||
44
apps/website/lib/view-models/SponsorshipPricingViewModel.ts
Normal file
44
apps/website/lib/view-models/SponsorshipPricingViewModel.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import type { GetEntitySponsorshipPricingResultDto } from '../dtos';
|
||||
|
||||
/**
|
||||
* Sponsorship Pricing View Model
|
||||
*
|
||||
* View model for sponsorship pricing data with UI-specific transformations.
|
||||
*/
|
||||
export class SponsorshipPricingViewModel {
|
||||
mainSlotPrice: number;
|
||||
secondarySlotPrice: number;
|
||||
currency: string;
|
||||
|
||||
constructor(dto: GetEntitySponsorshipPricingResultDto) {
|
||||
this.mainSlotPrice = dto.mainSlotPrice;
|
||||
this.secondarySlotPrice = dto.secondarySlotPrice;
|
||||
this.currency = dto.currency;
|
||||
}
|
||||
|
||||
/** UI-specific: Formatted main slot price */
|
||||
get formattedMainSlotPrice(): string {
|
||||
return `${this.currency} ${this.mainSlotPrice.toLocaleString()}`;
|
||||
}
|
||||
|
||||
/** UI-specific: Formatted secondary slot price */
|
||||
get formattedSecondarySlotPrice(): string {
|
||||
return `${this.currency} ${this.secondarySlotPrice.toLocaleString()}`;
|
||||
}
|
||||
|
||||
/** UI-specific: Price difference */
|
||||
get priceDifference(): number {
|
||||
return this.mainSlotPrice - this.secondarySlotPrice;
|
||||
}
|
||||
|
||||
/** UI-specific: Formatted price difference */
|
||||
get formattedPriceDifference(): string {
|
||||
return `${this.currency} ${this.priceDifference.toLocaleString()}`;
|
||||
}
|
||||
|
||||
/** UI-specific: Discount percentage for secondary slot */
|
||||
get secondaryDiscountPercentage(): number {
|
||||
if (this.mainSlotPrice === 0) return 0;
|
||||
return Math.round((1 - this.secondarySlotPrice / this.mainSlotPrice) * 100);
|
||||
}
|
||||
}
|
||||
9
apps/website/lib/view-models/UpdateAvatarViewModel.ts
Normal file
9
apps/website/lib/view-models/UpdateAvatarViewModel.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Update Avatar View Model
|
||||
*
|
||||
* Represents the result of an avatar update operation
|
||||
*/
|
||||
export interface UpdateAvatarViewModel {
|
||||
success: boolean;
|
||||
error?: string;
|
||||
}
|
||||
11
apps/website/lib/view-models/UploadMediaViewModel.ts
Normal file
11
apps/website/lib/view-models/UploadMediaViewModel.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Upload Media View Model
|
||||
*
|
||||
* Represents the result of a media upload operation
|
||||
*/
|
||||
export interface UploadMediaViewModel {
|
||||
success: boolean;
|
||||
mediaId?: string;
|
||||
url?: string;
|
||||
error?: string;
|
||||
}
|
||||
@@ -32,7 +32,10 @@ export { RaceResultsDetailViewModel } from './RaceResultsDetailViewModel';
|
||||
|
||||
// Sponsor ViewModels
|
||||
export { SponsorViewModel } from './SponsorViewModel';
|
||||
export { SponsorDashboardViewModel } from './SponsorDashboardViewModel';
|
||||
export { SponsorSponsorshipsViewModel } from './SponsorSponsorshipsViewModel';
|
||||
export { SponsorshipDetailViewModel } from './SponsorshipDetailViewModel';
|
||||
export { SponsorshipPricingViewModel } from './SponsorshipPricingViewModel';
|
||||
|
||||
// Team ViewModels
|
||||
export { TeamDetailsViewModel } from './TeamDetailsViewModel';
|
||||
|
||||
Reference in New Issue
Block a user