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:marco/helpers/widgets/my_snackbar.dart'; import 'package:flutter_contacts/flutter_contacts.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:marco/helpers/services/app_logger.dart'; enum Gender { male, female, other; const Gender(); } 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(); logSafe("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(), ); logSafe("Fields initialized for first_name, phone_number, last_name."); } void onGenderSelected(Gender? gender) { selectedGender = gender; logSafe("Gender selected: ${gender?.name}"); update(); } Future fetchRoles() async { logSafe("Fetching roles..."); try { final result = await ApiService.getRoles(); if (result != null) { roles = List>.from(result); logSafe("Roles fetched successfully."); update(); } else { logSafe("Failed to fetch roles: null result", level: LogLevel.error); } } catch (e, st) { logSafe("Error fetching roles", level: LogLevel.error, error: e, stackTrace: st); } } void onRoleSelected(String? roleId) { selectedRoleId = roleId; logSafe("Role selected: $roleId"); update(); } Future createEmployees() async { logSafe("Starting employee creation..."); if (selectedGender == null || selectedRoleId == null) { logSafe("Missing gender or role.", level: LogLevel.warning); 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(); logSafe("Creating employee", level: LogLevel.info); try { final response = await ApiService.createEmployee( firstName: firstName!, lastName: lastName!, phoneNumber: phoneNumber!, gender: selectedGender!.name, jobRoleId: selectedRoleId!, ); logSafe("Response: $response"); if (response == true) { logSafe("Employee created successfully."); showAppSnackbar( title: "Success", message: "Employee created successfully!", type: SnackbarType.success, ); return true; } else { logSafe("Failed to create employee (response false)", level: LogLevel.error); } } catch (e, st) { logSafe("Error creating employee", level: LogLevel.error, 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; 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]'), ''); final phoneWithoutCountryCode = normalizedPhone.length > 10 ? normalizedPhone.substring(normalizedPhone.length - 10) : normalizedPhone; basicValidator.getController('phone_number')?.text = phoneWithoutCountryCode; update(); } catch (e, st) { logSafe("Error fetching contacts", level: LogLevel.error, error: e, stackTrace: st); showAppSnackbar( title: "Error", message: "Failed to fetch contacts.", type: SnackbarType.error, ); } } }