import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import '../../core/services/chit_group_service.dart'; import '../../core/models/chit_group.dart'; import '../../core/models/user.dart'; class SelectMemberDialog extends StatefulWidget { final ChitGroup group; const SelectMemberDialog({ super.key, required this.group, }); @override State createState() => _SelectMemberDialogState(); } class _SelectMemberDialogState extends State { final ChitGroupService _service = ChitGroupService.to; final TextEditingController _searchController = TextEditingController(); List _users = []; List _filteredUsers = []; bool _isLoading = false; bool _isAdding = false; String _searchQuery = ''; User? _selectedUser; @override void initState() { super.initState(); _loadUsers(); } @override void dispose() { _searchController.dispose(); super.dispose(); } Future _loadUsers() async { setState(() => _isLoading = true); try { final users = await _service.getAllUsers(search: _searchQuery); setState(() { _users = users; _filteredUsers = users; }); } catch (e) { Get.snackbar('Error', 'Failed to load users'); } finally { setState(() => _isLoading = false); } } void _filterUsers(String query) { setState(() { _searchQuery = query; if (query.isEmpty) { _filteredUsers = _users; } else { _filteredUsers = _users.where((user) { return user.fullName.toLowerCase().contains(query.toLowerCase()) || user.mobileNumber.contains(query); }).toList(); } }); } Future _addSelectedUserToGroup() async { if (_selectedUser == null) { Get.snackbar( 'Error', 'Please select a user first', backgroundColor: Colors.orange.shade100, colorText: Colors.orange.shade800, snackPosition: SnackPosition.TOP, ); return; } setState(() => _isAdding = true); try { final success = await _service.addMemberToGroup(widget.group.id, { 'mobile_number': _selectedUser!.mobileNumber, }); if (success) { Get.back(); // Close dialog Get.snackbar( 'Success', '${_selectedUser!.fullName} added to chitfund successfully!', backgroundColor: Colors.green.shade100, colorText: Colors.green.shade800, snackPosition: SnackPosition.TOP, ); } } catch (e) { Get.snackbar( 'Error', 'Failed to add member. Please try again.', backgroundColor: Colors.red.shade100, colorText: Colors.red.shade800, snackPosition: SnackPosition.TOP, ); } finally { setState(() => _isAdding = false); } } @override Widget build(BuildContext context) { return Dialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16.r)), child: Container( width: 600.w, height: 0.8.sh, child: Column( children: [ // Header Container( padding: EdgeInsets.all(20.w), decoration: BoxDecoration( color: Colors.blue.shade600, borderRadius: BorderRadius.only( topLeft: Radius.circular(16.r), topRight: Radius.circular(16.r), ), ), child: Row( children: [ Icon( Icons.people, color: Colors.white, size: 24.w, ), SizedBox(width: 12.w), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Add Member to Chitfund', style: TextStyle( color: Colors.white, fontSize: 18.sp, fontWeight: FontWeight.w600, ), ), Text( 'Chitfund: ${widget.group.name}', style: TextStyle( color: Colors.white.withOpacity(0.8), fontSize: 14.sp, ), ), ], ), ), IconButton( onPressed: () => Get.back(), icon: const Icon(Icons.close, color: Colors.white), padding: EdgeInsets.zero, constraints: const BoxConstraints(), ), ], ), ), // User Selection Expanded( child: Padding( padding: EdgeInsets.all(16.w), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Search Bar TextField( controller: _searchController, decoration: InputDecoration( hintText: 'Search by name or mobile number...', prefixIcon: const Icon(Icons.search), suffixIcon: _isLoading ? SizedBox( width: 20.w, height: 20.w, child: const CircularProgressIndicator(strokeWidth: 2), ) : IconButton( icon: const Icon(Icons.refresh), onPressed: _loadUsers, ), border: OutlineInputBorder( borderRadius: BorderRadius.circular(8.r), ), ), onChanged: _filterUsers, ), SizedBox(height: 16.h), // User Dropdown Text( 'Select User', style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, color: Colors.grey.shade800, ), ), SizedBox(height: 8.h), DropdownButtonFormField( value: _selectedUser, decoration: InputDecoration( border: OutlineInputBorder( borderRadius: BorderRadius.circular(8.r), ), contentPadding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 8.h), ), hint: Text( _isLoading ? 'Loading users...' : 'Choose a user to add', style: TextStyle(fontSize: 14.sp), ), items: _filteredUsers.map((user) { return DropdownMenuItem( value: user, child: Row( children: [ CircleAvatar( radius: 12.r, backgroundColor: Colors.blue.shade100, child: Text( user.fullName.isNotEmpty ? user.fullName[0].toUpperCase() : '?', style: TextStyle( color: Colors.blue.shade700, fontWeight: FontWeight.w600, fontSize: 12.sp, ), ), ), SizedBox(width: 8.w), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ Text( user.fullName, style: TextStyle( fontSize: 14.sp, fontWeight: FontWeight.w600, ), overflow: TextOverflow.ellipsis, ), Text( user.mobileNumber, style: TextStyle( fontSize: 12.sp, color: Colors.grey.shade600, ), ), ], ), ), ], ), ); }).toList(), onChanged: (User? newValue) { setState(() { _selectedUser = newValue; }); }, ), SizedBox(height: 16.h), // Selected User Info if (_selectedUser != null) Container( padding: EdgeInsets.all(12.w), decoration: BoxDecoration( color: Colors.blue.shade50, borderRadius: BorderRadius.circular(8.r), border: Border.all(color: Colors.blue.shade200), ), child: Row( children: [ Icon( Icons.person, color: Colors.blue.shade600, size: 20.w, ), SizedBox(width: 8.w), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Selected: ${_selectedUser!.fullName}', style: TextStyle( fontSize: 14.sp, fontWeight: FontWeight.w600, color: Colors.blue.shade800, ), ), Text( 'Mobile: ${_selectedUser!.mobileNumber}', style: TextStyle( fontSize: 12.sp, color: Colors.blue.shade600, ), ), ], ), ), ], ), ), // Empty State if (_filteredUsers.isEmpty && !_isLoading) Expanded( child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.people_outline, size: 64.w, color: Colors.grey.shade400, ), SizedBox(height: 16.h), Text( _searchQuery.isEmpty ? 'No users found' : 'No users match your search', style: TextStyle( fontSize: 16.sp, color: Colors.grey.shade600, ), ), if (_searchQuery.isNotEmpty) ...[ SizedBox(height: 8.h), TextButton( onPressed: () { _searchController.clear(); _filterUsers(''); }, child: const Text('Clear search'), ), ], ], ), ), ), ], ), ), ), // Footer Container( padding: EdgeInsets.all(16.w), decoration: BoxDecoration( color: Colors.grey.shade50, borderRadius: BorderRadius.only( bottomLeft: Radius.circular(16.r), bottomRight: Radius.circular(16.r), ), ), child: Row( children: [ Expanded( child: Text( '${_filteredUsers.length} users found', style: TextStyle( fontSize: 14.sp, color: Colors.grey.shade600, ), ), ), SizedBox(width: 8.w), OutlinedButton( onPressed: () => Get.back(), child: const Text('Cancel'), ), SizedBox(width: 8.w), ElevatedButton( onPressed: _isAdding ? null : _addSelectedUserToGroup, style: ElevatedButton.styleFrom( backgroundColor: Colors.blue.shade600, foregroundColor: Colors.white, ), child: _isAdding ? SizedBox( width: 16.w, height: 16.w, child: const CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation(Colors.white), ), ) : const Text('Add Member'), ), ], ), ), ], ), ), ); } }