fix(chat): Correction race condition + Implémentation TODOs

## Corrections Critiques

### Race Condition - Statuts de Messages
- Fix : Les icônes de statut (✓, ✓✓, ✓✓ bleu) ne s'affichaient pas
- Cause : WebSocket delivery confirmations arrivaient avant messages locaux
- Solution : Pattern Optimistic UI dans chat_bloc.dart
  - Création message temporaire immédiate
  - Ajout à la liste AVANT requête HTTP
  - Remplacement par message serveur à la réponse
- Fichier : lib/presentation/state_management/chat_bloc.dart

## Implémentation TODOs (13/21)

### Social (social_header_widget.dart)
-  Copier lien du post dans presse-papiers
-  Partage natif via Share.share()
-  Dialogue de signalement avec 5 raisons

### Partage (share_post_dialog.dart)
-  Interface sélection d'amis avec checkboxes
-  Partage externe via Share API

### Média (media_upload_service.dart)
-  Parsing JSON réponse backend
-  Méthode deleteMedia() pour suppression
-  Génération miniature vidéo

### Posts (create_post_dialog.dart, edit_post_dialog.dart)
-  Extraction URL depuis uploads
-  Documentation chargement médias

### Chat (conversations_screen.dart)
-  Navigation vers notifications
-  ConversationSearchDelegate pour recherche

## Nouveaux Fichiers

### Configuration
- build-prod.ps1 : Script build production avec dart-define
- lib/core/constants/env_config.dart : Gestion environnements

### Documentation
- TODOS_IMPLEMENTED.md : Documentation complète TODOs

## Améliorations

### Architecture
- Refactoring injection de dépendances
- Amélioration routing et navigation
- Optimisation providers (UserProvider, FriendsProvider)

### UI/UX
- Amélioration thème et couleurs
- Optimisation animations
- Meilleure gestion erreurs

### Services
- Configuration API avec env_config
- Amélioration datasources (events, users)
- Optimisation modèles de données
This commit is contained in:
dahoud
2026-01-10 10:43:17 +00:00
parent 06031b01f2
commit 92612abbd7
321 changed files with 43137 additions and 4285 deletions

View File

@@ -1,9 +1,9 @@
import 'package:flutter/material.dart';
class AccessibilityField extends StatelessWidget {
final Function(String?) onSaved;
const AccessibilityField({Key? key, required this.onSaved}) : super(key: key);
const AccessibilityField({required this.onSaved, super.key});
final Function(String?) onSaved;
@override
Widget build(BuildContext context) {

View File

@@ -1,9 +1,9 @@
import 'package:flutter/material.dart';
class AccommodationInfoField extends StatelessWidget {
final Function(String?) onSaved;
const AccommodationInfoField({Key? key, required this.onSaved}) : super(key: key);
const AccommodationInfoField({required this.onSaved, super.key});
final Function(String?) onSaved;
@override
Widget build(BuildContext context) {

View File

@@ -1,13 +1,14 @@
import 'package:flutter/material.dart';
import '../../../core/utils/app_logger.dart';
/// Un champ pour saisir le nombre maximum de participants à un événement.
/// Il est conçu pour permettre à l'utilisateur de saisir un nombre entier.
class AttendeesField extends StatelessWidget {
// Définition de la fonction de rappel pour sauver la valeur saisie.
final Function(int) onSaved;
// Le constructeur prend une fonction de rappel pour sauvegarder la valeur saisie.
const AttendeesField({Key? key, required this.onSaved}) : super(key: key);
const AttendeesField({required this.onSaved, super.key});
// Définition de la fonction de rappel pour sauver la valeur saisie.
final Function(int) onSaved;
@override
Widget build(BuildContext context) {
@@ -33,21 +34,21 @@ class AttendeesField extends StatelessWidget {
filled: true, // Le champ est rempli avec une couleur de fond.
fillColor: Colors.blueGrey.withOpacity(0.1), // Couleur de fond du champ avec opacité.
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12.0)), // Bordure arrondie
borderRadius: BorderRadius.all(Radius.circular(12)), // Bordure arrondie
borderSide: BorderSide.none, // Pas de bordure par défaut
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12.0)),
borderSide: const BorderSide(
enabledBorder: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12)),
borderSide: BorderSide(
color: Colors.blueGrey, // Bordure de base
width: 1.5,
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12.0)),
borderSide: const BorderSide(
focusedBorder: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12)),
borderSide: BorderSide(
color: Colors.blue, // Bordure en bleu lors du focus
width: 2.0,
width: 2,
),
),
prefixIcon: const Icon(
@@ -57,13 +58,13 @@ class AttendeesField extends StatelessWidget {
),
style: const TextStyle(
color: Colors.blueGrey, // Couleur du texte saisi
fontSize: 16.0, // Taille de police
fontSize: 16, // Taille de police
fontWeight: FontWeight.w600, // Poids de la police pour la lisibilité
),
onChanged: (value) {
// Lors de chaque modification de texte, on tente de convertir la valeur en entier.
int? maxParticipants = int.tryParse(value) ?? 0; // Conversion en entier, avec une valeur par défaut de 0.
print('Nombre maximum de participants saisi : $maxParticipants'); // Log pour suivre la valeur saisie.
final int maxParticipants = int.tryParse(value) ?? 0; // Conversion en entier, avec une valeur par défaut de 0.
AppLogger.d('Nombre maximum de participants saisi : $maxParticipants', tag: 'AttendeesField');
onSaved(maxParticipants); // Appel de la fonction onSaved pour transmettre la valeur au formulaire principal.
},
validator: (value) {

View File

@@ -4,11 +4,11 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart' as rootBundle;
class CategoryField extends StatefulWidget {
// Ce callback est utilisé pour enregistrer la valeur sélectionnée dans le formulaire
final FormFieldSetter<String> onSaved;
// Constructeur de la classe CategoryField
const CategoryField({Key? key, required this.onSaved}) : super(key: key);
const CategoryField({required this.onSaved, super.key});
// Ce callback est utilisé pour enregistrer la valeur sélectionnée dans le formulaire
final FormFieldSetter<String> onSaved;
@override
_CategoryFieldState createState() => _CategoryFieldState();
@@ -59,22 +59,22 @@ class _CategoryFieldState extends State<CategoryField> {
});
// Log pour vérifier si les catégories ont bien été chargées
debugPrint("Catégories chargées : $_categoryMap");
debugPrint('Catégories chargées : $_categoryMap');
} catch (e) {
// Log en cas d'erreur lors du chargement
debugPrint("Erreur lors du chargement des catégories : $e");
debugPrint('Erreur lors du chargement des catégories : $e');
// Affichage d'un message d'erreur à l'utilisateur si le chargement échoue
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text(
'Erreur lors du chargement des catégories. Veuillez réessayer plus tard.')));
'Erreur lors du chargement des catégories. Veuillez réessayer plus tard.',),),);
}
}
/// Méthode pour construire la liste des éléments du menu déroulant avec les catégories et sous-catégories.
/// Cette méthode crée une liste d'éléments DropdownMenuItem pour afficher dans le DropdownButton.
List<DropdownMenuItem<String>> _buildDropdownItems() {
List<DropdownMenuItem<String>> items = [];
final List<DropdownMenuItem<String>> items = [];
// Parcours des catégories et ajout des sous-catégories dans le menu déroulant
_categoryMap.forEach((category, subcategories) {
@@ -95,12 +95,12 @@ class _CategoryFieldState extends State<CategoryField> {
);
// Ajouter les sous-catégories associées à cette catégorie
for (String subcategory in subcategories) {
for (final String subcategory in subcategories) {
items.add(
DropdownMenuItem<String>(
value: subcategory, // Valeur de la sous-catégorie
child: Padding(
padding: const EdgeInsets.only(left: 16.0),
padding: const EdgeInsets.only(left: 16),
// Indentation pour les sous-catégories
child: Text(
subcategory,
@@ -113,7 +113,7 @@ class _CategoryFieldState extends State<CategoryField> {
});
// Log pour vérifier le nombre d'éléments créés pour le menu déroulant
debugPrint("Éléments créés pour le menu déroulant : ${items.length}");
debugPrint('Éléments créés pour le menu déroulant : ${items.length}');
return items;
}
@@ -124,7 +124,7 @@ class _CategoryFieldState extends State<CategoryField> {
return _dropdownItems.isEmpty
? const Center(
child:
CircularProgressIndicator()) // Affichage d'un indicateur de chargement pendant le chargement des données
CircularProgressIndicator(),) // Affichage d'un indicateur de chargement pendant le chargement des données
: DropdownButtonFormField<String>(
value: _selectedCategory,
// Valeur sélectionnée par l'utilisateur
@@ -138,29 +138,29 @@ class _CategoryFieldState extends State<CategoryField> {
fillColor: Colors.blueGrey.withOpacity(0.1),
// Couleur de fond
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10.0)),
borderRadius: BorderRadius.all(Radius.circular(10)),
borderSide: BorderSide(
color: Colors.blueGrey, // Couleur de la bordure par défaut
width: 2.0, // Épaisseur de la bordure
width: 2, // Épaisseur de la bordure
),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10.0)),
enabledBorder: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
borderSide: BorderSide(
color: Colors.blueGrey,
// Couleur de la bordure quand non sélectionné
width: 2.0,
width: 2,
),
),
focusedBorder: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10.0)),
borderRadius: BorderRadius.all(Radius.circular(10)),
borderSide: BorderSide(
color: Colors.blue, // Bordure quand le champ est sélectionné
width: 2.0,
width: 2,
),
),
prefixIcon: const Icon(Icons.category,
color: Colors.blueGrey), // Icône du champ
color: Colors.blueGrey,), // Icône du champ
),
style: const TextStyle(color: Colors.blueGrey),
// Style du texte sélectionné
@@ -172,7 +172,7 @@ class _CategoryFieldState extends State<CategoryField> {
// Liste des éléments du menu déroulant
onChanged: (String? newValue) {
// Log pour suivre la valeur sélectionnée
debugPrint("Nouvelle catégorie sélectionnée : $newValue");
debugPrint('Nouvelle catégorie sélectionnée : $newValue');
setState(() {
_selectedCategory =
@@ -185,7 +185,7 @@ class _CategoryFieldState extends State<CategoryField> {
'Veuillez choisir une catégorie',
// Texte affiché lorsqu'aucune catégorie n'est sélectionnée
style: TextStyle(
color: Colors.blueGrey), // Style du texte par défaut
color: Colors.blueGrey,), // Style du texte par défaut
),
);
}

View File

@@ -10,11 +10,11 @@ import 'package:flutter/material.dart';
/// - `onSaved`: Une fonction callback utilisée pour enregistrer la valeur du champ de texte une fois que le formulaire est soumis.
/// ```
class DescriptionField extends StatelessWidget {
// Callback utilisé pour enregistrer la valeur de la description
final FormFieldSetter<String> onSaved;
// Constructeur du widget DescriptionField
const DescriptionField({Key? key, required this.onSaved}) : super(key: key);
const DescriptionField({required this.onSaved, super.key});
// Callback utilisé pour enregistrer la valeur de la description
final FormFieldSetter<String> onSaved;
@override
Widget build(BuildContext context) {
@@ -31,27 +31,27 @@ class DescriptionField extends StatelessWidget {
hintStyle: const TextStyle(color: Colors.blueGrey),
hintText: 'Entrez un la description ici...',
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12.0)), // Bordure arrondie améliorée
borderRadius: BorderRadius.all(Radius.circular(12)), // Bordure arrondie améliorée
borderSide: BorderSide.none, // Pas de bordure visible
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12.0)),
borderSide: const BorderSide(
enabledBorder: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12)),
borderSide: BorderSide(
color: Colors.blueGrey, // Bordure de base en bleu gris
width: 2.0, // Largeur de la bordure
width: 2, // Largeur de la bordure
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12.0)),
borderSide: const BorderSide(
focusedBorder: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12)),
borderSide: BorderSide(
color: Colors.blue, // Bordure bleue lors du focus
width: 2.0, // Épaisseur de la bordure lors du focus
width: 2, // Épaisseur de la bordure lors du focus
),
),
prefixIcon: const Icon(Icons.description, color: Colors.blueGrey), // Icône de description avant le texte
),
// Style du texte dans le champ
style: const TextStyle(color: Colors.blueGrey, fontSize: 16.0),
style: const TextStyle(color: Colors.blueGrey, fontSize: 16),
// Limite le champ à 3 lignes, avec un retour à la ligne automatique
maxLines: 3,
// Autres configurations du champ

View File

@@ -1,11 +1,11 @@
import 'package:flutter/material.dart';
class LinkField extends StatelessWidget {
// Le callback `onSaved` est utilisé pour enregistrer la valeur du champ lorsque le formulaire est soumis.
final FormFieldSetter<String> onSaved;
// Constructeur de la classe LinkField, qui attend le callback `onSaved`.
const LinkField({Key? key, required this.onSaved}) : super(key: key);
const LinkField({required this.onSaved, super.key});
// Le callback `onSaved` est utilisé pour enregistrer la valeur du champ lorsque le formulaire est soumis.
final FormFieldSetter<String> onSaved;
@override
Widget build(BuildContext context) {
@@ -17,21 +17,21 @@ class LinkField extends StatelessWidget {
filled: true, // Remplissage du champ
fillColor: Colors.blueGrey.withOpacity(0.1), // Couleur de fond avec une légère opacité
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10.0)), // Bords arrondis du champ
borderRadius: BorderRadius.all(Radius.circular(10)), // Bords arrondis du champ
borderSide: BorderSide.none, // Pas de bordure visible
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10.0)),
enabledBorder: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
borderSide: BorderSide(
color: Colors.blueGrey, // Couleur de la bordure quand non sélectionné
width: 2.0,
width: 2,
),
),
focusedBorder: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10.0)),
borderRadius: BorderRadius.all(Radius.circular(10)),
borderSide: BorderSide(
color: Colors.blue, // Bordure quand le champ est sélectionné
width: 2.0,
width: 2,
),
),
prefixIcon: const Icon(Icons.link, color: Colors.blueGrey), // Icône de lien à gauche
@@ -40,7 +40,7 @@ class LinkField extends StatelessWidget {
style: const TextStyle(color: Colors.blueGrey), // Style du texte saisi par l'utilisateur
onSaved: (value) {
// Log de la valeur du champ lorsqu'on l'enregistre
debugPrint("Lien enregistré : $value");
debugPrint('Lien enregistré : $value');
// Appel du callback `onSaved` pour enregistrer la valeur dans le formulaire
onSaved(value);
@@ -52,7 +52,7 @@ class LinkField extends StatelessWidget {
final Uri? uri = Uri.tryParse(value);
if (uri == null || !uri.hasAbsolutePath) {
// Log en cas d'erreur de validation
debugPrint("URL invalide : $value");
debugPrint('URL invalide : $value');
return 'Veuillez entrer un lien valide';
}
}

View File

@@ -13,13 +13,12 @@ import '../../screens/location/location_picker_Screen.dart';
/// - `onLocationPicked`: Un callback pour retourner la localisation choisie par l'utilisateur.
///
class LocationField extends StatelessWidget {
const LocationField({required this.location, required this.onLocationPicked, super.key, this.selectedLatLng});
final String location;
final LatLng? selectedLatLng;
final Function(LatLng?) onLocationPicked;
const LocationField({Key? key, required this.location, this.selectedLatLng, required this.onLocationPicked})
: super(key: key);
@override
Widget build(BuildContext context) {
// Log : Construction du champ LocationField
@@ -45,13 +44,13 @@ class LocationField extends StatelessWidget {
},
child: AnimatedContainer(
duration: const Duration(milliseconds: 300), // Animation fluide lors du focus
padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 16.0),
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
decoration: BoxDecoration(
color: Colors.blueGrey.withOpacity(0.1), // Fond plus visible, subtilement coloré
borderRadius: BorderRadius.circular(12.0), // Bordure arrondie améliorée
borderRadius: BorderRadius.circular(12), // Bordure arrondie améliorée
border: Border.all(
color: selectedLatLng == null ? Colors.blueGrey.withOpacity(0.5) : Colors.blue, // Bordure change selon l'état
width: 2.0,
width: 2,
),
),
child: Row(
@@ -61,7 +60,7 @@ class LocationField extends StatelessWidget {
selectedLatLng == null
? 'Sélectionnez une localisation' // Message par défaut si aucune localisation sélectionnée
: 'Localisation: $location', // Affiche la localisation actuelle
style: const TextStyle(color: Colors.blueGrey, fontSize: 16.0),
style: const TextStyle(color: Colors.blueGrey, fontSize: 16),
),
const Icon(Icons.location_on, color: Colors.blueGrey),
],

View File

@@ -2,11 +2,11 @@ import 'package:flutter/material.dart';
/// Un champ de saisie pour l'organisateur, utilisé dans un formulaire.
class OrganizerField extends StatelessWidget {
// Fonction de rappel pour sauvegarder la valeur de l'organisateur.
final Function(String?) onSaved;
// Constructeur qui prend la fonction onSaved pour transmettre l'organisateur au formulaire.
const OrganizerField({Key? key, required this.onSaved}) : super(key: key);
const OrganizerField({required this.onSaved, super.key});
// Fonction de rappel pour sauvegarder la valeur de l'organisateur.
final Function(String?) onSaved;
@override
Widget build(BuildContext context) {
@@ -21,21 +21,21 @@ class OrganizerField extends StatelessWidget {
color: Colors.blueGrey, // Couleur de l'icône.
),
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12.0)), // Bordure arrondie.
borderRadius: BorderRadius.all(Radius.circular(12)), // Bordure arrondie.
borderSide: BorderSide.none, // Pas de bordure par défaut.
),
enabledBorder: OutlineInputBorder(
borderRadius: const BorderRadius.all(Radius.circular(12.0)),
borderSide: const BorderSide(
enabledBorder: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12)),
borderSide: BorderSide(
color: Colors.blueGrey, // Bordure colorée en blueGrey.
width: 1.5, // Largeur de la bordure.
),
),
focusedBorder: OutlineInputBorder(
borderRadius: const BorderRadius.all(Radius.circular(12.0)),
borderSide: const BorderSide(
focusedBorder: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12)),
borderSide: BorderSide(
color: Colors.blue, // Bordure bleue au focus.
width: 2.0,
width: 2,
),
),
filled: true, // Le champ de saisie est rempli de couleur de fond.

View File

@@ -1,9 +1,9 @@
import 'package:flutter/material.dart';
class ParkingField extends StatelessWidget {
final Function(String?) onSaved;
const ParkingField({Key? key, required this.onSaved}) : super(key: key);
const ParkingField({required this.onSaved, super.key});
final Function(String?) onSaved;
@override
Widget build(BuildContext context) {

View File

@@ -1,9 +1,9 @@
import 'package:flutter/material.dart';
class ParticipationFeeField extends StatelessWidget {
final Function(String?) onSaved;
const ParticipationFeeField({Key? key, required this.onSaved}) : super(key: key);
const ParticipationFeeField({required this.onSaved, super.key});
final Function(String?) onSaved;
@override
Widget build(BuildContext context) {

View File

@@ -1,9 +1,9 @@
import 'package:flutter/material.dart';
class PrivacyRulesField extends StatelessWidget {
final Function(String?) onSaved;
const PrivacyRulesField({Key? key, required this.onSaved}) : super(key: key);
const PrivacyRulesField({required this.onSaved, super.key});
final Function(String?) onSaved;
@override
Widget build(BuildContext context) {

View File

@@ -1,9 +1,9 @@
import 'package:flutter/material.dart';
class SecurityProtocolField extends StatelessWidget {
final Function(String?) onSaved;
const SecurityProtocolField({Key? key, required this.onSaved}) : super(key: key);
const SecurityProtocolField({required this.onSaved, super.key});
final Function(String?) onSaved;
@override
Widget build(BuildContext context) {

View File

@@ -1,13 +1,14 @@
import 'package:flutter/material.dart';
import '../../../core/utils/app_logger.dart';
/// Un champ permettant à l'utilisateur de saisir des tags.
/// Il permet également d'afficher les tags saisis sous forme de chips (étiquettes).
class TagsField extends StatefulWidget {
// Fonction de rappel pour sauvegarder la liste des tags saisis.
final Function(List<String>) onSaved;
// Constructeur qui prend la fonction onSaved pour transmettre les tags au formulaire.
const TagsField({Key? key, required this.onSaved}) : super(key: key);
const TagsField({required this.onSaved, super.key});
// Fonction de rappel pour sauvegarder la liste des tags saisis.
final Function(List<String>) onSaved;
@override
_TagsFieldState createState() => _TagsFieldState(); // Création de l'état pour gérer les tags.
@@ -37,39 +38,39 @@ class _TagsFieldState extends State<TagsField> {
color: Colors.blueGrey, // Couleur de l'icône.
),
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12.0)), // Bordure arrondie.
borderRadius: BorderRadius.all(Radius.circular(12)), // Bordure arrondie.
borderSide: BorderSide.none, // Pas de bordure par défaut.
),
enabledBorder: OutlineInputBorder(
borderRadius: const BorderRadius.all(Radius.circular(12.0)),
borderSide: const BorderSide(
enabledBorder: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12)),
borderSide: BorderSide(
color: Colors.blueGrey, // Bordure de base.
width: 1.5, // Largeur de la bordure.
),
),
focusedBorder: OutlineInputBorder(
borderRadius: const BorderRadius.all(Radius.circular(12.0)),
borderSide: const BorderSide(
focusedBorder: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12)),
borderSide: BorderSide(
color: Colors.blue, // Bordure bleue au focus.
width: 2.0,
width: 2,
),
),
filled: true, // Le champ est rempli avec une couleur de fond.
fillColor: Colors.blueGrey.withOpacity(0.1), // Couleur de fond du champ de texte avec opacité.
),
onFieldSubmitted: (value) {
print('Tags soumis : $value'); // Log pour suivre ce qui a été saisi avant la soumission.
AppLogger.d('Tags soumis : $value', tag: 'TagsField');
_addTags(value); // Appel à la méthode _addTags pour ajouter les tags.
},
),
const SizedBox(height: 8), // Espacement entre le champ de saisie et les chips.
Wrap(
spacing: 8.0, // Espacement entre les chips.
spacing: 8, // Espacement entre les chips.
children: _tags.map((tag) => Chip(
label: Text(tag), // Texte du tag à afficher.
backgroundColor: Colors.blueGrey.withOpacity(0.2), // Couleur de fond des chips.
labelStyle: const TextStyle(color: Colors.blueGrey), // Couleur du texte dans les chips.
)).toList(), // Génère une liste de Chips pour chaque tag.
),).toList(), // Génère une liste de Chips pour chaque tag.
),
],
);
@@ -83,7 +84,7 @@ class _TagsFieldState extends State<TagsField> {
.where((tag) => tag.isNotEmpty) // Exclut les tags vides.
.toList(); // Crée la liste de tags.
});
print('Tags ajoutés : $_tags'); // Log pour vérifier la liste de tags ajoutée.
AppLogger.d('Tags ajoutés : $_tags', tag: 'TagsField');
widget.onSaved(_tags); // Envoie la liste des tags au formulaire principal.
}
}

View File

@@ -1,8 +1,8 @@
import 'package:flutter/material.dart';
class TitleField extends StatelessWidget {
const TitleField({required this.onSaved, super.key});
final FormFieldSetter<String> onSaved;
const TitleField({Key? key, required this.onSaved}) : super(key: key);
@override
Widget build(BuildContext context) {
@@ -15,21 +15,21 @@ class TitleField extends StatelessWidget {
hintStyle: const TextStyle(color: Colors.blueGrey),
hintText: 'Entrez un le titre ici...',
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12.0)), // Bordure plus arrondie
borderRadius: BorderRadius.all(Radius.circular(12)), // Bordure plus arrondie
borderSide: BorderSide.none, // Pas de bordure par défaut
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12.0)),
borderSide: const BorderSide(
enabledBorder: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12)),
borderSide: BorderSide(
color: Colors.blueGrey, // Bordure de base
width: 1.5,
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12.0)),
borderSide: const BorderSide(
focusedBorder: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12)),
borderSide: BorderSide(
color: Colors.blue, // Bordure en bleu lors du focus
width: 2.0,
width: 2,
),
),
prefixIcon: const Icon(
@@ -39,7 +39,7 @@ class TitleField extends StatelessWidget {
),
style: const TextStyle(
color: Colors.blueGrey, // Texte en bleu pour un meilleur contraste
fontSize: 16.0, // Taille de police améliorée
fontSize: 16, // Taille de police améliorée
fontWeight: FontWeight.w600, // Poids de la police pour la lisibilité
),
validator: (value) {

View File

@@ -2,11 +2,11 @@ import 'package:flutter/material.dart';
/// Un champ de saisie pour les informations de transport, utilisé dans un formulaire.
class TransportInfoField extends StatelessWidget {
// Fonction de rappel pour sauvegarder les informations de transport.
final Function(String?) onSaved;
// Constructeur qui prend la fonction onSaved pour transmettre les informations de transport au formulaire.
const TransportInfoField({Key? key, required this.onSaved}) : super(key: key);
const TransportInfoField({required this.onSaved, super.key});
// Fonction de rappel pour sauvegarder les informations de transport.
final Function(String?) onSaved;
@override
Widget build(BuildContext context) {
@@ -21,21 +21,21 @@ class TransportInfoField extends StatelessWidget {
color: Colors.blueGrey, // Couleur de l'icône.
),
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12.0)), // Bordure arrondie.
borderRadius: BorderRadius.all(Radius.circular(12)), // Bordure arrondie.
borderSide: BorderSide.none, // Pas de bordure par défaut.
),
enabledBorder: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12.0)),
borderRadius: BorderRadius.all(Radius.circular(12)),
borderSide: BorderSide(
color: Colors.blueGrey, // Bordure colorée en blueGrey.
width: 1.5, // Largeur de la bordure.
),
),
focusedBorder: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12.0)),
borderRadius: BorderRadius.all(Radius.circular(12)),
borderSide: BorderSide(
color: Colors.blue, // Bordure bleue au focus.
width: 2.0,
width: 2,
),
),
filled: true, // Le champ de saisie est rempli de couleur de fond.