import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:marco/controller/my_controller.dart'; import 'package:marco/helpers/widgets/my_form_validator.dart'; import 'package:marco/helpers/services/api_service.dart'; import 'package:logger/logger.dart'; import 'package:marco/helpers/widgets/my_snackbar.dart'; import 'package:flutter_contacts/flutter_contacts.dart'; import 'package:permission_handler/permission_handler.dart'; enum Gender { male, female, other; const Gender(); } final Logger logger = Logger(); class AddEmployeeController extends MyController { List files = []; final MyFormValidator basicValidator = MyFormValidator(); Gender? selectedGender; List> roles = []; String? selectedRoleId; final List> countries = [ {"code": "+91", "name": "India"}, {"code": "+1", "name": "USA"}, {"code": "+971", "name": "UAE"}, {"code": "+44", "name": "UK"}, {"code": "+81", "name": "Japan"}, {"code": "+61", "name": "Australia"}, {"code": "+49", "name": "Germany"}, {"code": "+33", "name": "France"}, {"code": "+86", "name": "China"}, ]; final Map minDigitsPerCountry = { "+91": 10, "+1": 10, "+971": 9, "+44": 10, "+81": 10, "+61": 9, "+49": 10, "+33": 9, "+86": 11, }; final Map maxDigitsPerCountry = { "+91": 10, "+1": 10, "+971": 9, "+44": 11, "+81": 10, "+61": 9, "+49": 11, "+33": 9, "+86": 11, }; String selectedCountryCode = "+91"; bool showOnline = true; final List categories = []; @override void onInit() { super.onInit(); logger.i("Initializing AddEmployeeController..."); _initializeFields(); fetchRoles(); } void _initializeFields() { basicValidator.addField( 'first_name', label: "First Name", required: true, controller: TextEditingController(), ); basicValidator.addField( 'phone_number', label: "Phone Number", required: true, controller: TextEditingController(), ); basicValidator.addField( 'last_name', label: "Last Name", required: true, controller: TextEditingController(), ); logger.i("Fields initialized for first_name, phone_number, last_name."); } void onGenderSelected(Gender? gender) { selectedGender = gender; logger.i("Gender selected: ${gender?.name}"); update(); } Future fetchRoles() async { logger.i("Fetching roles..."); try { final result = await ApiService.getRoles(); if (result != null) { roles = List>.from(result); logger.i("Roles fetched successfully."); update(); } else { logger.e("Failed to fetch roles: null result"); } } catch (e, st) { logger.e("Error fetching roles: $e", error: e, stackTrace: st); } } void onRoleSelected(String? roleId) { selectedRoleId = roleId; logger.i("Role selected: $roleId"); update(); } Future createEmployees() async { logger.i("Starting employee creation..."); if (selectedGender == null || selectedRoleId == null) { logger.w("Missing gender or role."); showAppSnackbar( title: "Missing Fields", message: "Please select both Gender and Role.", type: SnackbarType.warning, ); return false; } final firstName = basicValidator.getController("first_name")?.text.trim(); final lastName = basicValidator.getController("last_name")?.text.trim(); final phoneNumber = basicValidator.getController("phone_number")?.text.trim(); logger.i( "Creating employee with Name: $firstName $lastName, Phone: $phoneNumber, Gender: ${selectedGender!.name}"); try { final response = await ApiService.createEmployee( firstName: firstName!, lastName: lastName!, phoneNumber: phoneNumber!, gender: selectedGender!.name, jobRoleId: selectedRoleId!, ); if (response == true) { logger.i("Employee created successfully."); showAppSnackbar( title: "Success", message: "Employee created successfully!", type: SnackbarType.success, ); return true; } else { logger.e("Failed to create employee (response false)."); } } catch (e, st) { logger.e("Error creating employee: $e", error: e, stackTrace: st); } showAppSnackbar( title: "Error", message: "Failed to create employee.", type: SnackbarType.error, ); return false; } Future _checkAndRequestContactsPermission() async { final status = await Permission.contacts.request(); if (status.isGranted) { return true; } if (status.isPermanentlyDenied) { await openAppSettings(); } showAppSnackbar( title: "Permission Required", message: "Please allow Contacts permission from settings to pick a contact.", type: SnackbarType.warning, ); return false; } Future pickContact(BuildContext context) async { final permissionGranted = await _checkAndRequestContactsPermission(); if (!permissionGranted) return; try { final picked = await FlutterContacts.openExternalPick(); if (picked == null) return; // User canceled contact picking final contact = await FlutterContacts.getContact(picked.id, withProperties: true); if (contact == null) { showAppSnackbar( title: "Error", message: "Failed to load contact details.", type: SnackbarType.error, ); return; } if (contact.phones.isEmpty) { showAppSnackbar( title: "No Phone Number", message: "Selected contact has no phone number.", type: SnackbarType.warning, ); return; } final indiaPhones = contact.phones.where((p) { final normalized = p.number.replaceAll(RegExp(r'[^0-9+]'), ''); return normalized.startsWith('+91') || RegExp(r'^\d{10}$').hasMatch(normalized); }).toList(); if (indiaPhones.isEmpty) { showAppSnackbar( title: "No Indian Number", message: "Selected contact has no Indian (+91) phone number.", type: SnackbarType.warning, ); return; } String? selectedPhone; if (indiaPhones.length == 1) { selectedPhone = indiaPhones.first.number; } else { selectedPhone = await showDialog( context: context, builder: (ctx) => AlertDialog( title: Text("Choose an Indian number"), content: Column( mainAxisSize: MainAxisSize.min, children: indiaPhones .map((p) => ListTile( title: Text(p.number), onTap: () => Navigator.of(ctx).pop(p.number), )) .toList(), ), ), ); if (selectedPhone == null) return; } final normalizedPhone = selectedPhone.replaceAll(RegExp(r'[^0-9]'), ''); // Remove country code prefix if present, keep only 10 digits String phoneWithoutCountryCode; if (normalizedPhone.length > 10) { phoneWithoutCountryCode = normalizedPhone.substring(normalizedPhone.length - 10); } else { phoneWithoutCountryCode = normalizedPhone; } basicValidator.getController('phone_number')?.text = phoneWithoutCountryCode; update(); } catch (e, st) { logger.e("Error fetching contacts: $e", error: e, stackTrace: st); showAppSnackbar( title: "Error", message: "Failed to fetch contacts.", type: SnackbarType.error, ); } } }