57 lines
1.7 KiB
Markdown
57 lines
1.7 KiB
Markdown
# Settings Persistence Pattern (ShopProQuote)
|
|
|
|
## Architecture
|
|
|
|
Settings live in two places:
|
|
1. **localStorage** (`spq-settings` key) — always available, even without login
|
|
2. **PocketBase** `settings` collection — per-user JSON field (`data` field), only when logged in
|
|
|
|
## Loading order (Settings.tsx init)
|
|
|
|
1. `loadLocalSettings()` → reads localStorage, spreads over DEFAULT_SETTINGS
|
|
2. If logged in, fetch PB record → spread `{ ...DEFAULT_SETTINGS, ...data }` over the stored `data` JSON field
|
|
3. `saveLocalSettings(merged)` — overwrites localStorage with PB data so next load uses it
|
|
|
|
## Saving
|
|
|
|
- `updateSetting(key, value)` — updates local state + immediately writes to localStorage
|
|
- `saveAllSettings()` — saves to PocketBase (if logged in) + localStorage
|
|
|
|
## Type: ShopSettings (src/types.ts)
|
|
|
|
```typescript
|
|
export interface ShopSettings {
|
|
businessName: string;
|
|
businessAddress: string;
|
|
businessPhone: string;
|
|
serviceAdvisor: string;
|
|
taxRate: number;
|
|
taxLabel: string;
|
|
shopChargeRate: number;
|
|
shopChargeExplanation: string;
|
|
headerMessage: string;
|
|
footerMessage: string;
|
|
quoteFooterNote: string;
|
|
|
|
// PDF & Branding
|
|
logoUrl?: string;
|
|
showLogoOnPdf: boolean;
|
|
quoteExpiryDays: number;
|
|
quoteNumberPrefix: string;
|
|
pdfAccentColor: string;
|
|
|
|
// Business Ops
|
|
businessHours?: string;
|
|
defaultLaborRate: number;
|
|
paymentTerms: string;
|
|
}
|
|
```
|
|
|
|
## DEFAULT_SETTINGS lives in two places
|
|
|
|
Both MUST stay in sync:
|
|
- `src/pages/Settings.tsx` (the settings UI uses this)
|
|
- `src/pages/QuoteGenerator.tsx` (the PDF generator's `loadSettings()` fallback)
|
|
|
|
When adding a new setting: add to types.ts → add to both DEFAULT_SETTINGS → add UI field → add to pdf.ts usage.
|