Skip to content

The Shopper app

The Shopper app (apps/orascom-shopper-app) is the only customer-facing portal — everyone else in this platform is internal staff or brokers. A shopper browses destinations and units, reserves and pays online, pays an EOI holding fee, and — after buying — lives in a separate post-purchase Pre-Delivery owner area (payments, add-ons, services, referrals, resale).

  • Entry: src/main.tsx inits Sentry then renders I18nextProviderQueryClientProvider (React Query) → HelmetProvider + ToastContainer (main.tsx:52-87). src/app/app.tsx wraps USER_CONTEXTUNIT_COMPARE_CONTEXTCUSTOM_PAGES_CONTEXTCurrencyContext around the router (app.tsx:155-170).
  • Router: basename = process.env['NX_SHOPPER_PATH'] ?? '/' (routes.tsx:552).
  • 42 routes / screens: 4 auth/payment + 21 main + 17 pre-delivery (plus a * 404 catch-all).
  • Two endpoint maps (src/api/endpoints.ts): the public ENDPOINTS (prefix NX__SHOPPER_ENDPOINT_PREFIX) and PRE_DELIVERY_ENDPOINTS (prefix NX__PRE_DELIVERY_ENDPOINT_PREFIX) — both over base host NX__API_ENDPOINT.

The shopper authenticates with phone + one-time code (sendOtplogin), and can self-register (/register, phone + OTP). This is the mirror image of the agent apps: for an EOI the shopper never logs in — they only open the emailed/SMSed payment link and pay (see Submitting an EOI). Like every app here, there is no refresh token.

The public, pre-purchase journey — most of it works without logging in; reserving requires auth.

  1. Browse the inventory. /available-units (pages/available-units) lists units with filters, fed by React Query; destinations, country pages, and an interactive masterplan surround it.

    Shopper “Available Units” — the public units listing with filters and search.

  2. Open a unit. /unit-details/:unitId (pages/unit-details) shows media, the payment plan, and the reserve CTA; /similar-units/:unitId/:price and /compare-properties sit alongside.

    Shopper unit-details — media, payment plan, and the reserve call-to-action.

  3. Reserve & pay. /reserve-unit/:unitId (pages/reserve-property) is the multi-step reservation + online payment flow. The end-to-end money path is documented in Shopper buys a unit and The online payment pipeline. EOI holding fees are paid at /pay-eoi/:launchId/:eoiId.

    Shopper unit actions — reserve and download-brochure actions on a unit.

Once logged in, the shopper gets a Wish List and Account Settings, plus the whole Pre-Delivery area below.

Shopper “Wish List” — saved/favorited units (authenticated).

Shopper “Account Settings” — name, email, and phone (all blurred here as PII).

Pre-Delivery — the post-purchase owner area

Section titled “Pre-Delivery — the post-purchase owner area”

After a shopper buys, they enter a separate layout group (PreDeliveryLayout, prefix NX__PRE_DELIVERY_ENDPOINT_PREFIX) — an owner portal for everything that happens between purchase and handover.

Shopper Pre-Delivery owner portal — My Units / Payments / Services / Add-ons / Resell Assistance (greeting name blurred; empty state for a fresh account).

The 17 pre-delivery screens cover:

  • Units & contract: /pre-delivery/units (owned units), /pre-delivery/units/:unitId, /pre-delivery/sign-contract/:unitId.
  • Payments: /pre-delivery/payments (schedule across units), /pre-delivery/payments/:unitId (pay an installment).
  • Services & add-ons: /pre-delivery/services, /pre-delivery/addons (+ /:addonId and /purchase/:addonId).
  • Referrals & resale: /pre-delivery/referrals, /pre-delivery/my-referrals, /pre-delivery/resell-assistance, /pre-delivery/offers.
  • Owner account: /pre-delivery/owner-cards, /pre-delivery/settings, /pre-delivery/get-help, /pre-delivery/news.

Static/marketing pages are served from the Laravel Voyager CMS (there is no separate Payload CMS — see CMS & content), not hardcoded: /faqs, /about-us, /privacy-policy, /terms-and-conditions, /news-events, and dynamic /highlights/:pageSlug (getCustomPage{shopper prefix}/custom-pages) all pull from the CMS pages / custom-pages endpoints.