# 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<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.
