From 9eb55c358e34195d9438fb8c0781681f6df93943 Mon Sep 17 00:00:00 2001 From: Dayron Date: Sat, 11 Oct 2025 20:45:14 +0200 Subject: [PATCH] feat: Add user-specific group retrieval and enhance UI with dynamic theming --- lib/components/group/group_content.dart | 12 ++-- lib/components/home/create_trip_content.dart | 59 +++++++++++++------- lib/models/message.dart | 2 + lib/services/group_service.dart | 16 ++++++ lib/services/message_service.dart | 0 5 files changed, 64 insertions(+), 25 deletions(-) create mode 100644 lib/services/message_service.dart diff --git a/lib/components/group/group_content.dart b/lib/components/group/group_content.dart index a55c11d..b14831b 100644 --- a/lib/components/group/group_content.dart +++ b/lib/components/group/group_content.dart @@ -22,11 +22,11 @@ class _GroupContentState extends State { if (user == null || user.id == null) { return const Center( child: Text('Utilisateur non connecté'), - ); + ); } return StreamBuilder>( - stream: GroupService().getGroupsStream(), + stream: GroupService().getGroupsStreamByUser(user.id!), // Filtrer par utilisateur builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return _buildLoadingState(); @@ -52,11 +52,11 @@ class _GroupContentState extends State { } final groups = snapshot.data ?? []; - print("Groupes reçus: ${groups.length}"); + print("Groupes reçus pour l'utilisateur ${user.id}: ${groups.length}"); return RefreshIndicator( onRefresh: () async { - setState() {}; + setState(() {}); }, child: SingleChildScrollView( physics: const AlwaysScrollableScrollPhysics(), @@ -74,13 +74,15 @@ class _GroupContentState extends State { ), const SizedBox(height: 20), groups.isEmpty ? _buildEmptyState() : _buildGroupList(groups), + const SizedBox(height: 80), ], ), ), ); }, ); - }), + }, + ), ); } diff --git a/lib/components/home/create_trip_content.dart b/lib/components/home/create_trip_content.dart index 4cd51b1..fe0b1a8 100644 --- a/lib/components/home/create_trip_content.dart +++ b/lib/components/home/create_trip_content.dart @@ -287,12 +287,19 @@ class _CreateTripContentState extends State { required DateTime? date, required VoidCallback onTap, }) { + // Détecter le thème actuel + final isDarkMode = Theme.of(context).brightness == Brightness.dark; + final textColor = isDarkMode ? Colors.white : Colors.black; + final labelColor = isDarkMode ? Colors.white70 : Colors.grey[600]; + final iconColor = isDarkMode ? Colors.white70 : Colors.grey[600]; + final placeholderColor = isDarkMode ? Colors.white38 : Colors.grey[500]; + return InkWell( onTap: onTap, child: Container( padding: EdgeInsets.all(16), decoration: BoxDecoration( - border: Border.all(color: Colors.grey[400]!), + border: Border.all(color: isDarkMode ? Colors.white24 : Colors.grey[400]!), borderRadius: BorderRadius.circular(12), ), child: Column( @@ -300,12 +307,12 @@ class _CreateTripContentState extends State { children: [ Text( label, - style: TextStyle(fontSize: 12, color: Colors.grey[600]), + style: TextStyle(fontSize: 12, color: labelColor), ), SizedBox(height: 8), Row( children: [ - Icon(Icons.calendar_today, size: 16, color: Colors.grey[600]), + Icon(Icons.calendar_today, size: 16, color: iconColor), SizedBox(width: 8), Text( date != null @@ -313,7 +320,7 @@ class _CreateTripContentState extends State { : 'Sélectionner', style: TextStyle( fontSize: 16, - color: date != null ? Colors.black : Colors.grey[500], + color: date != null ? textColor : placeholderColor, ), ), ], @@ -403,25 +410,35 @@ class _CreateTripContentState extends State { }); } - Future _saveGroup() async { + Future _saveGroup(String currentUserId) async { if (!_formKey.currentState!.validate()) { return false; } - setState(() { - _isLoading = true; - }); + // Convertir les emails en IDs + final participantIds = await _changeUserEmailById(_participants); + + // Créer la liste des membres incluant le créateur + List allMembers = [currentUserId]; + + // Ajouter tous les participants (éviter les doublons) + for (String participantId in participantIds) { + if (!allMembers.contains(participantId)) { + allMembers.add(participantId); + } + } - final members = await _changeUserEmailById(_participants); + print('Membres du groupe: $allMembers'); final group = Group( id: '', name: _titleController.text.trim(), - members: members, + members: allMembers, // Contient le créateur + tous les participants ); final groupService = GroupService(); bool success = await groupService.createGroup(group); + print('Groupe créé avec succès: $success'); return success; } @@ -474,19 +491,21 @@ class _CreateTripContentState extends State { final userProvider = Provider.of(context, listen: false); final currentUser = userProvider.currentUser; - if (currentUser == null) { + if (currentUser == null || currentUser.id == null) { throw Exception('Utilisateur non connecté'); } print('Création du voyage par: ${currentUser.id} (${currentUser.email})'); // Convertir les emails en IDs utilisateur - List participantIds = []; - if (currentUser.id != null) { - participantIds.add(currentUser.id!); + List participantIds = await _changeUserEmailById(_participants); + + // Ajouter le créateur aux participants s'il n'y est pas déjà + if (!participantIds.contains(currentUser.id!)) { + participantIds.insert(0, currentUser.id!); } - participantIds = await _changeUserEmailById(_participants); + print('Participants IDs (avec créateur): $participantIds'); // Créer l'objet Trip avec les IDs des participants final trip = Trip( @@ -497,8 +516,8 @@ class _CreateTripContentState extends State { startDate: _startDate!, endDate: _endDate!, budget: double.tryParse(_budgetController.text) ?? 0.0, - createdBy: currentUser.id ?? '', - participants: participantIds, // Contient uniquement les IDs + createdBy: currentUser.id!, + participants: participantIds, // Contient le créateur + tous les participants createdAt: DateTime.now(), updatedAt: DateTime.now(), ); @@ -509,11 +528,11 @@ class _CreateTripContentState extends State { final tripService = TripService(); final success = await tripService.addTrip(trip); - //Créer le groupe associé au voyage - final successGroup = await _saveGroup(); + // Créer le groupe associé au voyage avec le créateur inclus + final successGroup = await _saveGroup(currentUser.id!); if (success && successGroup && mounted) { - print('Voyage créé avec succès !'); + print('Voyage et groupe créés avec succès !'); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Voyage créé avec succès !'), diff --git a/lib/models/message.dart b/lib/models/message.dart index b31fe11..d8f48f1 100644 --- a/lib/models/message.dart +++ b/lib/models/message.dart @@ -3,11 +3,13 @@ class Message { final DateTime timestamp; final String senderId; final String senderName; + final String groupId; Message({ required this.text, required this.timestamp, required this.senderId, required this.senderName, + required this.groupId, }); } \ No newline at end of file diff --git a/lib/services/group_service.dart b/lib/services/group_service.dart index 2b5e196..3ebbd9f 100644 --- a/lib/services/group_service.dart +++ b/lib/services/group_service.dart @@ -41,4 +41,20 @@ class GroupService { return false; } } + + // Stream pour obtenir les groupes d'un utilisateur spécifique + Stream> getGroupsStreamByUser(String userId) { + return _firestore + .collection('groups') + .where('members', arrayContains: userId) + .snapshots() + .map((snapshot) { + print('Groupes trouvés pour l\'utilisateur $userId: ${snapshot.docs.length}'); + return snapshot.docs.map((doc) { + final group = Group.fromMap(doc.data(), doc.id); + print('Groupe: ${group.name}, Membres: ${group.members.length}'); + return group; + }).toList(); + }); + } } \ No newline at end of file diff --git a/lib/services/message_service.dart b/lib/services/message_service.dart new file mode 100644 index 0000000..e69de29