import { createEffect, createResource, createSignal, For, Show } from "solid-js" import QRCode from "qrcode" import Modal from "@/components/Modal" import PaymentSetup from "@/components/PaymentSetup" import { getInvoice, getInvoiceBolt11, listInvoiceItems, type Invoice } from "@/lib/api" import { billingTenant } from "@/lib/state" type PayStatus = "idle" | "loading" | "success" | "error" type Bolt11Status = "idle" | "loading" | "ready" | "error" type PaymentInvoice = Pick & Partial> type PaymentDialogProps = { invoice: PaymentInvoice open: boolean onClose: () => void } export default function PaymentDialog(props: PaymentDialogProps) { const [bolt11, setBolt11] = createSignal("") const [qrDataUrl, setQrDataUrl] = createSignal("") const [bolt11Status, setBolt11Status] = createSignal("idle") const [bolt11Error, setBolt11Error] = createSignal("") const [payStatus, setPayStatus] = createSignal("idle") const [payError, setPayError] = createSignal("") const [showPaymentSetup, setShowPaymentSetup] = createSignal(false) const [setupSaved, setSetupSaved] = createSignal(false) const [items] = createResource( () => (props.open ? props.invoice.id : undefined), listInvoiceItems, ) const autopayConfigured = () => { const t = billingTenant() return Boolean(t?.nwc_is_set || t?.stripe_payment_method_id) } async function loadBolt11() { if (!props.invoice.id) return setBolt11Status("loading") setBolt11Error("") setBolt11("") setQrDataUrl("") try { const { lnbc } = await getInvoiceBolt11(props.invoice.id) setBolt11(lnbc) setQrDataUrl(await QRCode.toDataURL(lnbc, { width: 256, margin: 2 })) setBolt11Status("ready") } catch (e) { setBolt11Status("error") setBolt11Error(e instanceof Error ? e.message : "Failed to generate Lightning invoice") } } createEffect(() => { if (!props.open || !props.invoice.id) return void loadBolt11() }) function copyBolt11() { void navigator.clipboard.writeText(bolt11()) } async function checkPayment() { setPayStatus("loading") setPayError("") try { const invoice = await getInvoice(props.invoice.id) if (invoice.paid_at != null) { setPayStatus("success") } else { setPayStatus("error") setPayError("Payment not yet confirmed. Please try again after sending.") } } catch (e) { setPayStatus("error") setPayError(e instanceof Error ? e.message : "Failed to check payment status") } } function handleClose() { setPayStatus("idle") setPayError("") setBolt11Status("idle") setBolt11Error("") setBolt11("") setQrDataUrl("") props.onClose() } const amountLabel = () => `$${(props.invoice.amount / 100).toFixed(2)}` const periodLabel = () => { const { period_start, period_end } = props.invoice if (!period_start || !period_end) return "" const start = new Date(period_start * 1000).toLocaleDateString() const end = new Date(period_end * 1000).toLocaleDateString() return `${start} – ${end}` } return ( <> {/* Header */}

Pay Invoice

{amountLabel()}

Billing period {periodLabel()}

{/* Content */}
{/* What's being paid for — the invoice's actual line items */} 0}>

On this invoice

    {(item) => (
  • {item.description} ${(item.amount / 100).toFixed(2)}
  • )}

Pay with Lightning

Generating invoice...

Unable to generate invoice

{bolt11Error()}

Lightning invoice QR code
{/* Card / automatic payment alternative */}

Prefer to pay with a card?

} >

Payment confirmed!

Thank you. Your account is up to date.

{/* Error */}

{payError()}

{/* Footer */}
} >
{ setShowPaymentSetup(false) if (setupSaved()) { setSetupSaved(false) props.onClose() } }} onSaved={() => setSetupSaved(true)} /> ) }