- Ajout système complet de gestion des secteurs avec contours géographiques - Import des contours départementaux depuis GeoJSON - API REST pour la gestion des secteurs (/api/sectors) - Service de géolocalisation pour déterminer les secteurs - Migration base de données avec tables x_departements_contours et sectors_adresses - Interface Flutter pour visualisation et gestion des secteurs - Ajout thème sombre dans l'application - Corrections diverses et optimisations 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
453 lines
15 KiB
Markdown
453 lines
15 KiB
Markdown
# Gestion des Secteurs et de la Carte
|
|
|
|
Ce document centralise toutes les règles de gestion des secteurs et de la carte dans l'application Geosector.
|
|
|
|
**Dernière mise à jour** : Décembre 2024 - Améliorations de la détection d'adjacence et de l'ergonomie du drag
|
|
|
|
## Table des matières
|
|
|
|
1. [Vue d'ensemble](#vue-densemble)
|
|
2. [Structure des données](#structure-des-données)
|
|
3. [Modes de la carte](#modes-de-la-carte)
|
|
4. [Création d'un secteur](#création-dun-secteur)
|
|
5. [Gestion des secteurs adjacents](#gestion-des-secteurs-adjacents)
|
|
6. [Modification d'un secteur](#modification-dun-secteur)
|
|
7. [Suppression d'un secteur](#suppression-dun-secteur)
|
|
8. [Affichage des secteurs](#affichage-des-secteurs)
|
|
9. [Affichage des passages](#affichage-des-passages)
|
|
10. [Permissions et rôles](#permissions-et-rôles)
|
|
11. [Synchronisation API/Hive](#synchronisation-apihive)
|
|
12. [Interactions utilisateur](#interactions-utilisateur)
|
|
13. [Bonnes pratiques](#bonnes-pratiques)
|
|
|
|
## Vue d'ensemble
|
|
|
|
La carte administrative (`AdminMapPage`) permet aux administrateurs de gérer les secteurs géographiques d'une opération. Chaque secteur est un polygone défini par des coordonnées GPS et peut contenir des passages (adresses à visiter).
|
|
|
|
### Technologies utilisées
|
|
- **flutter_map** avec **MapBox** pour l'affichage de la carte
|
|
- **Hive** pour le stockage local des données
|
|
- **ValueListenableBuilder** pour la mise à jour réactive de l'interface
|
|
|
|
## Structure des données
|
|
|
|
### SectorModel
|
|
```dart
|
|
{
|
|
id: int, // Identifiant unique
|
|
libelle: String, // Nom du secteur
|
|
color: String, // Couleur hexadécimale (#RRGGBB)
|
|
sector: String // Coordonnées "lat/lng#lat/lng#..."
|
|
}
|
|
```
|
|
|
|
### PassageModel
|
|
```dart
|
|
{
|
|
id: int,
|
|
fk_sector: int, // ID du secteur
|
|
fk_user: int, // ID de l'utilisateur assigné
|
|
fk_type: int, // Type de passage (1-6)
|
|
gps_lat: String, // Latitude
|
|
gps_lng: String, // Longitude
|
|
numero: String, // Numéro de rue
|
|
rue: String, // Nom de la rue
|
|
ville: String, // Ville
|
|
// ... autres champs
|
|
}
|
|
```
|
|
|
|
### Types de passages
|
|
- **1** : Effectué (vert)
|
|
- **2** : À finaliser (orange)
|
|
- **3** : Refusé (rouge)
|
|
- **4** : Don (bleu)
|
|
- **5** : Lot (violet)
|
|
- **6** : Maison vide (gris)
|
|
|
|
## Modes de la carte
|
|
|
|
La carte peut être dans l'un des modes suivants :
|
|
|
|
### MapMode.view (Mode visualisation)
|
|
- Mode par défaut
|
|
- Permet de naviguer sur la carte
|
|
- Affiche les secteurs et passages
|
|
- Permet la sélection d'un secteur via la combobox
|
|
|
|
### MapMode.drawing (Mode création)
|
|
- Activé par le bouton "Créer un secteur"
|
|
- Affiche une carte d'aide explicative
|
|
- Permet de dessiner un nouveau secteur en cliquant sur la carte
|
|
- Points verts pour le premier point, bleus pour les suivants
|
|
- Fermeture du polygone en cliquant sur le premier point
|
|
|
|
### MapMode.editing (Mode édition)
|
|
- Activé par le bouton "Modifier un secteur"
|
|
- Permet de modifier les contours d'un secteur existant
|
|
- Sélectionner un secteur par clic ou via la combobox puis cliquer "Modifier"
|
|
- Points orange draggables avec magnétisme automatique
|
|
- Ajout de points via les points intermédiaires gris
|
|
- Suppression de points avec clic droit ou Ctrl+clic
|
|
|
|
### MapMode.deleting (Mode suppression)
|
|
- Activé par le bouton "Supprimer un secteur"
|
|
- Affiche une carte d'aide avec avertissements
|
|
- Permet de sélectionner un secteur à supprimer en cliquant dessus
|
|
- Le secteur sélectionné apparaît en rouge
|
|
|
|
## Création d'un secteur
|
|
|
|
### Processus de création
|
|
|
|
1. **Dessin du secteur**
|
|
- L'administrateur clique sur le bouton "Créer un secteur"
|
|
- Il dessine le contour en cliquant sur la carte (minimum 3 points)
|
|
- Il ferme le polygone en cliquant sur le premier point
|
|
|
|
2. **Dialog de création**
|
|
- Nom du secteur (obligatoire)
|
|
- Couleur du secteur (sélection dans une palette)
|
|
- Sélection des membres assignés (au moins un obligatoire)
|
|
|
|
3. **Envoi à l'API**
|
|
```json
|
|
{
|
|
"id": 0,
|
|
"libelle": "Nom du secteur",
|
|
"color": "#2196F3",
|
|
"sector": "lat/lng#lat/lng#...",
|
|
"operation_id": 3124,
|
|
"fk_entite": 5,
|
|
"users": [9999980, 9999985]
|
|
}
|
|
```
|
|
|
|
4. **Réponse de l'API**
|
|
```json
|
|
{
|
|
"status": "success",
|
|
"sector": { /* ou sector_id */ },
|
|
"passages_sector": [...],
|
|
"passages_created": 86,
|
|
"passages_integrated": 0,
|
|
"users_sectors": [...],
|
|
"warning": "Avertissement si débordement départemental",
|
|
"intersecting_departments": [
|
|
{
|
|
"code_dept": "35",
|
|
"nom_dept": "Ille-et-Vilaine",
|
|
"percentage_overlap": 85.2
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
5. **Traitement de la réponse**
|
|
- Le secteur est sauvegardé dans Hive
|
|
- Les passages sont créés avec les coordonnées GPS
|
|
- Les associations utilisateur-secteur sont traitées
|
|
- La carte se centre sur le nouveau secteur
|
|
|
|
### Règles de création
|
|
- Un secteur doit avoir au moins 3 points
|
|
- Le nom est obligatoire
|
|
- Au moins un membre doit être assigné
|
|
- Les coordonnées sont au format "latitude/longitude"
|
|
- Le dernier point doit fermer le polygone
|
|
- Les secteurs adjacents sont automatiquement corrigés (voir section dédiée)
|
|
|
|
## Gestion des secteurs adjacents
|
|
|
|
### Vue d'ensemble
|
|
|
|
L'application gère automatiquement la création de secteurs adjacents (partageant une bordure commune) sans générer d'erreur de chevauchement. Cette fonctionnalité est cruciale pour permettre un découpage précis du territoire.
|
|
|
|
### Correction automatique des points
|
|
|
|
#### Méthode `_correctPointsForAdjacency`
|
|
|
|
Cette méthode est appelée automatiquement lors de :
|
|
- La validation d'un nouveau secteur (création)
|
|
- La validation d'un secteur modifié (modification)
|
|
|
|
**Paramètres de correction :**
|
|
- **Distance de détection** : 10 mètres
|
|
- **Décalage de correction** : 2 mètres vers l'intérieur
|
|
- **Décalage fort** : 5 mètres (si chevauchement persistant)
|
|
|
|
**Processus en deux passes :**
|
|
|
|
1. **Première passe - Détection et correction des segments adjacents**
|
|
```dart
|
|
// Pour chaque segment du nouveau secteur
|
|
// Vérifier s'il est proche d'un segment existant
|
|
// Si oui, corriger les deux points du segment
|
|
```
|
|
|
|
2. **Deuxième passe - Vérification et correction forte**
|
|
```dart
|
|
// Appel à _ensureNoIntersection
|
|
// Si chevauchement détecté → _applyStrongerCorrection
|
|
```
|
|
|
|
### Calcul du décalage vers l'intérieur
|
|
|
|
#### Méthode `_offsetPointInward`
|
|
|
|
**Principe :**
|
|
- Calcule la bissectrice des segments adjacents
|
|
- Utilise le produit vectoriel pour déterminer la direction intérieure
|
|
- Applique un décalage en tenant compte de la latitude
|
|
|
|
**Formule de conversion :**
|
|
```dart
|
|
offsetDegreesLat = offsetMeters / 111320.0
|
|
offsetDegreesLng = offsetMeters / (111320.0 * cos(latitude))
|
|
```
|
|
|
|
### Détection intelligente des chevauchements
|
|
|
|
#### Méthode `_doPolygonsOverlap`
|
|
|
|
**Tolérance d'adjacence** : 2 mètres
|
|
|
|
**Règles de détection améliorées :**
|
|
1. **Points intérieurs** : Un point est considéré à l'intérieur seulement s'il est à plus de 2m du bord
|
|
2. **Vertices partagés** : Les vertices à moins de 5m de distance sont considérés comme partagés et ignorés
|
|
3. **Segments adjacents** : Deux segments alignés et proches ne sont pas considérés comme un chevauchement
|
|
4. **Seuil de détection** : Il faut au moins 3 points intérieurs ou 3 intersections pour détecter un chevauchement réel
|
|
5. **Exclusion du secteur en cours** : Lors de la modification, le secteur lui-même est exclu de la détection
|
|
|
|
#### Méthode `_areSegmentsAdjacent`
|
|
|
|
Détermine si deux segments sont adjacents (partagent une partie commune) :
|
|
- Vérifie l'alignement des segments
|
|
- Vérifie la proximité des points aux lignes opposées
|
|
- Retourne `true` si les segments sont sur la même ligne
|
|
|
|
### Magnétisme automatique
|
|
|
|
Lors de la sélection d'un secteur pour modification :
|
|
- Application automatique du magnétisme aux points proches
|
|
- Visualisation immédiate des ajustements
|
|
- Message d'information si des points ont été magnétisés
|
|
|
|
### Exemple de création de secteurs adjacents
|
|
|
|
```
|
|
Secteur A (existant) : Nouveau secteur B :
|
|
+--------+ +--------+
|
|
| | | |
|
|
| A | <-- bordure --> | B |
|
|
| | commune | |
|
|
+--------+ +--------+
|
|
```
|
|
|
|
**Résultat après correction automatique :**
|
|
- Les points de B sur la bordure commune sont décalés de 2m vers l'intérieur
|
|
- Aucune erreur de chevauchement
|
|
- Les secteurs restent visuellement adjacents
|
|
|
|
### Messages utilisateur
|
|
|
|
- **Correction appliquée** : "Les points ont été ajustés automatiquement pour éviter les chevauchements" (bleu)
|
|
- **Chevauchement détecté** : "Le nouveau secteur chevauche avec le secteur [nom]" (rouge)
|
|
- **Logging détaillé** : En cas de chevauchement détecté, les coordonnées des zones problématiques sont loggées
|
|
|
|
## Modification d'un secteur
|
|
|
|
### Processus de modification
|
|
|
|
1. **Sélection du secteur**
|
|
- Via la combobox ou clic sur la carte
|
|
- Bouton "Modifier" dans la barre d'outils
|
|
|
|
2. **Mode édition**
|
|
- Application automatique du magnétisme dès la sélection
|
|
- Points draggables instantanément (clic et drag immédiat)
|
|
- Points orange avec zone de détection élargie (50x50px)
|
|
- Ajout de points via les points intermédiaires gris
|
|
- Suppression avec clic droit ou Ctrl+clic
|
|
- Désactivation du drag de la carte pendant le déplacement d'un point
|
|
|
|
3. **Validation**
|
|
- Mêmes vérifications que pour la création
|
|
- Application de `_correctPointsForAdjacency` avec exclusion du secteur en cours
|
|
- Dialog pour modifier nom, couleur et membres
|
|
- Les membres déjà affectés sont automatiquement présélectionnés
|
|
- Affichage d'un dialog récapitulatif avec statistiques
|
|
|
|
### Règles de modification
|
|
- Minimum 3 points maintenu
|
|
- Correction automatique des adjacences
|
|
- Même processus de validation que la création
|
|
- Les passages sont automatiquement réaffectés selon le nouveau contour
|
|
|
|
## Suppression d'un secteur
|
|
|
|
### Processus de suppression
|
|
|
|
1. **Sélection du secteur**
|
|
- L'administrateur clique sur "Supprimer un secteur"
|
|
- Il clique sur le secteur à supprimer (surbrillance rouge)
|
|
|
|
2. **Dialog de confirmation**
|
|
- Affichage du nom du secteur
|
|
- Avertissements sur les conséquences
|
|
|
|
3. **Règles de suppression des passages**
|
|
- Passages "à finaliser" (type 2) sans nom d'habitant → **supprimés**
|
|
- Autres passages → **conservés mais réassignés au secteur 0**
|
|
|
|
4. **Réponse de l'API**
|
|
```json
|
|
{
|
|
"status": "success",
|
|
"passages_deleted": 45,
|
|
"passages_reassigned": 125
|
|
}
|
|
```
|
|
|
|
5. **Mise à jour locale**
|
|
- Suppression du secteur de Hive
|
|
- Mise à jour des passages selon les règles
|
|
- Actualisation automatique de la carte
|
|
|
|
## Affichage des secteurs
|
|
|
|
### Représentation visuelle
|
|
- **Polygones colorés** avec transparence (30% en normal, 50% si sélectionné)
|
|
- **Bordure** de la couleur du secteur (épaisseur 2px, 3px si sélectionné)
|
|
- **Mode suppression** : secteur en rouge avec bordure épaisse (4px)
|
|
|
|
### Filtrage par secteur
|
|
- Combobox en haut à gauche
|
|
- "Tous les secteurs" par défaut
|
|
- Sélection d'un secteur → zoom et centrage automatique
|
|
- Filtrage des passages affichés
|
|
|
|
## Affichage des passages
|
|
|
|
### Représentation visuelle
|
|
- **Marqueurs circulaires** de 14x14 pixels
|
|
- **Couleur principale** selon le type de passage
|
|
- **Bordure blanche** de 1px
|
|
- **Cliquables** pour afficher les détails
|
|
|
|
### Conditions d'affichage
|
|
- Coordonnées GPS valides (gps_lat et gps_lng)
|
|
- Type de passage reconnu (1-6)
|
|
- Appartenance au secteur sélectionné (si filtre actif)
|
|
|
|
### Informations au clic
|
|
- Adresse complète
|
|
- Nom de l'habitant (si disponible)
|
|
- Type de passage
|
|
- Informations de règlement (si applicable)
|
|
- Boutons d'édition/suppression
|
|
|
|
## Permissions et rôles
|
|
|
|
### Accès à la carte administrative
|
|
- **Rôle minimum requis** : Admin Amicale (rôle > 1)
|
|
- **Rôle 1 (Membre)** : Pas d'accès à la carte admin
|
|
- **Rôle 2+ (Admin)** : Accès complet aux fonctionnalités
|
|
|
|
### Actions autorisées
|
|
- **Création de secteur** : Admin+
|
|
- **Modification de secteur** : Admin+
|
|
- **Suppression de secteur** : Admin+
|
|
- **Visualisation** : Admin+
|
|
|
|
## Synchronisation API/Hive
|
|
|
|
### Principe "API First"
|
|
1. Toute modification passe d'abord par l'API
|
|
2. En cas de succès, mise à jour de Hive
|
|
3. En cas d'échec, aucune modification locale
|
|
|
|
### Flux de données
|
|
|
|
#### Chargement initial
|
|
```
|
|
API (login) → Secteurs/Passages → Hive → ValueListenableBuilder → UI
|
|
```
|
|
|
|
#### Création de secteur
|
|
```
|
|
UI → API → Réponse (secteur + passages) → Hive → Auto-refresh UI
|
|
```
|
|
|
|
#### Suppression de secteur
|
|
```
|
|
UI → API → Réponse (stats) → Mise à jour Hive → Auto-refresh UI
|
|
```
|
|
|
|
### Gestion des erreurs
|
|
- Affichage de SnackBar avec message d'erreur
|
|
- Pas de modification locale en cas d'échec API
|
|
- Log des erreurs pour debug
|
|
|
|
### Performance
|
|
- Utilisation de box caching dans les repositories
|
|
- ValueListenableBuilder pour éviter les rebuilds inutiles
|
|
- Chargement asynchrone des données
|
|
|
|
## Interactions utilisateur
|
|
|
|
### Gestion du drag des points
|
|
|
|
**Technologie utilisée** : `Listener` avec `onPointerDown`/`onPointerMove`/`onPointerUp`
|
|
|
|
**Avantages :**
|
|
- Démarrage instantané du drag au clic (onPointerDown)
|
|
- Pas de conflit avec les gestes de la carte
|
|
- Conversion directe des coordonnées écran en coordonnées géographiques
|
|
|
|
**Interactions supportées :**
|
|
- **Clic gauche** : Démarre le drag immédiatement
|
|
- **Clic droit / Ctrl+clic** : Supprime le point
|
|
- **Clic sur premier point (mode dessin)** : Ferme le polygone si 3+ points
|
|
- **Drag** : Déplace le point avec magnétisme en temps réel
|
|
|
|
### Dialog récapitulatif
|
|
|
|
Après chaque opération (création/modification/suppression), un dialog affiche :
|
|
- **Statistiques des passages** : créés, mis à jour, orphelins, total
|
|
- **Avertissements départementaux** : si le secteur est à cheval sur plusieurs départements
|
|
- **Icônes et couleurs** adaptées selon le type d'opération
|
|
|
|
## Bonnes pratiques
|
|
|
|
### Pour les développeurs
|
|
|
|
1. **Toujours passer par l'API** pour les modifications
|
|
2. **Utiliser les repositories** pour l'accès aux données
|
|
3. **Ne pas faire de setState** dans les ValueListenableBuilder
|
|
4. **Gérer les erreurs** avec ApiException
|
|
5. **Valider les données** avant envoi à l'API
|
|
6. **Logger les actions importantes** pour le debug
|
|
7. **Utiliser les mêmes méthodes de validation** pour création et modification :
|
|
- `_correctPointsForAdjacency` pour la correction automatique
|
|
- `_doPolygonsOverlap` pour la détection de chevauchement
|
|
- `_isValidPolygon` pour la validation de base
|
|
8. **Sauvegarder le contexte parent** avant d'ouvrir des dialogs pour éviter les erreurs de contexte
|
|
9. **Implémenter le chargement des associations** (ex: UserSectorModel) pour présélectionner les données
|
|
|
|
### Pour les utilisateurs
|
|
|
|
1. **Dessiner des secteurs cohérents** (pas de croisements)
|
|
2. **Nommer clairement** les secteurs
|
|
3. **Assigner les bons membres** dès la création
|
|
4. **Vérifier avant suppression** (action irréversible)
|
|
5. **Utiliser des couleurs distinctes** pour différencier les secteurs
|
|
6. **Pour les secteurs adjacents** :
|
|
- Dessiner normalement sans se soucier de la précision
|
|
- Le système ajuste automatiquement les bordures
|
|
- Vérifier le résultat après la correction automatique
|
|
7. **Pour la modification des secteurs** :
|
|
- Cliquer directement sur un point pour le déplacer (pas besoin de maintenir)
|
|
- Utiliser les points gris intermédiaires pour ajouter des sommets
|
|
- Clic droit ou Ctrl+clic pour supprimer un point
|
|
- Le magnétisme s'applique automatiquement aux bordures adjacentes |