This commit adds a full unauthenticated PWA for in-store retail order taking: - Dedicated `/new-order` route with complete order form, customer/company picker - Public `/api/counter/*` endpoints for search, order creation, and photo uploads - Photo capture and gallery selection with 10-photo per order limit - Offline caching via dedicated service worker and app manifest - Shortcut redirect at `/counter` for quick installation - Comprehensive setup and usage documentation in `docs/counter-pwa.md` - Minor cleanup to root layout metadata and service worker registration - Small layout fix for collection pool row text truncation Orders submitted via the PWA appear immediately in the main CRM's New tab, and the app is designed for trusted office kiosk phones without requiring user login.
110 lines
No EOL
4.8 KiB
Markdown
110 lines
No EOL
4.8 KiB
Markdown
# Counter PWA — install + use
|
|
|
|
A standalone, installable web app on the office counter phones. One tap, no
|
|
login, and the order lands on the **New** tab of the order board.
|
|
|
|
## What it does
|
|
|
|
- Pick an existing customer (search by name, email, or phone) — or tap
|
|
**Add new** to create a customer inline (and a new company in the same
|
|
sheet if needed).
|
|
- Add any number of line items (description, qty, optional price).
|
|
- Snap photos with the phone camera (up to 10 per order).
|
|
- Tap **Submit Order** — the order appears on `/orders` under the **New** tab
|
|
immediately (via PocketBase realtime).
|
|
|
|
## Install on a counter phone
|
|
|
|
### iPhone (Safari)
|
|
|
|
1. Open `https://<your-coolify-host>/new-order` in Safari.
|
|
2. Tap **Share → Add to Home Screen**.
|
|
3. Confirm the name "Counter". The icon appears on the home screen.
|
|
4. Tap the icon — it opens full-screen, no address bar.
|
|
|
|
### Android (Chrome)
|
|
|
|
1. Open the URL in Chrome.
|
|
2. Tap the **⋮ menu → Install app** (or "Add to Home Screen").
|
|
3. Confirm. The icon appears in the launcher.
|
|
4. Tap the icon — it opens full-screen.
|
|
|
|
The same shortcut URL works: `https://<host>/counter` redirects to `/new-order`.
|
|
|
|
## What runs where
|
|
|
|
| Layer | What |
|
|
|---|---|
|
|
| Browser (phone) | `/new-order` — single-screen form, no login |
|
|
| Next.js route handlers | `/api/counter/*` — public, no Bearer token |
|
|
| `src/lib/server/counter-service.ts` | Thin service layer; calls existing `createOrder()`, `createCustomer()`, `createCompany()` |
|
|
| PocketBase | `orders` row + `order_items` rows with `item_status="pending"` (lands on **New** tab) + photos on `orders.order_attachements` |
|
|
|
|
The counter routes intentionally do **not** go through the same Bearer-token
|
|
gate as `/api/v1/*` — the counter phones are kiosk-mode and assumed to be on
|
|
office Wi-Fi.
|
|
|
|
## Smoke test after deploy
|
|
|
|
1. `npm run dev` → open `http://<host>:3000/new-order` from the dev machine.
|
|
2. Pick an existing customer, add one line item, hit Submit.
|
|
3. Open `/orders` in the main app — confirm the new order sits on the
|
|
**New** tab.
|
|
4. Submit again, this time with a photo. Confirm the photo opens from the
|
|
order detail page (`/orders/<id>`).
|
|
5. From an iPhone on the same Wi-Fi, open the same URL → Add to Home Screen
|
|
→ confirm the standalone icon works.
|
|
|
|
## Troubleshooting
|
|
|
|
- **Order doesn't appear on the board.** Check Coolify logs for
|
|
`/api/counter/orders` — PB admin SDK auth (`PB_ADMIN_EMAIL` /
|
|
`PB_ADMIN_PASSWORD`) must be set in `.env.local`.
|
|
- **Photos rejected with 413.** The phone uploaded a file > the cap.
|
|
Default `COUNTER_MAX_PHOTO_MB=8`. Drop it lower if your network is slow,
|
|
or compress on the client (not implemented yet).
|
|
- **Customer combobox empty.** The `/api/counter/customers` endpoint failed
|
|
on first load — see toast in the top-right and check the browser console.
|
|
- **"Photo upload failed" after submit.** The order was saved (it appears
|
|
on the board) but the photos didn't make it. Open the order in the main
|
|
CRM and re-attach from there.
|
|
- **Sheet won't open on iPhone 16+.** Some iOS versions need a user-tap to
|
|
fire `<input capture>`. The form provides two buttons (camera + gallery)
|
|
so the operator can fall back to gallery.
|
|
|
|
## Files added / changed
|
|
|
|
```
|
|
src/app/(counter)/layout.tsx new
|
|
src/app/(counter)/shell.tsx new
|
|
src/app/(counter)/page.tsx new (redirect)
|
|
src/app/(counter)/new-order/page.tsx new
|
|
src/app/(counter)/new-order/components/ new dir
|
|
header.tsx
|
|
counter-select.tsx
|
|
new-customer-sheet.tsx
|
|
items-list.tsx
|
|
photo-capture.tsx
|
|
success-screen.tsx
|
|
src/lib/server/counter-service.ts new
|
|
src/app/api/counter/customers/route.ts new
|
|
src/app/api/counter/companies/route.ts new
|
|
src/app/api/counter/orders/route.ts new
|
|
src/app/api/counter/orders/[id]/attachments/route.ts new
|
|
public/manifest-counter.json new
|
|
public/sw-counter.js new
|
|
src/components/service-worker-registration.tsx edited (dual SW)
|
|
src/app/layout.tsx edited (cleanup)
|
|
next.config.ts edited (/counter redirect)
|
|
.env.local edited (COUNTER_MAX_PHOTO_MB)
|
|
```
|
|
|
|
## Out of scope (intentionally)
|
|
|
|
- No login / PIN — phones are physically controlled by staff.
|
|
- No offline-queue — a flaky network at submit time means the order is
|
|
lost. The PWA caches the page chrome so navigation stays fast, but a
|
|
pending-submit queue would be a separate feature.
|
|
- No per-user audit (rep picker left blank — rep can be set later in the
|
|
main CRM process page).
|
|
- No quote linking — counter orders are standalone. |