import dayjs from 'dayjs' import { ChevronLeft, ChevronRight, FileText, Receipt, ScrollText } from 'lucide-react' import { useEffect, useState } from 'react' import { toast } from 'sonner' import { Button, Card, CardFooter, cn, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from 'ui' import { ShimmeringLoader } from 'ui-patterns/ShimmeringLoader' import InvoicePayButton from './InvoicePayButton' import { InvoiceStatus } from '@/components/interfaces/Billing/Invoices.types' import InvoiceStatusBadge from '@/components/interfaces/Billing/InvoiceStatusBadge' import AlertError from '@/components/ui/AlertError' import { ButtonTooltip } from '@/components/ui/ButtonTooltip' import PartnerManagedResource from '@/components/ui/PartnerManagedResource' import { getInvoice } from '@/data/invoices/invoice-query' import { getInvoiceReceipt } from '@/data/invoices/invoice-receipt-query' import { useInvoicesCountQuery } from '@/data/invoices/invoices-count-query' import { useInvoicesQuery } from '@/data/invoices/invoices-query' import { isPartnerBillingOrganization } from '@/data/organizations/managed-by-utils' import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization' import { MANAGED_BY } from '@/lib/constants/infrastructure' import { formatCurrency } from '@/lib/helpers' import { Organization } from '@/types/base' const PAGE_LIMIT = 5 const getPartnerManagedResourceCta = (selectedOrganization: Organization) => { if (selectedOrganization.managed_by === MANAGED_BY.VERCEL_MARKETPLACE) { return { installationId: selectedOrganization?.partner_id, path: '/invoices', } } if (selectedOrganization.managed_by === MANAGED_BY.AWS_MARKETPLACE) { return { organizationSlug: selectedOrganization?.slug, overrideUrl: 'https://console.aws.amazon.com/billing/home#/bills', } } } export const InvoicesSettings = () => { const [page, setPage] = useState(1) const { data: selectedOrganization } = useSelectedOrganizationQuery() const slug = selectedOrganization?.slug const isPartnerBilledOrganization = isPartnerBillingOrganization( selectedOrganization?.billing_partner ) const offset = (page - 1) * PAGE_LIMIT const { data: count, isError: isErrorCount } = useInvoicesCountQuery( { slug, }, { enabled: !isPartnerBilledOrganization } ) const { data, error, isPending: isLoading, isError, } = useInvoicesQuery( { slug, offset, limit: PAGE_LIMIT, }, { enabled: !isPartnerBilledOrganization } ) const invoices = data || [] useEffect(() => { setPage(1) }, [slug]) const fetchInvoice = async (id: string) => { try { const invoice = await getInvoice({ invoiceId: id, slug }) if (invoice?.invoice_pdf) window.open(invoice.invoice_pdf, '_blank') } catch (error: any) { toast.error(`Failed to fetch the selected invoice: ${error.message}`) } } const fetchReceipt = async (invoiceId: string) => { if (!slug) return try { const receipt = await getInvoiceReceipt({ invoiceId, slug }) if (receipt?.receipt_pdf) window.open(receipt.receipt_pdf, '_blank') } catch (error: any) { toast.error(`Failed to fetch receipt: ${error.message}`) } } if (selectedOrganization && isPartnerBilledOrganization) { return ( ) } // Handle loading state faded text for table headers const tableHeadClassName = isLoading || invoices.length === 0 ? 'text-foreground-muted' : undefined return ( {invoices.length > 0 && ( Icon )} Date Amount Invoice number Status Actions {isLoading ? ( new Array(6).fill(0).map((_, idx) => ( 0 ? 6 : 5}> )) ) : isError ? ( 0 ? 6 : 5} className="p-0! rounded-b! overflow-hidden" > ) : invoices.length === 0 ? (

No invoices for this organization yet

) : ( <> {invoices.map((x) => { return (

{dayjs(x.period_end * 1000).format('MMM DD, YYYY')}

{formatCurrency(x.amount_due / 100)}

{x.number}

{x.amount_due > 0 && !x.payment_is_processing && [ InvoiceStatus.UNCOLLECTIBLE, InvoiceStatus.OPEN, InvoiceStatus.ISSUED, ].includes(x.status as InvoiceStatus) && ( )} } onClick={() => fetchInvoice(x.id)} tooltip={{ content: { side: 'bottom', text: 'Download invoice' } }} /> {x.status === InvoiceStatus.PAID && x.amount_due > 0 && ( } onClick={() => fetchReceipt(x.id)} tooltip={{ content: { side: 'bottom', text: 'Download receipt' } }} /> )}
) })} )}
{invoices.length > 0 && (

{isErrorCount ? 'Failed to retrieve total number of invoices' : typeof count === 'number' ? `Showing ${offset + 1} to ${offset + invoices.length} out of ${count} invoices` : `Showing ${offset + 1} to ${offset + invoices.length} invoices`}

)}
) }