78 lines
3.7 KiB
Markdown
78 lines
3.7 KiB
Markdown
# 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.
|