Staaarter

Billing Purchase Order Form

A form for enterprise customers to submit purchase order details for manual invoicing, covering the PO number, company name, billing contact email, an optional tax or VAT ID, and free-form notes. Validates the required fields on submit and swaps to a confirmation view once the PO is on file.

By Staaarter Team
Billing
Updated June 12, 2026
Docs
Live preview

Docs

Installation

A real shadcn registry command, not a copy-paste stand-in: it fetches this block plus its input, label, textarea, button dependencies and any missing npm packages, and installs them straight into your project.

npx shadcn add https://staaarter.com/r/billing-purchase-order-form.json

Prefer not to use the CLI? Copy the source from the Code toggle above into src/components/blocks/billing/billing105.tsx instead.

Usage

The file also exports billing105Demo, the exact props behind the preview above. Spread it to get a working section in one line, then replace it with your own data.

import { Billing105, billing105Demo } from "@/components/blocks/billing/billing105";

export default function Page() {
  return <Billing105 {...billing105Demo} />;
}

Props

PropTypeDefaultDescription
headingstring"Purchase order details"Heading above the form.
descriptionstring"Used to match invoices to your internal PO for manual billing."Supporting sentence under the heading.
defaultValuesPartial<PurchaseOrderValues>noneInitial field values. Any field left out starts blank.
submitLabelstring"Submit purchase order"Label on the submit button.
classNamestringnoneExtra classes for the outer card.

Types

interface PurchaseOrderValues {
  poNumber: string;
  companyName: string;
  billingEmail: string;
  taxId: string;
  notes: string;
}

Behavior notes

  • On submit, poNumber, companyName, and billingEmail are required; taxId and notes are optional and never block submission.
  • billingEmail is checked against a simple email-shaped regex, not a full RFC 5322 validator, so obviously malformed addresses get caught without rejecting valid edge cases.
  • A valid submit sets a submitting state for 700ms before switching to a confirmation view, standing in for a real save request. Replace the setTimeout in handleSubmit with your actual API call.
  • Editing any field after a failed submit clears that field's error and resets the status back to idle, so the user isn't stuck looking at a stale error.
  • The confirmation view includes a "Submit another" button that resets status back to idle without clearing the fields, so it's easy to file a second PO for a related purchase.

Frequently asked questions