diff --git a/lib/components/group/group_content.dart b/lib/components/group/group_content.dart index 45c704c..a55c11d 100644 --- a/lib/components/group/group_content.dart +++ b/lib/components/group/group_content.dart @@ -1,26 +1,125 @@ import 'package:flutter/material.dart'; +import 'package:travel_mate/models/group.dart'; +import 'package:provider/provider.dart'; +import '../../providers/user_provider.dart'; +import '../../services/group_service.dart'; -class GroupContent extends StatelessWidget { +class GroupContent extends StatefulWidget { const GroupContent({super.key}); + @override + State createState() => _GroupContentState(); +} + +class _GroupContentState extends State { + @override Widget build(BuildContext context) { + return Scaffold( + body: Consumer( + builder: (context, userProvider, child) { + final user = userProvider.currentUser; + if (user == null || user.id == null) { + return const Center( + child: Text('Utilisateur non connecté'), + ); + } + + return StreamBuilder>( + stream: GroupService().getGroupsStream(), + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return _buildLoadingState(); + } else if (snapshot.hasError) { + print('Erreur du stream: ${snapshot.error}'); + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text('Erreur lors du chargement des groupes.'), + const SizedBox(height: 8), + ElevatedButton( + onPressed: () { + setState(() { + // Forcer le rechargement du stream + }); + }, + child: const Text('Réessayer'), + ), + ], + ), + ); + } + + final groups = snapshot.data ?? []; + print("Groupes reçus: ${groups.length}"); + + return RefreshIndicator( + onRefresh: () async { + setState() {}; + }, + child: SingleChildScrollView( + physics: const AlwaysScrollableScrollPhysics(), + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Vos Groupes', + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + color: Theme.of(context).brightness == Brightness.dark ? Colors.white : Colors.black, + ), + ), + const SizedBox(height: 20), + groups.isEmpty ? _buildEmptyState() : _buildGroupList(groups), + ], + ), + ), + ); + }, + ); + }), + ); + } + + Widget _buildLoadingState() { return const Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon(Icons.group, size: 64, color: Colors.blue), - SizedBox(height: 16), - Text( - 'Chat de Groupe', - style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold), - ), - SizedBox(height: 8), - Text( - 'Communiquez avec vos compagnons de voyage', - style: TextStyle(fontSize: 16, color: Colors.grey), - ), - ], + child: Padding(padding: EdgeInsets.all(16.0), + child: CircularProgressIndicator(), + ), + ); + } + + Widget _buildEmptyState() { + return const Center( + child: Text( + 'Aucun groupe disponible. Créez ou rejoignez un voyage pour commencer à discuter!', + style: TextStyle(fontSize: 16, color: Colors.grey), + textAlign: TextAlign.center, + ), + ); + } + + Widget _buildGroupList(List groups) { + return Column( + children: groups.map((group) => _buildGroupCard(group)).toList(), + ); + } + + Widget _buildGroupCard(Group group) { + return Card( + margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 16), + child: ListTile( + leading: CircleAvatar( + child: Text(group.name.isNotEmpty ? group.name[0] : '?'), + ), + title: Text(group.name), + subtitle: Text('${group.members.length} membres'), + onTap: () { + // Logique pour ouvrir le chat de groupe + }, ), ); } diff --git a/lib/models/group.dart b/lib/models/group.dart new file mode 100644 index 0000000..2c46dea --- /dev/null +++ b/lib/models/group.dart @@ -0,0 +1,28 @@ +import 'package:travel_mate/models/user.dart'; + +class Group { + final String? id; + final String name; + final List members; + + Group({ + this.id, + required this.name, + required this.members, + }); + + factory Group.fromMap(Map data, String documentId) { + return Group( + id: documentId, + name: data['name'] ?? '', + members: List.from(data['members']?.map((member) => User.fromMap(member)) ?? []), + ); + } + + Map toMap() { + return { + 'name': name, + 'members': members.map((member) => member.toMap()).toList(), + }; + } +} \ No newline at end of file diff --git a/lib/models/message.dart b/lib/models/message.dart new file mode 100644 index 0000000..b31fe11 --- /dev/null +++ b/lib/models/message.dart @@ -0,0 +1,13 @@ +class Message { + final String text; + final DateTime timestamp; + final String senderId; + final String senderName; + + Message({ + required this.text, + required this.timestamp, + required this.senderId, + required this.senderName, + }); +} \ No newline at end of file diff --git a/lib/services/group_service.dart b/lib/services/group_service.dart new file mode 100644 index 0000000..337bb04 --- /dev/null +++ b/lib/services/group_service.dart @@ -0,0 +1,26 @@ +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:travel_mate/models/group.dart'; + +class GroupService { + final FirebaseFirestore _firestore = FirebaseFirestore.instance; + + Stream> getGroupsStream() { + return _firestore.collection('groups').snapshots().map((snapshot) { + return snapshot.docs.map((doc) { + return Group.fromMap(doc.data(), doc.id); + }).toList(); + }); + } + + Future createGroup(Group group) async { + await _firestore.collection('groups').add(group.toMap()); + } + + Future updateGroup(Group group) async { + await _firestore.collection('groups').doc(group.id).update(group.toMap()); + } + + Future deleteGroup(String groupId) async { + await _firestore.collection('groups').doc(groupId).delete(); + } +} \ No newline at end of file