- Extract the client-quote identity into its own store (QuoteProfile,
skatespots:deck-cost:quote) so it is NOT part of CalcState — loading or saving
a preset now keeps the same business name/logo/contact details.
- Client quote PDF: a real quote number counter (Q-0007, with a +1 button) and a
configurable validity window, shown as "Quote valid until <date>".
- PNG summary card now also draws the logo (top-right) and the business name.
A "Quote details" block (in the Result section) lets the user set a business/
shop name, a logo (stored as a data URL — no upload/network, capped 500 KB),
email/phone/website/address and notes/terms. The client quote PDF now renders a
logo + contact header, the line item + total, and the notes/terms. Bumped the
localStorage key to :v2 (and guarded preset/JSON loads) so an older saved sheet
without the quote block can't crash the tool.
Export ▾ now offers: PDF (full sheet), PDF (client quote — uses an optional
businessName), PNG summary card (canvas), XLSX multi-sheet workbook (lazy
SheetJS), CSV, Markdown, JSON, and Copy summary (clipboard).
Import auto-detects the CSV shape: a `name,order_cost,…` header is treated as a
supplier price list and replaces the Materials table; otherwise the CSV
round-trips the whole sheet. JSON still loads a backup.
- Export is now a menu: PDF (quote/print), CSV (spreadsheet-friendly
section,item,field,value rows), Markdown, JSON (backup).
- Import auto-detects .json / .csv: JSON loads a backup, CSV round-trips the
whole sheet (hand-rolled CSV quote/parse so commas in material names are safe).
- Currency picker now offers BOTH Bitcoin units — ₿ sats and ₿ BTC (plus fiat).
BTC is 1 per BTC, sats 1e8; switching converts between them and fiats
(BTC shows up to 8 decimals, trimmed).
- Default Materials is now a complete deck-build checklist, grouped: wood & core
(veneer/edge tape/logs), adhesives & fillers (glue/epoxy/filler), press/mold
consumables (release/vacuum film), shaping (sandpaper/saw+drill bits/masking
tape), finish & graphics (stain/primer/paint/clearcoat/grip) and Other. New
rows default to 0 so the worked example is unchanged.
The first pass overflowed the right margin (long value strings), had no section
separation, and split the Result across pages. Rebuilt the generator:
- accent rule + title, date/currency subtitle;
- each section gets a lime underline + a hairline rule;
- rows are two-line items (name + per-board value, then a grey detail line with
cost/boards/setup), so nothing runs past the margin;
- Result section is kept together (page-break guard) and the two selling prices
render in highlighted boxes;
- page numbers (n / N).
The toolbar's primary Export now generates a real PDF (lazy-loaded jspdf) — a
formatted one-page summary: labour, equipment, operations, materials, processes,
packaging, margins and the selling prices, plus the date/currency. Print-to-PDF
was rejected because window.print() doesn't work in the Capacitor WebView.
A secondary JSON export stays (for Import/backup); Import still reads JSON.
jspdf is dynamically imported so it never enters the initial bundle.
- Equipment now amortises setup time too: (cost + setupHrs × labor/hr) ÷ boards,
so the Setup (h) column actually does something.
- sats values round to whole numbers on currency conversion.
- Each section shows a per-board subtotal (equipment/materials/processes/packaging).
- Sticky summary bar (under the header) keeps cost + selling price visible while
you edit.
- Save/Load named presets (localStorage) + Export/Import JSON; Reset now confirms.
- Results gain "List a deck at this price →" (deep-links CreateListingPage with
?price¤cy, which now reads currency too) and "Get it made →" (Lab Builder).
Coinbase's exchange-rates response includes crypto (BTC, ETH, USDT, …). Filter
the picker to ISO-4217 fiat codes (FIAT_CODES) plus sats, so only real
currencies and bitcoin are selectable.
- getBtcRates()/useBtcRates() read every BTC→fiat rate from the ONE Coinbase
exchange-rates call the app already made, plus sats (1e8). No new endpoint.
- The calculator's currency control is now a searchable Popover: sats + every
fiat Coinbase reports, with a search box. Selecting a currency CONVERTS every
money field (labour, rent, utilities, subscriptions, equipment cost, material
order/shipping, packaging materials) by the live ratio; unitless fields
(overhead factor, board counts, minutes, margins) are untouched. Falls back to
relabel-only if rates aren't loaded.
- Currency symbols/formats for the common fiats.
A chip row at the top switches the whole sheet's unit: $ / € / £ / ₿ sats. Input
labels follow the unit and results reformat (sats are shown rounded, no
decimals). It relabels/reformats only — it does not convert values, since the
app only has a BTC/USD rate (no fiat↔fiat or reliable fiat↔sats conversion);
you enter amounts in the unit you think in. Choice persists with the rest.
- Removed the sticky category-chip row from /diy (sections still group the cards).
- New in-app tool at /diy/deck-cost (components/DeckCostCalculator.tsx): a
self-contained pricing model — labour rate + overhead, equipment amortisation,
operation expenses, materials (with order/unload time), process time,
packaging, profit margin and scrap → cost per board and a fair selling price
(no-packaging / with-packaging). State persists to localStorage; reset to the
worked example. The "Deck cost & pricing" card now links to it instead of
showing "Coming soon".
- Smoke test walks /diy/deck-cost.