Skip to main content

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

  1. Product detail → Add to Cart
  2. Tap cart icon → see grouped-by-store list
  3. Tap "Proceed to Checkout" on a store group
  4. Inline form: address (with autocomplete), phone, payment method
  5. Place Order → POST /api/store-orders → success state

Ad inquiry flow

  1. Product detail (an Ad) → Add to Cart
  2. Tap cart icon → see grouped-by-seller list of ads
  3. Tap "Send Inquiry"
  4. WhatsApp opens with pre-filled message to the consumer-seller

3. Web ↔ Mobile parity

CapabilityWebMobile
Group store products by store
Group ads by seller
Inline checkout form per store
WhatsApp inquiry per seller group✅ Bulk inquiry modal
Persist across refresheslocalStorageAsyncStorage 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

EndpointMethodPurpose
/api/store-ordersPOSTPlace store order (the success path of the checkout form)
/api/payments/initiate-storePOSTOnline 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 + StoreOrderItem rows 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_pickup regardless 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 logic
  • tests/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.