'use client'; import { useState, useEffect, useCallback } from 'react'; import Button from '../ui/Button'; import Input from '../ui/Input'; import { DollarSign, Star, Award, Plus, X, Bell } from 'lucide-react'; import PendingSponsorshipRequests, { type PendingRequestDTO } from '../sponsors/PendingSponsorshipRequests'; import { getGetPendingSponsorshipRequestsUseCase, getAcceptSponsorshipRequestUseCase, getRejectSponsorshipRequestUseCase, getSeasonRepository, } from '@/lib/di-container'; import { PendingSponsorshipRequestsPresenter } from '@/lib/presenters/PendingSponsorshipRequestsPresenter'; import { useEffectiveDriverId } from '@/lib/currentDriver'; 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 [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(''); const [pendingRequests, setPendingRequests] = useState([]); const [requestsLoading, setRequestsLoading] = useState(false); const [seasonId, setSeasonId] = useState(propSeasonId); // Load season ID if not provided useEffect(() => { async function loadSeasonId() { if (propSeasonId) { setSeasonId(propSeasonId); return; } try { const seasonRepo = getSeasonRepository(); const seasons = await seasonRepo.findByLeagueId(leagueId); const activeSeason = seasons.find(s => s.status === 'active') ?? seasons[0]; if (activeSeason) { setSeasonId(activeSeason.id); } } catch (err) { console.error('Failed to load season:', err); } } loadSeasonId(); }, [leagueId, propSeasonId]); // Load pending sponsorship requests const loadPendingRequests = useCallback(async () => { if (!seasonId) return; setRequestsLoading(true); try { const useCase = getGetPendingSponsorshipRequestsUseCase(); const presenter = new PendingSponsorshipRequestsPresenter(); await useCase.execute( { entityType: 'season', entityId: seasonId, }, presenter, ); const viewModel = presenter.getViewModel(); setPendingRequests(viewModel?.requests ?? []); } catch (err) { console.error('Failed to load pending requests:', err); } finally { setRequestsLoading(false); } }, [seasonId]); useEffect(() => { loadPendingRequests(); }, [loadPendingRequests]); const handleAcceptRequest = async (requestId: string) => { try { const useCase = getAcceptSponsorshipRequestUseCase(); await useCase.execute({ requestId, respondedBy: currentDriverId, }); await loadPendingRequests(); } 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) => { try { const useCase = getRejectSponsorshipRequestUseCase(); await useCase.execute({ requestId, respondedBy: currentDriverId, ...(reason ? { reason } : {}), }); await loadPendingRequests(); } 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; const occupiedSlots = slots.filter(s => s.isOccupied).length; return (
{/* Header */}

Sponsorships

Define pricing for main and secondary sponsor slots

{!readOnly && (
{availableSlots} slot{availableSlots !== 1 ? 's' : ''} available
)}
{/* Revenue Summary */} {totalRevenue > 0 && (
Total Revenue
${totalRevenue.toFixed(2)}
Platform Fee (10%)
-${platformFee.toFixed(2)}
Net Revenue
${netRevenue.toFixed(2)}
)} {/* Sponsorship Slots */}
{slots.map((slot, index) => { const isEditing = editingIndex === index; const Icon = 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" 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.

); }