import type { Metadata } from "next"; import BtcpayModalBridge from "../../../components/btcpay-modal-bridge"; import BtcpayModalCloseButton from "../../../components/btcpay-modal-close-button"; import BtcpayClassicCheckout from "../../../components/btcpay-classic-checkout"; import InvoicePaymentDetails from "../../../components/invoice-payment-details"; import InvoiceStatusAutoRefresh from "../../../components/invoice-status-auto-refresh"; import { formatRelativeTime } from "../../../components/relative-time"; import StatusRefreshButton from "../../../components/status-refresh-button"; export const dynamic = "force-dynamic"; export const metadata: Metadata = { title: "Payment Request", }; const apiBaseUrl = process.env.API_BASE_URL ?? "http://localhost:8000"; type InvoiceStatus = | "pending" | "payment_detected" | "confirmed" | "expired" | "invalid"; type InvoiceStatusResponse = { id: string; address: string; subaddress_index: number | null; amount_xmr: string; status: InvoiceStatus; confirmation_target: number; confirmations: number; created_at: string; expires_at: string | null; detected_at: string | null; confirmed_at: string | null; btcpay_amount?: string | null; btcpay_currency?: string | null; btcpay_checkout_style?: "standard" | "btcpay_classic" | null; qr_logo?: "monero" | "none" | "custom" | null; qr_logo_data_url?: string | null; quote?: { fiat_amount: string; fiat_currency: string; rate: string; source: string; quoted_at: string; } | null; }; const formatStatus = (status: InvoiceStatus) => { if (status === "payment_detected") { return "Payment detected"; } if (status === "pending") { return "Awaiting funds"; } if (status === "confirmed") { return "Confirmed"; } if (status === "invalid") { return "Invalid"; } return "Expired"; }; const formatTimestamp = (value: string | null) => { if (!value) { return { label: "-", relative: null }; } return { label: new Date(value).toLocaleString(), relative: formatRelativeTime(value), }; }; const statusPillStyles: Record = { pending: "bg-amber-100 text-amber-900", payment_detected: "bg-emerald-100 text-emerald-900", confirmed: "bg-ink/20 text-ink", expired: "bg-red-100 text-red-700", invalid: "bg-clay/15 text-clay", }; export default async function BtcpayModalInvoicePage({ params, }: { params: Promise<{ invoiceId: string }>; }) { const { invoiceId } = await params; const response = await fetch( `${apiBaseUrl}/api/core/public/invoice/${encodeURIComponent(invoiceId)}`, { cache: "no-store" } ); if (response.status === 404) { return (

Payment request

Invoice not found

The invoice id does not match a known invoice. Check the id and try again.

); } if (!response.ok) { return (

Payment request

Status unavailable

We could not load this invoice status. Refresh the page or try again later.

); } const invoice = (await response.json()) as InvoiceStatusResponse; const statusLabel = formatStatus(invoice.status); const confirmations = Math.max(0, invoice.confirmations ?? 0); const confirmationTarget = Math.max(0, invoice.confirmation_target); const hasDetectedPayment = invoice.status === "payment_detected" || invoice.status === "confirmed"; const createdTimestamp = formatTimestamp(invoice.created_at); const expiresTimestamp = formatTimestamp(invoice.expires_at); const isBtcpayInvoice = Boolean(invoice.btcpay_amount && invoice.btcpay_currency); const useClassicCheckout = isBtcpayInvoice && invoice.btcpay_checkout_style === "btcpay_classic"; return (
{useClassicCheckout ? (

Payment request

) : ( <>

Payment request

Payment request

Status {statusLabel}

Confirmations

{confirmations}/{confirmationTarget}

Created

{createdTimestamp.label}

Expires

{expiresTimestamp.label}

)}
); }