Cart Live
Dual-track cart: store products go through checkout, ad/resale items go through WhatsApp inquiry. Same UI, two flows.
1. Overview
When the user adds something to the cart, we don't know yet whether it's a store product (Add to Cart → Checkout) or an Ad (Add to Cart → "Send Inquiry" via WhatsApp). The cart page splits items at render time and shows the right CTA per group.
2. User journey
Store product flow
- Product detail → Add to Cart
- Tap cart icon → see grouped-by-store list
- Tap "Proceed to Checkout" on a store group
- Inline form: address (with autocomplete), phone, payment method
- Place Order → POST
/api/store-orders→ success state
Ad inquiry flow
- Product detail (an Ad) → Add to Cart
- Tap cart icon → see grouped-by-seller list of ads
- Tap "Send Inquiry"
- WhatsApp opens with pre-filled message to the consumer-seller
3. Web ↔ Mobile parity
| Capability | Web | Mobile |
|---|---|---|
| Group store products by store | ✅ | ✅ |
| Group ads by seller | ✅ | ✅ |
| Inline checkout form per store | ✅ | ✅ |
| WhatsApp inquiry per seller group | ✅ Bulk inquiry modal | ✅ |
| Persist across refreshes | localStorage | AsyncStorage ka26_cart_* / ka26_store_cart_* |
| Online payment | 🟡 Gated by PAYMENTS_ONLINE_ENABLED | 🟡 Same |
4. Key components
- Web:
src/app/(consumer)/cart/page.tsx(~600 lines) - Mobile:
mobile/app/cart.tsx - Inquiry modal:
src/components/storefront/BulkInquiryModal.tsx - Address autocomplete:
src/components/AddressAutocomplete.tsx(uses Nominatim; Mappls/Google planned)
5. APIs
| Endpoint | Method | Purpose |
|---|---|---|
/api/store-orders | POST | Place store order (the success path of the checkout form) |
/api/payments/initiate-store | POST | Online payment flow (currently 503 — flag off) |
The Cart itself is purely client-state; no /api/cart endpoint.
6. Database touchpoints
- Cart is NOT in the DB — it's in localStorage (web) / AsyncStorage (mobile).
- On checkout,
StoreOrder+StoreOrderItemrows are created.
7. Business logic
- Cart split:
item.product.storeId && item.product.store→ store group; else → ad group - Per-store checkout: each store can be checked out independently — multi-store orders aren't supported (one order = one store)
- Pickup auto-default: when fulfillmentType=pickup, the server forces
paymentMethod=pay_at_pickupregardless of cart state - WhatsApp gating: ads always show WhatsApp; stores show WhatsApp only if
store.allowWhatsApp !== false(admin-controlled per store)
8. Feature flags / env vars
PAYMENTS_ONLINE_ENABLED— when off, hides "Pay via UPI" + auto-snaps payment to COD
9. Tests
tests/store-product-flow.test.ts— 41 tests covering dual-track logictests/offline-only-launch.test.ts— auto-snap behaviour when flag flips
10. Known gotchas
- Cart doesn't survive logout — clearing localStorage clears the cart. Intentional but surprises users.
- One order per store: if user has items from 2 stores, they have to checkout twice. Multi-store cart was considered and dropped (delivery fees, payment splits, status tracking → too much complexity for v1).
- Cart age: items sit indefinitely. Old prices may be stale on revisit. Server validates current price at order placement.