Mobile — Shared

Cross-role mobile features (apps/mobile) that apply regardless of which identity is active — guest gating, chat, search, listings, identity switching, payments, layout, and the App Store demo account. Includes the confirmed reason Company/Office roles are currently unreachable.

mobile-company-office-gate

Company/Office accounts are entirely gated behind a 'Coming Soon' screen — confirmed intentional

P0

Confirm that Company and Office account types are deliberately locked app-wide — apps/mobile/src/app/(auth)/business-auth.tsx checks `const COMPANY_OFFICE_LOCKED = true;` and renders <ComingSoonGate /> instead of the real signup/login form, and both (company)/_layout.tsx and (office)/_layout.tsx short-circuit their entire tab navigators to that same gate — so that this documented, intentional kill-switch is treated as a release-readiness checkpoint to re-verify every release, not something QA needs to rediscover or escalate as a bug each pass.

Acceptance Criteria

  • AC-01COMPANY_OFFICE_LOCKED is true in the current build, and every entry point into company/office (the business-auth screen, the (company) tab group, the (office) tab group) shows the same 'قريباً' ComingSoonGate bottom sheet — non-dismissible, with only a 'العودة للرئيسية' way out.
  • AC-02'العودة للرئيسية' correctly returns the user to an individual identity if one exists on the account, or logs out to individual-auth if not — it never leaves the user stuck on a dead screen.
  • AC-03This flag's state is an explicit, called-out line item in every release QA sign-off — before shipping, confirm whether it's intentionally still true or whether product has asked for it to flip to false.
  • AC-04If/when this flips to false, every story in the Mobile — Company and Mobile — Office sections needs a full re-pass, since none of that functionality has been exercised by real users while the gate has been up.

Test Scenarios

  • TC-01Attempt to reach Office or Company signup from every entry point you can find (the selection screen doesn't offer them at all — see the Mobile — Individual section; also try deep-linking directly to /(auth)/business-auth?type=office) and confirm ComingSoonGate always appears, with no path reaching a real form.
  • TC-02Log in as an existing company/office test account (if one exists in the DB from before the lock) and confirm the (company)/(office) tab navigator is also gated — not just the auth screens.
  • TC-03Tap 'العودة للرئيسية' from the gate as a user with an individual identity available, and confirm it switches to that identity correctly; repeat as a user with no individual identity and confirm it logs out cleanly to individual-auth.
  • TC-04Before each release, explicitly re-check this flag's value in the shipped build (not just in the repo) since a build/env mismatch here would silently ship two completely unqualified onboarding paths to real users.
mobile-guest-guard

Guest action-gating shows the auth sheet, never a dead end

P0

Verify that every guarded action (Chat, Favorites, Notifications, Add Ad, Add Alert, Ask for Offer, Write Review) opens the Authentication Bottom Sheet for guest users, so that guests are always offered a clear path to sign up or log in instead of hitting a silent failure or crash.

No frame linked yet

Acceptance Criteria

  • AC-01guardAction() intercepts all 7 listed actions when no session exists.
  • AC-02The bottom sheet offers 'إنشاء حساب' (sign up), 'تسجيل دخول' (log in), and 'لاحقاً' (later/dismiss).
  • AC-03Dismissing via 'لاحقاً' returns the guest to the exact screen/state they were on.
  • AC-04The same actions work immediately (no sheet) once a real session exists.

Test Scenarios

  • TC-01As a guest, tap the heart icon on a property card in Search results, Property Detail, and Home feed — confirm the sheet appears in all three places, not just one.
  • TC-02As a guest, tap the '+' add-listing button and the 'Ask for Offer' button on a property — confirm both are gated.
  • TC-03Complete login from the sheet mid-flow (e.g. from Favorites) and confirm the originally-attempted action completes automatically or the user lands back where they intended.
  • TC-04Kill and relaunch the app as a guest — confirm gating still triggers after a cold start (not just first-session state).
mobile-chat-realtime

Real-time chat delivers and syncs across devices

P0

Verify the Socket.IO-backed chat (join_conversation/leave_conversation/send_message events, new_message/conversation_updated broadcasts) delivers messages reliably, so that buyers and sellers can trust conversations aren't dropped or duplicated. This applies identically to Individual chat and to company-chats/office-chats once the account-type gate lifts (mobile-company-office-gate) — all three screens share the same useChatStore.

No frame linked yet

Acceptance Criteria

  • AC-01Sending a message from device A appears on device B (same account, two sessions) within a few seconds without manual refresh.
  • AC-02conversation_updated correctly reorders/updates the chat list's last-message preview and unread badge.
  • AC-03Reopening the app after being offline reconnects the socket and catches up on missed messages via GET conversations/:id/messages.
  • AC-04POST conversations/:id/read clears the unread badge for that conversation only.

Test Scenarios

  • TC-01Two test accounts message each other; confirm delivery order matches send order on both ends.
  • TC-02Put device A in airplane mode mid-conversation, send messages from B, then bring A back online — confirm A receives the backlog.
  • TC-03Start a conversation from a Property Detail 'Chat' button as a guest — confirm this is gated by the auth sheet (see mobile-guest-guard), not a broken chat screen.
  • TC-04KNOWN STUB: attempt 'Attach image' and image download in a chat thread — these currently only console.log and do nothing visible. Confirm the buttons at least fail silently/gracefully rather than crashing, and file this as a known gap rather than a new bug.
mobile-add-listing

Multi-tab listing creation (Sell/Rent/Exchange) saves consistent data

P0

Verify the add-listing flow (SharedPropertyInfo + SellPropertyTab/RentPropertyTab/ExchangePropertyTab, driven by useListingStore, with a Preview step) produces a correctly-typed property regardless of which tab the user starts from, so that listings don't get created with the wrong type or missing required fields.

No frame linked yet

Acceptance Criteria

  • AC-01Fields entered in SharedPropertyInfo persist correctly when switching between Sell/Rent/Exchange tabs before submission.
  • AC-02Preview screen accurately reflects every field entered, including images, before final submission.
  • AC-03Required-field validation blocks submission with clear inline errors rather than a silent failure.
  • AC-04Successfully created listings appear immediately in the user's own listings/'My Ads' and in relevant search feeds.

Test Scenarios

  • TC-01Create a Sell listing with all fields, submit, and verify it appears with correct type/price/fields on Property Detail.
  • TC-02Start a Rent listing, switch to Exchange mid-flow, and confirm shared fields (location, images) aren't lost and type-specific fields (rent price vs. exchange terms) reset/validate appropriately.
  • TC-03Attempt to submit with a required field missing (e.g. no images, no price) and confirm the app blocks submission with a visible error rather than sending an incomplete request.
  • TC-04Edit an existing listing via /edit-listing/[id] and confirm changes save without duplicating the listing or resetting untouched fields.
mobile-identity-switch

Switching identities changes context everywhere, with no data bleed

P0

Verify that POST auth/identity/switch correctly changes the active identity across the whole app, so that a user managing multiple identities never sees another identity's listings, chats, or favorites mixed into the current one. Note: switching TO a company/office identity currently lands on the ComingSoonGate (see mobile-company-office-gate) rather than a real home screen — verify that transition is clean, not broken.

No frame linked yet

Acceptance Criteria

  • AC-01After switching identity, Home/tabs immediately reflect the new role's UI (individual tabs, or the ComingSoonGate for company/office while the lock is active).
  • AC-02Listings, chats, and favorites shown are scoped strictly to the active identity.
  • AC-03Switching back to a previous identity restores its exact prior state (scroll position not required, but data must match).
  • AC-04Push notifications/chat sockets reconnect under the new identity's context rather than continuing to stream the old identity's events.

Test Scenarios

  • TC-01With an active chat open under identity A, switch to identity B and confirm identity A's conversation is no longer visible/reachable as B.
  • TC-02Switch identities repeatedly (A→B→A) and confirm no duplicated tabs, stale cached screens, or crash.
  • TC-03If a test account has a pre-existing company/office identity, switch to it and confirm landing cleanly on ComingSoonGate rather than a half-rendered tab bar underneath it.
mobile-payments

Tap payment checkout completes and reconciles invoices correctly

P0

Verify the Tap payment gateway flow (POST payments/charge → redirect → /payment-callback → webhook → GET payments/status/:invoiceId) correctly reflects success and failure states, so that users are never charged without an invoice being marked paid, or shown 'success' when payment actually failed.

No frame linked yet

Acceptance Criteria

  • AC-01A successful Tap payment redirects to /payment-callback showing a success state, and the related invoice's status updates (visible in more/invoices).
  • AC-02A declined/cancelled Tap payment redirects to a failure state and does not mark the invoice as paid.
  • AC-03Webhook-driven status updates are reflected even if the user closes the app before the redirect completes (poll GET status/:invoiceId on next launch).
  • AC-04Account balance (more/account-balance) reflects completed payments accurately.

Test Scenarios

  • TC-01Complete a full checkout with Tap test card success credentials and confirm invoice + balance update.
  • TC-02Trigger a decline (Tap test card failure credentials) and confirm no invoice is falsely marked paid, and the user sees a clear failure message.
  • TC-03Start a payment, force-close the app before the in-app redirect fires, reopen, and confirm the invoice status still resolves correctly (webhook already landed server-side).
  • TC-04Double-submit a charge (rapid double-tap 'Pay') and confirm no duplicate charge/invoice is created.
mobile-ipad-layout

Responsive layout holds up on iPad breakpoints

P2

Verify the ContentContainer responsive breakpoints (md:/lg: Tailwind classes per docs/plans/07-ipad-layout.md) render correctly on iPad form factors, so that the App Store review team (and real iPad users) don't see a stretched/broken phone layout.

No frame linked yet

Acceptance Criteria

  • AC-01Key screens (Home, Search, Property Detail, Chat) use constrained/centered content width on iPad rather than full-bleed phone layout.
  • AC-02Rotating an iPad between portrait and landscape doesn't break layout or clip content.
  • AC-03Modals and bottom sheets (auth sheet, filter sheet, action sheet) remain usable and centered on iPad, not pinned oddly to a phone-sized area.

Test Scenarios

  • TC-01Run through Home → Search → Property Detail → Chat on an iPad simulator (or device) in both orientations.
  • TC-02Open the Authentication Bottom Sheet and GlobalFilterSheet on iPad and confirm they aren't stretched edge-to-edge in a way that looks broken.
  • TC-03Compare against the demo account (see mobile-demo-account) screens specifically, since those are what App Store reviewers will see.
mobile-demo-account

App Store demo account has believable, working seeded data

P0

Verify the demo account (demo@buyootna.cloud, per docs/plans/08-demo-account.md) has working seeded properties, a draft listing, favorites, chats, and an active subscription, so that App Store reviewers logging in with this account see a fully functional app rather than empty screens that could trigger another 4.2.2-style rejection.

No frame linked yet

Acceptance Criteria

  • AC-01Logging in as the demo account succeeds without OTP friction (or with clearly documented reviewer-facing OTP steps).
  • AC-02Home/Search show seeded, real-looking properties — not empty states.
  • AC-03The seeded draft listing is editable and viewable in add-listing/edit-listing flows.
  • AC-04Seeded favorites and chats are visible and navigable (chat thread has readable seeded messages).
  • AC-05The seeded subscription/plan shows correctly under more/plans and more/invoices.

Test Scenarios

  • TC-01Fresh install → log in as demo account → walk every guarded action (Chat, Favorites, Add Ad, etc.) end to end with no auth-sheet interruptions.
  • TC-02Confirm the seeded data survives a backend restart/reseed cycle (i.e. the seed script is idempotent and reviewer access doesn't silently break).
  • TC-03Verify no seeded content contains placeholder/lorem text visible to a reviewer.
  • TC-04Confirm the demo account is an Individual identity (not company/office), since those are gated — see mobile-company-office-gate.