# SPQ v1 → v2 Porting Patterns

## Architecture

- **v2**: React 19 + TypeScript + Vite + Tailwind CSS 4. Lives at `/mnt/seagate8tb/Websites/ShopProQuote.backup-20260626-2058/spq-v2/`
- **Backend**: Same PocketBase at 127.0.0.1:8091, proxied through `/pb` → served by a Python proxy script
- **Build**: `npx vite build` → `dist/` (code-split with React.lazy, ~38 chunks)
- **Serve**: `/tmp/spq-backup-server.py` — static files from dist/ + PB proxy on port 4173

## Common Pitfalls

### PocketBase collection field mismatches
SPQ's PocketBase collections often lack `created`/`updated` system fields because they were created via the API rather than the admin UI. Any query using `sort: '-created'` or `fields: '...,created'` will fail with 400. Replace with `sort: '-id'` (PB IDs are roughly chronological).

### Collection naming conventions
The same collection may be named `repairOrders` (camelCase) or `repair_orders` (snake_case) depending on how it was created. Always verify the exact name via `GET /api/collections` before writing queries. The error is a 404 with "The requested resource wasn't found" — identical to a missing collection.

### Existing collections vs expected collections
Collections that exist: `users`, `quotes`, `customers`, `appointments`, `services`, `settings`, `repairOrders`
Collections that may be missing: `invoices`, `service_advisors`, `vehicles`

### Page states when collections are missing
Pages should detect 404 responses and show a `SetupBanner` component with the collection name, required fields, and a link to `http://192.168.50.98:8091/_/` (PB admin). See `src/components/SetupBanner.tsx`.

### Build vs TypeScript
`npx tsc --noEmit` passing does NOT guarantee `npx vite build` success. Rolldown (Vite's bundler) enforces stricter module resolution. Always run the build after changes.

### React patterns from subagents
Subagents frequently produce:
- Buttons without `onClick` handlers (appear in DOM but do nothing)
- Nested components inside parent functions → input focus loss on every keystroke
- AI function modules with hardcoded fallbacks instead of real API calls
- Function signature drift between `ai.ts` exports and `QuoteGenerator.tsx` imports

### Test credentials
```
Email: demo@shop.com
Password: test1234
```
The demo user has no data — all pages show empty states.
