# UnionFlow Mobile - Application Flutter

![Flutter](https://img.shields.io/badge/Flutter-3.5.3-blue)
![Dart](https://img.shields.io/badge/Dart-3.x-blue)
![Platform](https://img.shields.io/badge/Platform-Android%20%7C%20iOS-green)
![License](https://img.shields.io/badge/License-Proprietary-red)

Application mobile multiplateforme pour la gestion des mutuelles, associations et organisations Lions Club Côte d'Ivoire.

---

## 📋 Table des Matières

- [Fonctionnalités](#fonctionnalités)
- [Architecture](#architecture)
- [Technologies](#technologies)
- [Prérequis](#prérequis)
- [Installation](#installation)
- [Configuration Environnement](#configuration-environnement)
- [Build & Release](#build--release)
- [Tests](#tests)
- [WebSocket Temps Réel](#websocket-temps-réel)
- [Sécurité](#sécurité)

---

## ✨ Fonctionnalités

### Authentification & Sécurité
- ✅ Authentification Keycloak OIDC (via WebView)
- ✅ JWT validation (issuer + expiry mobile-side)
- ✅ Role-based access control (RBAC)
- ✅ Permission engine granulaire
- ✅ Refresh token automatique

### Dashboard Intelligent
- ✅ Dashboard rôle-spécifique (8 dashboards)
- ✅ Stats temps réel via WebSocket
- ✅ KPI avec graphiques interactifs
- ✅ Activités récentes
- ✅ Mode offline avec cache

### Finance Workflow ⭐ **NOUVEAU**
- ✅ Approbations de transactions (approve/reject)
- ✅ Gestion budgets avec lignes budgétaires
- ✅ Validation formulaires réutilisable
- ✅ Retry automatique avec backoff exponentiel
- ✅ Offline queue (opérations en attente)

### Membres
- ✅ Liste membres avec recherche avancée
- ✅ Profils membres détaillés
- ✅ Création/modification membres
- ✅ Import/export données (futur)

### Cotisations
- ✅ Historique cotisations membre
- ✅ Statistiques cotisations
- ✅ Paiement Wave Money (futur)
- ✅ Rappels automatiques

### Événements
- ✅ Calendrier événements
- ✅ Inscription événements
- ✅ Détails événement avec participants
- ✅ Notifications rappel

### Solidarité
- ✅ Demandes d'aide (création, suivi)
- ✅ Propositions d'aide
- ✅ Workflow validation
- ✅ Commentaires et évaluations

### Notifications
- ✅ Notifications push temps réel (WebSocket)
- ✅ Centre de notifications
- ✅ Marquer comme lu
- ✅ Filtres par type

### Organisations
- ✅ Multi-organisations
- ✅ Gestion quotas membres
- ✅ Hiérarchie organisations

---

## 🏗️ Architecture

### Clean Architecture + BLoC Pattern

```
lib/
├── app/                           # Application setup
│   ├── app.dart                  # MyApp widget
│   └── router/                   # Navigation
├── core/                          # Core layer (shared)
│   ├── config/
│   │   └── environment.dart      # AppConfig (ENV-based)
│   ├── di/
│   │   └── injection_container.dart  # GetIt DI
│   ├── network/
│   │   ├── api_client.dart       # Dio client
│   │   ├── retry_policy.dart     # Retry avec backoff
│   │   └── offline_manager.dart  # Offline queue
│   ├── storage/
│   │   ├── dashboard_cache_manager.dart
│   │   └── pending_operations_store.dart
│   ├── validation/
│   │   └── validators.dart       # 20+ validators
│   ├── error/
│   │   └── failures.dart         # Either<Failure, T>
│   ├── utils/
│   │   └── logger.dart           # AppLogger
│   └── websocket/
│       └── websocket_service.dart  # WebSocket client
├── features/                      # Features (Clean Architecture)
│   ├── authentication/
│   │   ├── data/
│   │   │   ├── datasources/      # Keycloak WebView
│   │   │   ├── models/           # UserRole, Permission
│   │   │   └── repositories/
│   │   ├── domain/
│   │   │   ├── entities/         # User, Permission
│   │   │   ├── repositories/     # Abstract
│   │   │   └── usecases/         # Login, Logout
│   │   └── presentation/
│   │       ├── bloc/             # AuthBloc
│   │       └── pages/            # LoginPage
│   ├── dashboard/
│   │   ├── data/
│   │   │   ├── datasources/      # DashboardRemoteDatasource
│   │   │   ├── models/           # DashboardStatsModel
│   │   │   └── repositories/
│   │   ├── domain/
│   │   │   ├── entities/         # DashboardEntity
│   │   │   ├── repositories/
│   │   │   └── usecases/         # GetDashboardData
│   │   └── presentation/
│   │       ├── bloc/             # DashboardBloc
│   │       ├── pages/
│   │       │   ├── connected_dashboard_page.dart
│   │       │   └── role_dashboards/  # 8 dashboards
│   │       └── widgets/          # Stat cards, charts
│   ├── finance_workflow/  ⭐ **NOUVEAU**
│   │   ├── data/
│   │   │   ├── datasources/
│   │   │   ├── models/
│   │   │   └── repositories/     # Avec retry + offline
│   │   ├── domain/
│   │   │   ├── entities/
│   │   │   │   ├── transaction_approval.dart
│   │   │   │   └── budget.dart
│   │   │   ├── repositories/
│   │   │   └── usecases/
│   │   └── presentation/
│   │       ├── bloc/
│   │       ├── pages/
│   │       │   └── pending_approvals_page.dart
│   │       └── widgets/
│   │           ├── approve_dialog.dart
│   │           ├── reject_dialog.dart
│   │           └── create_budget_dialog.dart
│   ├── members/
│   ├── contributions/
│   ├── events/
│   ├── solidarity/
│   ├── organizations/
│   └── notifications/
├── shared/                        # Shared UI components
│   ├── design_system/
│   │   ├── tokens/               # AppColors, AppTypography
│   │   ├── theme/                # AppTheme
│   │   └── components/           # Reusable widgets
│   └── widgets/
│       ├── validated_text_field.dart
│       ├── error_display_widget.dart
│       └── confirmation_dialog.dart
└── main.dart                      # Entry point
```

**Pattern** : Data → Domain → Presentation

- **Data Layer** : Models, Datasources, Repositories Impl
- **Domain Layer** : Entities, Use Cases, Repository Interfaces
- **Presentation Layer** : BLoC, Pages, Widgets

---

## 🛠️ Technologies

### Core Stack

| Package | Version | Usage |
|---------|---------|-------|
| **flutter** | 3.5.3+ | Framework UI |
| **dart** | 3.x | Langage |
| **flutter_bloc** | ^8.1.0 | State management |
| **equatable** | ^2.0.5 | Value equality |
| **dartz** | ^0.10.1 | Functional programming (Either) |
| **get_it** | ^7.6.0 | Dependency injection |
| **injectable** | ^2.3.0 | DI code generation |
| **dio** | ^5.4.0 | HTTP client |
| **retrofit** | ^4.0.0 | Type-safe REST clients |
| **json_annotation** | ^4.8.0 | JSON serialization |
| **json_serializable** | ^6.6.0 | Code generation |
| **freezed** | ^2.4.0 | Immutable classes |
| **shared_preferences** | ^2.2.0 | Local storage |
| **connectivity_plus** | ^5.0.0 | Network status |
| **web_socket_channel** | ^2.4.0 | WebSocket client |
| **fl_chart** | ^0.66.0 | Charts |
| **intl** | ^0.18.0 | Internationalization |
| **logger** | ^2.0.0 | Logging |
| **webview_flutter** | ^4.5.0 | Keycloak WebView auth |

### Dev Dependencies

- **build_runner** : Code generation
- **flutter_test** : Tests unitaires
- **mockito** : Mocking
- **bloc_test** : Tests BLoC
- **flutter_lints** : Linting

---

## 📦 Prérequis

### Environnement de développement

- **Flutter SDK** : 3.5.3 ou supérieur
- **Dart SDK** : 3.x (inclus avec Flutter)
- **Android Studio** / **Xcode** (iOS)
- **Git** : 2.30+

### Services externes

- **Backend UnionFlow** : http://localhost:8085 (dev)
- **Keycloak** : http://localhost:8180 (dev)
- **Kafka** : localhost:9092 (optionnel, pour WebSocket)

---

## 🚀 Installation

### 1. Cloner le projet

```bash
git clone https://git.lions.dev/lionsdev/unionflow-mobile-apps.git
cd unionflow-mobile-apps
```

### 2. Installer les dépendances

```bash
flutter pub get
```

### 3. Générer le code (DTOs, DI)

```bash
flutter pub run build_runner build --delete-conflicting-outputs
```

### 4. Lancer l'app

```bash
# Dev (ENV=dev par défaut)
flutter run

# Ou avec env spécifique
flutter run --dart-define=ENV=dev
flutter run --dart-define=ENV=staging
flutter run --dart-define=ENV=prod
```

---

## ⚙️ Configuration Environnement

### AppConfig (environment.dart)

**Fichier** : `lib/core/config/environment.dart`

```dart
class AppConfig {
  static String get environment => const String.fromEnvironment('ENV', defaultValue: 'dev');

  static String get backendBaseUrl {
    switch (environment) {
      case 'prod':
        return 'https://api.lions.dev/unionflow';
      case 'staging':
        return 'https://staging-api.lions.dev/unionflow';
      case 'dev':
      default:
        return 'http://10.0.2.2:8085';  // Android emulator localhost
    }
  }

  static String get keycloakBaseUrl {
    switch (environment) {
      case 'prod':
        return 'https://security.lions.dev/realms/unionflow';
      case 'staging':
        return 'https://staging-security.lions.dev/realms/unionflow';
      case 'dev':
      default:
        return 'http://10.0.2.2:8180/realms/unionflow';
    }
  }

  static bool get enableLogging => environment != 'prod';
}
```

### Build avec environnement

```bash
# Dev
flutter run --dart-define=ENV=dev

# Staging
flutter run --dart-define=ENV=staging

# Production
flutter run --dart-define=ENV=prod --release
```

**Note** : `--dart-define` valeurs sont compile-time constants via `String.fromEnvironment()`.

---

## 📱 Build & Release

### Android APK/AAB

```bash
# Debug APK
flutter build apk --dart-define=ENV=dev

# Release APK
flutter build apk --release --dart-define=ENV=prod

# Release AAB (Google Play)
flutter build appbundle --release --dart-define=ENV=prod
```

**Output** :
- APK : `build/app/outputs/flutter-apk/app-release.apk`
- AAB : `build/app/outputs/bundle/release/app-release.aab`

### iOS IPA

```bash
# Release build
flutter build ios --release --dart-define=ENV=prod

# Ouvrir Xcode pour archiver
open ios/Runner.xcworkspace
```

### Signing (Android)

**Fichier** : `android/key.properties`

```properties
storePassword=your-store-password
keyPassword=your-key-password
keyAlias=upload
storeFile=/path/to/keystore.jks
```

**Note** : `key.properties` est gitignored (sécurité).

---

## 🧪 Tests

### Tests unitaires

```bash
# Tous les tests
flutter test

# Tests spécifiques
flutter test test/core/validation/validators_test.dart

# Avec couverture
flutter test --coverage
genhtml coverage/lcov.info -o coverage/html
open coverage/html/index.html
```

### Tests d'intégration

```bash
flutter test integration_test/finance_workflow_integration_test.dart
```

### Tests existants

✅ **54 tests validation** (validators_test.dart) - 100%
✅ **12 tests retry policy** (retry_policy_test.dart)
✅ **8 tests offline manager** (offline_manager_test.dart)

---

## 🔌 WebSocket Temps Réel

### Architecture Kafka → WebSocket → Mobile

```
Backend Services → Kafka Topics → WebSocket Server → Mobile App
```

**Topics consommés** :
- `unionflow.finance.approvals`
- `unionflow.dashboard.stats`
- `unionflow.notifications.user`

### WebSocketService

**Fichier** : `lib/core/websocket/websocket_service.dart`

```dart
@singleton
class WebSocketService {
  WebSocketChannel? _channel;

  void connect() {
    final wsUrl = '${AppConfig.backendBaseUrl.replaceFirst('http', 'ws')}/ws/dashboard';
    _channel = WebSocketChannel.connect(Uri.parse(wsUrl));

    _channel!.stream.listen(
      (message) {
        // Broadcast event to BLoCs
        _messageController.add(message);
      },
      onError: (error) => _reconnect(),
      onDone: () => _reconnect(),
    );
  }
}
```

**Reconnexion automatique** après 5 secondes en cas de déconnexion.

Voir [KAFKA_WEBSOCKET_ARCHITECTURE.md](../docs/KAFKA_WEBSOCKET_ARCHITECTURE.md) pour détails complets.

---

## 🔒 Sécurité

### Authentification Keycloak OIDC

- **Méthode** : WebView + Authorization Code Flow
- **Tokens** : JWT access token + refresh token
- **Validation mobile** : Issuer + expiry vérifiés localement
- **Signature backend** : Vérification signature JWT côté serveur

### Network Security (Android)

**Fichier** : `android/app/src/main/res/xml/network_security_config.xml`

```xml
<network-security-config>
  <base-config cleartextTrafficPermitted="false">
    <trust-anchors>
      <certificates src="system" />
    </trust-anchors>
  </base-config>

  <!-- Dev only -->
  <domain-config cleartextTrafficPermitted="true">
    <domain includeSubdomains="true">10.0.2.2</domain>  <!-- Android emulator -->
    <domain includeSubdomains="true">localhost</domain>
  </domain-config>
</network-security-config>
```

**Production** : `cleartextTrafficPermitted="false"` strict.

### ProGuard (Android)

**Fichier** : `android/app/proguard-rules.pro`

Règles de minification activées en release.

### App Transport Security (iOS)

**Fichier** : `ios/Runner/Info.plist`

HTTPS forcé en production.

---

## 📊 Performance

### Cache Dashboard

**TTL** : 5 minutes (stats dashboard)
**Storage** : SharedPreferences

### Offline Support

- **Pending operations** : Queue persistée (SharedPreferences)
- **Retry automatique** : Exponential backoff (3 tentatives)
- **Connectivity monitoring** : connectivity_plus

---

## 📚 Documentation

- **Architecture Kafka + WebSocket** : [KAFKA_WEBSOCKET_ARCHITECTURE.md](../docs/KAFKA_WEBSOCKET_ARCHITECTURE.md)
- **Form Validation** : [FORM_VALIDATION_IMPLEMENTATION.md](docs/FORM_VALIDATION_IMPLEMENTATION.md)
- **Error Handling** : [ERROR_HANDLING_IMPLEMENTATION.md](docs/ERROR_HANDLING_IMPLEMENTATION.md)
- **Finance Workflow** : [README.md](lib/features/finance_workflow/README.md)

---

## 📄 Licence

Propriétaire - © 2026 Lions Club Côte d'Ivoire

---

**Version** : 2.0.0
**Dernière mise à jour** : 2026-03-14
**Auteur** : Équipe UnionFlow
