'use client'; import { SponsorMetricCard } from '@/components/sponsors/SponsorMetricCard'; import { SponsorshipTierBadge } from '@/components/sponsors/SponsorshipTierBadge'; import { SponsorSlotCard } from '@/components/sponsors/SponsorSlotCard'; import { Button } from '@/ui/Button'; import { Card } from '@/ui/Card'; import { Heading } from '@/ui/Heading'; import { Icon } from '@/ui/Icon'; import { InfoBox } from '@/ui/InfoBox'; import { Stack } from '@/ui/primitives/Stack'; import { Text } from '@/ui/Text'; import { Activity, Calendar, Check, Loader2, LucideIcon, MessageCircle, Shield, Target, Users, Zap } from 'lucide-react'; import { useCallback, useState } from 'react'; import { getEntityLabel, getSponsorshipTagline, getTierStyles } from './SponsorInsightsCardHelpers'; import { SponsorMetric, SponsorshipSlot } from './SponsorInsightsCardTypes'; const ICON_MAP: Record = { users: Users, zap: Zap, calendar: Calendar, activity: Activity, shield: Shield, target: Target, message: MessageCircle, }; export type EntityType = 'league' | 'race' | 'driver' | 'team'; export interface SponsorInsightsProps { entityType: EntityType; entityId: string; entityName: string; tier: 'premium' | 'standard' | 'starter'; metrics: SponsorMetric[]; slots: SponsorshipSlot[]; additionalStats?: { label: string; items: Array<{ label: string; value: string | number }>; }; trustScore?: number; discordMembers?: number; monthlyActivity?: number; ctaLabel?: string; ctaHref?: string; currentSponsorId?: string; onSponsorshipRequested?: (tier: 'main' | 'secondary') => void; onNavigate: (href: string) => void; } export function SponsorInsightsCard({ entityType, entityId, entityName, tier, metrics, slots, additionalStats, trustScore, discordMembers, monthlyActivity, ctaLabel, ctaHref, currentSponsorId, onSponsorshipRequested, onNavigate, }: SponsorInsightsProps) { const tierStyles = getTierStyles(tier); const [applyingTier, setApplyingTier] = useState<'main' | 'secondary' | null>(null); const [appliedTiers, setAppliedTiers] = useState>(new Set()); const [error, setError] = useState(null); const mainSlot = slots.find(s => s.tier === 'main'); const secondarySlots = slots.filter(s => s.tier === 'secondary'); const availableSecondary = secondarySlots.filter(s => s.available).length; const getSponsorableEntityType = useCallback((type: EntityType): 'driver' | 'team' | 'race' | 'season' => { switch (type) { case 'league': return 'season'; case 'race': return 'race'; case 'driver': return 'driver'; case 'team': return 'team'; } }, []); const handleSponsorClick = useCallback(async (slotTier: 'main' | 'secondary') => { if (!currentSponsorId) { const href = ctaHref || `/sponsor/${entityType}s/${entityId}?tier=${slotTier}`; onNavigate(href); return; } if (appliedTiers.has(slotTier)) { onNavigate(`/sponsor/dashboard`); return; } setApplyingTier(slotTier); setError(null); try { const slot = slotTier === 'main' ? mainSlot : secondarySlots[0]; const slotPrice = slot?.price ?? 0; const request = { sponsorId: currentSponsorId, entityType: getSponsorableEntityType(entityType), entityId, tier: slotTier, offeredAmount: slotPrice * 100, currency: (slot?.currency as 'USD' | 'EUR' | 'GBP') ?? 'USD', message: `Interested in sponsoring ${entityName} as ${slotTier} sponsor.`, }; console.log('Sponsorship request:', request); setAppliedTiers(prev => new Set([...prev, slotTier])); onSponsorshipRequested?.(slotTier); } catch (err) { console.error('Failed to apply for sponsorship:', err); setError(err instanceof Error ? err.message : 'Failed to submit sponsorship request'); } finally { setApplyingTier(null); } }, [currentSponsorId, ctaHref, entityType, entityId, entityName, onNavigate, mainSlot, secondarySlots, appliedTiers, getSponsorableEntityType, onSponsorshipRequested]); return ( Sponsorship Opportunity {getSponsorshipTagline(entityType)} {metrics.slice(0, 4).map((metric, index) => { const IconComponent = typeof metric.icon === 'string' ? ICON_MAP[metric.icon] || Target : metric.icon; return ( ); })} {(trustScore !== undefined || discordMembers !== undefined || monthlyActivity !== undefined) && ( {trustScore !== undefined && ( Trust Score: {trustScore}/100 )} {discordMembers !== undefined && ( Discord: {discordMembers.toLocaleString()} )} {monthlyActivity !== undefined && ( Monthly Activity: {monthlyActivity}% )} )} {mainSlot && ( handleSponsorClick('main')} disabled={applyingTier === 'main'} size="sm" > {applyingTier === 'main' ? ( Applying... ) : appliedTiers.has('main') ? ( Applied ) : ( 'Apply to Sponsor' )} } /> )} {secondarySlots.length > 0 && ( 0 ? 'text-purple-400' : 'text-gray-500'} benefits={secondarySlots[0]?.benefits.join(' • ') || 'Logo placement on page'} available={availableSecondary > 0} price={`$${secondarySlots[0]?.price.toLocaleString()}/season`} action={ } /> )} {additionalStats && ( {additionalStats.label} {additionalStats.items.map((item, index) => ( {item.label}: {typeof item.value === 'number' ? item.value.toLocaleString() : item.value} ))} )} {error && ( )} 10% platform fee applies • Logos burned on all liveries • Sponsorships are attached to seasons {appliedTiers.size > 0 && ' • Application pending review'} ); }