{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "invoice-page", "title": "Invoice Page", "description": "Invoice layout with from/to addresses, line items table, subtotal/tax/shipping/total, and print button.", "registryDependencies": [ "https://raw.githubusercontent.com/dnachavez/adminlte-next/master/public/r/adminlte-theme.json", "https://raw.githubusercontent.com/dnachavez/adminlte-next/master/public/r/adminlte-table.json", "https://raw.githubusercontent.com/dnachavez/adminlte-next/master/public/r/adminlte-button.json" ], "files": [ { "path": "registry/new-york/invoice-page/blocks/invoice-page.tsx", "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { cn } from \"@/registry/new-york/adminlte-theme/lib/cn\"\n\ninterface InvoiceItem {\n id: string\n quantity: number\n description: string\n serialNumber?: string\n unitPrice: number\n}\n\ninterface InvoicePageProps extends React.HTMLAttributes {\n invoiceNumber: string\n date: string\n dueDate?: string\n from: {\n name: string\n address: string\n phone?: string\n email?: string\n }\n to: {\n name: string\n address: string\n phone?: string\n email?: string\n }\n items: InvoiceItem[]\n paymentMethod?: string\n taxRate?: number\n shippingCost?: number\n onPrint?: () => void\n}\n\nfunction InvoicePage({\n className,\n invoiceNumber,\n date,\n dueDate,\n from,\n to,\n items,\n paymentMethod = \"Credit Card\",\n taxRate = 0,\n shippingCost = 0,\n onPrint,\n ...props\n}: InvoicePageProps) {\n const subtotal = items.reduce((sum, item) => sum + item.quantity * item.unitPrice, 0)\n const tax = subtotal * (taxRate / 100)\n const total = subtotal + tax + shippingCost\n\n return (\n \n {/* Header */}\n
\n
\n
\n

{from.name}

\n
\n {from.address &&
{from.address}
}\n {from.phone &&
Phone: {from.phone}
}\n {from.email &&
Email: {from.email}
}\n
\n
\n
\n

\n Invoice #{invoiceNumber}\n

\n
\n
Date: {date}
\n {dueDate &&
Due: {dueDate}
}\n
Payment: {paymentMethod}
\n
\n
\n
\n\n {/* To */}\n
\n

To:

\n
\n {to.name}\n {to.address &&
{to.address}
}\n {to.phone &&
Phone: {to.phone}
}\n {to.email &&
Email: {to.email}
}\n
\n
\n
\n\n {/* Items */}\n
\n \n \n \n \n \n \n \n \n \n \n {items.map((item) => (\n \n \n \n \n \n \n ))}\n \n
QtyProductSerial #Subtotal
{item.quantity}{item.description}{item.serialNumber || \"-\"}\n ${(item.quantity * item.unitPrice).toFixed(2)}\n
\n
\n\n {/* Totals */}\n
\n
\n
\n
\n Subtotal:\n ${subtotal.toFixed(2)}\n
\n {taxRate > 0 && (\n
\n Tax ({taxRate}%):\n ${tax.toFixed(2)}\n
\n )}\n {shippingCost > 0 && (\n
\n Shipping:\n ${shippingCost.toFixed(2)}\n
\n )}\n
\n Total:\n ${total.toFixed(2)}\n
\n
\n
\n
\n\n {/* Footer */}\n
\n window.print()}\n >\n 🖨 Print\n \n \n Submit Payment\n \n
\n \n )\n}\n\nexport { InvoicePage }\nexport type { InvoicePageProps, InvoiceItem }\n", "type": "registry:component" } ], "type": "registry:block" }