Files
geo/app/README-APP.md
d6soft 511be5a535 Fix: Hive sync et update entité via API REST
- Correction mapping JSON membres (fk_role, chk_active)
- Ajout traitement amicale au login
- Fix callback onSubmit pour sync Hive après update API
2025-06-09 18:46:49 +02:00

8.2 KiB

GEOSECTOR

Une application puissante et intuitive de gestion de vos distributions de calendriers par secteurs géographiques pour les amicales de pompiers.

📱 Présentation

GEOSECTOR est une application Flutter qui permet aux amicales de pompiers de gérer efficacement la distribution de calendriers par secteurs géographiques.

Fonctionnalités principales

  • Gestion des secteurs géographiques avec cartes interactives (Flutter Map)
  • Suivi des passages avec géolocalisation
  • Interface différenciée : utilisateur et administrateur
  • Authentification sécurisée avec gestion des rôles@
  • Chat intégré avec système de notifications
  • Stockage local avec synchronisation en ligne
  • Support multi-plateforme : Web, iOS, Android

🏗️ Architecture

Stack technique

  • Framework : Flutter 3.32
  • Routing : Go Router
  • Base de données locale : Hive
  • Gestion d'état : Repository Pattern (Pas de Provider, Get.It, etc...)
  • Cartes : Flutter Map avec Mapbox
  • API : Dio pour les requêtes HTTP
  • Chat : MQTT5 Client

Architecture de données : Hive + Provider + Repository

L'application utilise une architecture en couches pour la gestion des données :

UI Layer (Widgets)
    ↓
Repository Layer (Business Logic)
    ↓
Data Layer (Hive + API)

Couches de l'architecture

  1. UI Layer : Widgets Flutter qui affichent les données
  2. Repository Layer : Logique métier et orchestration des sources de données
  3. Data Layer : Stockage local (Hive) et API distante

Structure des dossiers

lib/
├── core/
│   ├── config/
│   ├── constants/
│   ├── errors/
│   ├── network/
│   └── utils/
├── data/
│   ├── datasources/
│   ├── models/
│   └── repositories/
├── domain/
│   ├── entities/
│   ├── repositories/
│   └── usecases/
├── presentation/
│   ├── pages/
│   ├── providers/
│   ├── widgets/
│   └── theme/
└── main.dart

🚀 Installation et configuration

Prérequis

  • Flutter 3.x
  • Dart SDK
  • Android Studio / VS Code
  • Émulateur ou appareil physique

Installation

  1. Cloner le repository

    git clone https://github.com/votre-repo/geosector.git
    cd geosector
    
  2. Installer les dépendances

    flutter pub get
    
  3. Configuration des clés API

    Créer un fichier .env à la racine :

    MAPBOX_ACCESS_TOKEN=your_mapbox_token
    API_BASE_URL=https://your-api.com
    MQTT_BROKER_URL=your-mqtt-broker
    
  4. Lancer l'application

    flutter run
    

📦 Dépendances principales

dependencies:
  flutter:
    sdk: flutter

  # État et navigation
  go_router: ^12.1.3

  # Stockage local
  hive: ^2.2.3
  hive_flutter: ^1.1.0

  # Réseau
  dio: ^5.4.0

  # Cartes
  flutter_map: ^6.1.0
  geolocator: ^10.1.0

  # Chat
  mqtt5_client: ^4.2.0

  # UI
  flutter_screenutil: ^5.9.0
  cached_network_image: ^3.3.0

dev_dependencies:
  hive_generator: ^2.0.1
  build_runner: ^2.4.7

🗄️ Modèles de données

if (!Hive.isAdapterRegistered(0)) { Hive.registerAdapter(UserModelAdapter()); } if (!Hive.isAdapterRegistered(1)) { Hive.registerAdapter(OperationModelAdapter()); } if (!Hive.isAdapterRegistered(3)) { Hive.registerAdapter(SectorModelAdapter()); } if (!Hive.isAdapterRegistered(4)) { Hive.registerAdapter(PassageModelAdapter()); } if (!Hive.isAdapterRegistered(5)) { Hive.registerAdapter(MembreModelAdapter()); } if (!Hive.isAdapterRegistered(6)) { Hive.registerAdapter(UserSectorModelAdapter()); } if (!Hive.isAdapterRegistered(7)) { Hive.registerAdapter(RegionModelAdapter()); } if (!Hive.isAdapterRegistered(10)) { Hive.registerAdapter(ClientModelAdapter()); } if (!Hive.isAdapterRegistered(11)) { Hive.registerAdapter(AmicaleModelAdapter()); }

// Chat adapters
if (!Hive.isAdapterRegistered(20)) {
  Hive.registerAdapter(ConversationModelAdapter());
}
if (!Hive.isAdapterRegistered(21)) {
  Hive.registerAdapter(MessageModelAdapter());
}
if (!Hive.isAdapterRegistered(22)) {
  Hive.registerAdapter(ParticipantModelAdapter());
}
if (!Hive.isAdapterRegistered(23)) {
  Hive.registerAdapter(AnonymousUserModelAdapter());
}
if (!Hive.isAdapterRegistered(24)) {
  Hive.registerAdapter(AudienceTargetModelAdapter());
}
if (!Hive.isAdapterRegistered(25)) {
  Hive.registerAdapter(NotificationSettingsAdapter());
}

🗺️ Cartes et géolocalisation

Configuration Flutter Map

FlutterMap(
  options: MapOptions(
    center: LatLng(46.2276, 2.2137), // Centre de la France
    zoom: 6.0,
  ),
  children: [
    TileLayer(
      urlTemplate: 'https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}',
      additionalOptions: {
        'accessToken': mapboxToken,
        'id': 'mapbox/streets-v11',
      },
    ),
    PolygonLayer(
      polygons: secteurs.map((secteur) => Polygon(
        points: secteur.polygone,
        color: Color(int.parse(secteur.couleur)),
        borderColor: Colors.black,
        borderStrokeWidth: 2.0,
      )).toList(),
    ),
  ],
)

💬 Chat intégré

Configuration MQTT

class ChatService {
  late MqttClient client;

  Future<void> connect() async {
    client = MqttClient('mqtt://broker-url', 'client-id');
    await client.connect();

    client.subscribe('geosector/chat', MqttQos.atLeastOnce);
    client.updates!.listen((messages) {
      // Traitement des messages
    });
  }
}

🔐 Authentification

Gestion des rôles

class AuthProvider extends ChangeNotifier {
  Utilisateur? _currentUser;

  bool get isAdmin => _currentUser?.role == 'admin';
  bool get isAuthenticated => _currentUser != null;

  Future<void> login(String email, String password) async {
    // Logique d'authentification
  }

  void logout() {
    _currentUser = null;
    notifyListeners();
  }
}

📱 Interface utilisateur

Thème de l'application

class AppTheme {
  static ThemeData get lightTheme => ThemeData(
    primarySwatch: Colors.red,
    appBarTheme: AppBarTheme(
      backgroundColor: Colors.red[700],
      elevation: 0,
    ),
    elevatedButtonTheme: ElevatedButtonThemeData(
      style: ElevatedButton.styleFrom(
        backgroundColor: Colors.red[700],
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(8),
        ),
      ),
    ),
  );
}

🔄 Synchronisation des données

Repository Pattern

class SecteurRepository {
  final SecteurLocalDataSource _localDataSource;
  final SecteurRemoteDataSource _remoteDataSource;

  Future<List<Secteur>> getAllSecteurs() async {
    try {
      // Essayer de récupérer depuis l'API
      final remoteSecteurs = await _remoteDataSource.getAllSecteurs();
      await _localDataSource.cacheSecteurs(remoteSecteurs);
      return remoteSecteurs;
    } catch (e) {
      // Fallback sur le cache local
      return await _localDataSource.getAllSecteurs();
    }
  }
}

🧪 Tests

Tests unitaires

flutter test

Tests d'intégration

flutter test integration_test/

📚 Documentation

🤝 Contribution

  1. Fork le projet
  2. Créer une branche feature (git checkout -b feature/AmazingFeature)
  3. Commit vos changements (git commit -m 'Add some AmazingFeature')
  4. Push vers la branche (git push origin feature/AmazingFeature)
  5. Ouvrir une Pull Request

📄 Licence

Distribué sous la licence MIT. Voir LICENSE pour plus d'informations.

👥 Équipe

📞 Support

Pour toute question ou problème :


GEOSECTOR - Simplifiant la gestion des distributions de calendriers pour les amicales de pompiers 🚒