Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Tenant Portal — Mobile App

React Native + Expo (SDK 57) tenant portal: rent payments, maintenance ticketing, notices and lease details. Styled with NativeWind, navigated with Expo Router.

Stack

Concern Choice
Runtime Expo SDK 57 · React Native 0.86 · React 19.2
Navigation Expo Router (stack + bottom tabs, typed routes)
Styling NativeWind 4.2 (Tailwind 3.4) with dark: variants
Data Axios + useQuery / useMutation hooks (no query library)
Session expo-secure-store (tokens) + AsyncStorage (cached profile)
Media expo-image-picker (camera + library, up to 4 photos)

Directory structure

src/
  app/                        # Expo Router file-based routes
    _layout.tsx               # Providers, splash gate, root stack, auth guard
    index.tsx                 # Entry redirect (dashboard vs sign-in)
    sign-in.tsx               # Email/password auth
    (tabs)/
      _layout.tsx             # Bottom tab navigator (5 tabs)
      dashboard.tsx           # Rent status, quick actions, active requests
      payments.tsx            # Billing history + filters
      maintenance.tsx         # Ticket list + status filters
      notices.tsx             # Announcement feed
      profile.tsx             # Profile & lease details
    ticket/
      new.tsx                 # Create ticket (modal): category, priority, photos
      [id].tsx                # Ticket detail + activity timeline
    checkout.tsx              # Mock secure payment gateway (modal)
    receipt/[id].tsx          # Invoice / receipt

  api/                        # One module per resource; all HTTP lives here
    client.ts                 # Axios instance, auth header, refresh, ApiError
    auth.ts dashboard.ts payments.ts tickets.ts announcements.ts profile.ts

  hooks/
    use-query.ts              # Loading / error / refresh / refetch-on-focus
    use-mutation.ts           # Writes with pending + error state
    use-dashboard.ts use-tickets.ts use-payments.ts ...

  providers/auth-provider.tsx # Session restore, sign in/out, 401 handling
  components/                 # Feature components (rent card, ticket row, ...)
    ui/                       # Card, Badge, Button, Field, Chip, Screen, states
  constants/
    config.ts                 # API URL resolution
    domain.ts                 # Status → label/colour metadata (single source)
  lib/                        # storage.ts, format.ts
  types/api.ts                # Wire types mirroring the API

Why these boundaries

  • api/ never imports from components/. Screens depend on hooks, hooks depend on services, services depend on the client. Swapping the transport touches one file.
  • Status metadata lives in constants/domain.ts. A badge, a filter chip and a timeline row cannot drift apart on wording or colour.
  • useQuery takes a memoised fetcher as its dependency. Wrap the call in useCallback and the query re-runs exactly when its inputs change.

Navigation

A root stack owns the auth screen, the tab group and the modal/detail screens; the (tabs) group owns the five primary destinations.

Stack (root)
├── index          → redirect
├── sign-in        → headerShown: false
├── (tabs)         → Dashboard · Rent · Requests · Notices · Profile
├── ticket/new     → modal
├── ticket/[id]    → pushed detail
├── checkout       → modal
└── receipt/[id]   → pushed detail

The guard lives in src/app/_layout.tsx: it holds the splash screen until the stored session is restored, then bounces between /sign-in and /dashboard.

Setup

npm install
npm start          # then i / a, or scan with a dev build

Point the app at the API with EXPO_PUBLIC_API_URL:

# .env
EXPO_PUBLIC_API_URL=http://192.168.1.9:4000

When it is unset the app derives the host from the Metro connection, so a phone on the same Wi-Fi reaches the dev machine without configuration. localhost only works on a simulator.

The API is expected at <origin>/api and must be reachable for anything past the sign-in screen.

Scripts

npm start          # Metro
npm run ios        # native build + run
npm run android
npm run lint       # ESLint (expo config)
npx tsc --noEmit   # typecheck
npx expo-doctor    # dependency/config validation

Notes

  • expo-secure-store has no web implementation; the storage adapter falls back to AsyncStorage for expo start --web. A browser build shipping to users should use the API's httpOnly cookie flow instead.
  • Photo uploads are capped at 4 images / 5MB each and compressed to quality: 0.7 before upload.
  • The payment screen is a mock gateway. The request → confirm → receipt flow is what survives swapping in a real provider; only the pay() call changes.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages