DOCS/kanban/cards/5-planifie/290-refonte-visuelle-config-section-et-dialogues.md
2026-09-04 16:48:04 +02:00

54 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: Refonte visuelle des écrans Configuration & Section, et de leurs dialogues
area: manager
horizon: v1
tags: manager-app, UI, dialogues
flag: good | Maquette prête, code à faire
src: DOCS/claude design/refonte-configuration-sections.html
---
<p><strong>Lots 1 à 5 codés le 04/09</strong> (<code>flutter analyze</code> sans erreur, <code>flutter build web</code> passe ; <strong>rien de vérifié à l'écran</strong>). Pilote <code>select_resource_modal</code> : coquille standard, corps souple, plus de double défilement, <code>showValues</code> mort supprimé, largeur <code>0,85</code> conservée. Lot 1 : <code>text_field_container</code> sans <code>width: double.infinity</code> ni rayon 29, compteur discret dans <code>rounded_input_field</code>. Lot 2 : libellé au-dessus et plus d'auto-centrage dans <code>string_</code>/<code>multi_string_</code>/<code>resource_</code>/<code>check_input_container</code>. Lot 3 : grille responsive de sections, réordonnancement par <code>Draggable</code>/<code>DragTarget</code> (<code>ReorderableListView</code> ne fait pas de grille, et pas de dépendance nouvelle), tuile « Ajouter » à la place du bouton vert. Lot 4 : les deux écrans de détail en <code>EditorHeader</code> + <code>EditorColumns</code> + <code>Pane</code> (nouveau <code>Components/pane.dart</code>), <code>_buildFooter</code> supprimé, le QR devient le rail « Diffusion ». Lot 5 : grille de types dans <code>new_section_popup</code>, modal de traduction en rail de langues + <code>IndexedStack</code>, et <code>multi_input_modal</code> réduit à une redirection <code>isHTML: false</code>. 24 clés i18n ajoutées en FR/EN/NL.</p>
<p>🐛 <strong>Le bug des catégories est confirmé et corrigé</strong> : <code>showCreateOrUpdateCategories</code> recevait un <code>newValues</code> vide de l'appelant et le renvoyait tel quel — valider sans rien toucher <em>effaçait</em> les catégories. Le tampon part maintenant des catégories existantes, et les libellés en dur sont passés par <code>AppLocalizations</code>.</p>
<p><strong>Lot 6 entamé</strong> : <code>Components/collection_editor.dart</code> existe — liste ordonnée à gauche (réordonnancement par poignée), élément édité en place à droite, ligne « Ajouter » en fin de liste, suppression dans l'en-tête du détail. Trois types migrés : <strong>Slider</strong> et <strong>Article</strong> (via un <code>ContentFields</code> partagé, extrait de <code>showNewOrUpdateContentSlider</code>) et <strong>PDF</strong> (le bloc figé <code>70 × 440</code> disparaît). Les filtres d'envoi au backend sont conservés à l'identique (contenus sans ressource exclus, champs d'article recopiés).</p>
<p>⚠️ <strong>Trois fichiers sont devenus du code mort mais ne sont pas supprimés</strong> : <code>pdf_file_input_container.dart</code>, <code>pdf_list.dart</code>, <code>new_update_pdfFile.dart</code>. Ils portent des modifications non committées d'un autre lot — les effacer perdrait ce travail. À supprimer une fois l'arbre propre.</p>
<p><strong>Lot 6 terminé pour le gabarit B.</strong> Décision prise le 04/09 (artifact <code>4af75171</code>) : <code>CollectionEditor</code> reçoit un <strong>mode distant</strong> (<code>RemoteCollection</code> : <code>create</code> / <code>delete</code> / <code>reorder</code> asynchrones, voile de chargement, retour à l'état d'avant si l'appel échoue). <strong>Quiz</strong> l'utilise : la modale de question disparaît, les messages de score remontent en tête de carte, les réponses gardent <code>QuizzResponseList</code> tel quel. <strong>Menu</strong> garde la navigation vers <code>sub_section_edit_screen</code> — une sous-section est une section complète — et prend la grille de tuiles, extraite en <code>SectionGrid</code> et partagée avec les sections d'une configuration. <strong>Parcours</strong> : liste qui suit son contenu, les deux <code>SizedBox(height: 500)</code> de <code>event_config</code> et <code>section_parcours_config</code> retirés, éditeur à fenêtre unique inchangé.</p>
<p>🐛 <strong>Le rang en double est corrigé</strong> dans Quiz et Menu : ils n'écrivaient que l'<code>order</code> de l'élément déplacé, les autres gardaient le leur. La liste entière est renumérotée et envoyée en un <code>Future.wait</code>, comme le faisait déjà Parcours.</p>
<p><strong>Agenda n'a pas été migré, et c'est délibéré</strong> : ses événements sont groupés par langue (<code>_displayGroups</code>, pastilles de langue quand un groupe en compte plusieurs) et n'ont pas d'ordre — une liste ordonnée à édition en place perdrait le groupement. Il reçoit ce qui lui revient : hauteur pilotée par le contenu (le <code>height: 600</code> saute), lignes au système de tokens, modale conservée.</p>
<p><strong>Gabarit C — Jeu est fait, Map et Événement sont dégrossis.</strong> <code>game_config</code> devient champs à gauche + canevas à droite : le canevas montre le découpage réel de l'image en <code>rows × cols</code>, seule décision que le formulaire ne montrait pas. Au passage, son <code>TabBar</code> n'en était pas un — les deux onglets construisaient le même formulaire et ne servaient qu'à écrire <code>gameType</code> : c'est devenu un choix à deux valeurs, et le <code>SizedBox(height: 650)</code> a disparu. <code>geoloc_input_container</code> passe à la coquille standard et affiche les coordonnées retenues au lieu d'un bouton « Changer la localisation », la carte prenant la hauteur disponible. Côté <code>map_config</code> : en-tête en grille de tokens, <code>height: 700</code> et <code>height: 70</code> retirés. Côté <code>event_config</code> : <code>height: 600</code> retiré, la liste des blocs suit son contenu.</p>
<p><strong>Reste : le canevas de Map et d'Événement — et il est maintenant maquetté</strong> : <code>DOCS/claude design/refonte-gabarit-canevas.html</code> (diffusion : artifact <code>caf400b5</code>). Liste des points, fiche, carte côte à côte ; les points non sélectionnés restent visibles en gris ; <code>MapGeometryPicker</code> sort de son dialogue pour devenir le canevas (déplacement, pas écriture) ; les informations pratiques d'un point (5 champs sur 9) sont repliées derrière un compteur. Absorbe <code>showNewOrUpdateGeoPoint</code> (362 l.), <code>geometry_input_container</code> et <code>showNewOrUpdateMapAnnotation</code> (182 l.). <strong>Une question produit reste ouverte</strong> : que montre le canevas d'Événement quand <code>baseSectionMapId</code> est nul — carte vide, ou invitation à choisir un plan d'abord (ma proposition).</p>
<p><strong>Étape 1 du canevas faite le 04/09</strong> : <code>Components/map_canvas.dart</code> — le dessin est sorti du dialogue. Il reçoit une géométrie, la rend modifiable, rend la main <em>à chaque changement</em> (pas de bouton « Enregistrer » : c'est l'écran qui enregistre), et affiche les autres tracés en fond via <code>MapCanvasGhost</code>. Barre d'outils compacte sur la carte, pied qui donne les coordonnées et ce qu'on modifie, bouton « agrandir » optionnel. <code>MapGeometryPicker</code> n'est plus qu'une coquille autour de lui, donc <code>etape_fields</code> et <code>showNewOrUpdateEventAgenda</code> ne bougent pas. Au passage, ses libellés « Ligne » / « Polygone » en dur sont passés par <code>AppLocalizations</code>. <strong>Taille tranchée</strong> : 420 px par défaut + mode agrandi, pas une interface centrée carte — un point porte neuf champs traduits, la carte n'en porte qu'un.</p>
<p><strong>Étapes 2 à 4 faites : le gabarit C est en place dans Map.</strong> <code>Map/geo_point_editor.dart</code> — liste des points à gauche, fiche au centre, carte à droite ; les points non sélectionnés apparaissent en fond ; le mode agrandi replie la fiche et garde le rail. Les neuf champs traduits sont rangés par fréquence : titre, catégorie, description et image visibles, les cinq informations pratiques repliées derrière un compteur. <code>map_config</code> passe de 937 à ~510 lignes : la modale <code>showNewOrUpdateGeoPoint</code> n'est plus appelée, <code>getElement</code> et son <code>boxDecoration</code> sont supprimés, et recherche + catégories filtrent désormais la liste <em>et</em> la carte par un seul calcul. Les points sont créés, modifiés et supprimés directement par l'API (<code>sectionMapCreate</code> / <code>Update</code> / <code>Delete</code>), la suppression passant par la confirmation destructive.</p>
<p><strong>Étape 5 faite : le canevas d'Événement.</strong> Les annotations passent dans l'éditeur de collection en mode distant, avec le canevas dans le panneau d'édition. <strong>Plan par défaut</strong> retenu (décision Thomas) : le premier plan disponible est pris quand <code>baseSectionMapId</code> est nul, plutôt que de bloquer. 🐛 <strong>Trouvé en chemin</strong> : <code>MapAnnotationDTO</code> portait déjà un champ <code>geometry</code> que l'ancienne modale ne remplissait <em>jamais</em> — elle ne réglait que <code>geometryType</code>. Une annotation déclarait donc une forme sans jamais recevoir de coordonnées ; le canevas les lui donne. Enfin <code>showMultiStringInputAndResourceHTML</code> est passé à la coquille standard : plus aucun dialogue de ce chantier sur l'ancienne.</p>
<p><strong>Plan de test</strong> : <code>DOCS/test-plan-refonte-config-section.md</code>, 14 sections. Rien n'a été vérifié à l'écran — <code>flutter analyze</code> propre et <code>flutter build web</code> qui passe, c'est tout.</p>
<p><strong>Reste</strong> : supprimer le code mort une fois l'arbre git propre — <code>showNewOrUpdateGeoPoint</code>, <code>showNewOrUpdateMapAnnotation</code>, <code>pdf_file_input_container</code>, <code>pdf_list</code>, <code>new_update_pdfFile</code>, <code>listView_card_subSection</code>, <code>new_update_question_quizz</code> ; et <code>geometry_input_container</code> quand <code>etape_fields</code> et <code>showNewOrUpdateEventAgenda</code> auront leur canevas.</p> Restent aussi <code>showMultiStringInputAndResourceHTML</code> sur l'ancienne coquille, et le code mort à supprimer une fois l'arbre propre : <code>pdf_file_input_container</code>, <code>pdf_list</code>, <code>new_update_pdfFile</code>, <code>listView_card_subSection</code>, <code>new_update_question_quizz</code>.<br>⚠️ <strong>À vérifier manuellement en priorité</strong> : les deux chemins qui recréent les contrôleurs Quill (traduction IA, « appliquer à toutes les langues ») ; les hauteurs figées restées autour des champs devenus plus hauts (<code>height: 70</code>, <code>100</code>) dans les écrans non repris — <code>showNewOrUpdateGeoPoint</code>, <code>showNewOrUpdateEventAgenda</code>, <code>sub_section_edit_screen</code>, <code>new_configuration_popup</code>.</p>
<p><strong>Maquette prête et complète</strong> : <code>DOCS/claude design/refonte-configuration-sections.html</code> (diffusion : artifact <code>4d0c2ad6</code>). Elle contient le diagnostic, les deux écrans, les 3 gabarits qui couvrent les 13 types de section, la coquille de dialogue, et deux dialogues dessinés — traduction et choix du type. <strong>Rien à décider côté design : tout est tranché.</strong></p>
<p><strong>Le blanc ne vient pas des écrans mais de 4 composants partagés.</strong> <code>text_field_container.dart</code> impose <code>width: double.infinity</code> + rayon 29 ; <code>string_input_container.dart</code> met le label à gauche dans un <code>Row</code> ; <code>multi_string_input_container</code> et <code>resource_input_container</code> se centrent eux-mêmes ; <code>section_reorderList.dart</code> réserve <code>0,3 × hauteur</code> pour une liste horizontale de cartes 150×150. On les corrige une fois, les 13 types en héritent.</p>
<p>⚠️ <strong>Aucune direction visuelle à inventer</strong> : <code>constants.dart</code> porte déjà le système (<code>kSpace1..8</code>, <code>kRadiusInput</code> 5 / <code>Card</code> 8 / <code>Shell</code> 10 / <code>Pill</code>, <code>kTitleCard</code>, <code>kLabelField</code>, <code>kTextHint</code>) et <code>confirmation_dialog.dart</code> + <code>resource_picker.dart</code> l'appliquent déjà. Ces deux écrans sont simplement <em>antérieurs</em> au système.</p>
<p><strong>Premier pas conseillé : <code>select_resource_modal.dart</code>, pas les composants partagés.</strong> Un fichier, ~15 lignes, zéro ligne dans <code>ResourcesScreen</code>, et ça corrige un vrai bug — <code>AlertDialog</code> dispose de <code>hauteur 48</code> mais le contenu en demande <code>0,85 × hauteur</code> plus titre plus actions, d'où un défilement dans un défilement. Ça sert de pilote avant de toucher aux composants qui irriguent 30 écrans. ⛔ <strong>Ne pas toucher à la largeur <code>0,85</code></strong> : la règle du rail de facettes de <code>v1-mediatheque-plan.md</code> §3.3 est écrite sur cette hypothèse et déjà codée.</p>
<p>⚠️ <strong>Deux pièges qui ne sont pas du visuel.</strong> D'abord, <code>manager-app</code> n'a que 3 tests, aucun sur ces composants : vérification manuelle, et il reste des conteneurs à hauteur figée (<code>height: 70</code>, <code>100</code>, <code>SizedBox(height: 250)</code>) autour — ce qui rentrait juste débordera. Ensuite un chemin d'écriture est câblé dans les composants : <code>section_detail_screen.dart:270</code> déclenche un <code>save(true, …)</code> depuis <code>MultiStringInputContainer.onGetResult</code>, et la ligne 381 un <code>save(false, …)</code> depuis la case iBeacon. À ne pas perdre ni dédoubler.</p>
<p>⚠️ <strong>Le piège Quill</strong> (remonté de mémoire par Thomas, confirmé dans le code). Ça marche aujourd'hui <em>parce que</em> l'empilement vertical monte toutes les langues : <code>_controllers</code> est bâtie une fois dans <code>initState</code> (<code>translation_input_container.dart:52</code>) et libérée seulement dans <code>dispose</code>. Le rail de langues de la maquette casse cette propriété s'il reconstruit l'éditeur à chaque bascule. <strong>Règle : map construite une fois pour toutes les langues, bascule par <code>IndexedStack</code>/<code>Offstage</code>, jamais de <code>TabBarView</code></strong> (construction paresseuse, enfants lâchés hors écran sans <code>AutomaticKeepAliveClientMixin</code>). Trace d'une tentative abandonnée : <code>translation_tab.dart</code> existe en <code>TabBar</code>, son appel est en commentaire dans <code>multi_input_modal.dart:46-51</code>. À retester en priorité : la traduction IA (ligne 142) et « appliquer à toutes les langues » (ligne 183), les deux chemins qui libèrent et recréent les contrôleurs.</p>
<p><strong>Deux fusions et un ménage</strong> décidés dans la maquette : <code>multi_input_modal.dart</code> est le jumeau sans HTML du modal de traduction (même travail, deux implémentations) → une coquille, deux corps, Quill si <code>isHTML</code> et champ simple sinon ; les 8 <code>showNewOrUpdate*</code> et les 2 sélecteurs géo disparaissent dans les gabarits B et C ; <code>showValues</code> est mort en double (<code>select_resource_modal.dart:64</code> et <code>multi_input_modal.dart:186</code>, appel commenté ligne 53).</p>
<p>⚠️ <strong>Conflit résolu avec l'audit</strong><code>security/audit-manager-app.md</code> recommandait d'extraire un <code>FormDialogScaffold</code> pour les 15 occurrences des <code>showNewOrUpdate*</code>. Or la refonte les <strong>supprime</strong> : les extraire d'abord, ce serait refactoriser du code à jeter. <strong>Ordre imposé : absorber d'abord (gabarits B et C), extraire ensuite sur ce qui survit</strong> — traduction, nouvelle section, nouvelle configuration, sélecteur de couleur, fichiers PDF, catégories. L'audit et <code>STATUS.md</code> ont été annotés en ce sens le 2026-09-04.</p>
<p>🐛 <strong>Trouvé en passant, à vérifier</strong> : <code>pdf_file_input_container.dart</code> et <code>category_input_container.dart</code> sont un copier-coller — mêmes dimensions, même structure — mais le second a ses libellés en dur (« Annuler », « Valider ») et son <code>onGetResult(result)</code> <strong>commenté</strong>. Une catégorie de carte modifiée ne remonte peut-être pas à la volée. Lecture de code, pas testé.</p>