import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import '../../core/services/api_service.dart'; import '../../core/models/user.dart'; class AddUserDialog extends StatefulWidget { const AddUserDialog({super.key}); @override State createState() => _AddUserDialogState(); } class _AddUserDialogState extends State { final _formKey = GlobalKey(); final _mobileNumberController = TextEditingController(); final _fullNameController = TextEditingController(); final _emailController = TextEditingController(); final _addressController = TextEditingController(); final _emergencyContactController = TextEditingController(); final ApiService _apiService = ApiService(); bool _isLoading = false; bool _isCheckingMobile = false; @override void dispose() { _mobileNumberController.dispose(); _fullNameController.dispose(); _emailController.dispose(); _addressController.dispose(); _emergencyContactController.dispose(); super.dispose(); } Future _checkMobileNumberExists(String mobileNumber) async { if (mobileNumber.length != 10) return false; setState(() => _isCheckingMobile = true); try { final response = await _apiService.getAllUsers(); if (response['success'] == true && response['data'] != null) { final usersData = response['data']['users'] as List; final users = usersData.map((userData) => User.fromJson(userData)).toList(); final exists = users.any((user) => user.mobileNumber == mobileNumber); if (exists) { Get.snackbar( 'Mobile Number Exists', 'A user with this mobile number already exists!', backgroundColor: Colors.orange.shade100, colorText: Colors.orange.shade800, snackPosition: SnackPosition.TOP, duration: const Duration(seconds: 2), ); } return exists; } return false; } catch (e) { print('Error checking mobile number: $e'); return false; // Allow creation if check fails } finally { setState(() => _isCheckingMobile = false); } } Future _addUser() async { if (!_formKey.currentState!.validate()) return; setState(() => _isLoading = true); try { // Check if mobile number already exists final mobileExists = await _checkMobileNumberExists(_mobileNumberController.text.trim()); if (mobileExists) { Get.snackbar( 'Error', 'A user with this mobile number already exists!', backgroundColor: Colors.orange.shade100, colorText: Colors.orange.shade800, snackPosition: SnackPosition.TOP, ); return; } // Call the API to create a new user final response = await _apiService.createMember( _mobileNumberController.text.trim(), _fullNameController.text.trim(), email: _emailController.text.trim().isNotEmpty ? _emailController.text.trim() : null, address: _addressController.text.trim().isNotEmpty ? _addressController.text.trim() : null, emergencyContact: _emergencyContactController.text.trim().isNotEmpty ? _emergencyContactController.text.trim() : null, ); if (response['success'] == true) { Navigator.of(context).pop(); // Close dialog Get.snackbar( 'Success', 'User added successfully! You can now select them for chitfunds.', backgroundColor: Colors.green.shade100, colorText: Colors.green.shade800, snackPosition: SnackPosition.TOP, ); } else { throw Exception(response['message'] ?? 'Failed to create user'); } } catch (e) { Get.snackbar( 'Error', 'Failed to add user. Please try again.', backgroundColor: Colors.red.shade100, colorText: Colors.red.shade800, snackPosition: SnackPosition.TOP, ); } finally { setState(() => _isLoading = false); } } @override Widget build(BuildContext context) { return Dialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16.r)), child: Container( width: 500.w, constraints: BoxConstraints(maxHeight: 0.8.sh), child: Column( mainAxisSize: MainAxisSize.min, children: [ // Header Container( padding: EdgeInsets.all(20.w), decoration: BoxDecoration( color: Colors.green.shade600, borderRadius: BorderRadius.only( topLeft: Radius.circular(16.r), topRight: Radius.circular(16.r), ), ), child: Row( children: [ Icon( Icons.person_add, color: Colors.white, size: 24.w, ), SizedBox(width: 12.w), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Add New User', style: TextStyle( color: Colors.white, fontSize: 18.sp, fontWeight: FontWeight.w600, ), ), Text( 'Create a new user account', style: TextStyle( color: Colors.white.withOpacity(0.8), fontSize: 14.sp, ), ), ], ), ), IconButton( onPressed: () => Navigator.of(context).pop(), icon: const Icon(Icons.close, color: Colors.white), padding: EdgeInsets.zero, constraints: const BoxConstraints(), ), ], ), ), // Form Content Flexible( child: SingleChildScrollView( padding: EdgeInsets.all(20.w), child: Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // User Information Section _buildSectionTitle('User Information'), SizedBox(height: 16.h), // Mobile Number TextFormField( controller: _mobileNumberController, decoration: InputDecoration( labelText: 'Mobile Number *', hintText: 'Enter 10-digit mobile number', prefixIcon: const Icon(Icons.phone), suffixIcon: _isCheckingMobile ? SizedBox( width: 20.w, height: 20.w, child: const CircularProgressIndicator(strokeWidth: 2), ) : null, border: OutlineInputBorder( borderRadius: BorderRadius.circular(8.r), ), ), keyboardType: TextInputType.phone, maxLength: 10, onChanged: (value) { if (value.length == 10) { _checkMobileNumberExists(value); } }, validator: (value) { if (value == null || value.trim().isEmpty) { return 'Mobile number is required'; } if (value.length != 10) { return 'Mobile number must be 10 digits'; } if (!RegExp(r'^[0-9]+$').hasMatch(value)) { return 'Mobile number must contain only digits'; } return null; }, ), SizedBox(height: 16.h), // Full Name TextFormField( controller: _fullNameController, decoration: InputDecoration( labelText: 'Full Name *', hintText: 'Enter full name', prefixIcon: const Icon(Icons.person), border: OutlineInputBorder( borderRadius: BorderRadius.circular(8.r), ), ), validator: (value) { if (value == null || value.trim().isEmpty) { return 'Full name is required'; } if (value.trim().length < 2) { return 'Name must be at least 2 characters'; } return null; }, ), SizedBox(height: 16.h), // Email (Optional) TextFormField( controller: _emailController, decoration: InputDecoration( labelText: 'Email (Optional)', hintText: 'Enter email address', prefixIcon: const Icon(Icons.email), border: OutlineInputBorder( borderRadius: BorderRadius.circular(8.r), ), ), keyboardType: TextInputType.emailAddress, validator: (value) { if (value != null && value.trim().isNotEmpty) { if (!RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$').hasMatch(value)) { return 'Please enter a valid email address'; } } return null; }, ), SizedBox(height: 16.h), // Address (Optional) TextFormField( controller: _addressController, decoration: InputDecoration( labelText: 'Address (Optional)', hintText: 'Enter address', prefixIcon: const Icon(Icons.location_on), border: OutlineInputBorder( borderRadius: BorderRadius.circular(8.r), ), ), maxLines: 2, ), SizedBox(height: 16.h), // Emergency Contact (Optional) TextFormField( controller: _emergencyContactController, decoration: InputDecoration( labelText: 'Emergency Contact (Optional)', hintText: 'Enter emergency contact number', prefixIcon: const Icon(Icons.emergency), border: OutlineInputBorder( borderRadius: BorderRadius.circular(8.r), ), ), keyboardType: TextInputType.phone, maxLength: 10, validator: (value) { if (value != null && value.trim().isNotEmpty) { if (value.length != 10) { return 'Emergency contact must be 10 digits'; } if (!RegExp(r'^[0-9]+$').hasMatch(value)) { return 'Emergency contact must contain only digits'; } } return null; }, ), SizedBox(height: 24.h), // Action Buttons Row( children: [ Expanded( child: OutlinedButton( onPressed: () => Navigator.of(context).pop(), style: OutlinedButton.styleFrom( padding: EdgeInsets.symmetric(vertical: 16.h), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.r), ), ), child: Text( 'Cancel', style: TextStyle(fontSize: 16.sp), ), ), ), SizedBox(width: 16.w), Expanded( child: ElevatedButton( onPressed: _isLoading ? null : _addUser, style: ElevatedButton.styleFrom( backgroundColor: Colors.green.shade600, foregroundColor: Colors.white, padding: EdgeInsets.symmetric(vertical: 16.h), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.r), ), ), child: _isLoading ? SizedBox( height: 20.h, width: 20.w, child: const CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation(Colors.white), ), ) : Text( 'Add User', style: TextStyle(fontSize: 16.sp), ), ), ), ], ), ], ), ), ), ), ], ), ), ); } Widget _buildSectionTitle(String title) { return Text( title, style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, color: Colors.grey.shade800, ), ); } }