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,39 +1,39 @@
|
||||
import 'dart:io'; // Pour l'usage des fichiers (image)
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||
import 'dart:io'; // Pour l'usage des fichiers (image)
|
||||
import '../../widgets/fields/category_field.dart'; // Importation des widgets personnalisés
|
||||
|
||||
import '../../../core/utils/app_logger.dart';
|
||||
import '../../widgets/date_picker.dart';
|
||||
import '../../widgets/fields/accessibility_field.dart';
|
||||
import '../../widgets/fields/accommodation_info_field.dart';
|
||||
import '../../widgets/fields/attendees_field.dart';
|
||||
import '../../widgets/fields/category_field.dart'; // Importation des widgets personnalisés
|
||||
import '../../widgets/fields/description_field.dart';
|
||||
import '../../widgets/fields/link_field.dart';
|
||||
import '../../widgets/fields/location_field.dart';
|
||||
import '../../widgets/submit_button.dart';
|
||||
import '../../widgets/fields/title_field.dart';
|
||||
import '../../widgets/image_preview_picker.dart';
|
||||
import '../../widgets/fields/tags_field.dart';
|
||||
import '../../widgets/fields/attendees_field.dart';
|
||||
import '../../widgets/fields/organizer_field.dart';
|
||||
import '../../widgets/fields/transport_info_field.dart';
|
||||
import '../../widgets/fields/accommodation_info_field.dart';
|
||||
import '../../widgets/fields/parking_field.dart';
|
||||
import '../../widgets/fields/participation_fee_field.dart';
|
||||
import '../../widgets/fields/privacy_rules_field.dart';
|
||||
import '../../widgets/fields/security_protocol_field.dart';
|
||||
import '../../widgets/fields/parking_field.dart';
|
||||
import '../../widgets/fields/accessibility_field.dart';
|
||||
import '../../widgets/fields/participation_fee_field.dart';
|
||||
import '../../widgets/fields/tags_field.dart';
|
||||
import '../../widgets/fields/title_field.dart';
|
||||
import '../../widgets/fields/transport_info_field.dart';
|
||||
import '../../widgets/image_preview_picker.dart';
|
||||
import '../../widgets/submit_button.dart';
|
||||
|
||||
/// Page pour ajouter un événement
|
||||
/// Permet à l'utilisateur de remplir un formulaire avec des détails sur l'événement
|
||||
class AddEventPage extends StatefulWidget {
|
||||
|
||||
const AddEventPage({
|
||||
required this.userId, required this.userFirstName, required this.userLastName, super.key,
|
||||
});
|
||||
final String userId;
|
||||
final String userFirstName;
|
||||
final String userLastName;
|
||||
|
||||
const AddEventPage({
|
||||
super.key,
|
||||
required this.userId,
|
||||
required this.userFirstName,
|
||||
required this.userLastName,
|
||||
});
|
||||
|
||||
@override
|
||||
_AddEventPageState createState() => _AddEventPageState();
|
||||
}
|
||||
@@ -52,16 +52,16 @@ class _AddEventPageState extends State<AddEventPage> {
|
||||
String _organizer = '';
|
||||
List<String> _tags = [];
|
||||
int _maxParticipants = 0;
|
||||
LatLng? _selectedLatLng = const LatLng(5.348722, -3.985038); // Coordonnées par défaut
|
||||
final LatLng _selectedLatLng = const LatLng(5.348722, -3.985038); // Coordonnées par défaut
|
||||
File? _selectedImageFile; // Image sélectionnée
|
||||
String _status = 'Actif';
|
||||
String _organizerEmail = '';
|
||||
String _organizerPhone = '';
|
||||
final String _status = 'Actif';
|
||||
final String _organizerEmail = '';
|
||||
final String _organizerPhone = '';
|
||||
int _participationFee = 0;
|
||||
String _privacyRules = '';
|
||||
String _transportInfo = '';
|
||||
String _accommodationInfo = '';
|
||||
bool _isAccessible = false;
|
||||
final bool _isAccessible = false;
|
||||
bool _hasParking = false;
|
||||
String _securityProtocol = '';
|
||||
|
||||
@@ -83,7 +83,7 @@ class _AddEventPageState extends State<AddEventPage> {
|
||||
children: [
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
@@ -173,27 +173,18 @@ class _AddEventPageState extends State<AddEventPage> {
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
SubmitButton(
|
||||
text: 'Créer l\'événement',
|
||||
onPressed: () {
|
||||
if (_formKey.currentState?.validate() ?? false) {
|
||||
// Log des données de l'événement avant l'envoi
|
||||
print('Titre de l\'événement : $_title');
|
||||
print('Description de l\'événement : $_description');
|
||||
print('Date de début : $_selectedDate');
|
||||
print('Date de fin : $_endDate');
|
||||
print('Lieu : $_location');
|
||||
print('Catégorie : $_category');
|
||||
print('Lien de l\'événement : $_link');
|
||||
print('Organisateur : $_organizer');
|
||||
print('Tags : $_tags');
|
||||
print('Maximum de participants : $_maxParticipants');
|
||||
print('Image sélectionnée : $_selectedImageFile');
|
||||
print('Transport : $_transportInfo');
|
||||
print('Hébergement : $_accommodationInfo');
|
||||
print('Règles de confidentialité : $_privacyRules');
|
||||
print('Protocole de sécurité : $_securityProtocol');
|
||||
print('Parking disponible : $_hasParking');
|
||||
print('Accessibilité : $_isAccessible');
|
||||
print('Frais de participation : $_participationFee');
|
||||
AppLogger.i(
|
||||
'Création d\'événement: titre=$_title, lieu=$_location, catégorie=$_category, participants=$_maxParticipants',
|
||||
tag: 'AddEventDialog',
|
||||
);
|
||||
AppLogger.d(
|
||||
'Détails: description=${_description.length} chars, dates=$_selectedDate -> $_endDate, tags=${_tags.length}, image=${_selectedImageFile != null}',
|
||||
tag: 'AddEventDialog',
|
||||
);
|
||||
// Logique d'envoi des données vers le backend...
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
@@ -219,7 +210,7 @@ class _AddEventPageState extends State<AddEventPage> {
|
||||
// En-tête de section pour mieux organiser les champs
|
||||
Widget _buildSectionHeader(String title) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: Text(
|
||||
title,
|
||||
style: const TextStyle(
|
||||
|
||||
Reference in New Issue
Block a user