'use client'; import { Badge } from '@/ui/Badge'; import { Button } from '@/ui/Button'; import { Heading } from '@/ui/Heading'; import { Icon } from '@/ui/Icon'; import { Input } from '@/ui/Input'; import { Stack } from '@/ui/Stack'; import { StatBox } from '@/ui/StatBox'; import { Text } from '@/ui/Text'; import { Award, DollarSign, Star, X } from 'lucide-react'; import { useState } from 'react'; import { PendingSponsorshipRequests } from '../sponsors/PendingSponsorshipRequests'; import { useLeagueSeasons } from "@/hooks/league/useLeagueSeasons"; import { useSponsorshipRequests } from "@/hooks/league/useSponsorshipRequests"; import { useEffectiveDriverId } from "@/hooks/useEffectiveDriverId"; import { useInject } from '@/lib/di/hooks/useInject'; import { SPONSOR_SERVICE_TOKEN } from '@/lib/di/tokens'; interface SponsorshipSlot { tier: 'main' | 'secondary'; sponsorName?: string; logoUrl?: string; price: number; isOccupied: boolean; } interface LeagueSponsorshipsSectionProps { leagueId: string; seasonId?: string; readOnly?: boolean; } export function LeagueSponsorshipsSection({ leagueId, seasonId: propSeasonId, readOnly = false }: LeagueSponsorshipsSectionProps) { const currentDriverId = useEffectiveDriverId(); const sponsorshipService = useInject(SPONSOR_SERVICE_TOKEN); const [slots, setSlots] = useState([ { tier: 'main', price: 500, isOccupied: false }, { tier: 'secondary', price: 200, isOccupied: false }, { tier: 'secondary', price: 200, isOccupied: false }, ]); const [editingIndex, setEditingIndex] = useState(null); const [tempPrice, setTempPrice] = useState(''); // Load season ID if not provided const { data: seasonsResult } = useLeagueSeasons(leagueId); const seasons = seasonsResult?.isOk() ? seasonsResult.unwrap() : []; const activeSeason = seasons.find((s: any) => s.status === 'active') ?? seasons[0]; const seasonId = propSeasonId || activeSeason?.seasonId; // Load pending sponsorship requests const { data: pendingRequestsData, isLoading: requestsLoading, refetch: refetchRequests } = useSponsorshipRequests('season', seasonId || ''); const pendingRequests = pendingRequestsData?.requests || []; const handleAcceptRequest = async (requestId: string) => { if (!currentDriverId) return; try { await (sponsorshipService as any).acceptSponsorshipRequest(requestId, currentDriverId); await refetchRequests(); } catch (err) { console.error('Failed to accept request:', err); alert(err instanceof Error ? err.message : 'Failed to accept request'); } }; const handleRejectRequest = async (requestId: string, reason?: string) => { if (!currentDriverId) return; try { await (sponsorshipService as any).rejectSponsorshipRequest(requestId, currentDriverId, reason); await refetchRequests(); } catch (err) { console.error('Failed to reject request:', err); alert(err instanceof Error ? err.message : 'Failed to reject request'); } }; const handleEditPrice = (index: number) => { const slot = slots[index]; if (!slot) return; setEditingIndex(index); setTempPrice(slot.price.toString()); }; const handleSavePrice = (index: number) => { const price = parseFloat(tempPrice); if (!isNaN(price) && price > 0) { const updated = [...slots]; const slot = updated[index]; if (slot) { slot.price = price; setSlots(updated); } } setEditingIndex(null); setTempPrice(''); }; const handleCancelEdit = () => { setEditingIndex(null); setTempPrice(''); }; const totalRevenue = slots.reduce((sum, slot) => slot.isOccupied ? sum + slot.price : sum, 0 ); const platformFee = totalRevenue * 0.10; const netRevenue = totalRevenue - platformFee; const availableSlots = slots.filter(s => !s.isOccupied).length; return ( {/* Header */} Sponsorships Define pricing for sponsor slots in this league. Sponsors pay per season. These sponsors are attached to seasons in this league, so you can change partners from season to season. {!readOnly && ( {availableSlots} slot{availableSlots !== 1 ? 's' : ''} available )} {/* Revenue Summary */} {totalRevenue > 0 && ( )} {/* Sponsorship Slots */} {slots.map((slot, index) => { const isEditing = editingIndex === index; const IconComp = slot.tier === 'main' ? Star : Award; return ( {slot.tier === 'main' ? 'Main Sponsor' : 'Secondary Sponsor'} {slot.isOccupied && ( Occupied )} {slot.tier === 'main' ? 'Big livery slot • League page logo • Name in league title' : 'Small livery slot • League page logo'} {isEditing ? ( ) => setTempPrice(e.target.value)} placeholder="Price" // eslint-disable-next-line gridpilot-rules/component-classification className="w-32" min="0" step="0.01" /> ) : ( <> ${slot.price.toFixed(2)} per season {!readOnly && !slot.isOccupied && ( )} )} ); })} {/* Pending Sponsorship Requests */} {!readOnly && (pendingRequests.length > 0 || requestsLoading) && ( )} {/* Alpha Notice */} Alpha Note: Sponsorship management is demonstration-only. In production, sponsors can browse leagues, select slots, and complete payment integration. ); }