# 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.quoteExpiryDays` instead of hardcoded 30 - Tax line uses `settings.taxLabel` instead 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: ```typescript 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: ```typescript 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` 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.