refactor page to use services
This commit is contained in:
192
apps/website/lib/view-models/LeagueDetailPageViewModel.ts
Normal file
192
apps/website/lib/view-models/LeagueDetailPageViewModel.ts
Normal file
@@ -0,0 +1,192 @@
|
||||
import { LeagueWithCapacityDTO } from '../types/generated/LeagueWithCapacityDTO';
|
||||
import { LeagueStatsDTO } from '../types/generated/LeagueStatsDTO';
|
||||
import { LeagueMembershipsDTO } from '../types/generated/LeagueMembershipsDTO';
|
||||
import { LeagueScheduleDTO } from '../types/generated/LeagueScheduleDTO';
|
||||
import { LeagueStandingsDTO } from '../types/generated/LeagueStandingsDTO';
|
||||
import { DriverDTO } from '../types/DriverDTO';
|
||||
import { RaceDTO } from '../types/generated/RaceDTO';
|
||||
import { LeagueScoringConfigDTO } from '../types/LeagueScoringConfigDTO';
|
||||
|
||||
// Sponsor info type
|
||||
export interface SponsorInfo {
|
||||
id: string;
|
||||
name: string;
|
||||
logoUrl?: string;
|
||||
websiteUrl?: string;
|
||||
tier: 'main' | 'secondary';
|
||||
tagline?: string;
|
||||
}
|
||||
|
||||
// Driver summary for management section
|
||||
export interface DriverSummary {
|
||||
driver: DriverDTO;
|
||||
rating: number | null;
|
||||
rank: number | null;
|
||||
}
|
||||
|
||||
// League membership with role
|
||||
export interface LeagueMembershipWithRole {
|
||||
driverId: string;
|
||||
role: 'owner' | 'admin' | 'steward' | 'member';
|
||||
status: 'active' | 'inactive';
|
||||
joinedAt: string;
|
||||
}
|
||||
|
||||
export class LeagueDetailPageViewModel {
|
||||
// League basic info
|
||||
id: string;
|
||||
name: string;
|
||||
description?: string;
|
||||
ownerId: string;
|
||||
createdAt: string;
|
||||
settings: {
|
||||
maxDrivers?: number;
|
||||
};
|
||||
socialLinks?: {
|
||||
discordUrl?: string;
|
||||
youtubeUrl?: string;
|
||||
websiteUrl?: string;
|
||||
};
|
||||
|
||||
// Owner info
|
||||
owner: DriverDTO | null;
|
||||
|
||||
// Scoring configuration
|
||||
scoringConfig: LeagueScoringConfigDTO | null;
|
||||
|
||||
// Drivers and memberships
|
||||
drivers: DriverDTO[];
|
||||
memberships: LeagueMembershipWithRole[];
|
||||
|
||||
// Races
|
||||
allRaces: RaceDTO[];
|
||||
runningRaces: RaceDTO[];
|
||||
|
||||
// Stats
|
||||
averageSOF: number | null;
|
||||
completedRacesCount: number;
|
||||
|
||||
// Sponsors
|
||||
sponsors: SponsorInfo[];
|
||||
|
||||
// Sponsor insights data
|
||||
sponsorInsights: {
|
||||
avgViewsPerRace: number;
|
||||
totalImpressions: number;
|
||||
engagementRate: string;
|
||||
estimatedReach: number;
|
||||
mainSponsorAvailable: boolean;
|
||||
secondarySlotsAvailable: number;
|
||||
mainSponsorPrice: number;
|
||||
secondaryPrice: number;
|
||||
tier: 'premium' | 'standard' | 'starter';
|
||||
trustScore: number;
|
||||
discordMembers: number;
|
||||
monthlyActivity: number;
|
||||
};
|
||||
|
||||
// Driver summaries for management
|
||||
ownerSummary: DriverSummary | null;
|
||||
adminSummaries: DriverSummary[];
|
||||
stewardSummaries: DriverSummary[];
|
||||
|
||||
constructor(
|
||||
league: LeagueWithCapacityDTO,
|
||||
owner: DriverDTO | null,
|
||||
scoringConfig: LeagueScoringConfigDTO | null,
|
||||
drivers: DriverDTO[],
|
||||
memberships: LeagueMembershipsDTO,
|
||||
allRaces: RaceDTO[],
|
||||
leagueStats: LeagueStatsDTO,
|
||||
sponsors: SponsorInfo[]
|
||||
) {
|
||||
this.id = league.id;
|
||||
this.name = league.name;
|
||||
this.description = league.description;
|
||||
this.ownerId = league.ownerId;
|
||||
this.createdAt = league.createdAt;
|
||||
this.settings = {
|
||||
maxDrivers: league.maxDrivers,
|
||||
};
|
||||
this.socialLinks = league.socialLinks;
|
||||
|
||||
this.owner = owner;
|
||||
this.scoringConfig = scoringConfig;
|
||||
this.drivers = drivers;
|
||||
this.memberships = memberships.memberships.map(m => ({
|
||||
driverId: m.driverId,
|
||||
role: m.role,
|
||||
status: m.status,
|
||||
joinedAt: m.joinedAt,
|
||||
}));
|
||||
|
||||
this.allRaces = allRaces;
|
||||
this.runningRaces = allRaces.filter(r => r.status === 'running');
|
||||
|
||||
this.averageSOF = leagueStats.averageSOF ?? null;
|
||||
this.completedRacesCount = leagueStats.completedRaces ?? 0;
|
||||
|
||||
this.sponsors = sponsors;
|
||||
|
||||
// Calculate sponsor insights
|
||||
const memberCount = this.memberships.length;
|
||||
const mainSponsorTaken = this.sponsors.some(s => s.tier === 'main');
|
||||
const secondaryTaken = this.sponsors.filter(s => s.tier === 'secondary').length;
|
||||
|
||||
this.sponsorInsights = {
|
||||
avgViewsPerRace: 5400 + memberCount * 50,
|
||||
totalImpressions: 45000 + memberCount * 500,
|
||||
engagementRate: (3.5 + (memberCount / 50)).toFixed(1),
|
||||
estimatedReach: memberCount * 150,
|
||||
mainSponsorAvailable: !mainSponsorTaken,
|
||||
secondarySlotsAvailable: Math.max(0, 2 - secondaryTaken),
|
||||
mainSponsorPrice: 800 + Math.floor(memberCount * 10),
|
||||
secondaryPrice: 250 + Math.floor(memberCount * 3),
|
||||
tier: (this.averageSOF && this.averageSOF > 3000 ? 'premium' : this.averageSOF && this.averageSOF > 2000 ? 'standard' : 'starter') as 'premium' | 'standard' | 'starter',
|
||||
trustScore: Math.min(100, 60 + memberCount + this.completedRacesCount),
|
||||
discordMembers: memberCount * 3,
|
||||
monthlyActivity: Math.min(100, 40 + this.completedRacesCount * 2),
|
||||
};
|
||||
|
||||
// Build driver summaries
|
||||
this.ownerSummary = this.buildDriverSummary(this.ownerId);
|
||||
this.adminSummaries = this.memberships
|
||||
.filter(m => m.role === 'admin')
|
||||
.slice(0, 3)
|
||||
.map(m => this.buildDriverSummary(m.driverId))
|
||||
.filter((s): s is DriverSummary => s !== null);
|
||||
this.stewardSummaries = this.memberships
|
||||
.filter(m => m.role === 'steward')
|
||||
.slice(0, 3)
|
||||
.map(m => this.buildDriverSummary(m.driverId))
|
||||
.filter((s): s is DriverSummary => s !== null);
|
||||
}
|
||||
|
||||
private buildDriverSummary(driverId: string): DriverSummary | null {
|
||||
const driver = this.drivers.find(d => d.id === driverId);
|
||||
if (!driver) return null;
|
||||
|
||||
// TODO: Get driver stats and rankings from service
|
||||
// For now, return basic info
|
||||
return {
|
||||
driver,
|
||||
rating: null, // TODO: fetch from service
|
||||
rank: null, // TODO: fetch from service
|
||||
};
|
||||
}
|
||||
|
||||
// UI helper methods
|
||||
get isSponsorMode(): boolean {
|
||||
// TODO: implement sponsor mode check
|
||||
return false;
|
||||
}
|
||||
|
||||
get currentUserMembership(): LeagueMembershipWithRole | null {
|
||||
// TODO: get current user ID and find membership
|
||||
return null;
|
||||
}
|
||||
|
||||
get canEndRaces(): boolean {
|
||||
return this.currentUserMembership?.role === 'admin' || this.currentUserMembership?.role === 'owner';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user