# 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