'use client'; import { useState, useEffect } from 'react'; import { motion, useReducedMotion } from 'framer-motion'; import Card from '@/components/ui/Card'; import Button from '@/components/ui/Button'; import StatCard from '@/components/ui/StatCard'; import SectionHeader from '@/components/ui/SectionHeader'; import StatusBadge from '@/components/ui/StatusBadge'; import InfoBanner from '@/components/ui/InfoBanner'; import PageHeader from '@/components/ui/PageHeader'; import { siteConfig } from '@/lib/siteConfig'; import { BillingViewModel } from '@/lib/view-models/BillingViewModel'; import { SponsorService } from '@/lib/services/sponsors/SponsorService'; import { ServiceFactory } from '@/lib/services/ServiceFactory'; import { CreditCard, DollarSign, Calendar, Download, Plus, Check, AlertTriangle, FileText, ArrowRight, TrendingUp, Receipt, Building2, Wallet, Clock, ChevronRight, Info, ExternalLink, Percent } from 'lucide-react'; // ============================================================================ // Types // ============================================================================ interface PaymentMethod { id: string; type: 'card' | 'bank' | 'sepa'; last4: string; brand?: string; isDefault: boolean; expiryMonth?: number; expiryYear?: number; bankName?: string; } interface Invoice { id: string; invoiceNumber: string; date: Date; dueDate: Date; amount: number; vatAmount: number; totalAmount: number; status: 'paid' | 'pending' | 'overdue' | 'failed'; description: string; sponsorshipType: 'league' | 'team' | 'driver' | 'race' | 'platform'; pdfUrl: string; } interface BillingStats { totalSpent: number; pendingAmount: number; nextPaymentDate: Date; nextPaymentAmount: number; activeSponsorships: number; averageMonthlySpend: number; } // ============================================================================ // Mock Data // ============================================================================ // ============================================================================ // Components // ============================================================================ function PaymentMethodCard({ method, onSetDefault, onRemove }: { method: any; onSetDefault: () => void; onRemove: () => void; }) { const shouldReduceMotion = useReducedMotion(); const getIcon = () => { if (method.type === 'sepa') return Building2; return CreditCard; }; const Icon = getIcon(); const getLabel = () => { if (method.type === 'sepa' && method.bankName) { return `${method.bankName} •••• ${method.last4}`; } return `${method.brand} •••• ${method.last4}`; }; return (
{method.displayLabel} {method.isDefault && ( Default )}
{method.expiryDisplay && ( Expires {method.expiryDisplay} )} {method.type === 'sepa' && ( SEPA Direct Debit )}
{!method.isDefault && ( )}
); } function InvoiceRow({ invoice, index }: { invoice: any; index: number }) { const shouldReduceMotion = useReducedMotion(); const statusConfig = { paid: { icon: Check, label: 'Paid', color: 'text-performance-green', bg: 'bg-performance-green/10', border: 'border-performance-green/30' }, pending: { icon: Clock, label: 'Pending', color: 'text-warning-amber', bg: 'bg-warning-amber/10', border: 'border-warning-amber/30' }, overdue: { icon: AlertTriangle, label: 'Overdue', color: 'text-racing-red', bg: 'bg-racing-red/10', border: 'border-racing-red/30' }, failed: { icon: AlertTriangle, label: 'Failed', color: 'text-racing-red', bg: 'bg-racing-red/10', border: 'border-racing-red/30' }, }; const typeLabels = { league: 'League', team: 'Team', driver: 'Driver', race: 'Race', platform: 'Platform', }; const status = statusConfig[invoice.status]; const StatusIcon = status.icon; return (
{invoice.description} {typeLabels[invoice.sponsorshipType]}
{invoice.invoiceNumber} {invoice.formattedDate}
{invoice.formattedTotalAmount}
incl. {invoice.formattedVatAmount} VAT
{status.label}
); } // ============================================================================ // Main Component // ============================================================================ export default function SponsorBillingPage() { const shouldReduceMotion = useReducedMotion(); const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [showAllInvoices, setShowAllInvoices] = useState(false); useEffect(() => { const loadBilling = async () => { try { const sponsorService = ServiceFactory.getSponsorService(); const billingData = await sponsorService.getBilling('demo-sponsor-1'); setData(new BillingViewModel(billingData)); } catch (err) { console.error('Error loading billing data:', err); setError('Failed to load billing data'); } finally { setLoading(false); } }; loadBilling(); }, []); if (loading) { return (

Loading billing data...

); } if (error || !data) { return (

{error || 'No billing data available'}

); } const handleSetDefault = (methodId: string) => { setPaymentMethods(methods => methods.map(m => ({ ...m, isDefault: m.id === methodId })) ); }; const handleRemoveMethod = (methodId: string) => { if (confirm('Remove this payment method?')) { setPaymentMethods(methods => methods.filter(m => m.id !== methodId)); } }; const handleSetDefault = (methodId: string) => { // In a real app, this would call an API console.log('Setting default payment method:', methodId); }; const handleRemoveMethod = (methodId: string) => { if (confirm('Remove this payment method?')) { // In a real app, this would call an API console.log('Removing payment method:', methodId); } }; const containerVariants = { hidden: { opacity: 0 }, visible: { opacity: 1, transition: { staggerChildren: shouldReduceMotion ? 0 : 0.1, }, }, }; const itemVariants = { hidden: { opacity: 0, y: 20 }, visible: { opacity: 1, y: 0 }, }; return ( {/* Header */} {/* Stats Grid */} i.status === 'pending' || i.status === 'overdue').length} invoices`} color="text-warning-amber" bgColor="bg-warning-amber/10" /> {/* Payment Methods */} Add Payment Method } />
{data.paymentMethods.map((method) => ( handleSetDefault(method.id)} onRemove={() => handleRemoveMethod(method.id)} /> ))}

We support Visa, Mastercard, American Express, and SEPA Direct Debit.

All payment information is securely processed and stored by our payment provider.

{/* Billing History */} Export All } />
{data.invoices.slice(0, showAllInvoices ? data.invoices.length : 4).map((invoice, index) => ( ))}
{data.invoices.length > 4 && (
)}
{/* Platform Fee & VAT Information */} {/* Platform Fee */}

Platform Fee

{siteConfig.fees.platformFeePercent}%

{siteConfig.fees.description}

• Applied to all sponsorship payments

• Covers platform maintenance and analytics

• Ensures quality sponsorship placements

{/* VAT Information */}

VAT Information

{siteConfig.vat.notice}

Standard VAT Rate {siteConfig.vat.standardRate}%
B2B Reverse Charge Available

Enter your VAT ID in Settings to enable reverse charge for B2B transactions.

{/* Billing Support */}

Need help with billing?

Contact our billing support for questions about invoices, payments, or refunds.

); }