/* PROMPT POUR GÉNÉRER UN ÉCRAN BASÉ SUR CE FICHIER DE DÉFINITION : Créer un écran HTML basé sur le fichier de définition frmMeetingMinute.def. L'objectif est de créer un écran pour pouvoir éditer la classe clsMeetingMinute qui se trouve dans le fichier PVs.js. L'écran doit aussi permettre l'édition des listes qui composent la classe pour permettre l'ajout d'éléments dans ces liste et l'édition des propriété des éléments des listes L'écran doit être construit de manière responsive et compatible avec les devices mobiles. CARACTÉRISTIQUES REQUISES : - Structure à 2 colonnes (libellé + champ de saisie) qui s'adapte en une colonne sur mobile - Wrappers de liste avec boutons d'ajout intégrés dans l'en-tête du wrapper (pas de sections séparées) - Chaque liste doit avoir un wrapper cliquable pour afficher/masquer le contenu avec animation - Chaque ligne de liste doit avoir un bouton corbeille pour supprimer l'élément - Les boutons d'ajout doivent empêcher le toggle du wrapper (event.stopPropagation()) - Interface moderne avec police Inter et variables CSS pour la cohérence CONFIGURATIONS SPÉCIFIQUES DANS LE .DEF : Le fichier .def contient toutes les règles spécifiques de mise en page qui ne sont pas le comportement par défaut : - Layout en 3 colonnes pour Title | Location | MeetingDateTime - Wrapper Tags enroulé par défaut (status=wrapped) - Champ Id invisible et non éditable - Champs obligatoires marqués avec required=true - Placeholders et validations selon les spécifications - Largeurs de colonnes définies (width=3, width=6, etc.) FONCTIONNALITÉS : - Ajout dynamique d'éléments dans les listes avec sections de saisie complètes - Suppression avec confirmation et mise à jour automatique des compteurs - Sauvegarde des données avec les classes du fichier PVs.js - Mise à jour automatique des options de présentateur quand des participants sont ajoutés/supprimés - Compteurs dynamiques dans les titres des wrappers STYLE ET UX : - Design Material Design avec ombres et transitions fluides - Couleurs cohérentes avec variables CSS - Boutons avec icônes SVG - Avatars pour les participants et numéros pour les sujets - Responsive design avec media queries pour mobile - Animations d'ouverture/fermeture des wrappers L'écran doit utiliser les classes Person, Tag, Topic, et MeetingMinute du fichier PVs.js. */ // ============================================================================= // FICHIER DE DÉFINITION : frmMeetingMinute.def // ============================================================================= // Ce fichier définit la configuration des éléments graphiques de l'écran frmMeetingMinute // // FORMAT GÉNÉRAL : // [Classe].[Propriété] : [Paramètre]=[Valeur] // // PARAMÈTRES DISPONIBLES : // - status=expanded|wrapped : État d'ouverture/fermeture d'un wrapper de liste // - visible=true|false : Visibilité d'un champ (true par défaut) // - editable=true|false : Possibilité de modifier un champ (true par défaut) // - required=true|false : Champ obligatoire (false par défaut) // - placeholder=[texte] : Texte d'aide dans un champ vide // - width=[nombre] : Largeur en colonnes (1-12) // - height=[nombre] : Hauteur en lignes pour les textarea // - order=[nombre] : Ordre d'affichage (1, 2, 3, ...) // - group=[nom] : Groupe de champs pour organisation // - validation=[règle] : Règle de validation (email, number, date, etc.) // - default=[valeur] : Valeur par défaut // - readonly=true|false : Lecture seule (alias de editable=false) // - hidden=true|false : Caché (alias de visible=false) // // LAYOUT : // Utilisez le séparateur | pour placer des champs sur la même ligne // Utilisez des espaces pour l'indentation et l'organisation // // EXEMPLES : // clsMeetingMinute.Title | clsMeetingMinute.Location | clsMeetingMinute.MeetingDateTime // clsMeetingMinute.Description : height=4 // clsMeetingMinute.Id : visible=false // ============================================================================= // ============================================================================= // SECTION : PROPRIÉTÉS PRINCIPALES DE MEETINGMINUTE // ============================================================================= // Identifiant unique (généré automatiquement) clsMeetingMinute.Id : visible=false, editable=false // Titre de la réunion clsMeetingMinute.Title : required=true, placeholder="Titre de la réunion", width=6 // Lieu de la réunion clsMeetingMinute.Location : placeholder="Lieu de la réunion", width=3 // Date et heure de la réunion clsMeetingMinute.MeetingDateTime : required=true, validation=datetime, width=3 // ============================================================================= // SECTION : LAYOUT - ORGANISATION DES CHAMPS // ============================================================================= // Ligne 1 : Titre, Lieu, Date/Heure sur la même ligne clsMeetingMinute.Title | clsMeetingMinute.Location | clsMeetingMinute.MeetingDateTime // ============================================================================= // SECTION : PARTICIPANTS // ============================================================================= // Wrapper des participants (ouvert par défaut) clsMeetingMinute.Attendees : status=expanded // Propriétés des participants individuels clsPerson.FirstName : required=true, placeholder="Prénom", width=3 clsPerson.LastName : required=true, placeholder="Nom", width=3 clsPerson.ShortName : placeholder="Surnom (ex: LCR)", width=2 clsPerson.Email : validation=email, placeholder="email@exemple.ch", width=4 clsPerson.Image : placeholder="nom_fichier.jpg", width=2 // ============================================================================= // SECTION : SUJETS // ============================================================================= // Wrapper des sujets (ouvert par défaut) clsMeetingMinute.Topics : status=expanded // Propriétés des sujets individuels clsTopic.Title : required=true, placeholder="Titre du sujet", width=6 clsTopic.Description : height=3, placeholder="Description détaillée du sujet", width=6 clsTopic.Duration : validation=number, placeholder="Durée en minutes", width=2 clsTopic.Category : placeholder="Catégorie (ex: Décision, Information)", width=4 clsTopic.Presenter : required=true, width=4 // ============================================================================= // SECTION : TAGS // ============================================================================= // Wrapper des tags (enroulé par défaut) clsMeetingMinute.Tags : status=wrapped // Propriétés des tags individuels clsTag.Name : required=true, placeholder="Nom du tag", width=4 clsTag.Color : default="#e0e0e0", width=2 // ============================================================================= // SECTION : CONFIGURATION AVANCÉE // ============================================================================= // Configuration des boutons d'action btnSave : visible=true, order=1 btnSettings : visible=true, order=2 // Configuration des wrappers wrapperParticipants : status=expanded, order=1 wrapperTopics : status=expanded, order=2 wrapperTags : status=wrapped, order=3 // ============================================================================= // SECTION : VALIDATION ET CONTRAINTES // ============================================================================= // Validation des emails clsPerson.Email : validation=email, required=false // Validation des nombres clsTopic.Duration : validation=number, min=0, max=480 // Validation des dates clsMeetingMinute.MeetingDateTime : validation=datetime, min="today" // ============================================================================= // SECTION : STYLES ET PRÉSENTATION // ============================================================================= // Champs avec style spécial clsMeetingMinute.Title : style=title, font-weight=bold clsMeetingMinute.Id : style=hidden clsTopic.Description : style=textarea, resize=vertical // ============================================================================= // FIN DU FICHIER DE DÉFINITION // =============================================================================