import { useState } from 'react'; import { Receipt, Download, Loader2, ChevronLeft, ChevronRight, Clock } from 'lucide-react'; import type { InvoiceResponse } from '@/infrastructure/http/api/subscription'; import { subscriptionApi } from '@/infrastructure/http/api/subscription'; import type { PaginationMeta } from '@archer/api-interface/schemas/shared/pagination-meta.response'; import { useTranslation } from '@/i18n/TranslationProvider'; interface InvoiceListProps { invoices: InvoiceResponse[]; meta?: PaginationMeta; isLoading?: boolean; onPageChange?: (page: number) => void; onPayNow?: (transactionId: string) => void; } const statusColors: Record = { completed: 'bg-green-100 text-green-700', pending: 'bg-yellow-100 text-yellow-700', failed: 'bg-red-100 text-red-700', refunded: 'bg-gray-100 text-gray-700', }; export function InvoiceList({ invoices, meta, isLoading, onPageChange, onPayNow }: InvoiceListProps) { const { t, locale } = useTranslation(); const [downloadingId, setDownloadingId] = useState(null); const handleDownloadPdf = async (invoice: InvoiceResponse) => { setDownloadingId(invoice.id); try { const blob = await subscriptionApi.downloadInvoicePdf(invoice.id); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = invoice.invoiceNumber ? `RE-${invoice.invoiceNumber}.pdf` : `invoice-${invoice.id}.pdf`; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); } catch { // silently fail — button only shown when hasPdf is true } finally { setDownloadingId(null); } }; if (isLoading) { return (
{[1, 2, 3].map((i) => (
))}
); } if (invoices.length === 0) { return (

{t('subscription.noPaymentHistory')}

); } return (
{invoices.map((invoice) => (

{invoice.description || t('subscription.payment')}

{new Date(invoice.createdAt).toLocaleDateString(locale)} {invoice.invoiceNumber && ( <> · {invoice.invoiceNumber} )}
{invoice.status}
{invoice.originalAmount && invoice.discountAmount ? ( <> {'\u20AC'}{invoice.originalAmount.toFixed(2)} {'\u20AC'}{invoice.amount.toFixed(2)} {invoice.appliedCampaigns && invoice.appliedCampaigns.length > 0 && ( {invoice.appliedCampaigns.map(c => c.name[locale] || c.name.en || '').filter(Boolean).join(', ')} )} ) : ( {'\u20AC'}{invoice.amount.toFixed(2)} )}
{invoice.status === 'pending' && onPayNow ? ( ) : invoice.hasPdf ? ( ) : invoice.status === 'completed' ? (
{t('subscription.invoiceReady')}
) : null}
))}
{meta && meta.totalPages > 1 && (
{meta.total} {t('common.total')}
{meta.page} / {meta.totalPages}
)}
); }