/** * Value Object: SponsorshipPricing * * Represents the sponsorship slot configuration and pricing for any sponsorable entity. * Used by drivers, teams, races, and leagues to define their sponsorship offerings. */ import { Money } from './Money'; export interface SponsorshipSlotConfig { tier: 'main' | 'secondary'; price: Money; benefits: string[]; available: boolean; maxSlots: number; // How many sponsors of this tier can exist (1 for main, 2 for secondary typically) } export interface SponsorshipPricingProps { mainSlot?: SponsorshipSlotConfig; secondarySlots?: SponsorshipSlotConfig; acceptingApplications: boolean; customRequirements?: string; } export class SponsorshipPricing { readonly mainSlot?: SponsorshipSlotConfig; readonly secondarySlots?: SponsorshipSlotConfig; readonly acceptingApplications: boolean; readonly customRequirements?: string; private constructor(props: SponsorshipPricingProps) { this.mainSlot = props.mainSlot; this.secondarySlots = props.secondarySlots; this.acceptingApplications = props.acceptingApplications; this.customRequirements = props.customRequirements; } static create(props: Partial = {}): SponsorshipPricing { return new SponsorshipPricing({ mainSlot: props.mainSlot, secondarySlots: props.secondarySlots, acceptingApplications: props.acceptingApplications ?? true, customRequirements: props.customRequirements, }); } /** * Create default pricing for a driver */ static defaultDriver(): SponsorshipPricing { return new SponsorshipPricing({ mainSlot: { tier: 'main', price: Money.create(200, 'USD'), benefits: ['Suit logo', 'Helmet branding', 'Social mentions'], available: true, maxSlots: 1, }, acceptingApplications: true, }); } /** * Create default pricing for a team */ static defaultTeam(): SponsorshipPricing { return new SponsorshipPricing({ mainSlot: { tier: 'main', price: Money.create(500, 'USD'), benefits: ['Team name suffix', 'Car livery', 'All driver suits'], available: true, maxSlots: 1, }, secondarySlots: { tier: 'secondary', price: Money.create(250, 'USD'), benefits: ['Team page logo', 'Minor livery placement'], available: true, maxSlots: 2, }, acceptingApplications: true, }); } /** * Create default pricing for a race */ static defaultRace(): SponsorshipPricing { return new SponsorshipPricing({ mainSlot: { tier: 'main', price: Money.create(300, 'USD'), benefits: ['Race title sponsor', 'Stream overlay', 'Results banner'], available: true, maxSlots: 1, }, acceptingApplications: true, }); } /** * Create default pricing for a league/season */ static defaultLeague(): SponsorshipPricing { return new SponsorshipPricing({ mainSlot: { tier: 'main', price: Money.create(800, 'USD'), benefits: ['Hood placement', 'League banner', 'Prominent logo', 'League page URL'], available: true, maxSlots: 1, }, secondarySlots: { tier: 'secondary', price: Money.create(250, 'USD'), benefits: ['Side logo placement', 'League page listing'], available: true, maxSlots: 2, }, acceptingApplications: true, }); } /** * Check if a specific tier is available */ isSlotAvailable(tier: 'main' | 'secondary'): boolean { if (tier === 'main') { return !!this.mainSlot?.available; } return !!this.secondarySlots?.available; } /** * Get price for a specific tier */ getPrice(tier: 'main' | 'secondary'): Money | null { if (tier === 'main') { return this.mainSlot?.price ?? null; } return this.secondarySlots?.price ?? null; } /** * Get benefits for a specific tier */ getBenefits(tier: 'main' | 'secondary'): string[] { if (tier === 'main') { return this.mainSlot?.benefits ?? []; } return this.secondarySlots?.benefits ?? []; } /** * Update main slot pricing */ updateMainSlot(config: Partial): SponsorshipPricing { const currentMain = this.mainSlot ?? { tier: 'main' as const, price: Money.create(0, 'USD'), benefits: [], available: true, maxSlots: 1, }; return new SponsorshipPricing({ ...this, mainSlot: { ...currentMain, ...config, tier: 'main', }, }); } /** * Update secondary slot pricing */ updateSecondarySlot(config: Partial): SponsorshipPricing { const currentSecondary = this.secondarySlots ?? { tier: 'secondary' as const, price: Money.create(0, 'USD'), benefits: [], available: true, maxSlots: 2, }; return new SponsorshipPricing({ ...this, secondarySlots: { ...currentSecondary, ...config, tier: 'secondary', }, }); } /** * Enable/disable accepting applications */ setAcceptingApplications(accepting: boolean): SponsorshipPricing { return new SponsorshipPricing({ ...this, acceptingApplications: accepting, }); } }