import type { SponsorDashboardDTO } from '../types/generated/SponsorDashboardDTO'; import { SponsorshipViewModel } from './SponsorshipViewModel'; import { ActivityItemViewModel } from './ActivityItemViewModel'; import { RenewalAlertViewModel } from './RenewalAlertViewModel'; /** * Sponsor Dashboard View Model * * View model for sponsor dashboard data with UI-specific transformations. */ export class SponsorDashboardViewModel { sponsorId: string; sponsorName: string; metrics: any; sponsorships: { leagues: SponsorshipViewModel[]; teams: SponsorshipViewModel[]; drivers: SponsorshipViewModel[]; races: SponsorshipViewModel[]; platform: SponsorshipViewModel[]; }; recentActivity: ActivityItemViewModel[]; upcomingRenewals: RenewalAlertViewModel[]; constructor(dto: SponsorDashboardDTO) { this.sponsorId = dto.sponsorId; this.sponsorName = dto.sponsorName; this.metrics = dto.metrics; this.sponsorships = { leagues: (dto.sponsorships?.leagues || []).map(s => new SponsorshipViewModel(s)), teams: (dto.sponsorships?.teams || []).map(s => new SponsorshipViewModel(s)), drivers: (dto.sponsorships?.drivers || []).map(s => new SponsorshipViewModel(s)), races: (dto.sponsorships?.races || []).map(s => new SponsorshipViewModel(s)), platform: (dto.sponsorships?.platform || []).map(s => new SponsorshipViewModel(s)), }; this.recentActivity = (dto.recentActivity || []).map(a => new ActivityItemViewModel(a)); this.upcomingRenewals = (dto.upcomingRenewals || []).map(r => new RenewalAlertViewModel(r)); } get totalSponsorships(): number { return this.sponsorships.leagues.length + this.sponsorships.teams.length + this.sponsorships.drivers.length + this.sponsorships.races.length + this.sponsorships.platform.length; } get activeSponsorships(): number { const all = [ ...this.sponsorships.leagues, ...this.sponsorships.teams, ...this.sponsorships.drivers, ...this.sponsorships.races, ...this.sponsorships.platform, ]; return all.filter(s => s.status === 'active').length; } get totalInvestment(): number { const all = [ ...this.sponsorships.leagues, ...this.sponsorships.teams, ...this.sponsorships.drivers, ...this.sponsorships.races, ...this.sponsorships.platform, ]; return all.filter(s => s.status === 'active').reduce((sum, s) => sum + s.price, 0); } get totalImpressions(): number { const all = [ ...this.sponsorships.leagues, ...this.sponsorships.teams, ...this.sponsorships.drivers, ...this.sponsorships.races, ...this.sponsorships.platform, ]; return all.reduce((sum, s) => sum + s.impressions, 0); } /** 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`; } /** UI-specific: Cost per 1K views */ get costPerThousandViews(): string { if (this.totalImpressions === 0) return '$0.00'; return `$${(this.totalInvestment / this.totalImpressions * 1000).toFixed(2)}`; } /** UI-specific: Category data for charts */ get categoryData() { return { leagues: { count: this.sponsorships.leagues.length, impressions: this.sponsorships.leagues.reduce((sum, l) => sum + l.impressions, 0), }, teams: { count: this.sponsorships.teams.length, impressions: this.sponsorships.teams.reduce((sum, t) => sum + t.impressions, 0), }, drivers: { count: this.sponsorships.drivers.length, impressions: this.sponsorships.drivers.reduce((sum, d) => sum + d.impressions, 0), }, races: { count: this.sponsorships.races.length, impressions: this.sponsorships.races.reduce((sum, r) => sum + r.impressions, 0), }, platform: { count: this.sponsorships.platform.length, impressions: this.sponsorships.platform.reduce((sum, p) => sum + p.impressions, 0), }, }; } }