import React, { useEffect, useRef } from 'react'; import { useParams, Link } from 'react-router-dom'; import { useQuery } from '@tanstack/react-query'; import { api } from '@/lib/api'; import { formatMoney } from '@/lib/currency'; import { ArrowLeft, Printer } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { InlineLoadingState } from '@/components/LoadingState'; import { ErrorCard } from '@/components/ErrorCard'; import { getPageLoadErrorMessage } from '@/lib/errorHandling'; import { __ } from '@/lib/i18n'; function Money({ value, currency, symbol }: { value?: number; currency?: string; symbol?: string }) { return <>{formatMoney(value, { currency, symbol })}; } export default function Invoice() { const { id } = useParams<{ id: string }>(); const siteTitle = (window as any).wnw?.siteTitle || 'WooNooW'; const qrRef = useRef(null); const q = useQuery({ queryKey: ['order', id], enabled: !!id, queryFn: () => api.get(`/orders/${id}`), }); const order = q.data; // Check if all items are virtual const isVirtualOnly = React.useMemo(() => { if (!order?.items || order.items.length === 0) return false; return order.items.every((item: any) => item.virtual || item.downloadable); }, [order?.items]); // Generate QR code useEffect(() => { if (!qrRef.current || !order) return; (async () => { try { const mod = await import('qrcode'); const QR = (mod as any).default || (mod as any); const text = `ORDER:${order.number || id}`; await QR.toCanvas(qrRef.current, text, { width: 96, margin: 1 }); } catch (_) { // QR library not available } })(); }, [order, id]); const handlePrint = () => { window.print(); }; if (q.isLoading) { return ; } if (q.isError) { return ( q.refetch()} /> ); } if (!order) return null; return (
{/* Actions bar - hidden on print */}
{/* Invoice content */}
{/* Invoice Header */}
{__('INVOICE')}
#{order.number}
{siteTitle}
{window.location.origin}
{/* Invoice Meta */}
{__('Invoice Date')}
{new Date((order.date_ts || 0) * 1000).toLocaleDateString()}
{order.payment_method && ( <>
{__('Payment Method')}
{order.payment_method}
)}
{/* Billing & Shipping */}
{__('Bill To')}
{order.billing?.name || '—'}
{order.billing?.email &&
{order.billing.email}
} {order.billing?.phone &&
{order.billing.phone}
}
{!isVirtualOnly && order.shipping?.name && (
{__('Ship To')}
{order.shipping?.name || '—'}
)}
{/* Items Table */} {(order.items || []).map((it: any, idx: number) => ( ))}
{__('Product')} {__('Qty')} {__('Price')} {__('Total')}
{it.name}
{it.sku &&
SKU: {it.sku}
}
{it.qty}
{/* Totals */}
{__('Subtotal')}
{(order.totals?.discount || 0) > 0 && (
{__('Discount')} -
)} {(order.totals?.shipping || 0) > 0 && (
{__('Shipping')}
)} {(order.totals?.tax || 0) > 0 && (
{__('Tax')}
)}
{__('Total')}
{/* Footer */}

{__('Thank you for your business!')}

{siteTitle} • {window.location.origin}

); }