A UK address at checkout is charged 20% VAT and shown $25.20; the order, the receipt and the admin page say $ and nothing else, while the row underneath says USD and Stripe is charged in it. Say it where it is read, once, from one place.
What done looks like:
[ ] src/money.ts keeps the one answer: CURRENCY and a formatter that can be asked for the named form ($25.20 USD) as well as the bare one. No page builds a currency string of its own.
[ ] The currency is named beside the figure a shopper is deciding on: the cart total, the checkout total, the pay page's approve button, the order total and the receipt total. Line items stay bare — naming it once per block is enough, and the pages must not turn into noise.
[ ] The order page and the receipt name the currency of the order row (order.currency), not the app's constant, so an order placed before a change still reads as what it was charged.
[ ] The admin order page and /admin totals name it the same way, and src/tty.ts's order and payment screens do too.
[ ] No layout shift and no new element: this is text inside the totals block that already exists.
[ ] Tests: the checkout, order and receipt pages contain the order's currency beside the total; an order row with a currency other than USD renders that one.
Files I expect to change: src/money.ts, src/pages/cart.ts, src/pages/checkout.ts, src/pages/order.ts, src/pages/admin.ts, src/mail.ts, src/tty.ts, src/server.test.ts, src/units.test.ts.
Risks: the totals blocks are the same markup the gift-card order change touches, so this waits for #71 rather than racing it. formatCents is asserted on in many tests — keep its output byte-for-byte and add the named form beside it, never in place of it. Stripe's line items already send order.currency.toLowerCase(); do not touch that wire.
Suggested: mason, who has been in the page modules most recently.
A UK address at checkout is charged 20% VAT and shown
$25.20; the order, the receipt and the admin page say$and nothing else, while the row underneath saysUSDand Stripe is charged in it. Say it where it is read, once, from one place.What done looks like:
src/money.tskeeps the one answer:CURRENCYand a formatter that can be asked for the named form ($25.20 USD) as well as the bare one. No page builds a currency string of its own.order.currency), not the app's constant, so an order placed before a change still reads as what it was charged./admintotals name it the same way, andsrc/tty.ts's order and payment screens do too.Files I expect to change:
src/money.ts,src/pages/cart.ts,src/pages/checkout.ts,src/pages/order.ts,src/pages/admin.ts,src/mail.ts,src/tty.ts,src/server.test.ts,src/units.test.ts.Risks: the totals blocks are the same markup the gift-card order change touches, so this waits for #71 rather than racing it.
formatCentsis asserted on in many tests — keep its output byte-for-byte and add the named form beside it, never in place of it. Stripe's line items already sendorder.currency.toLowerCase(); do not touch that wire.Suggested: mason, who has been in the page modules most recently.