A bilingual (English/Arabic) food-ordering web app with a customer storefront, an admin dashboard, live order tracking, delivery-zone management, and a points-based loyalty system. Built as a single codebase that compiles into two independent deployments.
Stack: React 18 · TypeScript · Vite · Supabase (Postgres + Auth + RLS) · Leaflet · Vercel
Customer Storefront
- Menu browsing by category with a scroll-spy nav that highlights the current section (IntersectionObserver, not scroll listeners)
- Debounced search across item names/descriptions, including Arabic translations
- Product detail modal with "you might also like" recommendations
- Cart drawer with quantity controls and O(1) line-item lookups
- Today's Offers — time-limited promotions with strikethrough pricing
- Checkout for delivery or pickup, with a Leaflet map picker + geolocation to drop a delivery pin
- Delivery-zone detection — Haversine distance math resolves the customer's coordinates to the correct zone, fee, and minimum order
- Live order tracking — a status timeline (pending → confirmed → preparing → on the way → delivered) that auto-refreshes, plus a copyable order reference code
- Order history for signed-in customers
Admin Dashboard (separate deployment)
- Orders management with per-order status updates
- Menu & category CRUD — pricing, emojis, badges, images, availability toggles, sort order, bilingual fields
- Offers/promotions management
- Delivery-zone editor — center coordinate + radius, per-zone fee and minimum order
- Business settings — hours, contact channels, social links, currency, tax rate, prep time, store-open and payment toggles
- Loyalty rewards manager + analytics (outstanding points, members, redemptions)
Loyalty & Rewards System
- Append-only points ledger (balance = sum of deltas) rather than a mutable balance — full audit trail of earn/redeem/refund events
- Server-authoritative redemption with
pg_advisory_xact_lockper customer to prevent double-spend under concurrent orders - Idempotent earning — a unique index guarantees points are credited exactly once per order, even if its status flips repeatedly; earned only on delivered orders to prevent farming
- Automatic refunds — a trigger refunds redeemed points when an order is cancelled
- 4 reward types: free item, % off an item, fixed amount off the order, % off the order — each with a configurable minimum order; delivery fee is never discounted
- Configurable via a master on/off switch and an adjustable points-per-currency earn rate
Engineering Highlights
- Dual-build architecture — one
VITE_APPenv flag tree-shakes the codebase into two zero-overlap bundles (storefront ships no admin code and vice versa), deployed as separate Vercel projects - Server-authoritative pricing — all prices re-fetched server-side at order time via Postgres RPCs; the client never controls totals
- Security via Row Level Security — the publishable key is safe in the browser; all access is
enforced by Postgres policies and an
is_staff()predicate - Dual authentication — phone-OTP login for customers, email/password for staff
- Full i18n + RTL — ~150 translation keys, dual-language catalog fields, dynamic
dir/langswitching, persisted preference - Geographic delivery zones without PostGIS — Haversine distance computed directly in SQL
- Lean client — custom fetch wrapper over PostgREST/GoTrue instead of a heavy SDK