This commit is contained in:
2025-12-10 12:38:55 +01:00
parent 0f7fe67d3c
commit fbbcf414a4
87 changed files with 11972 additions and 390 deletions

View File

@@ -30,6 +30,63 @@ export interface DemoTeamDTO {
memberCount: number;
}
/**
* Demo sponsor data for seeding
*/
export interface DemoSponsorDTO {
id: string;
name: string;
contactEmail: string;
logoUrl: string;
websiteUrl: string;
tagline: string;
}
/**
* Demo season sponsorship data
*/
export interface DemoSeasonSponsorshipDTO {
id: string;
seasonId: string;
sponsorId: string;
tier: 'main' | 'secondary';
pricingAmount: number;
pricingCurrency: 'USD' | 'EUR' | 'GBP';
status: 'pending' | 'active' | 'cancelled';
description?: string;
}
/**
* Demo sponsorship request data for seeding pending requests
*/
export interface DemoSponsorshipRequestDTO {
id: string;
sponsorId: string;
entityType: 'driver' | 'team' | 'race' | 'season';
entityId: string;
tier: 'main' | 'secondary';
offeredAmount: number;
currency: 'USD' | 'EUR' | 'GBP';
message?: string;
status: 'pending' | 'accepted' | 'rejected' | 'withdrawn';
createdAt: Date;
}
/**
* Demo sponsorship pricing configuration for entities
*/
export interface DemoSponsorshipPricingDTO {
entityType: 'driver' | 'team' | 'race' | 'season';
entityId: string;
mainSlotPrice: number;
mainSlotBenefits: string[];
secondarySlotPrice?: number;
secondarySlotBenefits?: string[];
secondaryMaxSlots?: number;
acceptingApplications: boolean;
customRequirements?: string;
}
export type RacingSeedData = {
drivers: Driver[];
leagues: League[];
@@ -40,6 +97,10 @@ export type RacingSeedData = {
friendships: Friendship[];
feedEvents: FeedItem[];
teams: DemoTeamDTO[];
sponsors: DemoSponsorDTO[];
seasonSponsorships: DemoSeasonSponsorshipDTO[];
sponsorshipRequests: DemoSponsorshipRequestDTO[];
sponsorshipPricings: DemoSponsorshipPricingDTO[];
};
const POINTS_TABLE: Record<number, number> = {
@@ -519,6 +580,316 @@ function createFeedEvents(
return sorted;
}
/**
* Demo sponsors data - realistic sim racing sponsors
*/
const DEMO_SPONSORS: DemoSponsorDTO[] = [
{
id: 'sponsor-fanatec',
name: 'Fanatec',
contactEmail: 'partnerships@fanatec.com',
logoUrl: '/images/sponsors/fanatec.svg',
websiteUrl: 'https://fanatec.com',
tagline: 'The world\'s leading sim racing hardware',
},
{
id: 'sponsor-simucube',
name: 'Simucube',
contactEmail: 'sponsors@simucube.com',
logoUrl: '/images/sponsors/simucube.svg',
websiteUrl: 'https://simucube.com',
tagline: 'Professional Direct Drive Wheels',
},
{
id: 'sponsor-heusinkveld',
name: 'Heusinkveld',
contactEmail: 'info@heusinkveld.com',
logoUrl: '/images/sponsors/heusinkveld.svg',
websiteUrl: 'https://heusinkveld.com',
tagline: 'Sim Racing Pedals & Hardware',
},
{
id: 'sponsor-trak-racer',
name: 'Trak Racer',
contactEmail: 'partnerships@trakracer.com',
logoUrl: '/images/sponsors/trak-racer.svg',
websiteUrl: 'https://trakracer.com',
tagline: 'Premium Racing Simulators & Cockpits',
},
{
id: 'sponsor-simlab',
name: 'Sim-Lab',
contactEmail: 'sponsor@sim-lab.eu',
logoUrl: '/images/sponsors/simlab.svg',
websiteUrl: 'https://sim-lab.eu',
tagline: 'Aluminum Profile Sim Racing Rigs',
},
{
id: 'sponsor-motionrig',
name: 'MotionRig Pro',
contactEmail: 'business@motionrigpro.com',
logoUrl: '/images/sponsors/motionrig.svg',
websiteUrl: 'https://motionrigpro.com',
tagline: 'Feel every turn, every bump',
},
];
/**
* Create season sponsorships linking sponsors to leagues
*/
function createSeasonSponsorships(
leagues: League[],
sponsors: DemoSponsorDTO[],
): DemoSeasonSponsorshipDTO[] {
const sponsorships: DemoSeasonSponsorshipDTO[] = [];
// GridPilot Sprint Series - sponsored by Fanatec (main) + Heusinkveld & Simucube (secondary)
const sprintLeague = leagues.find(l => l.name === 'GridPilot Sprint Series');
if (sprintLeague) {
sponsorships.push({
id: `sponsorship-${sprintLeague.id}-fanatec`,
seasonId: `season-${sprintLeague.id}-demo`,
sponsorId: 'sponsor-fanatec',
tier: 'main',
pricingAmount: 5000,
pricingCurrency: 'USD',
status: 'active',
description: 'Main sponsor for the Sprint Series - premium wheel branding',
});
sponsorships.push({
id: `sponsorship-${sprintLeague.id}-heusinkveld`,
seasonId: `season-${sprintLeague.id}-demo`,
sponsorId: 'sponsor-heusinkveld',
tier: 'secondary',
pricingAmount: 2000,
pricingCurrency: 'USD',
status: 'active',
});
sponsorships.push({
id: `sponsorship-${sprintLeague.id}-simucube`,
seasonId: `season-${sprintLeague.id}-demo`,
sponsorId: 'sponsor-simucube',
tier: 'secondary',
pricingAmount: 2000,
pricingCurrency: 'USD',
status: 'active',
});
}
// GridPilot Endurance Cup - sponsored by Trak Racer (main) + Sim-Lab (secondary)
const enduranceLeague = leagues.find(l => l.name === 'GridPilot Endurance Cup');
if (enduranceLeague) {
sponsorships.push({
id: `sponsorship-${enduranceLeague.id}-trakracer`,
seasonId: `season-${enduranceLeague.id}-demo`,
sponsorId: 'sponsor-trak-racer',
tier: 'main',
pricingAmount: 7500,
pricingCurrency: 'USD',
status: 'active',
description: 'Endurance series naming rights',
});
sponsorships.push({
id: `sponsorship-${enduranceLeague.id}-simlab`,
seasonId: `season-${enduranceLeague.id}-demo`,
sponsorId: 'sponsor-simlab',
tier: 'secondary',
pricingAmount: 3000,
pricingCurrency: 'USD',
status: 'active',
});
}
// GridPilot Club Ladder - sponsored by MotionRig Pro (main)
const clubLeague = leagues.find(l => l.name === 'GridPilot Club Ladder');
if (clubLeague) {
sponsorships.push({
id: `sponsorship-${clubLeague.id}-motionrig`,
seasonId: `season-${clubLeague.id}-demo`,
sponsorId: 'sponsor-motionrig',
tier: 'main',
pricingAmount: 3500,
pricingCurrency: 'USD',
status: 'active',
description: 'Club ladder motion platform showcase',
});
}
return sponsorships;
}
/**
* Create sponsorship pricing configurations for demo entities
*/
function createSponsorshipPricings(
leagues: League[],
teams: DemoTeamDTO[],
drivers: Driver[],
races: Race[],
): DemoSponsorshipPricingDTO[] {
const pricings: DemoSponsorshipPricingDTO[] = [];
// League/Season pricing - all leagues can accept sponsorships
leagues.forEach((league, index) => {
const basePrice = 500 + (index * 100);
pricings.push({
entityType: 'season',
entityId: `season-${league.id}-demo`,
mainSlotPrice: basePrice * 10, // Main sponsor is more expensive
mainSlotBenefits: ['Hood placement', 'League banner', 'Prominent logo', 'League page URL'],
secondarySlotPrice: basePrice * 3,
secondarySlotBenefits: ['Side logo placement', 'League page listing'],
secondaryMaxSlots: 2,
acceptingApplications: true,
});
});
// Team pricing - first 10 teams accept sponsorships
teams.slice(0, 10).forEach((team, index) => {
pricings.push({
entityType: 'team',
entityId: team.id,
mainSlotPrice: 500 + (index * 50),
mainSlotBenefits: ['Team name suffix', 'Car livery', 'All driver suits'],
secondarySlotPrice: 250 + (index * 25),
secondarySlotBenefits: ['Team page logo', 'Minor livery placement'],
secondaryMaxSlots: 2,
acceptingApplications: true,
});
});
// Driver pricing - first 20 drivers accept sponsorships
drivers.slice(0, 20).forEach((driver, index) => {
pricings.push({
entityType: 'driver',
entityId: driver.id,
mainSlotPrice: 200 + (index * 20),
mainSlotBenefits: ['Suit logo', 'Helmet branding', 'Social mentions'],
acceptingApplications: index % 3 !== 0, // Some drivers not accepting
});
});
// Race pricing - upcoming races can have title sponsors
const upcomingRaces = races.filter(r => r.status === 'scheduled').slice(0, 10);
upcomingRaces.forEach((race, index) => {
pricings.push({
entityType: 'race',
entityId: race.id,
mainSlotPrice: 300 + (index * 30),
mainSlotBenefits: ['Race title sponsor', 'Stream overlay', 'Results banner'],
acceptingApplications: true,
});
});
return pricings;
}
/**
* Create demo sponsorship requests (some pending, some accepted/rejected)
*/
function createSponsorshipRequests(
sponsors: DemoSponsorDTO[],
leagues: League[],
teams: DemoTeamDTO[],
drivers: Driver[],
races: Race[],
): DemoSponsorshipRequestDTO[] {
const requests: DemoSponsorshipRequestDTO[] = [];
const now = new Date();
// Pending request: Simucube wants to sponsor a driver
requests.push({
id: 'req-simucube-driver-1',
sponsorId: 'sponsor-simucube',
entityType: 'driver',
entityId: drivers[5].id,
tier: 'main',
offeredAmount: 25000, // $250.00 in cents
currency: 'USD',
message: 'We would love to sponsor your racing career! Simucube offers the best direct drive wheels in sim racing.',
status: 'pending',
createdAt: new Date(now.getTime() - 2 * 24 * 60 * 60 * 1000), // 2 days ago
});
// Pending request: Heusinkveld wants to sponsor a team
requests.push({
id: 'req-heusinkveld-team-1',
sponsorId: 'sponsor-heusinkveld',
entityType: 'team',
entityId: teams[2].id,
tier: 'main',
offeredAmount: 55000, // $550.00 in cents
currency: 'USD',
message: 'Heusinkveld pedals are known for their precision. We believe your team embodies the same values.',
status: 'pending',
createdAt: new Date(now.getTime() - 3 * 24 * 60 * 60 * 1000), // 3 days ago
});
// Pending request: Trak Racer wants to sponsor a race
const upcomingRace = races.find(r => r.status === 'scheduled');
if (upcomingRace) {
requests.push({
id: 'req-trakracer-race-1',
sponsorId: 'sponsor-trak-racer',
entityType: 'race',
entityId: upcomingRace.id,
tier: 'main',
offeredAmount: 35000, // $350.00 in cents
currency: 'USD',
message: 'We would like to be the title sponsor for this exciting race event!',
status: 'pending',
createdAt: new Date(now.getTime() - 1 * 24 * 60 * 60 * 1000), // 1 day ago
});
}
// Pending request: MotionRig Pro wants secondary spot on a league
const clubLeague = leagues.find(l => l.name === 'Sprint Challenge League');
if (clubLeague) {
requests.push({
id: 'req-motionrig-league-1',
sponsorId: 'sponsor-motionrig',
entityType: 'season',
entityId: `season-${clubLeague.id}-demo`,
tier: 'secondary',
offeredAmount: 150000, // $1500.00 in cents
currency: 'USD',
message: 'MotionRig Pro would love to be a secondary sponsor. Our motion platforms are perfect for your competitive drivers.',
status: 'pending',
createdAt: new Date(now.getTime() - 5 * 24 * 60 * 60 * 1000), // 5 days ago
});
}
// Already accepted request (for history)
requests.push({
id: 'req-simlab-team-accepted',
sponsorId: 'sponsor-simlab',
entityType: 'team',
entityId: teams[0].id,
tier: 'secondary',
offeredAmount: 30000,
currency: 'USD',
message: 'Sim-Lab rigs are the foundation of any competitive setup.',
status: 'accepted',
createdAt: new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000), // 30 days ago
});
// Already rejected request (for history)
requests.push({
id: 'req-motionrig-driver-rejected',
sponsorId: 'sponsor-motionrig',
entityType: 'driver',
entityId: drivers[10].id,
tier: 'main',
offeredAmount: 15000,
currency: 'USD',
message: 'Would you like to represent MotionRig Pro?',
status: 'rejected',
createdAt: new Date(now.getTime() - 20 * 24 * 60 * 60 * 1000), // 20 days ago
});
return requests;
}
export function createStaticRacingSeed(seed: number): RacingSeedData {
faker.seed(seed);
@@ -531,6 +902,10 @@ export function createStaticRacingSeed(seed: number): RacingSeedData {
const friendships = createFriendships(drivers);
const feedEvents = createFeedEvents(drivers, leagues, races, friendships);
const standings = createStandings(leagues, results);
const sponsors = DEMO_SPONSORS;
const seasonSponsorships = createSeasonSponsorships(leagues, sponsors);
const sponsorshipPricings = createSponsorshipPricings(leagues, teams, drivers, races);
const sponsorshipRequests = createSponsorshipRequests(sponsors, leagues, teams, drivers, races);
return {
drivers,
@@ -542,6 +917,10 @@ export function createStaticRacingSeed(seed: number): RacingSeedData {
friendships,
feedEvents,
teams,
sponsors,
seasonSponsorships,
sponsorshipRequests,
sponsorshipPricings,
};
}
@@ -568,6 +947,10 @@ export const teams = staticSeed.teams;
export const memberships = staticSeed.memberships;
export const friendships = staticSeed.friendships;
export const feedEvents = staticSeed.feedEvents;
export const sponsors = staticSeed.sponsors;
export const seasonSponsorships = staticSeed.seasonSponsorships;
export const sponsorshipRequests = staticSeed.sponsorshipRequests;
export const sponsorshipPricings = staticSeed.sponsorshipPricings;
/**
* Derived friend DTOs for UI consumption.