'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}
}>
PDF
);
}
// ============================================================================
// 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.
}>
Contact Support
);
}