import 'package:flutter/material.dart'; import 'package:hive_flutter/hive_flutter.dart'; import '../models/room.dart'; import '../services/chat_service.dart'; import '../services/chat_config_loader.dart'; import '../widgets/recipient_selector.dart'; import 'chat_page.dart'; /// Version embarquée de RoomsPage sans AppBar pour intégration class RoomsPageEmbedded extends StatefulWidget { final VoidCallback? onAddPressed; final VoidCallback? onRefreshPressed; const RoomsPageEmbedded({ super.key, this.onAddPressed, this.onRefreshPressed, }); @override State createState() => RoomsPageEmbeddedState(); } class RoomsPageEmbeddedState extends State { final _service = ChatService.instance; bool _isLoading = true; @override void initState() { super.initState(); _loadRooms(); } Future _loadRooms() async { setState(() => _isLoading = true); await _service.getRooms(); setState(() => _isLoading = false); widget.onRefreshPressed?.call(); } @override Widget build(BuildContext context) { final helpText = ChatConfigLoader.instance.getHelpText(_service.currentUserRole); if (_isLoading) { return const Center(child: CircularProgressIndicator()); } return ValueListenableBuilder>( valueListenable: _service.roomsBox.listenable(), builder: (context, box, _) { final rooms = box.values.toList() ..sort((a, b) => (b.lastMessageAt ?? b.createdAt) .compareTo(a.lastMessageAt ?? a.createdAt)); if (rooms.isEmpty) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.chat_bubble_outline, size: 64, color: Colors.grey[400], ), const SizedBox(height: 16), Text( 'Aucune conversation', style: TextStyle( fontSize: 16, color: Colors.grey[600], ), ), const SizedBox(height: 8), TextButton( onPressed: widget.onAddPressed ?? createNewConversation, child: const Text('Démarrer une conversation'), ), if (helpText.isNotEmpty) Padding( padding: const EdgeInsets.only(top: 8), child: Text( helpText, style: TextStyle( fontSize: 13, color: Colors.grey[500], ), textAlign: TextAlign.center, ), ), ], ), ); } return RefreshIndicator( onRefresh: _loadRooms, child: ListView.builder( itemCount: rooms.length, itemBuilder: (context, index) { final room = rooms[index]; return _RoomTile(room: room); }, ), ); }, ); } Future createNewConversation() async { final currentRole = _service.currentUserRole; final config = ChatConfigLoader.instance.getPossibleRecipientsConfig(currentRole); // Déterminer si on permet la sélection multiple // Pour role 1 (membre), permettre la sélection multiple pour contacter plusieurs membres/admins // Pour role 2 (admin amicale), permettre la sélection multiple pour GEOSECTOR ou Amicale // Pour role 9 (super admin), permettre la sélection multiple selon config final allowMultiple = (currentRole == 1) || (currentRole == 2) || (currentRole == 9 && config.any((c) => c['allow_selection'] == true)); // Ouvrir le dialog de sélection final result = await RecipientSelectorDialog.show( context, allowMultiple: allowMultiple, ); if (result != null) { final recipients = result['recipients'] as List>?; final initialMessage = result['initial_message'] as String?; if (recipients != null && recipients.isNotEmpty) { try { Room? newRoom; if (recipients.length == 1) { // Conversation privée final recipient = recipients.first; newRoom = await _service.createPrivateRoom( recipientId: recipient['id'], recipientName: recipient['name'], recipientRole: recipient['role'], recipientEntite: recipient['entite_id'], initialMessage: initialMessage, ); } else { // Conversation de groupe final participantIds = recipients.map((r) => r['id'] as int).toList(); // Déterminer le titre en fonction du type de groupe String title; if (currentRole == 1) { // Pour un membre final hasAdmins = recipients.any((r) => r['role'] == 2); final hasMembers = recipients.any((r) => r['role'] == 1); if (hasAdmins && !hasMembers) { title = 'Administrateurs Amicale'; } else if (recipients.length > 3) { title = '${recipients.take(3).map((r) => r['name']).join(', ')} et ${recipients.length - 3} autres'; } else { title = recipients.map((r) => r['name']).join(', '); } } else if (currentRole == 2) { // Pour un admin d'amicale final hasSuperAdmins = recipients.any((r) => r['role'] == 9); final hasMembers = recipients.any((r) => r['role'] == 1); if (hasSuperAdmins && !hasMembers) { title = 'GEOSECTOR Support'; } else if (!hasSuperAdmins && hasMembers && recipients.length > 5) { title = 'Amicale - Tous les membres'; } else if (recipients.length > 3) { title = '${recipients.take(3).map((r) => r['name']).join(', ')} et ${recipients.length - 3} autres'; } else { title = recipients.map((r) => r['name']).join(', '); } } else { // Pour un super admin if (recipients.length > 3) { title = '${recipients.take(3).map((r) => r['name']).join(', ')} et ${recipients.length - 3} autres'; } else { title = recipients.map((r) => r['name']).join(', '); } } // Créer la room avec le bon type newRoom = await _service.createRoom( title: title, participantIds: participantIds, type: (currentRole == 1 || currentRole == 2) ? 'group' : 'broadcast', initialMessage: initialMessage, ); } if (newRoom != null && mounted) { // Naviguer vers la nouvelle conversation Navigator.push( context, MaterialPageRoute( builder: (_) => ChatPage( roomId: newRoom!.id, roomTitle: newRoom.title, ), ), ); } } catch (e) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(e.toString()), backgroundColor: Colors.red, ), ); } } } } } // Méthode publique pour rafraîchir void refresh() { _loadRooms(); } } /// Widget simple pour une tuile de room class _RoomTile extends StatelessWidget { final Room room; const _RoomTile({required this.room}); @override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( color: Colors.white, border: Border( bottom: BorderSide(color: Colors.grey[200]!), ), ), child: ListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), leading: CircleAvatar( backgroundColor: const Color(0xFF2563EB), child: Text( room.title[0].toUpperCase(), style: const TextStyle(color: Colors.white), ), ), title: Text( room.title, style: const TextStyle( fontWeight: FontWeight.w600, fontSize: 16, ), ), subtitle: room.lastMessage != null ? Text( room.lastMessage!, maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle(color: Colors.grey[600]), ) : null, trailing: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.end, children: [ if (room.lastMessageAt != null) Text( _formatTime(room.lastMessageAt!), style: TextStyle( fontSize: 12, color: Colors.grey[500], ), ), if (room.unreadCount > 0) Container( margin: const EdgeInsets.only(top: 4), padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), decoration: BoxDecoration( color: const Color(0xFF2563EB), borderRadius: BorderRadius.circular(10), ), child: Text( room.unreadCount.toString(), style: const TextStyle( color: Colors.white, fontSize: 11, fontWeight: FontWeight.bold, ), ), ), ], ), onTap: () { Navigator.push( context, MaterialPageRoute( builder: (_) => ChatPage( roomId: room.id, roomTitle: room.title, ), ), ); }, ), ); } String _formatTime(DateTime date) { final now = DateTime.now(); final diff = now.difference(date); if (diff.inDays > 0) { return '${diff.inDays}j'; } else if (diff.inHours > 0) { return '${diff.inHours}h'; } else if (diff.inMinutes > 0) { return '${diff.inMinutes}m'; } else { return 'Maintenant'; } } }