Files
Salon/docs/frontend-spec-requirements.md
T

9.5 KiB

Frontend Technical Specs and Requirements (MVP)

Purpose

Define the implementation contract for the React frontend against the current backend REST API so the customer flows (auth, search, booking, payment, profile) can ship reliably for KSA.

Scope

In scope:

  • Customer web app (React + Vite) for Phase 1 flows.
  • API integration contracts for current backend endpoints.
  • UX/error/loading behavior and test requirements.
  • i18n/RTL and KSA timezone handling.

Out of scope (Phase 2+):

  • Manager/staff admin dashboards.
  • Advanced reporting/reviews moderation tools.
  • Full observability product dashboards.

Product and Platform Constraints

  • Market default: KSA first.
  • Default locale: ar-sa; fallback: en.
  • Timezone baseline: Asia/Riyadh (+03:00).
  • API error contract: HTTP status + detail where applicable.
  • Booking/payment operations must avoid duplicate side effects.

UX Priorities (Primary Contract)

  • First screen for authenticated and guest users MUST be a feed of nearby/available salons.
  • The feed is the default home experience and primary entry to booking.
  • Main customer navigation MUST be bottom tabs (mobile-first), not header-first navigation.
  • Bottom tabs MUST include at minimum:
    • Home/Feed
    • Bookings
    • Profile
  • Optional tabs (when implemented) may include Search/Explore and Payments, but must not displace Home/Feed as default.

Frontend Architecture Requirements

Runtime and Stack

  • React 18 + Vite.
  • React Router (BrowserRouter) for route navigation.
  • i18next + react-i18next for translations and direction switching.
  • fetch wrapper in src/api/client.js as single API boundary.
  • Auth/session state in AuthContext.

Route Map (Customer)

  • / home feed (nearby/available salons) + search/filter.
  • /salon/:id salon detail.
  • /login phone OTP login.
  • /book?salon=<id> booking creation.
  • /pay?booking=<id> payment initiation.
  • /pay/return payment callback/return surface.
  • /bookings customer booking history.
  • /profile customer profile summary.

Module Boundaries

  • src/api/: all HTTP logic, standardized errors.
  • src/contexts/: auth/session lifecycle only.
  • src/hooks/: domain-side UI logic (useSalonSearch, usePaymentForm).
  • src/pages/: route-level composition.
  • src/components/: reusable presentation and guarded wrappers.
  • src/i18n/: locale dictionaries and locale/direction state.

Functional Requirements

FR-1 Phone-First Authentication

  • Login MUST use:
    • POST /api/auth/phone/request/
    • POST /api/auth/phone/verify/
  • Password auth endpoint (/api/auth/token/) MUST NOT be used (returns 410).
  • Login request form MUST collect:
    • phone_number (accept KSA local or E.164 input)
    • channel (sms or whatsapp)
    • optional: device_id (recommended for abuse controls)
  • Verify step MUST submit request_id + 6-digit code.
  • On success, frontend MUST persist access and refresh tokens and user payload.

FR-2 Session Restore and Token Refresh

  • On app boot, if access exists:
    • call GET /api/auth/me/.
  • If 401/token invalid:
    • call POST /api/auth/token/refresh/ once.
    • retry GET /api/auth/me/ with new access token.
  • If refresh fails, frontend MUST clear tokens and require re-login.

FR-3 Salon Discovery

  • Home MUST render a salon feed by default on first load.
  • Feed data MUST come from GET /api/salons/ and support query params for discovery.
  • Home search MUST call GET /api/salons/?q=<query>.
  • Search SHOULD support additional filters when UI is added:
    • city
    • service
  • Nearby/available ranking can be client-side initially, but server response MUST remain source of truth.
  • Result cards MUST link to /salon/:id.

FR-4 Salon Detail

  • Detail page MUST call GET /api/salons/:id/.
  • UI MUST render:
    • salon base info
    • services (duration, amount, currency)
    • staff list
    • optional reviews/photos if present
  • CTA MUST deep-link to booking flow with salon id.

FR-5 Booking Creation

  • Booking page MUST require authenticated user.
  • Create booking with POST /api/bookings/ using:
    • service
    • staff (required)
    • start_time
    • end_time
    • optional notes
  • end_time MUST match service duration exactly.
  • Datetime submitted to backend MUST include explicit offset (+03:00 for KSA baseline).
  • On success (201), frontend MUST navigate to payment flow with booking id.

FR-6 Booking History

  • /bookings MUST call authenticated GET /api/bookings/.
  • List MUST show booking id, status, salon/service labels, datetime, and price.
  • Datetime rendering MUST use active locale formatting.

FR-7 Payment Initiation (Idempotent)

  • Payment submission MUST call POST /api/payments/.
  • Payload requirements:
    • booking_id (number)
    • provider = moyasar
    • idempotency_key (UUID)
    • source object with supported type (stcpay, token, applepay, samsungpay)
    • callback_url required for source.type=token
  • Frontend MUST disable duplicate submits while request is in-flight.
  • Same payment attempt retry MUST reuse the same idempotency_key.
  • New attempt MUST generate a new key.
  • If response includes redirect_url, frontend MUST redirect.

FR-8 Payment Return Handling

  • /pay/return MUST parse query params:
    • status
    • id
  • Success statuses shown as success UX: paid, captured, authorized.
  • Non-success statuses MUST show neutral/pending/failure guidance and link to profile/bookings.

FR-9 Locale and Direction

  • App MUST allow switching between ar-sa and en.
  • Locale switch MUST:
    • persist preference in local storage
    • set <html lang>
    • set <html dir> (rtl for ar-sa, ltr for en)
  • API calls MUST include Accept-Language header with active locale.

API Contract Requirements

Endpoint Auth Request Success Error handling
POST /api/auth/phone/request/ No phone_number, channel, optional profile fields 201 with request_id, expires_at 429 may include retry_after_seconds; show wait message
POST /api/auth/phone/verify/ No request_id, code 200 with access, refresh, user 400 invalid/expired code
POST /api/auth/token/refresh/ No refresh 200 with new access logout on failure
GET /api/auth/me/ Bearer - 200 user payload 401 triggers refresh flow
GET /api/salons/ No q, optional city, service 200 list show localized generic fetch error
GET /api/salons/:id/ No - 200 detail object show detail/fallback
POST /api/bookings/ Bearer booking payload 201 booking 400 field validation errors
GET /api/bookings/ Bearer - 200 list auth + generic errors
POST /api/payments/ Bearer payment payload 201 created or 200 reused idempotent record 400/403 with details; never auto-retry with new key

Error and State Handling Requirements

  • API wrapper MUST throw structured errors with:
    • HTTP status
    • parsed response body
    • best message (detail first, fallback to response text)
  • For validation objects ({field: [msg]}), UI SHOULD render first field message near form and keep raw object in debug logs.
  • For 429 with retry_after_seconds, UI MUST display server-provided cooldown.
  • All mutating forms MUST expose:
    • idle/loading/error/success states
    • submit button disabled while loading

Security and Abuse-Resistance Requirements

  • Use Bearer access token for authenticated endpoints only.
  • Include optional device_id during phone auth request to strengthen backend abuse controls.
  • Never send raw card PAN/CVV data to backend; use tokenized sources only.
  • On logout, clear user and both tokens from memory + storage.

Accessibility and UX Requirements

  • All interactive controls MUST have accessible labels.
  • Auth/booking/payment forms MUST be keyboard usable.
  • Error text MUST be visible and associated with active form context.
  • Layout MUST remain usable on mobile widths (>=320px) and desktop.

Non-Functional Requirements

  • Reliability: no duplicate payment submission side effects for one attempt.
  • Consistency: API errors surfaced predictably and localized where available.
  • Maintainability: domain behavior in hooks/services, not route components.
  • Extensibility: route/module structure must support manager/staff pages later without rewrite.

Test Requirements (Frontend)

  • Test stack: vitest + Testing Library.
  • Required coverage for release:
    • phone login request + verify success/failure + 429 cooldown message
    • auth restore and refresh-token fallback
    • protected route redirect behavior
    • salon search loading/empty/results/error
    • booking form validation + API error mapping + success redirect
    • payment form source validation + idempotency key reuse on retry + redirect behavior
    • locale switching persists and sets lang/dir
    • bookings list rendering and localized datetime output

Run:

  • cd frontend && npm run test

Definition of Done (Frontend)

  • All FR requirements implemented for in-scope routes.
  • API integrations match endpoint/payload contract above.
  • No use of deprecated password login API.
  • All listed frontend tests pass.
  • ar-sa and en UX verified on mobile + desktop.

Known Dependencies and Open Decisions

  • OAuth/social-linking policy is not finalized; keep social login UI hidden for now.
  • Cancellation and refund policies are not finalized; do not ship irreversible customer actions until policy finalization.
  • Detailed business-hours/timezone policy beyond current backend validation remains open; keep KSA-offset submission and avoid client-side assumptions that override server validation.