feat: Livraison version 3.0.6

- Amélioration de la gestion des entités et des utilisateurs
- Mise à jour des modèles Amicale et Client avec champs supplémentaires
- Ajout du service de logging et amélioration du chargement UI
- Refactoring des formulaires utilisateur et amicale
- Intégration de file_picker et image_picker pour la gestion des fichiers
- Amélioration de la gestion des membres et de leur suppression
- Optimisation des performances de l'API
- Mise à jour de la documentation technique

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-08-08 20:33:54 +02:00
parent 599b9fcda0
commit 206c76c7db
69 changed files with 203569 additions and 174972 deletions

View File

@@ -96,6 +96,7 @@ GEOSECTOR est une solution complète développée en Flutter qui révolutionne l
| **Géolocalisation** | Geolocator | 10.1.0 | Services de localisation |
| **Chat** | MQTT5 Client | 4.2.0 | Messagerie temps réel |
| **UI** | Material Design 3 | Native | Composants d'interface |
| **Logging** | LoggerService | Custom | Logs conditionnels par env |
### 🏛️ Architecture en couches
@@ -423,6 +424,355 @@ Interface : Affichage utilisateur via ApiException.showError()
Network Errors : "Problème de connexion réseau"
Timeout : "Délai d'attente dépassé"
## 🔧 Pattern de gestion des erreurs API dans les Repositories
### 🎯 Problème à résoudre
Les messages d'erreur spécifiques de l'API (comme "Cet email est déjà utilisé") n'étaient pas affichés à l'utilisateur. À la place, un message générique "Erreur inattendue" apparaissait.
### 📝 Modifications requises
#### **1. ApiService - Conversion automatique des DioException**
Toutes les méthodes HTTP génériques doivent convertir les `DioException` en `ApiException` :
```dart
// ✅ CORRECT - ApiService avec conversion automatique
Future<Response> put(String path, {dynamic data}) async {
try {
return await _dio.put(path, data: data);
} on DioException catch (e) {
throw ApiException.fromDioException(e); // ← Extraction automatique du message
} catch (e) {
if (e is ApiException) rethrow;
throw ApiException('Erreur inattendue lors de la requête PUT', originalError: e);
}
}
```
Appliquer le même pattern pour `post()`, `get()`, `delete()`.
#### **2. Repository - Simplification de la gestion des erreurs**
```dart
// ❌ INCORRECT - Code inutile qui ne sera jamais exécuté
Future<bool> updateMembre(MembreModel membre) async {
try {
final response = await ApiService.instance.put('/users/${membre.id}', data: data);
if (response.statusCode == 200) {
await saveMembreBox(membre);
return true;
}
// ⚠️ CE CODE NE SERA JAMAIS ATTEINT car Dio lance une exception pour les codes d'erreur
if (response.data != null && response.data is Map<String, dynamic>) {
final responseData = response.data as Map<String, dynamic>;
if (responseData['status'] == 'error') {
throw Exception(responseData['message']);
}
}
return false;
} catch (e) {
rethrow;
}
}
```
```dart
// ✅ CORRECT - Code simplifié et fonctionnel
Future<bool> updateMembre(MembreModel membre) async {
try {
final response = await ApiService.instance.put('/users/${membre.id}', data: data);
// Si on arrive ici, c'est que la requête a réussi (200)
await saveMembreBox(membre);
return true;
} catch (e) {
// L'ApiException contient déjà le message extrait de l'API
rethrow; // Propager l'exception pour affichage
}
}
```
#### **3. Amélioration des logs (avec LoggerService)**
```dart
// ✅ CORRECT - Logs propres sans détails techniques
catch (e) {
// Ne pas logger les détails techniques de DioException
if (e is ApiException) {
LoggerService.error('Erreur lors de la mise à jour: ${e.message}');
} else {
LoggerService.error('Erreur lors de la mise à jour');
}
rethrow;
}
```
N'oubliez pas d'importer `ApiException` :
```dart
import 'package:geosector_app/core/utils/api_exception.dart';
```
### 🔄 Flux d'erreur corrigé
```mermaid
sequenceDiagram
participant API as API Server
participant Dio as Dio Client
participant AS as ApiService
participant AE as ApiException
participant R as Repository
participant UI as Interface
UI->>R: updateData()
R->>AS: put('/endpoint')
AS->>Dio: HTTP PUT
Dio->>API: Request
alt Code d'erreur (409, 400, etc.)
API-->>Dio: Error + JSON body
Note over API: {"status": "error",<br/>"message": "Message spécifique"}
Dio-->>AS: DioException
AS->>AE: fromDioException()
Note over AE: Extrait message<br/>depuis response.data
AE-->>AS: ApiException("Message spécifique")
AS-->>R: throw ApiException
R-->>UI: throw ApiException
UI->>UI: showError("Message spécifique")
else Succès (200, 201)
API-->>Dio: Success
Dio-->>AS: Response
AS-->>R: Response
R->>R: Sauvegarde Hive
R-->>UI: return true
end
```
### ✅ Checklist de migration
Pour chaque repository :
- [ ] Vérifier que l'ApiService convertit les DioException en ApiException
- [ ] Simplifier le code : supprimer les vérifications de statut après l'appel API
- [ ] Propager les exceptions avec `rethrow`
- [ ] Améliorer les logs pour ne pas afficher les détails techniques
- [ ] Importer `ApiException` si nécessaire
- [ ] Tester avec une erreur 409 pour vérifier l'affichage du message
### 📊 Résultat attendu
| Avant | Après |
|-------|-------|
| "Erreur inattendue" | "Cet email est déjà utilisé par un autre utilisateur" |
| Logs avec stack trace Dio | Message d'erreur simple et clair |
| Code complexe avec vérifications inutiles | Code simplifié et maintenable |
Cette approche garantit que tous les messages d'erreur de l'API sont correctement affichés à l'utilisateur, améliorant ainsi l'expérience utilisateur et facilitant le débogage.
## 📝 Service de Logging Intelligent
### 🎯 Vue d'ensemble
GEOSECTOR v2.0 implémente un **LoggerService centralisé** qui désactive automatiquement les logs de debug en production, optimisant ainsi les performances et la sécurité tout en facilitant le développement.
### 🔍 Détection automatique de l'environnement
Le LoggerService détecte automatiquement l'environnement d'exécution :
```dart
// Détection basée sur l'URL pour le web
if (currentUrl.contains('dapp.geosector.fr')) DEV
if (currentUrl.contains('rapp.geosector.fr')) REC
Sinon PROD
// Pour mobile/desktop : utilise kReleaseMode de Flutter
```
**Comportement par environnement :**
| Environnement | Logs Debug | Logs Erreur | Stack Traces |
|---------------|------------|-------------|--------------|
| **DEV** | ✅ Activés | ✅ Activés | ✅ Complètes |
| **REC** | ✅ Activés | ✅ Activés | ✅ Complètes |
| **PROD** | ❌ Désactivés | ✅ Activés | ❌ Masquées |
### 🛠️ API du LoggerService
#### **Méthodes principales**
```dart
// Remplacement direct de debugPrint
LoggerService.log('Message simple');
// Logs catégorisés avec emojis automatiques
LoggerService.info('Information'); //
LoggerService.success('Opération réussie'); // ✅
LoggerService.warning('Attention'); // ⚠️
LoggerService.error('Erreur', exception); // ❌ (toujours affiché)
LoggerService.debug('Debug', emoji: '🔧'); // 🔧
// Logs spécialisés
LoggerService.api('Requête API envoyée'); // 🔗
LoggerService.database('Box Hive ouverte'); // 💾
LoggerService.navigation('Route: /admin'); // 🧭
LoggerService.performance('Temps: 45ms'); // ⏱️
```
#### **Fonctionnalités avancées**
```dart
// Logs groupés pour améliorer la lisibilité
LoggerService.group('Traitement utilisateur', [
'Validation des données',
'Appel API',
'Sauvegarde locale',
'Notification envoyée'
]);
// Affiche :
// ┌─ Traitement utilisateur
// ├─ Validation des données
// ├─ Appel API
// ├─ Sauvegarde locale
// └─ Notification envoyée
// Log JSON formaté
LoggerService.json('Payload API', {
'id': 123,
'name': 'Test',
'active': true
});
// Affiche :
// 📋 Payload API:
// id: 123
// name: Test
// active: true
// Log conditionnel
LoggerService.conditional(
'Debug spécifique',
condition: user.role > 2
);
```
### 🔄 Migration depuis debugPrint
#### **Avant (debugPrint partout)**
```dart
debugPrint('🔄 Début de la création d\'un nouveau membre');
debugPrint('📤 Données envoyées à l\'API: $data');
debugPrint('❌ Erreur: $e');
```
#### **Après (LoggerService)**
```dart
LoggerService.info('Début de la création d\'un nouveau membre');
LoggerService.api('Données envoyées à l\'API: $data');
LoggerService.error('Erreur lors de la création', e);
```
### 📋 Utilisation avec les extensions
Pour une syntaxe encore plus concise, utilisez les extensions String :
```dart
// Import nécessaire
import 'package:geosector_app/core/services/logger_service.dart';
// Utilisation directe sur les strings
'Connexion réussie'.logSuccess();
'Erreur de validation'.logError(exception);
'Requête GET /users'.logApi();
'Box membres ouverte'.logDatabase();
```
### 🎯 Bonnes pratiques
#### **1. Catégorisation des logs**
```dart
// ✅ BON - Log catégorisé et clair
LoggerService.api('POST /users - Création membre');
LoggerService.database('Sauvegarde dans Box membres');
// ❌ MAUVAIS - Log générique sans contexte
debugPrint('Traitement en cours...');
```
#### **2. Gestion des erreurs**
```dart
try {
await operation();
LoggerService.success('Opération terminée');
} catch (e, stackTrace) {
// Les erreurs sont TOUJOURS loggées, même en PROD
LoggerService.error('Échec de l\'opération', e, stackTrace);
}
```
#### **3. Logs de performance**
```dart
final stopwatch = Stopwatch()..start();
await heavyOperation();
stopwatch.stop();
LoggerService.performance('Opération lourde: ${stopwatch.elapsedMilliseconds}ms');
```
### 🔒 Sécurité et performances
#### **Avantages en production**
1. **Sécurité** : Aucune information sensible exposée dans la console
2. **Performance** : Pas d'appels inutiles à debugPrint
3. **Taille** : Bundle JavaScript plus léger (tree shaking)
4. **Professionnalisme** : Console propre pour les utilisateurs finaux
#### **Conservation des logs d'erreur**
Les erreurs restent visibles en production pour faciliter le support :
```dart
// Toujours affiché, même en PROD
LoggerService.error('Erreur critique détectée', error);
// Mais sans la stack trace complète qui pourrait révéler
// des détails d'implémentation
```
### 📊 Impact sur le codebase
| Métrique | Avant | Après |
|----------|-------|-------|
| **Logs en PROD** | Tous visibles | Erreurs uniquement |
| **Performance web** | debugPrint actifs | Désactivés automatiquement |
| **Maintenance** | debugPrint dispersés | Service centralisé |
| **Lisibilité** | Emojis manuels | Catégorisation automatique |
### 🚀 Configuration et initialisation
Le LoggerService fonctionne automatiquement sans configuration :
```dart
// main.dart - Aucune initialisation requise
void main() async {
// LoggerService détecte automatiquement l'environnement
// via ApiService.getCurrentEnvironment()
runApp(GeosectorApp());
}
// Utilisation immédiate dans n'importe quel fichier
LoggerService.info('Application démarrée');
```
Cette architecture garantit un système de logging professionnel, sécurisé et performant, adapté aux besoins de développement tout en protégeant la production. 📝✨
## 🎯 Gestion des rôles
### Hiérarchie des permissions