'use client'; import { useState } from 'react'; import { motion, useReducedMotion } from 'framer-motion'; import { Card } from '@/ui/Card'; import { Button } from '@/ui/Button'; import { StatCard } from '@/ui/StatCard'; import { Box } from '@/ui/Box'; import { Stack } from '@/ui/Stack'; import { Text } from '@/ui/Text'; import { Heading } from '@/ui/Heading'; import { SectionHeader } from '@/ui/SectionHeader'; import { InfoBanner } from '@/ui/InfoBanner'; import { PageHeader } from '@/ui/PageHeader'; import { Icon } from '@/ui/Icon'; import { siteConfig } from '@/lib/siteConfig'; import { useSponsorBilling } from "@/hooks/sponsor/useSponsorBilling"; import { CreditCard, DollarSign, Calendar, Download, Plus, Check, AlertTriangle, FileText, TrendingUp, Receipt, Building2, Wallet, Clock, ChevronRight, Info, ExternalLink, Percent, Loader2 } from 'lucide-react'; import type { PaymentMethodDTO, InvoiceDTO } from '@/lib/types/tbd/SponsorBillingDTO'; // ============================================================================ // Components // ============================================================================ function PaymentMethodCardComponent({ method, onSetDefault, onRemove }: { method: PaymentMethodDTO; onSetDefault: () => void; onRemove: () => void; }) { const shouldReduceMotion = useReducedMotion(); const getIcon = () => { if (method.type === 'sepa') return Building2; return CreditCard; }; const MethodIcon = getIcon(); const displayLabel = method.type === 'sepa' && method.bankName ? `${method.bankName} •••• ${method.last4}` : `${method.brand} •••• ${method.last4}`; const expiryDisplay = method.expiryMonth && method.expiryYear ? `${method.expiryMonth}/${method.expiryYear}` : null; return ( {displayLabel} {method.isDefault && ( Default )} {expiryDisplay && ( Expires {expiryDisplay} )} {method.type === 'sepa' && ( SEPA Direct Debit )} {!method.isDefault && ( )} ); } function InvoiceRowComponent({ invoice, index }: { invoice: InvoiceDTO; 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 as keyof typeof statusConfig]; const StatusIcon = status.icon; return ( {invoice.description} {typeLabels[invoice.sponsorshipType as keyof typeof typeLabels]} {invoice.invoiceNumber} {new globalThis.Date(invoice.date).toLocaleDateString()} ${invoice.totalAmount.toFixed(2)} incl. ${invoice.vatAmount.toFixed(2)} VAT {status.label} ); } // ============================================================================ // Main Component // ============================================================================ export default function SponsorBillingPage() { const shouldReduceMotion = useReducedMotion(); const [showAllInvoices, setShowAllInvoices] = useState(false); const { data: billingData, isLoading, error, retry } = useSponsorBilling('demo-sponsor-1'); if (isLoading) { return ( Loading billing data... ); } if (error || !billingData) { return ( {error?.message || 'No billing data available'} {error && ( )} ); } const data = billingData; 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 (window.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`} variant="orange" /> {/* Payment Methods */} }> Add Payment Method } /> {data.paymentMethods.map((method: PaymentMethodDTO) => ( 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: InvoiceDTO, index: number) => ( ))} {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. ); }