Purchase Order UI — Direct Send Design
This document builds up and discusses the UI design changes needed to let users
send a Purchase Order directly from the system — part of
PDEV-970 — Enable Direct email sending for Purchase Orders
(under the PDEV-968
umbrella, alongside its Email Order sibling
PDEV-969).
The backend send capability already exists — see the
Email module API reference
(POST /v1/shop-access/email/job), which accepts attachments. The work here is the
front-end surface that will call it for the Purchase Order flow.
The Email Order (direct-send design) sends the order as the email body. A Purchase Order is different: it is a formal document the supplier expects as a PDF, and the system already generates that PDF. So the model here is a cover email with the PO PDF attached — not the PO rendered inline. We start by recording the current PO sidebar, then show the proposed order sheet with a “Send via email” primary, and finally the cover-email composer that primary opens.
The two composers (this one and the Email Order sibling) share ~90% of their chrome. A companion audit — Direct-Send Composer — Shared-Component Audit — enumerates the overlap and proposes a shared foundation that PDEV-1019 can execute against.
Current Purchase Order View
Section titled “Current Purchase Order View”The Purchase Order surface is the OrderSidebar slide-over in
arda-frontend-app. It opens from the right when a user starts a purchase order
for items whose supplier order method is PURCHASE_ORDER. It is a full order
sheet — not an email — assembled from several sections:
- Header — a “Purchase order” title with a close (X) control.
- Order header form (
OrderHeaderForm) — supplier (“To”), PO number, created-on / deliver-by dates, deliver-to address, and vendor details. - Order sheet (
OrderSheet) — the editable line-items table. - Tax / fee / discount and Order summary — adjustments and the computed totals.
- Terms (
OrderTermsSection) — payment terms, shipping terms, shipping via, a note to the vendor, and terms & conditions. - Footer — Cancel, Preview, Download, and Start order.
The only outbound actions today are Download and Preview, which render the
order to a PO PDF (generatePurchaseOrderPDF); Start order accepts the
items without producing a document. In every case the order’s items are accepted
and moved to In Progress. To actually get the PO to the supplier, the user
downloads the PDF and emails it themselves from their own mail client. Closing
that gap — a real “Send” that emails the PO PDF via the backend job endpoint —
is the purpose of this project.
Live Mock
Section titled “Live Mock”A working prototype of the redesigned PO sidebar. Think of it as two views in one panel: the order sheet (the surface above, redressed with a new primary action), and the cover-email composer the primary opens. Both run live below; try the interactions directly.
Order-sheet page
Section titled “Order-sheet page”Structurally the same as today — order header form, line items, taxes / fees / discounts, grand total — with one change in the footer: the primary action is a split button labelled “Send via email”. Its caret menu carries Download (the current PDF export) and Start order (accept without emailing), which today live as top-level footer buttons. Cancel stays on the left.
Clicking Send via email advances the panel to the composer; Cancel in the composer footer returns to the order sheet.
The mock renders the sheet as a grey-block skeleton (no dummy data) so reviewers focus on the layout and the new primary rather than fictional line items.
Cover-email composer
Section titled “Cover-email composer”- PO PDF as the payload; the email is a cover note. The generated
PurchaseOrder-{number}.pdfsits directly below the body as a chip with a paperclip glyph inside the chip — it rides along automatically on a direct send. An Edit ghost button next to the chip returns to the order-sheet page without losing edits to the body. - Gmail-style addresses, From first. From, To, and Cc are recipient-chip fields (in that order — reply-to reads at the top). From defaults to your logged-in email and Cc is pre-seeded with the same address (self-CC). To opens with the supplier’s order address. Type and press Enter (or comma) to add a chip, double-click a chip to edit, and click × — or Backspace in the empty input — to remove it.
- Subject. Defaults to
Purchase Order {number} from {tenant}and is editable inline. - Body — a single prefilled rich-text canvas. The body is one
Tiptap-powered editor with
StarterKit(paragraphs, bold/italic, lists) — no preview toggle. It arrives prefilled with the greeting, cover line, and sign-off; you can rewrite any of it inline. - Powered by Arda — toggle switch. A switch below the attachment controls whether the “Powered by Arda” signature is included in the sent message (default on).
- Revert & undo. Revert all in the footer (shown once any field has been edited) resets every field, the body, and the badge toggle to their defaults; ⌘Z / Ctrl+Z undoes the most recent address change (Tiptap owns its own undo stack for the body).
- Send — split primary. Send is a split button: the main action sends the HTML body with the PO PDF attached automatically (fires on ⌘↵ / Ctrl+↵), and the caret menu offers Open as mailto. A successful Send closes the panel and accepts the order (in this mock, the panel switches to a confirmation with a Reset to start over).
- Copy — plain text. Copy writes the cover note as plain text and accepts the order. A tooltip reminds you: “Don’t forget to attach the PO” — the clipboard can’t carry the PDF.
A toast also confirms each outcome (e.g. “Purchase order sent”), but the panel closing is the primary confirmation.
No direct sending available
Section titled “No direct sending available”This section captures the variant for when direct send is not available — for
example, a tenant whose EmailConfiguration has no authorized send address, so
the composer falls back to a copy-only flow. The address chips and the Send
split are hidden. The body, attachment row, and Powered-by-Arda toggle are
unchanged, and the footer offers Open in email as the default action
with Copy secondary.
The key PO-specific wrinkle: a mailto: draft and the clipboard cannot carry
attachments. So in restricted mode the attachment row carries a Download PO
PDF button and a short hint — the user downloads the PO PDF, opens a draft
(or copies the cover note) and attaches the PDF to their own message before
sending.
Data Inserts
Section titled “Data Inserts”The cover email is assembled from data: the body is prefilled from the PO draft
plus tenant/user context, the PO PDF is the generated document, and the send
envelope (To, Cc, subject, from) is resolved at send time. The table lists each
data-driven element, where it comes from in the system, the placeholder the
live mock above uses (in mocks/_sample-po.ts), and whether the mock lets you
edit it inline (click into the body to edit; “Revert all” in the footer
restores every field). Static chrome — the “Powered by Arda” badge (toggleable
via the switch below the attachment) — is omitted from the table.
| Element | Where the data comes from | Mock value (this page) | Editable in mock |
|---|---|---|---|
| Cover-note body | Prefilled from the PO draft supplier name (OrderDraft.supplierName), PO number and deliver-by date (OrderDraft.poNumber / deliverBy), and the authenticated user’s sign-off (userContext.name / userContext.email) — a single Tiptap document combining greeting, cover line, and sign-off. | bodyDefault — greeting to “Stark Industries”, references PO-001234 / Jul 14, 2026, sign-off from “developer@arda.cards” | Yes — one rich-text canvas (Tiptap + StarterKit) |
| Attachment — PO PDF | The document produced by generatePurchaseOrderPDF from the draft, sent as EmailJobInput.attachments[] | attachmentName (“PurchaseOrder-PO-001234.pdf”, 38 KB) | No — generated from the order sheet |
| Recipient (To) | Supplier order/contact email (Business Affiliate). Required for direct send. | toAddresses (“orders@…”, “tony@…”) | Yes — Gmail-style To chips (add / edit / remove) |
| Recipient (Cc) | Carbon-copy recipients. Seeded with the logged-in user’s email (self-CC) so a copy returns to the sender; editable/removable. | ccAddresses (seeded with “developer@arda.cards”) | Yes — Gmail-style Cc chips (add / edit / remove) |
| Subject | Template of PO number + tenant company name (composed client-side, editable) | subjectDefault (“Purchase Order PO-001234 from Acme Operations”) | Yes |
| From address (reply-to) | The editable “From” is the message reply-to, defaulting to the logged-in user’s email. The actual envelope sender is bound to the tenant’s EmailConfiguration (shown read-only as “sent via …”). | From chip = senderEmail (“developer@arda.cards”); envelope sender = fromAddress (“noreply@…”) | Yes — single From chip (reply-to); envelope sender is read-only |
Copyright: © Arda Systems 2025-2026, All rights reserved