diff --git a/repositories/d-sports-engage-native.mdx b/repositories/d-sports-engage-native.mdx index e79c1b6..cd2cfff 100644 --- a/repositories/d-sports-engage-native.mdx +++ b/repositories/d-sports-engage-native.mdx @@ -6,71 +6,130 @@ icon: "smartphone" ## Overview -**d-sports-engage-native** (package name: `engage-native`) is the native mobile app for D-Sports. It mirrors the core PWA experience on iOS and Android: wallet, shop, leaderboard, locker room, and profile. +**d-sports-engage-native** (package name: `engage-native`, version **1.17.3**) is the native mobile app for D-Sports. It mirrors the core PWA experience on iOS, Android, and web: wallet, shop, leaderboard, locker room, and profile. -- **Run:** `bunx expo start` or `bun run start` — then press `a` for Android or `i` for iOS, or scan the QR code with Expo Go. +```bash +# Install dependencies +bun install + +# Start development server +bunx expo start +# Press 'a' for Android, 'i' for iOS, or scan QR with Expo Go +``` ## Tech stack -| Category | Technology | -| ---------- | ------------------------- | -| Framework | Expo 54, React Native 0.81, React 19 | -| Auth | Clerk (Expo) | -| Payments | RevenueCat (react-native-purchases) | -| Web3 | Thirdweb | -| State | Zustand | -| Storage | MMKV | -| UI | Lucide React Native | -| Navigation | Expo Router | -| Package | Bun | +| Category | Technology | +| ----------- | ------------------------------------------- | +| Framework | Expo 54, React Native 0.81, React 19 | +| Auth | Clerk (Expo) | +| Payments | RevenueCat (react-native-purchases) | +| Web3 | Thirdweb 5.x (Arbitrum, Ethereum, Polygon) | +| State | Zustand 5 + MMKV 4 persistence | +| UI | Lucide React Native, Reanimated 4 | +| Navigation | Expo Router 6 (typed routes) | +| Monitoring | Sentry, OneSignal | +| Package | Bun | ## Features - **Wallet** — Tokens, holdings, pack opening, crypto checkout (via PWA backend) -- **Shop** — Collectibles, cart, coin bundles, checkout -- **Leaderboard** — Rankings and filters -- **Locker room** — Social feed and engagement -- **Profile** — User profile and settings -- **Theme** — Dark/light mode (default dark) - -## What changed since last docs sync - -- Team-aware experiences were expanded to align with backend team/favorites behavior. -- Quest and rewards surfaces were updated to support per-team progression and pass-aware eligibility. -- Pack opening and odds disclosure UX were upgraded with safer interactions and clearer status/error handling. -- Settings and account flows were expanded, including in-app account deletion and richer support/data controls. +- **Shop** — Collectibles, cart, coin bundles, fiat (RevenueCat) and crypto (Thirdweb) checkout +- **Leaderboard** — Rankings, filters, and team-scoped views +- **Locker room** — Social feed, quests, daily games (Pick'Em, Spin Wheel, Guess the Player) +- **Profile** — User profile, achievements, badges, milestone avatars, follow lists +- **Settings** — Account, appearance, accessibility, notifications, support, legal, changelog +- **Theme** — Dark/light mode (default dark, base `#0a0e1a`) + +## Project structure + +```tree +app/ +├── (auth)/ # Login, signup, SSO callback, password reset +├── (onboarding)/ # New user onboarding flow +├── (tabs)/ # Main tab navigation (5 tabs) +│ ├── wallet.tsx # Wallet screen (JSX only — logic in hook) +│ ├── shop.tsx # Shop screen (JSX only — logic in hook) +│ ├── leaderboard/ # Leaderboard with team sub-routes +│ ├── locker-room/ # Social feed with game sub-routes +│ └── profile.tsx # User profile +├── settings/ # 15+ settings pages +└── _layout.tsx # Root layout with providers + auth guard + +components/ +├── wallet/ # 9 extracted wallet sub-components +├── shop/ # 7 extracted shop sub-components +├── locker-room/ # Feed, quests, games, explore components +├── leaderboard/ # Base leaderboard and team views +├── profile/ # Achievements, badges, milestone avatar +├── settings/ # Setting items, sections, modals, tabs +├── ui/ # Reusable UI primitives +└── Icon/ # Lucide icon wrapper + +hooks/ # Feature hooks (wallet, shop, feed, etc.) +lib/api/ # API client modules with MMKV cache +context/ # User, collectibles, navbar, action contexts +theme/ # Colors, typography, spacing tokens +``` + +## Environment variables + +All runtime variables use the `EXPO_PUBLIC_` prefix. You need to configure the following in your `.env`: + +| Variable | Purpose | +| ---------------------------------------- | ------------------------------ | +| `EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY` | Clerk authentication | +| `EXPO_PUBLIC_API_URL` | Backend API base URL | +| `EXPO_PUBLIC_TW_CLIENT_ID` | Thirdweb Web3 client | +| `EXPO_PUBLIC_REVENUECAT_API_KEY` | RevenueCat in-app purchases | +| `EXPO_PUBLIC_REVENUECAT_APPSTORE_ID` | RevenueCat App Store ID | +| `EXPO_PUBLIC_REVENUECAT_ENTITLEMENT` | RevenueCat entitlement name | +| `EXPO_PUBLIC_SUPABASE_URL` | Supabase client URL | +| `EXPO_PUBLIC_SUPABASE_KEY` | Supabase publishable key | + +## EAS build profiles + +Builds are managed through EAS with the following profiles: + +| Profile | Use case | Distribution | +| --------------------- | --------------------------------- | ------------ | +| `development` | Dev client (simulator) | Internal | +| `development-device` | Dev client (physical device) | Internal | +| `preview` | Internal testing (APK on Android) | Internal | +| `staging` | Pre-release validation | Auto-increment | +| `production` | App Store / Play Store | Auto-increment | + +```bash +# Development build +bun run build:dev + +# Preview build +bun run build:preview + +# Production build + auto-submit (iOS) +bun run build:submit:ios + +# OTA update +bun run update +``` ## Backend integration surfaces - Primary API source: `d-sports-api` under `/api/*`. - Native app consumes team, league, quest, reward, wallet, commerce, and social endpoints. -- Retry/caching logic and auth token injection are centralized in app API client modules. - -## Quest and pass UX integration +- Retry/caching logic and auth token injection are centralized in `lib/api/client.ts`. +- MMKV cache-first fetching via `lib/api/cache.ts` provides offline resilience. -- Quest UI now reflects team-scoped eligibility and pass-gated progression where applicable. -- Reward presentation differentiates free/unpaid states and claimability. -- Native progression state is expected to mirror backend eligibility and completion semantics. +## Checkout and payments -## Team-aware experiences - -- Team discovery, favorite-team interactions, and leaderboard context are integrated across locker room and profile surfaces. -- Team and league metadata is sourced from backend sync pipelines fed by the `leagues` repository. +- **Fiat payments** — RevenueCat handles Apple IAP (native), Google Play (native), and Stripe (web). +- **Crypto payments** — Thirdweb SDK signs on-chain transactions via `POST /api/checkout/crypto` and `POST /api/checkout/crypto/verify` on the PWA backend. Supported chains: Arbitrum (default), Ethereum, Polygon. ## Compliance and legal: pack opening odds - Native odds disclosure behavior is documented with policy-aligned copy and evidence requirements. - Disclosure values must come from backend payloads and remain visible/accessible near open actions. -## Getting started - -1. Clone the repository and run `bun install`. -2. Configure environment (Clerk, RevenueCat, Thirdweb, API base URL) per repo README. -3. Run `bunx expo start`. -4. For development builds: `bun run build:dev` (EAS) or run with Expo dev client. - -The app targets both native and web (responsive) and uses the same backend (d-sports-api) as the PWA for API and checkout flows. - ## Deep dives - [Architecture](/repositories/d-sports-engage-native/architecture) diff --git a/repositories/d-sports-engage-native/architecture.mdx b/repositories/d-sports-engage-native/architecture.mdx index af786e3..5eb17f3 100644 --- a/repositories/d-sports-engage-native/architecture.mdx +++ b/repositories/d-sports-engage-native/architecture.mdx @@ -3,28 +3,81 @@ title: "Native architecture" description: "Architecture overview for d-sports-engage-native application layers and platform behavior." --- -## App architecture +## Routing -The native app is structured around Expo Router screens, feature-oriented components, shared hooks, and API modules. +The app uses **Expo Router 6** with file-based routing and typed routes enabled. Route groups organize the navigation hierarchy: -- Routing: `app/*` with grouped routes for tabs/auth/onboarding/settings. -- Feature logic: extracted hooks for wallet, shop, locker room, and settings. -- Shared contexts: user, collectibles, accessibility, and UI visibility/state controls. +| Route group | Purpose | +| ----------------- | ----------------------------------------- | +| `(auth)/` | Login, signup, SSO callback, password reset | +| `(onboarding)/` | New user onboarding flow | +| `(tabs)/` | Main 5-tab navigation | +| `settings/` | Settings pages with nested modals/tabs | -## State and context boundaries +The root layout (`app/_layout.tsx`) wraps the app in provider hierarchy (Clerk, RevenueCat, Thirdweb, user context, theme, accessibility) and handles auth-based redirects. -- Local/ephemeral UI state lives near feature hooks and components. -- Cross-screen state is managed with context providers and persisted storage where required. -- User/session-sensitive state is coordinated with backend auth and profile sync endpoints. +## Screen-hook pattern -## API client and retry behavior +Screen files contain **only imports and JSX**. All state, effects, and handlers live in dedicated hooks: -- All network calls route through `lib/api/*` modules. -- Client wrappers handle auth token propagation, error normalization, and retry strategy. -- Quest/reward/team flows should consume backend eligibility as source of truth. +- `hooks/use-wallet-screen.ts` — wallet state, token fetch, PIN verification, transaction handlers +- `hooks/use-shop-screen.ts` — cart state, product queries, carousel auto-scroll, checkout logic +- `hooks/use-feed-section.ts` — locker room feed loading, pagination, interactions + +Sub-components are extracted into `components/wallet/`, `components/shop/`, and `components/locker-room/` with barrel exports via `index.ts`. + +## Tab bar architecture + +The tab bar implementation differs by platform: + +- **iOS** — `app/(tabs)/_layout.ios.tsx` uses `NativeTabs` from `expo-router/unstable-native-tabs` for system tab bar behavior. Uses `systemChromeMaterialDark` material with gold selection tint (`#FFD700`). +- **Android and web** — `app/(tabs)/_layout.tsx` renders a custom `PillTabBar` overlay with `expo-blur` and tints from `tab-config.ts`. +- **Shared config** — `app/(tabs)/tab-config.ts` defines tab order, SF Symbol pairs (iOS), and active-tab pathname matching rules. + +## State management + +| Layer | Technology | Scope | +| ---------------- | ---------------- | ------------------------------ | +| Global store | Zustand 5 | Theme, cart, points | +| Persistence | MMKV 4 | Synchronous read/write | +| Auth and profile | React Context | `UserContext` in `context/` | +| Collectibles | React Context | `CollectiblesContext` | +| UI visibility | React Context | Navbar visibility, FAB state | +| Accessibility | React Context | Font scale, reduced motion | + +Zustand persistence uses an MMKV adapter (`services/storage.ts`). The store (`services/store.ts`) provides `getItem()`, `setItem()`, and `removeItem()`. + +## API client layer + +All network calls route through `lib/api/*` modules: + +- `lib/api/client.ts` — base HTTP client with auth token injection and error normalization +- `lib/api/cache.ts` — `fetchWithCache()` MMKV cache-first fetching for offline resilience +- Domain modules: `wallet-api`, `shop-api`, `user-api`, `quests-api`, `leaderboard-api`, `locker-room-api`, `teams-api`, `collectibles-api`, `checkout-api`, `games-api` +- `lib/api/index.ts` — `useApi()` hook that exposes all modules + +Quest, reward, and team flows consume backend eligibility as the source of truth. + +## Theme system + +- `theme/colors.ts` — brand colors (Gold `#F5C842`, Royal Blue `#4169E1`), dark/light palettes with base dark `#0a0e1a` +- `theme/typography.ts` and `theme/fonts.ts` — type scale and font definitions +- `theme/spacing.ts` — spacing tokens +- `components/theme-provider.tsx` — `useTheme()` hook provides `resolvedTheme` ## Platform-specific behavior -- iOS/Android platform differences are handled in native-specific components and runtime checks. -- Web-target support exists but mobile behavior is primary for interaction and performance design. -- Haptics, modal controls, and animation handling are implemented with platform-safe fallbacks. +- **iOS** — Native tab bar (Liquid Glass), Apple Sign-In, haptic feedback, system push via OneSignal +- **Android** — Custom pill tab bar with blur, edge-to-edge layout, adaptive icon +- **Web** — PWA-ready (`display: standalone`), responsive `maxWidth: 480px` container (`components/layout/AppScreen.tsx`), web hover states via `WebHoverWrapper`, keyboard navigation support +- Haptics, modal controls, and animations use platform-safe fallbacks via Reanimated 4 + +## Path aliases + +Import using the `@/*` alias (maps to project root): + +```typescript +import { useUser } from "@/context/user-context"; +import { getTokenColors } from "@/lib/token-utils"; +import type { Token } from "@/types/wallet.types"; +``` diff --git a/repositories/d-sports-engage-native/feature-mapping.mdx b/repositories/d-sports-engage-native/feature-mapping.mdx index 27fbcd7..ce69b44 100644 --- a/repositories/d-sports-engage-native/feature-mapping.mdx +++ b/repositories/d-sports-engage-native/feature-mapping.mdx @@ -5,22 +5,70 @@ description: "Native feature coverage and parity mapping against backend/PWA beh ## Feature parity with backend/PWA -`d-sports-engage-native` targets high parity with `d-sports-api` feature behavior while optimizing for mobile UX patterns. +`d-sports-engage-native` targets high parity with `d-sports-api` feature behavior while optimizing for mobile UX patterns. The table below summarizes surface coverage: + +| Surface | Native status | Key components | +| -------------------- | ------------- | --------------------------------------- | +| Wallet | Full | Token list, holdings, pack opening, crypto checkout | +| Shop | Full | Collectibles, cart, coin bundles, fiat + crypto | +| Leaderboard | Full | Global and team-scoped rankings | +| Locker room | Full | Feed, quests, daily games | +| Profile | Full | Achievements, badges, milestone avatars, follows | +| Settings | Full | 15+ pages including account deletion | +| Notifications | Full | OneSignal push + in-app notifications | +| Onboarding | Full | Multi-step team selection flow | ## Wallet and pack opening - Wallet screens consume balances, token data, and secure key/pin flows from backend APIs. - Pack browsing, purchase, and open flows use backend-driven states and inventory refresh behavior. - Odds-disclosure surfaces read backend-provided probability payloads. +- Opened packs section tracks previously opened pack contents. +- Token detail modals show price history, send/receive actions, and connected wallet info. + +## Shop and checkout + +- Collectible browsing with rarity-based card styling and 3D model viewers (GLB via Filament on native, Three.js on web). +- Cart with quantity management, coin bundles, and featured pack carousels. +- **Fiat checkout** — RevenueCat handles Apple IAP, Google Play, and Stripe (web). +- **Crypto checkout** — Thirdweb SDK for on-chain transactions. Chains: Arbitrum (default), Ethereum, Polygon. Flow: wallet select → `prepareTransaction` → `sendTransaction` → poll verification. ## Quest, rewards, and pass surfaces - Quest UI supports team-aware progression and pass-gated eligibility. - Reward states and claim flows follow backend quest/reward APIs. - Global pass and event pass effects are reflected in native quest visibility/completion UX. +- Quest detail modals show requirements, progress, and reward previews. + +## Daily games + +- **Daily Pick'Em** — team-based prediction game with streak tracking. +- **Daily Spin Wheel** — animated prize wheel with reward distribution. +- **Guess the Player** — player identification game with hint system. + +Games are surfaced in the locker room via the `FeaturedGamesCarousel` component and backed by `lib/api/games-api.ts`. ## Team and leaderboard integration - Teams and leagues metadata are consumed from backend `/api/teams` and `/api/leagues`. - Leaderboard displays and team-scoped ranking views align with backend leaderboard contracts. - Favorite-team interactions influence quest and leaderboard context where backend eligibility requires it. +- Team detail modals show roster, stats, and fan community info. + +## Profile and achievements + +- Profile cards with header, stats, and follow/following counts. +- Achievement system with cards, chips, and detail modals. +- Milestone avatars with level-based visual progression. +- Badge system with cached images and asset resolution via `lib/badge-utils.ts`. +- Points history modal with transaction log. + +## Settings + +- **Account** — profile editing, connected accounts, blocked users, security, account deletion +- **Appearance** — theme toggle (dark/light) +- **Accessibility** — font scale, reduced motion, screen reader optimizations +- **Notifications** — push notification preferences +- **Support** — help center, contact support, report a problem +- **Legal** — terms of service, privacy policy, EULA +- **Changelog** — in-app version history diff --git a/repositories/d-sports-engage-native/integration-contracts.mdx b/repositories/d-sports-engage-native/integration-contracts.mdx index 82b923a..d265e18 100644 --- a/repositories/d-sports-engage-native/integration-contracts.mdx +++ b/repositories/d-sports-engage-native/integration-contracts.mdx @@ -3,10 +3,35 @@ title: "Integration contracts" description: "Backend-facing contracts and behavior expectations for native client integrations." --- -## Auth/session contracts +## Auth and session contracts -- Native auth uses backend-compatible token/session validation flows. +- Native auth uses **Clerk** for authentication with backend-compatible token/session validation. - Protected feature calls require authenticated user context and must handle session expiry gracefully. +- SSO callback handling in `app/(auth)/sso-callback.tsx` for OAuth providers. +- Email/password auth logic is centralized in `hooks/use-email-password-auth.ts`. + +## API client contracts + +All API calls flow through `lib/api/client.ts` which provides: + +- Automatic auth token injection from Clerk session +- Error normalization and consistent error response shapes +- Base URL configured via `EXPO_PUBLIC_API_URL` + +Domain-specific modules in `lib/api/` map to backend route groups: + +| Module | Backend routes consumed | +| ------------------- | -------------------------------------- | +| `user-api.ts` | `/api/user/*` — profile, settings, follows | +| `wallet-api.ts` | `/api/wallet/*` — balances, tokens, transactions | +| `shop-api.ts` | `/api/shop/*` — products, inventory | +| `checkout-api.ts` | `/api/checkout/*` — fiat and crypto payments | +| `collectibles-api.ts` | `/api/collectibles/*` — packs, items | +| `quests-api.ts` | `/api/quests/*` — progression, claims | +| `leaderboard-api.ts`| `/api/leaderboard/*` — rankings | +| `locker-room-api.ts`| `/api/locker-room/*` — posts, comments | +| `teams-api.ts` | `/api/teams/*`, `/api/leagues/*` | +| `games-api.ts` | `/api/games/*` — daily games | ## Quest and reward API contracts @@ -20,8 +45,22 @@ description: "Backend-facing contracts and behavior expectations for native clie - League metadata and branding come from `/api/leagues`. - Synced canonical data changes can propagate asynchronously; client should tolerate short-lived staleness. +## Checkout contracts + +- **Fiat** — RevenueCat SDK communicates with Apple/Google/Stripe. Server-side receipt validation happens through RevenueCat webhooks. +- **Crypto** — Client calls `POST /api/checkout/crypto` to get payment parameters, signs with Thirdweb, then polls `POST /api/checkout/crypto/verify` for confirmation. + +## Caching behavior + +`lib/api/cache.ts` implements MMKV-backed cache-first fetching: + +- Cached responses are returned immediately while a background refresh occurs. +- Cache keys are derived from the request URL and parameters. +- Stale data is acceptable for read-heavy surfaces (leaderboards, team lists) but mutations always hit the network. + ## Error handling and fallback UX - Show user-actionable errors for purchase/open/claim failures. - Avoid silent failures for mutation endpoints. - Use retry/backoff for transient network failures; avoid retry storms on authorization or validation errors. +- Structured logging via `lib/logger.ts` with Sentry integration for error tracking.