From 1c65c4dc7481336aff6f9dc3d0031833843543b9 Mon Sep 17 00:00:00 2001 From: Nikolaz Date: Wed, 23 Sep 2026 09:59:15 +0200 Subject: [PATCH] Carnet d'adresses : ajout/modification via une popup modale MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Formulaire de création/modification affiché dans une fenêtre modale (bouton « Ajouter une adresse » + action « Modifier » d'une ligne) - Fermeture au succès, sur « Annuler » ou clic sur l'arrière-plan - Suggestions BAN rendues dans le flux du panneau pour éviter la troncature - Specs : Exigence 15 (nouveau critère 17) + description CarnetAdressesComponent --- .kiro/specs/schotziad-km-tracker/design.md | 5 +- .../schotziad-km-tracker/requirements.md | 1 + .../carnet-adresses.component.html | 21 ++++++-- .../carnet-adresses.component.scss | 51 +++++++++++++++++-- .../carnet-adresses.component.ts | 22 ++++++++ 5 files changed, 89 insertions(+), 11 deletions(-) diff --git a/.kiro/specs/schotziad-km-tracker/design.md b/.kiro/specs/schotziad-km-tracker/design.md index 7770358..20b92b3 100644 --- a/.kiro/specs/schotziad-km-tracker/design.md +++ b/.kiro/specs/schotziad-km-tracker/design.md @@ -337,8 +337,9 @@ src/ - Montants en euros à 2 décimales **`CarnetAdressesComponent`** -- Liste des Adresses_Nommées (Dénomination + adresse + indication si coordonnées disponibles), triée par Dénomination -- Formulaire de création / modification : champ `denomination` (1–100 car.) et champ `adresse` avec autocomplétion BAN (1–255 car.) +- Liste des Adresses_Nommées (Dénomination + adresse + indication si coordonnées disponibles), triée par Dénomination, avec un bouton « Ajouter une adresse » au-dessus de la liste +- Formulaire de création / modification présenté dans une **fenêtre modale** (overlay `.modale-overlay` + panneau `.modale-panneau`, motif partagé avec `ConfirmDialogComponent` / `ConsultationJourComponent`), ouvert via le bouton « Ajouter une adresse » (mode création) ou l'action « Modifier » d'une ligne (mode édition) ; fermée par enregistrement réussi, par le bouton « Annuler », ou par un clic sur l'arrière-plan. Le signal `modaleOuverte` pilote l'affichage +- Champ `denomination` (1–100 car.) et champ `adresse` avec autocomplétion BAN (1–255 car.) ; dans la modale, les suggestions BAN sont rendues **dans le flux** du panneau (et non en position absolue) pour éviter toute troncature par le défilement du panneau - **Autocomplétion BAN** : appel à `https://api-adresse.data.gouv.fr/search/?q={saisie}&limit=5` dès 3 caractères saisis, avec debounce de 300 ms, maximum 5 suggestions ; à la sélection, le libellé normalisé remplit le champ et les coordonnées `(lat, lon)` sont conservées pour transmission - Actions par ligne : modifier (→ formulaire pré-rempli), supprimer (→ dialog de confirmation) - À chaque succès de création, modification ou suppression, affiche un message de confirmation via `NotificationService` diff --git a/.kiro/specs/schotziad-km-tracker/requirements.md b/.kiro/specs/schotziad-km-tracker/requirements.md index c4d2c2a..d26bc39 100644 --- a/.kiro/specs/schotziad-km-tracker/requirements.md +++ b/.kiro/specs/schotziad-km-tracker/requirements.md @@ -376,6 +376,7 @@ L'application est composée d'un frontend Angular/TypeScript et d'un backend C#. 14. WHEN l'utilisateur confirme la suppression d'une Adresse_Nommee, THE Backend SHALL supprimer l'Adresse_Nommee du Carnet_Adresses en conservant inchangés les Trajets déjà enregistrés, qui gardent leur texte d'adresse et leurs coordonnées géographiques stockés. 15. WHEN le Backend a créé, modifié ou supprimé une Adresse_Nommee avec succès, THE Frontend SHALL afficher un message de confirmation indiquant que l'opération a réussi. 16. WHEN le Frontend affiche le formulaire de saisie ou d'insertion d'un Trajet, THE Frontend SHALL proposer la liste des Adresses_Nommées du Carnet_Adresses par leur Dénomination pour le champ adresse de départ et pour le champ adresse d'arrivée. +17. WHEN l'utilisateur active la création d'une Adresse_Nommee (bouton « Ajouter une adresse ») ou la modification d'une Adresse_Nommee existante depuis la liste, THE Frontend SHALL présenter le formulaire de saisie dans une fenêtre modale superposée à la liste, et SHALL fermer cette fenêtre modale après un enregistrement réussi, après annulation par l'utilisateur, ou lors d'un clic sur l'arrière-plan de la fenêtre modale. --- diff --git a/frontend/src/app/features/carnet-adresses/carnet-adresses.component.html b/frontend/src/app/features/carnet-adresses/carnet-adresses.component.html index fdde493..cb62359 100644 --- a/frontend/src/app/features/carnet-adresses/carnet-adresses.component.html +++ b/frontend/src/app/features/carnet-adresses/carnet-adresses.component.html @@ -1,8 +1,18 @@
-

Carnet d'adresses

+
+

Carnet d'adresses

+ +
- -
+ +
+

{{ enEdition ? 'Modifier une adresse' : 'Ajouter une adresse' }}

@@ -56,11 +66,12 @@ -
- + +
diff --git a/frontend/src/app/features/carnet-adresses/carnet-adresses.component.scss b/frontend/src/app/features/carnet-adresses/carnet-adresses.component.scss index 4f67548..f09b5ec 100644 --- a/frontend/src/app/features/carnet-adresses/carnet-adresses.component.scss +++ b/frontend/src/app/features/carnet-adresses/carnet-adresses.component.scss @@ -17,14 +17,57 @@ } } +.carnet__entete { + display: flex; + justify-content: space-between; + align-items: center; + gap: 1rem; +} + +.btn--ajouter { + background: #0074b8; + color: #fff; + white-space: nowrap; + + &:hover { + background: #f28c28; + } +} + +.modale-overlay { + position: fixed; + inset: 0; + z-index: 1000; + display: flex; + align-items: center; + justify-content: center; + padding: 1rem; + background: rgba(0, 0, 0, 0.45); +} + +.modale-panneau { + width: 100%; + max-width: 480px; + max-height: 90vh; + overflow-y: auto; + background: #fff; + border-radius: 10px; + box-shadow: 0 12px 32px rgba(0, 0, 0, 0.25); +} + +// Dans la popup, l'overlay 'overflow-y: auto' du panneau tronque un menu +// positionné en absolu : on affiche donc les suggestions dans le flux normal. +.modale-panneau .suggestions { + position: static; + box-shadow: none; + max-height: 180px; +} + .carnet__form { display: flex; flex-direction: column; gap: 1rem; - padding: 1rem; - border: 1px solid #dcdcdc; - border-radius: 8px; - background: #fafafa; + padding: 1.25rem; } .field { diff --git a/frontend/src/app/features/carnet-adresses/carnet-adresses.component.ts b/frontend/src/app/features/carnet-adresses/carnet-adresses.component.ts index ee61936..47d6a30 100644 --- a/frontend/src/app/features/carnet-adresses/carnet-adresses.component.ts +++ b/frontend/src/app/features/carnet-adresses/carnet-adresses.component.ts @@ -60,6 +60,9 @@ export class CarnetAdressesComponent implements OnInit, OnDestroy { /** Identifiant de l'adresse en cours d'édition (null = création). */ readonly editionId = signal(null); + /** Ouverture de la popup de création / modification. */ + readonly modaleOuverte = signal(false); + /** Suggestions BAN courantes pour le champ adresse. */ readonly suggestions = signal([]); @@ -131,6 +134,24 @@ export class CarnetAdressesComponent implements OnInit, OnDestroy { denomination: adresse.denomination, adresse: adresse.adresse, }); + this.modaleOuverte.set(true); + } + + /** Ouvre la popup en mode création (formulaire vierge). */ + ouvrirCreation(): void { + this.editionId.set(null); + this.latitude = null; + this.longitude = null; + this.suggestions.set([]); + this.form.reset({ denomination: '', adresse: '' }); + this.modaleOuverte.set(true); + } + + /** Ferme la popup uniquement lors d'un clic sur le fond (pas sur le panneau). */ + fermerSurOverlay(event: MouseEvent): void { + if (event.target === event.currentTarget) { + this.annuler(); + } } /** Réinitialise le formulaire en mode création. */ @@ -140,6 +161,7 @@ export class CarnetAdressesComponent implements OnInit, OnDestroy { this.longitude = null; this.suggestions.set([]); this.form.reset({ denomination: '', adresse: '' }); + this.modaleOuverte.set(false); } /** Réagit à la saisie du champ adresse pour alimenter l'autocomplétion BAN. */