import 'package:flutter/material.dart'; import '../models/channel.dart'; import '../models/group_member.dart'; import '../services/api_service.dart'; import '../services/auth_service.dart'; class GroupMembersScreen extends StatefulWidget { final Channel channel; final String? currentUserId; const GroupMembersScreen({ super.key, required this.channel, this.currentUserId, }); @override State createState() => _GroupMembersScreenState(); } class _GroupMembersScreenState extends State { late final ApiService _api; List _members = []; bool _loading = true; bool _isManager = false; @override void initState() { super.initState(); _api = ApiService(AuthService()); _load(); } Future _load() async { setState(() => _loading = true); final list = await _api.getGroupMembers(widget.channel.id); if (!mounted) return; final isManager = list.any( (m) => m.userId == widget.currentUserId && m.isManager, ); setState(() { _members = list; _isManager = isManager; _loading = false; }); } Future _showInviteDialog() async { String username = ''; final confirmed = await showDialog( context: context, builder: (ctx) => _InviteDialog(onUsernameChanged: (v) => username = v), ); if (confirmed == true && username.trim().isNotEmpty) { final err = await _api.inviteMember(widget.channel.id, username.trim()); if (!mounted) return; ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text( err ?? 'دعوت‌نامه ارسال شد', style: const TextStyle(fontSize: 11), textAlign: TextAlign.center, ), backgroundColor: err == null ? const Color(0xFF1C1C1E) : const Color(0xFF333333), behavior: SnackBarBehavior.floating, duration: const Duration(seconds: 2), margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 40), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(20), ), ), ); } } Future _removeMember(GroupMember member) async { final confirmed = await showDialog( context: context, builder: (ctx) => AlertDialog( backgroundColor: const Color(0xFF1C1C1E), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), contentPadding: const EdgeInsets.all(16), content: Column( mainAxisSize: MainAxisSize.min, children: [ const Icon( Icons.person_remove_outlined, color: Colors.red, size: 28, ), const SizedBox(height: 8), Text( 'حذف ${member.username}؟', style: const TextStyle( color: Colors.white, fontSize: 12, fontWeight: FontWeight.bold, ), textAlign: TextAlign.center, ), const SizedBox(height: 12), Row( children: [ Expanded( child: TextButton( onPressed: () => Navigator.pop(ctx, false), child: const Text( 'انصراف', style: TextStyle(color: Colors.white54, fontSize: 11), ), ), ), Expanded( child: TextButton( onPressed: () => Navigator.pop(ctx, true), child: const Text( 'حذف', style: TextStyle(color: Colors.red, fontSize: 11), ), ), ), ], ), ], ), ), ); if (confirmed == true) { final err = await _api.removeMember(widget.channel.id, member.userId); if (!mounted) return; if (err != null) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text( err, style: const TextStyle(fontSize: 11), textAlign: TextAlign.center, ), backgroundColor: const Color(0xFF333333), behavior: SnackBarBehavior.floating, duration: const Duration(seconds: 2), margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 40), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(20), ), ), ); } else { _load(); } } } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.black, // استفاده از Stack برای قرار دادن دکمه شناور روی محتوا body: Stack( children: [ SafeArea( child: Column( children: [ // هدر ساده شده (فقط نمایش اطلاعات، بدون دکمه‌های کناری) Padding( padding: const EdgeInsets.symmetric( horizontal: 12, vertical: 8, ), child: Column( children: [ // نام گروه و تعداد اعضا وسط‌چین Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( widget.channel.type == 'PUBLIC' ? Icons.public : Icons.lock_outline, color: const Color(0xFF00C853), size: 12, ), const SizedBox(width: 4), Flexible( child: Text( widget.channel.name, style: const TextStyle( color: Color(0xFF00C853), fontSize: 12, fontWeight: FontWeight.bold, ), overflow: TextOverflow.ellipsis, ), ), ], ), if (!_loading) Text( '${_members.length} عضو', style: const TextStyle( color: Colors.white38, fontSize: 10, ), ), ], ), ), const Divider(height: 1, color: Color(0xFF333333)), // لیست اعضا Expanded( child: _loading ? const Center( child: CircularProgressIndicator( color: Color(0xFF00C853), strokeWidth: 2, ), ) : _members.isEmpty ? const Center( child: Text( 'عضوی یافت نشد', style: TextStyle( color: Colors.white38, fontSize: 11, ), ), ) : ListView.builder( padding: const EdgeInsets.only( bottom: 60, ), // فضای خالی برای دکمه شناور پایین itemCount: _members.length, itemBuilder: (ctx, i) { final m = _members[i]; final isMe = m.userId == widget.currentUserId; return _MemberTile( member: m, isMe: isMe, canRemove: _isManager && !isMe && !m.isManager, onRemove: () => _removeMember(m), ); }, ), ), ], ), ), // دکمه شناور افزودن عضو (فقط برای مدیر) در پایین صفحه وسط if (_isManager) Positioned( bottom: 10, left: 0, right: 0, child: Center( child: FloatingActionButton( heroTag: "invite_btn", // جلوگیری از تداخل HeroTag mini: true, // سایز کوچکتر مناسب ساعت onPressed: _showInviteDialog, backgroundColor: const Color(0xFF00C853), child: const Icon( Icons.person_add, color: Colors.black, size: 20, ), ), ), ), ], ), ); } } class _MemberTile extends StatelessWidget { final GroupMember member; final bool isMe; final bool canRemove; final VoidCallback onRemove; const _MemberTile({ required this.member, required this.isMe, required this.canRemove, required this.onRemove, }); @override Widget build(BuildContext context) { return Container( margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), height: 36, // کاهش ارتفاع آیتم decoration: BoxDecoration( color: const Color(0xFF1C1C1E), borderRadius: BorderRadius.circular(10), ), padding: const EdgeInsets.symmetric(horizontal: 8), child: Row( children: [ // Online indicator Container( width: 6, height: 6, decoration: BoxDecoration( shape: BoxShape.circle, color: member.isOnline ? const Color(0xFF00C853) : Colors.white24, ), ), const SizedBox(width: 8), // Username Expanded( child: Text( member.username + (isMe ? ' (من)' : ''), style: TextStyle( color: isMe ? const Color(0xFF00C853) : Colors.white, fontSize: 11, fontWeight: member.isManager ? FontWeight.bold : FontWeight.normal, ), overflow: TextOverflow.ellipsis, ), ), // Role badge if (member.isManager) Container( padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 1), decoration: BoxDecoration( color: const Color(0xFF00C853).withOpacity(0.15), borderRadius: BorderRadius.circular(6), ), child: const Text( 'مدیر', style: TextStyle(color: Color(0xFF00C853), fontSize: 8), ), ), // Remove button if (canRemove) ...[ const SizedBox(width: 4), GestureDetector( onTap: onRemove, child: const Icon( Icons.remove_circle_outline, color: Colors.red, size: 16, ), ), ], ], ), ); } } // ── Invite Dialog ────────────────────────────────────────────────────────── class _InviteDialog extends StatefulWidget { final ValueChanged onUsernameChanged; const _InviteDialog({required this.onUsernameChanged}); @override State<_InviteDialog> createState() => _InviteDialogState(); } class _InviteDialogState extends State<_InviteDialog> { final _ctrl = TextEditingController(); @override void dispose() { _ctrl.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return AlertDialog( backgroundColor: const Color(0xFF1C1C1E), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), contentPadding: const EdgeInsets.all(16), content: Column( mainAxisSize: MainAxisSize.min, children: [ const Icon( Icons.person_add_outlined, color: Color(0xFF00C853), size: 26, ), const SizedBox(height: 8), const Text( 'دعوت عضو', style: TextStyle( color: Colors.white, fontSize: 12, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 10), TextField( controller: _ctrl, autofocus: true, textAlign: TextAlign.center, style: const TextStyle(color: Colors.white, fontSize: 12), decoration: InputDecoration( hintText: 'نام کاربری', hintStyle: const TextStyle(color: Colors.white38, fontSize: 11), filled: true, fillColor: Colors.white.withOpacity(0.05), border: OutlineInputBorder( borderRadius: BorderRadius.circular(10), borderSide: BorderSide.none, ), contentPadding: const EdgeInsets.symmetric( horizontal: 12, vertical: 8, ), ), onChanged: widget.onUsernameChanged, ), const SizedBox(height: 12), Row( children: [ Expanded( child: TextButton( onPressed: () => Navigator.pop(context, false), child: const Text( 'انصراف', style: TextStyle(color: Colors.white54, fontSize: 11), ), ), ), Expanded( child: TextButton( onPressed: () => Navigator.pop(context, true), child: const Text( 'ارسال', style: TextStyle( color: Color(0xFF00C853), fontSize: 11, fontWeight: FontWeight.bold, ), ), ), ), ], ), ], ), ); } }