import 'dart:convert'; import 'dart:io'; import 'package:crypto/crypto.dart'; import 'dart:math'; import 'package:http/http.dart' as http; import 'package:permission_handler/permission_handler.dart'; import 'package:sefer_driver/views/auth/captin/egypt_card_a_i.dart'; import 'package:flutter/material.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import 'package:sefer_driver/main.dart'; import 'package:sefer_driver/views/home/Captin/home_captain/home_captin.dart'; import 'package:location/location.dart'; import '../../../constant/api_key.dart'; import '../../../print.dart'; import '../../../views/auth/captin/otp_page.dart'; import '../../../views/auth/captin/otp_token_page.dart'; import '../../../views/auth/syria/pending_driver_page.dart'; import '../../firebase/local_notification.dart'; import '../../firebase/notification_service.dart'; import '../../functions/encrypt_decrypt.dart'; import '../../functions/package_info.dart'; import '../../functions/security_checks.dart'; class LoginDriverController extends GetxController { final formKey = GlobalKey(); TextEditingController emailController = TextEditingController(); TextEditingController phoneController = TextEditingController(); TextEditingController passwordController = TextEditingController(); TextEditingController passwordController2 = TextEditingController(); bool isAgreeTerms = false; bool isGoogleDashOpen = false; bool isGoogleLogin = false; bool isloading = false; late int isTest = 1; final FlutterSecureStorage _storage = const FlutterSecureStorage(); final location = Location(); void changeAgreeTerm() { isAgreeTerms = !isAgreeTerms; update(); } bool isPasswordHidden = true; void togglePasswordVisibility() { isPasswordHidden = !isPasswordHidden; update([ 'passwordVisibility' ]); // Use a unique ID to only update the password field } void changeGoogleDashOpen() { isGoogleDashOpen = !isGoogleDashOpen; update(); } @override void onInit() async { box.write(BoxName.countryCode, 'Egypt'); // box.write(BoxName.driverID, '34feffd3fa72d6bee56b'); // await getAppTester(); getJWT(); super.onInit(); } // getAppTester() async { // var res = await CRUD().get( // link: AppLink.getTesterApp, // payload: {'appPlatform': AppInformation.appName}); // // Log.print('res: ${res}'); // if (res != 'failure') { // var d = jsonDecode(res); // isTest = d['message'][0]['isTest']; // // Log.print('isTest: ${isTest}'); // box.write(BoxName.isTest, isTest); // // Log.print('isTest: ${box.read(BoxName.isTest)}'); // update(); // } else { // isTest = 0; // box.write(BoxName.isTest, isTest); // update(); // return false; // } // } updateAppTester(String appPlatform) async { await CRUD().post( link: AppLink.updateTesterApp, payload: {'appPlatform': appPlatform}); } isPhoneVerified() async { // 1. أولاً نتأكد هل يوجد رقم هاتف محفوظ محلياً (تجاوز الـ OTP) String? savedPhone = box.read(BoxName.phoneDriver); Log.print('savedPhone: ${savedPhone}'); if (savedPhone == null || savedPhone.isEmpty) { // لا يوجد رقم محفوظ، نعيد المستخدم لصفحة إدخال الرقم Get.offAll(() => PhoneNumberScreen()); return; } var res = await CRUD().post( link: AppLink.isPhoneVerified, payload: {'phone_number': savedPhone}); Log.print('isPhoneVerified Res: $res'); if (res != 'failure') { // الحالة 1: السائق موجود ومفعل -> نذهب للصفحة التالية Get.offAll(() => EgyptCardAI()); } else { // الحالة 2: الرد فشل (السائق غير موجود في الداتا بيز) if (savedPhone != null && savedPhone.isNotEmpty) { // بما أن الرقم محفوظ، فهذا مستخدم جديد أكمل التحقق // نوجهه لصفحة التسجيل/البطاقة بدلاً من العودة للبداية Log.print('New User Detected, redirecting to Registration...'); Get.offAll(() => EgyptCardAI()); } else { // لا يوجد رقم محفوظ ولا مستخدم في السيرفر -> عودة للبداية Get.offAll(() => PhoneNumberScreen()); } } } // isPhoneVerified() async { // var res = await CRUD().post( // link: AppLink.isPhoneVerified, // payload: {'phone_number': box.read(BoxName.phoneDriver)}); // Log.print('isPhoneVerified: ${res}'); // if (res != 'failure') { // // Get.offAll(() => SyrianCardAI()); // Get.offAll(() => EgyptCardAI()); // // isloading = false; // // update(); // } else { // Get.offAll(() => PhoneNumberScreen()); // } // } void saveAgreementTerms() { box.write(BoxName.agreeTerms, 'agreed'); update(); } void saveCountryCode(String countryCode) { box.write(BoxName.countryCode, countryCode); update(); } var dev = ''; getJwtWallet() async { if (box.read(BoxName.security_check).toString() != 'passed') { Log.print('Security check failed'); return; } Log.print('Security check passed'); String fingerPrint = await DeviceHelper.getDeviceFingerprint(); // Log.print('fingerPrint: ${fingerPrint}'); dev = Platform.isAndroid ? 'android' : 'ios'; var payload = { 'id': box.read(BoxName.driverID), 'password': AK.passnpassenger, 'aud': '${AK.allowedWallet}$dev', 'fingerPrint': fingerPrint }; var response1 = await http.post( Uri.parse(AppLink.loginJwtWalletDriver), body: payload, ); // Log.print('response.request: ${response1.request}'); // Log.print('response.JwtWallet: ${response1.body}'); // print(payload); // Log.print('payment["jwt"]: ${jsonDecode(response1.body)['jwt']}'); await box.write(BoxName.hmac, jsonDecode(response1.body)['hmac']); return jsonDecode(response1.body)['jwt'].toString(); } String shortHash(String password) { var bytes = utf8.encode(password); var digest = sha256.convert(bytes); return base64UrlEncode(digest.bytes); } getJWT() async { dev = Platform.isAndroid ? 'android' : 'ios'; Log.print( 'box.read(BoxName.firstTimeLoadKey): ${box.read(BoxName.firstTimeLoadKey)}'); if (box.read(BoxName.firstTimeLoadKey).toString() != 'false') { var payload = { 'id': box.read(BoxName.driverID) ?? AK.newId, 'password': AK.passnpassenger, 'aud': '${AK.allowed}$dev', }; // Log.print('payload: ${payload}'); var response0 = await http.post( Uri.parse(AppLink.loginFirstTimeDriver), body: payload, ); // Log.print('response0: ${response0.body}'); Log.print('request: ${response0.request}'); if (response0.statusCode == 200) { final decodedResponse1 = jsonDecode(response0.body); // Log.print('decodedResponse1: ${decodedResponse1}'); final jwt = decodedResponse1['jwt']; box.write(BoxName.jwt, c(jwt)); // ✅ بعد التأكد أن كل المفاتيح موجودة await EncryptionHelper.initialize(); // await AppInitializer().getKey(); } else {} } else { await EncryptionHelper.initialize(); var payload = { 'id': box.read(BoxName.driverID), 'password': box.read(BoxName.emailDriver), 'aud': '${AK.allowed}$dev', }; // print(payload); var response1 = await http.post( Uri.parse(AppLink.loginJwtDriver), body: payload, ); // print(response1.request); // print(response1.body); if (response1.statusCode == 200) { final decodedResponse1 = jsonDecode(response1.body); // Log.print('decodedResponse1: ${decodedResponse1}'); final jwt = decodedResponse1['jwt']; await box.write(BoxName.jwt, c(jwt)); // await AppInitializer().getKey(); } } } Future getLocationPermission() async { var status = await Permission.locationAlways.status; if (!status.isGranted) { await Permission.locationAlways.request(); } update(); } String generateUniqueIdFromEmail(String email) { // Step 1: Extract the local part of the email String localPart = email.split('@')[0]; // Step 2: Replace invalid characters (if any) String cleanLocalPart = localPart.replaceAll(RegExp(r'[^a-zA-Z0-9]'), ''); // Step 3: Ensure it does not exceed 24 characters if (cleanLocalPart.length > 24) { cleanLocalPart = cleanLocalPart.substring(0, 24); } // Step 4: Generate a random suffix if needed String suffix = generateRandomSuffix(24 - cleanLocalPart.length); return cleanLocalPart + suffix; } String generateRandomSuffix(int length) { const String chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; Random random = Random(); return List.generate(length, (index) => chars[random.nextInt(chars.length)]) .join(''); } bool isInviteDriverFound = false; Future updateInvitationCodeFromRegister() async { var res = await CRUD().post( link: AppLink.updateDriverInvitationDirectly, payload: { "inviterDriverPhone": box.read(BoxName.phoneDriver).toString(), }, ); Log.print('invite: ${res}'); box.write(BoxName.isInstall, '1'); // ✅ تصحيح 1: التحقق من أن الرد ليس 'failure' وأنه Map قبل القراءة if (res != 'failure' && res is Map && res['status'] == 'success') { isInviteDriverFound = true; update(); NotificationController().showNotification( "Code approved".tr, "Code approved".tr, 'tone2', ''); // ✅ تصحيح 2: استخراج التوكن حسب هيكل PHP الجديد (مفتاح 'data') String? targetToken; // الهيكل الجديد: {status: success, data: {token: ...}} if (res['data'] != null && res['data']['token'] != null) { targetToken = res['data']['token'].toString(); } // دعم الهيكل القديم للاحتياط: {status: success, message: [{token: ...}]} else if (res['message'] is List && res['message'].isNotEmpty) { targetToken = res['message'][0]['token'].toString(); } if (targetToken != null) { NotificationService.sendNotification( target: targetToken, title: 'You have received a gift token!'.tr, body: 'for '.tr + box.read(BoxName.phoneDriver).toString(), isTopic: false, tone: 'tone2', driverList: [], category: 'You have received a gift token!', ); } } else { // فشل التحديث (الكود غير موجود أو خطأ سيرفر) // لا تفعل شيئاً أو اعرض رسالة خطأ صامتة } } loginWithGoogleCredential(String driverID, String email) async { isloading = true; update(); try { // 1. تجهيز البيانات الإضافية للأمان String platformName = Platform.isIOS ? 'ios' : 'android'; String storedPhone = box.read(BoxName.phoneDriver)?.toString() ?? ''; // 2. إرسال الطلب الموحد (Login + Token + PackageInfo) var res = await CRUD().get(link: AppLink.loginFromGoogleCaptin, payload: { 'id': driverID, 'email': email, // ضروري للمطابقة الأمنية في السيرفر 'phone': storedPhone, // اختياري، لزيادة الموثوقية 'platform': platformName // لجلب معلومات التحديث المناسبة للجهاز }); Log.print('loginWithGoogleCredential Response: $res'); if (res == 'failure') { // فشل الدخول (البيانات غير موجودة أو غير مطابقة) // نحاول التحقق من حالة الهاتف لتوجيهه للتسجيل إذا كان جديداً await isPhoneVerified(); isloading = false; update(); return false; } else { var jsonResponse = jsonDecode(res); if (jsonResponse['status'] == 'success') { // --------------------------------------------------------- // A. معالجة بيانات السائق الأساسية // --------------------------------------------------------- var d = jsonResponse['data'][0]; if (d['is_verified'].toString() == '1') { // حفظ البيانات في التخزين المحلي box.write(BoxName.emailDriver, d['email']); box.write(BoxName.firstTimeLoadKey, 'false'); box.write(BoxName.driverID, d['id']); box.write(BoxName.isTest, '1'); // أو حسب القيمة القادمة box.write(BoxName.gender, d['gender']); box.write(BoxName.phoneVerified, d['is_verified'].toString()); box.write(BoxName.phoneDriver, d['phone']); box.write(BoxName.is_claimed, d['is_claimed']); if (box.read(BoxName.isInstall).toString() == 'null' || box.read(BoxName.isInstall).toString() == '') { box.write(BoxName.isInstall, d['isInstall']); } Log.print( 'isInstall for update invitation: ${box.read(BoxName.isInstall)}'); // box.write(BoxName.isInstall, d['isInstall']); box.write(BoxName.nameArabic, d['name_arabic']); // تأكد أن هذا الحقل موجود في الرد أو عدله box.write(BoxName.bankCodeDriver, d['bankCode']); box.write(BoxName.accountBankNumberDriver, d['accountBank']); box.write( BoxName.nameDriver, '${d['first_name']} ${d['last_name']}'); int categoryId = int.tryParse(d['vehicle_category_id']?.toString() ?? '0') ?? 0; // معالجة سنة السيارة بشكل آمن لتجنب الكراش int carYear = int.tryParse(d['year']?.toString() ?? '0') ?? 0; box.write(BoxName.carYear, carYear); // منطق تحديد نوع السيارة String gender = d['gender']?.toString() ?? ''; if (categoryId == 2) { // 2 = دراجة / سكوتر (حسب قاعدة البيانات) if (gender == 'Male') { box.write(BoxName.carTypeOfDriver, 'Scooter'); } else { box.write(BoxName.carTypeOfDriver, 'Pink Bike'); } } else if (categoryId == 3) { // 3 = فان (إذا كان لديكم فئة فان) box.write(BoxName.carTypeOfDriver, 'Van'); } else if (carYear > 2017) { if (gender != 'Male') { box.write(BoxName.carTypeOfDriver, 'Lady'); } else { box.write(BoxName.carTypeOfDriver, 'Comfort'); } } else if (carYear > 2002 && carYear <= 2017) { box.write(BoxName.carTypeOfDriver, 'Speed'); } else if (carYear <= 2002 && carYear > 0) { box.write(BoxName.carTypeOfDriver, 'Awfar Car'); } // --------------------------------------------------------- // B. معالجة التحديثات (Package Info) من نفس الرد // --------------------------------------------------------- // if (jsonResponse['package_info'] != null && // (jsonResponse['package_info'] as List).isNotEmpty) { // var pkg = jsonResponse['package_info'][0]; // // استدعاء دالة فحص التحديث (تأكد من وجودها أو مرر البيانات لها) // // checkUpdateFromData(pkg); // checkForUpdate(Get.context!); // } // --------------------------------------------------------- // C. معالجة كود الدعوة // --------------------------------------------------------- if (box.read(BoxName.isInstall) == null || box.read(BoxName.isInstall).toString() == '0') { updateInvitationCodeFromRegister(); } // --------------------------------------------------------- // D. التحقق الأمني (Device Fingerprint & Token) // --------------------------------------------------------- if (d['status'].toString() != 'yet') { // استخراج التوكن من الرد المجمع (دون طلب جديد) List? tokenList = jsonResponse['driver_token']; // توليد بصمة الجهاز الحالية String currentFingerPrint = await DeviceHelper.getDeviceFingerprint(); await storage.write( key: BoxName.fingerPrint, value: currentFingerPrint); if (tokenList != null && tokenList.isNotEmpty) { var tokenData = tokenList[0]; String serverToken = tokenData['token'].toString(); String serverFingerPrint = tokenData['fingerPrint'].toString(); String localToken = box.read(BoxName.tokenDriver)?.toString() ?? ""; // التحقق من تطابق التوكن والبصمة if (serverToken != localToken || serverFingerPrint != currentFingerPrint) { isloading = false; update(); await Get.defaultDialog( barrierDismissible: false, title: 'Device Change Detected'.tr, middleText: 'Please verify your identity'.tr, textConfirm: 'Verify'.tr, confirmTextColor: Colors.white, onConfirm: () { Get.back(); // إغلاق الديالوج // الانتقال لصفحة التحقق مع تمرير البيانات اللازمة Get.to(() => OtpVerificationPage( phone: d['phone'].toString(), deviceToken: currentFingerPrint, // نمرر التوكن القادم من السيرفر ليستعمل في التحقق لاحقاً token: jsonEncode( {'status': 'success', 'data': tokenList}), ptoken: serverToken, )); }, ); return true; // إيقاف التنفيذ هنا (بانتظار التحقق) } } // إذا كل شيء سليم، الدخول للرئيسية Get.offAll(() => HomeCaptain()); } else { // الحالة "yet" تعني أن السائق لم يكمل رفع الوثائق Get.offAll(() => DriverVerificationScreen()); } isloading = false; update(); return true; } else { // الحساب موجود لكن رقم الهاتف غير مفعل Get.offAll(() => PhoneNumberScreen()); isloading = false; update(); return false; } } else { // الرد من السيرفر ليس success (رغم أنه ليس failure في الاتصال) Get.offAll(() => PhoneNumberScreen()); isloading = false; update(); return false; } } } catch (e) { Log.print("Login Critical Error: $e"); isloading = false; update(); return false; } } logintest(String driverID, email) async { isloading = true; update(); // await SecurityHelper.performSecurityChecks(); // Log.print('(BoxName.emailDriver): ${box.read(BoxName.emailDriver)}'); var res = await CRUD() .get(link: AppLink.loginUsingCredentialsWithoutGoogle, payload: { 'email': email ?? 'yet', 'id': driverID, }); // print('res is $res'); // if (res == 'failure') { // await isPhoneVerified(); // // Get.snackbar('Failure', '', backgroundColor: Colors.red); // } else // { var jsonDecoeded = jsonDecode(res); var d = jsonDecoeded['data'][0]; if (jsonDecoeded.isNotEmpty) { if (jsonDecoeded['status'] == 'success') // && // d['is_verified'].toString() == '1') { box.write(BoxName.emailDriver, d['email']); box.write(BoxName.firstTimeLoadKey, 'false'); box.write(BoxName.driverID, (d['id'])); box.write(BoxName.isTest, '1'); box.write(BoxName.gender, (d['gender'])); box.write(BoxName.phoneVerified, d['is_verified'].toString()); box.write(BoxName.phoneDriver, (d['phone'])); box.write(BoxName.is_claimed, d['is_claimed']); box.write(BoxName.isInstall, d['isInstall']); // box.write( // BoxName.isGiftToken, d['isGiftToken']); box.write(BoxName.nameArabic, (d['name_arabic'])); box.write(BoxName.carYear, d['year']); box.write(BoxName.bankCodeDriver, (d['bankCode'])); box.write(BoxName.accountBankNumberDriver, (d['accountBank'])); box.write( BoxName.nameDriver, '${(d['first_name'])}' ' ${(d['last_name'])}'); if (((d['model']).toString().contains('دراجه') || d['make'].toString().contains('دراجه '))) { if ((d['gender']).toString() == 'Male') { box.write(BoxName.carTypeOfDriver, 'Scooter'); } else { box.write(BoxName.carTypeOfDriver, 'Pink Bike'); } } else if (int.parse(d['year'].toString()) > 2017) { if (d['gender'].toString() != 'Male') { box.write(BoxName.carTypeOfDriver, 'Lady'); } else { box.write(BoxName.carTypeOfDriver, 'Comfort'); } } else if (int.parse(d['year'].toString()) > 2002 && int.parse(d['year'].toString()) < 2017) { box.write(BoxName.carTypeOfDriver, 'Speed'); } else if (int.parse(d['year'].toString()) < 2002) { box.write(BoxName.carTypeOfDriver, 'Awfar Car'); } // updateAppTester(AppInformation.appName); // var token = await CRUD().get( // link: AppLink.getDriverToken, // payload: {'captain_id': (box.read(BoxName.driverID)).toString()}); // String fingerPrint = await DeviceHelper.getDeviceFingerprint(); // await storage.write( // key: BoxName.fingerPrint, value: fingerPrint.toString()); Get.off(() => HomeCaptain()); // } else { // Get.offAll(() => PhoneNumberScreen()); // isloading = false; // update(); // } // } // else { // mySnackbarSuccess(''); // isloading = false; // update(); } } } loginUsingCredentialsWithoutGoogle( String password, String email, String phone) async { isloading = true; // تحديد نوع العملية (ليس جوجل) isGoogleLogin = false; update(); try { String platformName = Platform.isIOS ? 'ios' : 'android'; // 1. إرسال الطلب (إضافة Platform) var res = await CRUD() .get(link: AppLink.loginUsingCredentialsWithoutGoogle, payload: { 'email': email, 'password': password, 'phone': phone, // <-- يجب إضافة هذا السطر 'platform': platformName }); // حفظ الإيميل لمحاولات الدخول اللاحقة box.write(BoxName.emailDriver, email); if (res == 'failure') { // في حال الفشل (كلمة مرور خطأ أو مستخدم غير موجود) // نقوم بفحص حالة الهاتف إذا كان مسجلاً من قبل لتوجيهه await isPhoneVerified(); isloading = false; update(); return false; } else { var jsonResponse = jsonDecode(res); if (jsonResponse['status'] == 'success' && jsonResponse['data'].isNotEmpty) { var d = jsonResponse['data'][0]; // 2. التحقق من تفعيل الهاتف if (d['is_verified'].toString() == '1') { // --- A. حفظ البيانات الأساسية --- box.write(BoxName.emailDriver, d['email']); box.write(BoxName.firstTimeLoadKey, 'false'); box.write(BoxName.driverID, d['id']); box.write(BoxName.isTest, '1'); box.write(BoxName.gender, d['gender']); box.write(BoxName.phoneVerified, d['is_verified'].toString()); box.write(BoxName.phoneDriver, d['phone']); box.write(BoxName.is_claimed, d['is_claimed']); box.write(BoxName.isInstall, d['isInstall']); box.write(BoxName.nameArabic, d['name_arabic']); box.write(BoxName.bankCodeDriver, d['bankCode']); box.write(BoxName.accountBankNumberDriver, d['accountBank']); box.write( BoxName.nameDriver, '${d['first_name']} ${d['last_name']}'); // --- B. منطق نوع السيارة --- int categoryId = int.tryParse(d['vehicle_category_id']?.toString() ?? '0') ?? 0; int carYear = int.tryParse(d['year']?.toString() ?? '0') ?? 0; box.write(BoxName.carYear, carYear); String gender = d['gender']?.toString() ?? ''; if (categoryId == 2) { if (gender == 'Male') { box.write(BoxName.carTypeOfDriver, 'Scooter'); } else { box.write(BoxName.carTypeOfDriver, 'Pink Bike'); } } else if (categoryId == 3) { box.write(BoxName.carTypeOfDriver, 'Van'); } else if (carYear > 2017) { if (gender != 'Male') { box.write(BoxName.carTypeOfDriver, 'Lady'); } else { box.write(BoxName.carTypeOfDriver, 'Comfort'); } } else if (carYear > 2002 && carYear <= 2017) { box.write(BoxName.carTypeOfDriver, 'Speed'); } else if (carYear <= 2002 && carYear > 0) { box.write(BoxName.carTypeOfDriver, 'Awfar Car'); } // --- C. كود الدعوة --- if (box.read(BoxName.isInstall) == null || box.read(BoxName.isInstall).toString() == '0') { updateInvitationCodeFromRegister(); } // --- D. التحقق الأمني (Device Fingerprint) --- if (d['status'].toString() != 'yet') { // الـ PHP المعدل يعيد driver_token داخل object السائق List? tokenList = d['driver_token']; String currentFingerPrint = await DeviceHelper.getDeviceFingerprint(); await storage.write( key: BoxName.fingerPrint, value: currentFingerPrint); if (tokenList != null && tokenList.isNotEmpty) { // نأخذ أحدث توكن (أو الأول في القائمة) var tokenData = tokenList[0]; String serverToken = tokenData['token'].toString(); String serverFingerPrint = tokenData['fingerPrint'].toString(); String localToken = box.read(BoxName.tokenDriver)?.toString() ?? ""; // إذا اختلف التوكن أو البصمة => جهاز جديد if (serverToken != localToken || serverFingerPrint != currentFingerPrint) { isloading = false; update(); await Get.defaultDialog( barrierDismissible: false, title: 'Device Change Detected'.tr, middleText: 'Please verify your identity'.tr, textConfirm: 'Verify'.tr, confirmTextColor: Colors.white, onConfirm: () { Get.back(); Get.to(() => OtpVerificationPage( phone: d['phone'].toString(), deviceToken: currentFingerPrint, // تمرير قائمة التوكنات لاستخدامها في التحقق token: jsonEncode( {'status': 'success', 'data': tokenList}), ptoken: serverToken, )); }, ); return true; } } // الدخول للرئيسية Get.offAll(() => HomeCaptain()); } else { // لم يكمل الوثائق Get.offAll(() => DriverVerificationScreen()); } isloading = false; update(); return true; } else { // الحساب موجود لكن غير مفعل Get.offAll(() => PhoneNumberScreen()); isloading = false; update(); return false; } } else { // استجابة غير متوقعة أو data فارغة Get.snackbar("Error".tr, "Login Failed".tr); isloading = false; update(); return false; } } } catch (e) { Log.print("Login Credentials Error: $e"); isloading = false; update(); return false; } } void loginByBoxData() async { Get.to(() => HomeCaptain()); await CRUD().post(link: AppLink.addTokensDriver, payload: { 'token': box.read(BoxName.tokenDriver).toString(), 'captain_id': box.read(BoxName.driverID).toString() }); } }