110 lines
4.8 KiB
Markdown
110 lines
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.
|