# El Captain Flutter Client

Guardian & Participant mobile app for El Captain Sports Management platform.

## Stack

| Layer | Technology |
|-------|-----------|
| Framework | Flutter 3.44.2 / Dart 3.12.2 |
| State | flutter_riverpod 2.6 |
| Navigation | go_router 14.6 |
| HTTP | dio 5.7 (Sanctum bearer tokens) |
| Animations | flutter_animate 4.5 |
| Push | firebase_messaging 15.1 |
| Local auth | flutter_secure_storage |

## Architecture

```
lib/
├── config/
│   └── instance.dart          # Per-client config (base URL, app name, package ID)
├── core/
│   ├── api/
│   │   ├── api_client.dart    # Dio setup, auth interceptor, error handler
│   │   └── api_service.dart   # 59 endpoint methods
│   ├── auth/
│   │   └── auth_store.dart    # Riverpod notifier (token, user, participants)
│   ├── l10n/
│   │   ├── app_localizations.dart  # Arabic/English string map
│   │   └── locale_provider.dart    # Locale toggle (persisted)
│   ├── router/
│   │   └── app_router.dart    # GoRouter config with animated transitions
│   ├── theme/
│   │   ├── app_theme.dart     # Light theme, Cairo/Inter fonts, colors
│   │   └── app_animations.dart # Custom page transitions
│   ├── utils/
│   │   └── money.dart         # formatMoney(int piasters) → "X.XX ج.م"
│   └── widgets/
│       ├── animated_card.dart
│       └── loading_overlay.dart
└── features/
    ├── splash/            # Animated splash → auth check → route
    ├── auth/
    │   ├── login_screen.dart    # Phone input → OTP request
    │   └── otp_screen.dart      # 6-digit OTP → token
    ├── home/
    │   ├── home_shell.dart      # Bottom nav shell (dashboard, schedule, notifications, profile)
    │   └── dashboard_screen.dart # Children cards, stats, today sessions
    ├── schedule/          # Day picker + session list
    ├── notifications/     # Paginated notification list
    ├── profile/           # Settings, language toggle, logout
    ├── participants/      # Participant detail + action grid
    ├── attendance/        # Paginated attendance records
    ├── invoices/          # Invoice list with status badges
    ├── evaluations/       # Evaluation cards with criteria bars
    ├── events/            # Academy events list
    ├── shop/              # Product grid
    ├── messages/          # Message history
    ├── service_requests/  # Request form + list
    └── registration/      # Self-registration (pre-register flow)
```

## Instance Configuration

Edit `lib/config/instance.dart` to point to a specific client's backend:

```dart
class InstanceConfig {
  static const String baseUrl = 'https://oc-sport.caprover.al-arcade.com';
  static const String appName = 'OC Sport';
  static const String appNameAr = 'او سي سبورت';
  static const String packageId = 'com.ocsport.app';

  static const String apiVersion = 'v1';
  static String get apiUrl => '$baseUrl/api/$apiVersion';
}
```

## Current Deployment

| Field | Value |
|-------|-------|
| Backend URL | `https://oc-sport.caprover.al-arcade.com` |
| API Base | `https://oc-sport.caprover.al-arcade.com/api/v1` |
| Academy | او سي سبورت (OC Sport) |
| Admin Email | admin@oc-sport.com |
| Admin Password | ocsportadmin |
| OTP Mode | demo (code is always `123456`) |
| Admin Phone | +201000000001 |

## Authentication Flow

1. User enters phone number (Egyptian format: `01XXXXXXXXX`)
2. App calls `POST /auth/otp/request` → backend caches OTP (demo: `123456`)
3. User enters 6-digit code
4. App calls `POST /auth/otp/verify` → returns `{ token, user, participants }`
5. Token stored in `flutter_secure_storage`
6. All subsequent requests include `Authorization: Bearer {token}`
7. On 401 response, user is redirected to login

## API Endpoints (59 routes)

### Public (no auth required)

| Method | Path | Description |
|--------|------|-------------|
| GET | `/health` | Health check |
| GET | `/app/config` | Academy info, theme, features, auth config |
| POST | `/auth/otp/request` | Request OTP (body: `{phone}`) |
| POST | `/auth/otp/verify` | Verify OTP (body: `{phone, otp}`) → token |

### Auth (Bearer token required)

| Method | Path | Description |
|--------|------|-------------|
| GET | `/auth/me` | Current user + linked participants |
| POST | `/auth/logout` | Revoke current token |
| GET | `/profile` | User profile data |
| PATCH | `/profile` | Update profile |
| POST | `/profile/photo` | Upload profile photo |

### Dashboard & Children

| Method | Path | Description |
|--------|------|-------------|
| GET | `/dashboard` | Children, totals, today sessions, announcement |
| GET | `/guardian/children` | List linked participants |

### Participant Detail

All participant endpoints require the logged-in user to be linked as a guardian.

| Method | Path | Description |
|--------|------|-------------|
| GET | `/participants/{uuid}` | Full participant detail |
| GET | `/participants/{uuid}/summary` | Stats summary (rate, balance, enrollments) |
| GET | `/participants/{uuid}/schedule` | Weekly schedule |
| GET | `/participants/{uuid}/attendance` | Paginated attendance records |
| GET | `/participants/{uuid}/invoices` | Paginated invoices |
| GET | `/participants/{uuid}/evaluations` | Evaluation list |
| GET | `/participants/{uuid}/evaluations/{evalUuid}` | Single evaluation detail |
| GET | `/participants/{uuid}/enrollments` | Active enrollments |
| GET | `/participants/{uuid}/wallet` | Wallet balance |
| GET | `/participants/{uuid}/wallet/transactions` | Wallet transaction history |
| GET | `/participants/{uuid}/documents` | Uploaded documents |
| GET | `/participants/{uuid}/installments` | Payment installments |

### Academy (public content)

| Method | Path | Description |
|--------|------|-------------|
| GET | `/academy/events` | Paginated events |
| GET | `/academy/events/{uuid}` | Event detail |
| GET | `/academy/news` | Paginated news |
| GET | `/academy/news/{uuid}` | News article detail |
| GET | `/academy/programs` | Training programs list |
| GET | `/academy/gallery` | Photo gallery |
| GET | `/branches` | Academy branches |

### Events Registration

| Method | Path | Description |
|--------|------|-------------|
| POST | `/events/{uuid}/register` | Register participant for event |
| GET | `/events/my-registrations` | User's event registrations |

### Shop & Orders

| Method | Path | Description |
|--------|------|-------------|
| GET | `/products` | Product catalog |
| POST | `/orders/create` | Place an order |
| GET | `/orders` | Order history |

### Payments

| Method | Path | Description |
|--------|------|-------------|
| POST | `/payments/initiate` | Start payment (body: `{invoice_uuid}`) |
| POST | `/payments/callback` | Payment gateway callback |
| GET | `/payments/{uuid}/receipt` | Payment receipt |
| GET | `/invoices/{uuid}` | Invoice detail |

### Notifications

| Method | Path | Description |
|--------|------|-------------|
| GET | `/notifications` | Paginated notifications |
| PATCH | `/notifications/{id}/read` | Mark one as read |
| POST | `/notifications/read-all` | Mark all as read |
| GET | `/notifications/preferences` | Notification preferences |
| POST | `/notifications/preferences` | Update preferences |

### Messages & Service Requests

| Method | Path | Description |
|--------|------|-------------|
| GET | `/messages` | Message list |
| POST | `/messages/send` | Send message |
| GET | `/service-requests` | Service request list |
| POST | `/service-requests` | Create service request |
| POST | `/service-requests/{uuid}/cancel` | Cancel request |

### Absences

| Method | Path | Description |
|--------|------|-------------|
| POST | `/absences/report` | Report planned absence |

### Push Notifications & Devices

| Method | Path | Description |
|--------|------|-------------|
| POST | `/devices/register` | Register FCM device token |
| PATCH | `/devices/refresh` | Refresh device token |
| DELETE | `/devices/{token}` | Unregister device |
| GET | `/push/badge` | Unread badge count |
| POST | `/push/track` | Track push analytics events |
| POST | `/push/heartbeat` | Device heartbeat |

### Broadcast & Deep Links

| Method | Path | Description |
|--------|------|-------------|
| POST | `/broadcast/send` | Send broadcast (admin) |
| GET | `/broadcast/history` | Broadcast history |
| GET | `/deeplinks/routes` | Available deep link routes |

## Design Principles

### Arabic-First RTL
- Default locale: `ar`
- Directionality wrapper in `MaterialApp.router` builder
- Cairo font (Arabic) / Inter font (Latin fallback)
- All strings in localization map with Arabic primary

### Animations
Every screen has entrance animations:
- Cards: fadeIn + slideY/slideX with staggered delays
- Avatar/icons: scale with easeOutBack curve
- Lists: per-item stagger (80ms between items)
- Page transitions: custom fade+slide via GoRouter

### Money
- Stored as piasters (integer)
- Displayed via `formatMoney(int)` → `"5,500.00 ج.م"`
- Never float arithmetic

### Authorization
- Guardian can only see their own linked participants
- 403 returned for unauthorized participant access
- Token expires on logout (revoked server-side)

## Running Locally

```bash
# Install dependencies
flutter pub get

# Run on iOS simulator
flutter run

# Build iOS (no codesign for CI)
flutter build ios --no-codesign

# Build APK
flutter build apk --release
```

## Required Assets

```
assets/
├── branding/
│   └── logo.png          # Academy logo (loaded from backend if available)
├── animations/
│   └── splash.json       # Lottie splash animation
├── icons/
│   └── (svg icons)
└── fonts/
    ├── Cairo-Regular.ttf
    ├── Cairo-Medium.ttf
    ├── Cairo-SemiBold.ttf
    ├── Cairo-Bold.ttf
    ├── Inter-Regular.ttf
    ├── Inter-Medium.ttf
    ├── Inter-SemiBold.ttf
    └── Inter-Bold.ttf
```

## Multi-Client Architecture

This app is designed for **one app per academy**. Each client gets their own build with a unique `instance.dart` config pointing to their CapRover-deployed backend.

To create a new client build:
1. Copy `lib/config/instance.dart`
2. Update `baseUrl`, `appName`, `appNameAr`, `packageId`
3. Replace branding assets
4. Build for the target platform

## Endpoint Test Results (2026-07-27)

All 59 API routes tested against `oc-sport.caprover.al-arcade.com`:

| Status | Count | Notes |
|--------|-------|-------|
| 200 OK | 55 | Working correctly |
| 404 | 1 | `/register/pre-register` (not yet implemented on backend) |
| N/A | 3 | POST-only endpoints (callback, heartbeat, broadcast) — need specific payloads |

### Verified Working Endpoints

- Health check
- App config (academy info, theme, features)
- OTP request + verify → token generation
- Auth me + logout
- Profile read
- Dashboard (children, totals, sessions, announcements)
- Guardian children list
- All participant sub-endpoints (detail, summary, schedule, attendance, invoices, evaluations, enrollments, wallet, documents)
- Products catalog
- Events list
- News
- Programs (23 programs loaded)
- Gallery
- Branches
- Service requests
- Messages
- Push badge count
- Notification preferences
- Notifications list

### Known Issues

1. **Rate limiting on OTP**: 3 attempts per 10 minutes per phone number. Use tinker to generate tokens for testing.
2. **Pre-register route**: Not implemented on backend yet — needs `POST /api/v1/register/pre-register` controller.
