3.7 KiB
New Features Added 2026-06-28
Settings Page — 8 tabs (was 6)
Two new tabs added:
PDF & Branding Tab
| Setting | Field | Effect |
|---|---|---|
| Logo | logoUrl (base64 data-URL) |
Upload PNG/JPG (max 500KB), shows on PDF quotes |
| Show logo on PDF | showLogoOnPdf (boolean) |
Toggle logo visibility |
| Quote Expiry (days) | quoteExpiryDays (number) |
Replaces hardcoded "30 days" in PDF footer |
| Quote Number Prefix | quoteNumberPrefix (string) |
Prepended to quote IDs on PDF |
| Accent Color | pdfAccentColor (hex string) |
Color picker — changes green accent on PDF headers/badges |
Business Ops Tab
| Setting | Field | Effect |
|---|---|---|
| Tax Label | taxLabel (string) |
Rename "Tax" to "Sales Tax", "HST", etc. |
| Payment Terms | paymentTerms (string) |
Shown on invoices/quotes ("Due on Receipt", "Net 15", "Net 30") |
| Default Labor Rate | defaultLaborRate (number) |
Preset $/hr when adding catalog services |
| Business Hours | businessHours (string) |
Free-text or JSON schedule for appointment system |
Files changed: types.ts (ShopSettings), pages/Settings.tsx (PDFBrandingSection + BusinessOpsSection components), lib/pdf.ts (reads new fields)
PDF generator integration:
const ACCENT: ColorTuple = settings.pdfAccentColor ? hexToRgb(settings.pdfAccentColor) : GR— replaces hardcoded GR color- Footer uses
settings.quoteExpiryDaysinstead of hardcoded 30 - Tax line uses
settings.taxLabelinstead of hardcoded "Tax" - Logo renders via
doc.addImage()on page 1 - Payment terms appear in summary section
Dashboard — Custom Dropdown with Search
Replaced the Recent Quotes table (desktop) + card list (mobile) with a custom dropdown component:
- Trigger button: "Jump to a recent quote…" with rotating chevron
- Search input: Pinned at top of panel, filters by customer name / RO# / vehicle info
- Result rows: Each shows customer name + RO# on one line, vehicle + date below, total + status badge on the right
- Behavior: click-outside-to-close, auto-focus on search when opened, query resets on navigation
Shop Charge Defaults to true
In ServiceSearch.handleAdd(), applyShopCharge now defaults to true instead of undefined:
addService({ ...service, selected: true, approved: true, customerDecision: 'approved', priority: undefined, applyShopCharge: true });
Previously the checkbox was unchecked by default and the shop charge was $0.00/hidden unless the user manually checked it on each service. The per-service toggle still exists for exceptions.
AI Write Now Includes Technician Notes
handleAiWrite in QuoteGenerator.tsx now passes technicianNotes: svc.technicianNotes to aiWriteExplanation. The existing prompt builder in ai.ts already handles it:
if (technicianNotes) {
additionalContext += `\nTechnician's internal notes: "${technicianNotes}"`;
}
So the AI-generated explanation incorporates the tech's internal notes as context.
PDF-to-Images Export
New file: src/lib/pdf-to-images.ts
downloadPdfAsImages(pdfInput: jsPDF | Blob, customerName: string): Promise<void>
Accepts either a jsPDF instance or a Blob. Converts every page to PNG via pdfjs-dist and triggers a download per page: Jon_Smith_Page1.png, Jon_Smith_Page2.png, etc.
Setup required:
npm install pdfjs-dist- Worker config in
main.tsx:pdfjsLib.GlobalWorkerOptions.workerSrc = new URL('pdfjs-dist/build/pdf.worker.min.mjs', import.meta.url).toString() - Scale configurable via
getViewport({ scale })(default 2 = Retina)
Button added in QuoteGenerator QuoteSummary: blue border "Export as Images" button between Print and Save.