75 lines
2.7 KiB
TypeScript
75 lines
2.7 KiB
TypeScript
/**
|
|
* Available Leagues View Model
|
|
*
|
|
* View model for leagues available for sponsorship.
|
|
*
|
|
* Accepts AvailableLeaguesViewData as input and produces UI-ready data.
|
|
*/
|
|
import { ViewModel } from "../contracts/view-models/ViewModel";
|
|
import { CurrencyFormatter } from "../formatters/CurrencyFormatter";
|
|
import { LeagueTierFormatter } from "../formatters/LeagueTierFormatter";
|
|
import { NumberFormatter } from "../formatters/NumberFormatter";
|
|
import { SeasonStatusFormatter } from "../formatters/SeasonStatusFormatter";
|
|
import { AvailableLeaguesViewData, AvailableLeagueViewData } from "../view-data/AvailableLeaguesViewData";
|
|
|
|
export class AvailableLeaguesViewModel extends ViewModel {
|
|
readonly leagues: AvailableLeagueViewModel[];
|
|
|
|
constructor(data: AvailableLeaguesViewData) {
|
|
super();
|
|
this.leagues = data.leagues.map(league => new AvailableLeagueViewModel(league));
|
|
}
|
|
}
|
|
|
|
export class AvailableLeagueViewModel extends ViewModel {
|
|
private readonly data: AvailableLeagueViewData;
|
|
|
|
constructor(data: AvailableLeagueViewData) {
|
|
super();
|
|
this.data = data;
|
|
}
|
|
|
|
get id(): string { return this.data.id; }
|
|
get name(): string { return this.data.name; }
|
|
get game(): string { return this.data.game; }
|
|
get drivers(): number { return this.data.drivers; }
|
|
get avgViewsPerRace(): number { return this.data.avgViewsPerRace; }
|
|
get mainSponsorSlot() { return this.data.mainSponsorSlot; }
|
|
get secondarySlots() { return this.data.secondarySlots; }
|
|
get rating(): number { return this.data.rating; }
|
|
get tier(): 'premium' | 'standard' | 'starter' { return this.data.tier; }
|
|
get nextRace(): string | undefined { return this.data.nextRace; }
|
|
get seasonStatus(): 'active' | 'upcoming' | 'completed' { return this.data.seasonStatus; }
|
|
get description(): string { return this.data.description; }
|
|
|
|
/** UI-specific: Formatted average views */
|
|
get formattedAvgViews(): string {
|
|
return NumberFormatter.formatCompact(this.avgViewsPerRace);
|
|
}
|
|
|
|
/** UI-specific: CPM calculation */
|
|
get cpm(): number {
|
|
return Math.round((this.mainSponsorSlot.price / this.avgViewsPerRace) * 1000);
|
|
}
|
|
|
|
/** UI-specific: Formatted CPM */
|
|
get formattedCpm(): string {
|
|
return CurrencyFormatter.formatCompact(this.cpm);
|
|
}
|
|
|
|
/** UI-specific: Check if any sponsor slots are available */
|
|
get hasAvailableSlots(): boolean {
|
|
return this.mainSponsorSlot.available || this.secondarySlots.available > 0;
|
|
}
|
|
|
|
/** UI-specific: Tier configuration for badge styling */
|
|
get tierConfig() {
|
|
return LeagueTierFormatter.getDisplay(this.tier);
|
|
}
|
|
|
|
/** UI-specific: Status configuration for season state */
|
|
get statusConfig() {
|
|
return SeasonStatusFormatter.getDisplay(this.seasonStatus);
|
|
}
|
|
|
|
} |