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
This commit is contained in:
@@ -23,7 +23,7 @@ GEOSECTOR est une application Flutter qui permet aux amicales de pompiers de gé
|
||||
- **Framework** : Flutter 3.32
|
||||
- **Routing** : Go Router
|
||||
- **Base de données locale** : Hive
|
||||
- **Gestion d'état** : Provider + Repository Pattern
|
||||
- **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
|
||||
@@ -35,8 +35,6 @@ L'application utilise une architecture en couches pour la gestion des données :
|
||||
```
|
||||
UI Layer (Widgets)
|
||||
↓
|
||||
Provider Layer (State Management)
|
||||
↓
|
||||
Repository Layer (Business Logic)
|
||||
↓
|
||||
Data Layer (Hive + API)
|
||||
@@ -45,9 +43,8 @@ Data Layer (Hive + API)
|
||||
#### Couches de l'architecture
|
||||
|
||||
1. **UI Layer** : Widgets Flutter qui affichent les données
|
||||
2. **Provider Layer** : Gestion d'état avec ChangeNotifier
|
||||
3. **Repository Layer** : Logique métier et orchestration des sources de données
|
||||
4. **Data Layer** : Stockage local (Hive) et API distante
|
||||
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
|
||||
|
||||
@@ -87,19 +84,22 @@ lib/
|
||||
### Installation
|
||||
|
||||
1. **Cloner le repository**
|
||||
|
||||
```bash
|
||||
git clone https://github.com/votre-repo/geosector.git
|
||||
cd geosector
|
||||
```
|
||||
|
||||
2. **Installer les dépendances**
|
||||
|
||||
```bash
|
||||
flutter pub get
|
||||
```
|
||||
|
||||
3. **Configuration des clés API**
|
||||
|
||||
|
||||
Créer un fichier `.env` à la racine :
|
||||
|
||||
```env
|
||||
MAPBOX_ACCESS_TOKEN=your_mapbox_token
|
||||
API_BASE_URL=https://your-api.com
|
||||
@@ -117,29 +117,28 @@ lib/
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
|
||||
# État et navigation
|
||||
provider: ^6.1.1
|
||||
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
|
||||
@@ -147,116 +146,53 @@ dev_dependencies:
|
||||
|
||||
## 🗄️ Modèles de données
|
||||
|
||||
### Secteur
|
||||
|
||||
```dart
|
||||
@HiveType(typeId: 0)
|
||||
class Secteur extends HiveObject {
|
||||
@HiveField(0)
|
||||
String id;
|
||||
|
||||
@HiveField(1)
|
||||
String nom;
|
||||
|
||||
@HiveField(2)
|
||||
List<LatLng> polygone;
|
||||
|
||||
@HiveField(3)
|
||||
String couleur;
|
||||
|
||||
@HiveField(4)
|
||||
int nombreCalendriers;
|
||||
|
||||
@HiveField(5)
|
||||
DateTime dateCreation;
|
||||
if (!Hive.isAdapterRegistered(0)) {
|
||||
Hive.registerAdapter(UserModelAdapter());
|
||||
}
|
||||
```
|
||||
|
||||
### Passage
|
||||
|
||||
```dart
|
||||
@HiveType(typeId: 1)
|
||||
class Passage extends HiveObject {
|
||||
@HiveField(0)
|
||||
String id;
|
||||
|
||||
@HiveField(1)
|
||||
String secteurId;
|
||||
|
||||
@HiveField(2)
|
||||
String utilisateurId;
|
||||
|
||||
@HiveField(3)
|
||||
DateTime datePassage;
|
||||
|
||||
@HiveField(4)
|
||||
LatLng position;
|
||||
|
||||
@HiveField(5)
|
||||
int calendriersDistribues;
|
||||
|
||||
@HiveField(6)
|
||||
String commentaire;
|
||||
|
||||
@HiveField(7)
|
||||
List<String> photos;
|
||||
if (!Hive.isAdapterRegistered(1)) {
|
||||
Hive.registerAdapter(OperationModelAdapter());
|
||||
}
|
||||
```
|
||||
|
||||
### Utilisateur
|
||||
|
||||
```dart
|
||||
@HiveType(typeId: 2)
|
||||
class Utilisateur extends HiveObject {
|
||||
@HiveField(0)
|
||||
String id;
|
||||
|
||||
@HiveField(1)
|
||||
String nom;
|
||||
|
||||
@HiveField(2)
|
||||
String email;
|
||||
|
||||
@HiveField(3)
|
||||
String role; // 'admin' ou 'user'
|
||||
|
||||
@HiveField(4)
|
||||
List<String> secteursAssignes;
|
||||
|
||||
@HiveField(5)
|
||||
DateTime dernierLogin;
|
||||
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());
|
||||
}
|
||||
```
|
||||
|
||||
## 🔧 Gestion d'état avec Provider
|
||||
|
||||
### SecteurProvider
|
||||
|
||||
```dart
|
||||
class SecteurProvider extends ChangeNotifier {
|
||||
final SecteurRepository _repository;
|
||||
|
||||
List<Secteur> _secteurs = [];
|
||||
bool _isLoading = false;
|
||||
|
||||
List<Secteur> get secteurs => _secteurs;
|
||||
bool get isLoading => _isLoading;
|
||||
|
||||
Future<void> loadSecteurs() async {
|
||||
_isLoading = true;
|
||||
notifyListeners();
|
||||
|
||||
try {
|
||||
_secteurs = await _repository.getAllSecteurs();
|
||||
} catch (e) {
|
||||
// Gestion d'erreur
|
||||
} finally {
|
||||
_isLoading = false;
|
||||
notifyListeners();
|
||||
// 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
|
||||
|
||||
@@ -295,11 +231,11 @@ FlutterMap(
|
||||
```dart
|
||||
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
|
||||
@@ -315,14 +251,14 @@ class ChatService {
|
||||
```dart
|
||||
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();
|
||||
@@ -362,7 +298,7 @@ class AppTheme {
|
||||
class SecteurRepository {
|
||||
final SecteurLocalDataSource _localDataSource;
|
||||
final SecteurRemoteDataSource _remoteDataSource;
|
||||
|
||||
|
||||
Future<List<Secteur>> getAllSecteurs() async {
|
||||
try {
|
||||
// Essayer de récupérer depuis l'API
|
||||
|
||||
Reference in New Issue
Block a user