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:
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
],
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user