429 lines
8.6 KiB
Markdown
429 lines
8.6 KiB
Markdown
# 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** : Provider + Repository Pattern
|
|
- **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)
|
|
↓
|
|
Provider Layer (State Management)
|
|
↓
|
|
Repository Layer (Business Logic)
|
|
↓
|
|
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
|
|
|
|
### 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**
|
|
```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
|
|
MQTT_BROKER_URL=your-mqtt-broker
|
|
```
|
|
|
|
4. **Lancer l'application**
|
|
```bash
|
|
flutter run
|
|
```
|
|
|
|
## 📦 Dépendances principales
|
|
|
|
```yaml
|
|
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
|
|
```
|
|
|
|
## 🗄️ 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;
|
|
}
|
|
```
|
|
|
|
### 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;
|
|
}
|
|
```
|
|
|
|
### 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;
|
|
}
|
|
```
|
|
|
|
## 🔧 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();
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## 🗺️ Cartes et géolocalisation
|
|
|
|
### Configuration Flutter Map
|
|
|
|
```dart
|
|
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
|
|
|
|
```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
|
|
});
|
|
}
|
|
}
|
|
```
|
|
|
|
## 🔐 Authentification
|
|
|
|
### Gestion des rôles
|
|
|
|
```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();
|
|
}
|
|
}
|
|
```
|
|
|
|
## 📱 Interface utilisateur
|
|
|
|
### Thème de l'application
|
|
|
|
```dart
|
|
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
|
|
|
|
```dart
|
|
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
|
|
|
|
```bash
|
|
flutter test
|
|
```
|
|
|
|
### Tests d'intégration
|
|
|
|
```bash
|
|
flutter test integration_test/
|
|
```
|
|
|
|
## 📚 Documentation
|
|
|
|
- [Guide d'utilisation](docs/guide-utilisation.md)
|
|
- [API Reference](docs/api-reference.md)
|
|
- [Architecture détaillée](docs/architecture.md)
|
|
- [Contribution](docs/contributing.md)
|
|
|
|
## 🤝 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
|
|
|
|
- **Développeur Principal** - [@votre-username](https://github.com/votre-username)
|
|
- **Designer UI/UX** - [@designer-username](https://github.com/designer-username)
|
|
|
|
## 📞 Support
|
|
|
|
Pour toute question ou problème :
|
|
|
|
- 📧 Email : support@geosector.com
|
|
- 🐛 Issues : [GitHub Issues](https://github.com/votre-repo/geosector/issues)
|
|
- 📖 Documentation : [Wiki](https://github.com/votre-repo/geosector/wiki)
|
|
|
|
---
|
|
|
|
**GEOSECTOR** - Simplifiant la gestion des distributions de calendriers pour les amicales de pompiers 🚒
|