import 'dart:io'; import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/src/public_ext.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_crashlytics/firebase_crashlytics.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; // import 'package:huawei_hmsavailability/huawei_hmsavailability.dart'; import 'package:mohem_flutter_app/api/login_api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:intl/intl.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/classes/consts.dart'; import 'package:mohem_flutter_app/classes/notifications.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/dialogs/otp_dialog.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/models/basic_member_information_model.dart'; import 'package:mohem_flutter_app/models/check_mobile_app_version_model.dart'; import 'package:mohem_flutter_app/models/generic_response_model.dart'; import 'package:mohem_flutter_app/models/get_mobile_login_info_list_model.dart'; import 'package:mohem_flutter_app/models/member_information_list_model.dart'; import 'package:mohem_flutter_app/models/member_login_list_model.dart'; import 'package:mohem_flutter_app/models/privilege_list_model.dart'; import 'package:mohem_flutter_app/widgets/button/default_button.dart'; import 'package:mohem_flutter_app/widgets/input_widget.dart'; import 'package:safe_device/safe_device.dart'; // import 'package:safe_device/safe_device.dart'; import 'package:wifi_iot/wifi_iot.dart'; class LoginScreen extends StatefulWidget { LoginScreen({Key? key}) : super(key: key); @override _LoginScreenState createState() { return _LoginScreenState(); } } class _LoginScreenState extends State { TextEditingController username = TextEditingController(); TextEditingController password = TextEditingController(); TextEditingController nationalId = TextEditingController(); TextEditingController dobController = TextEditingController(); DateTime? selectedDob; CheckMobileAppVersionModel? _checkMobileAppVersion; MemberLoginListModel? _memberLoginList; late final FirebaseMessaging _firebaseMessaging; bool _autoLogin = false; bool? isAppOpenBySystem; bool isJailBroken = false; bool isRealDevice = true; bool isDevelopmentModeEnable = false; BasicMemberInformationModel? _basicMemberInformation; GenericResponseModel? genericResponseModel; // late HmsApiAvailability hmsApiAvailability; @override void initState() { super.initState(); ApiConsts.selectedMemberType = MemberType.employee; ApiConsts.ISDependetLogin = false; // hmsApiAvailability = HmsApiAvailability(); // checkFirebaseToken(); if (kReleaseMode) { checkDeviceSafety(); } } void checkDeviceSafety() { try { SafeDevice.isJailBroken.then((bool value) { isJailBroken = value; }); SafeDevice.isRealDevice.then((value) { isRealDevice = value; }); if (Platform.isAndroid) { // isOnExternalStorage = await SafeDevice.isOnExternalStorage; // SafeDevice.isDevelopmentModeEnable.then((value) { // isDevelopmentModeEnable = value; // }); } } catch (error) { print(error); } } @override void dispose() { dobController.dispose(); super.dispose(); } String? firebaseToken; GetMobileLoginInfoListModel? loginInfo; Future checkFirebaseToken() async { try { await checkPrefs(); Utils.showLoading(context); if (Platform.isAndroid) { try { if (!(await Utils.isGoogleServicesAvailable())) { print("HUAWEI APPPP GALLERYYYY!!!!"); AppNotifications().init(firebaseToken, context); AppState().setIsHuawei = true; AppNotifications().initHuaweiPush(checkLoginInfo); } else { print("GOOGLE PLAY STOREEEE!!!!"); await Firebase.initializeApp(); _firebaseMessaging = FirebaseMessaging.instance; try { firebaseToken = await _firebaseMessaging.getToken(); } catch (ex) { firebaseToken = ""; } AppNotifications().init(firebaseToken, context); if (isJailBroken || !isRealDevice) { Utils.hideLoading(context); Navigator.pushNamedAndRemoveUntil(context, AppRoutes.unsafeDeviceScreen, (_) => false); } else { checkLoginInfo(); } await FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true); } // }); } catch (ex) {} } else { await Firebase.initializeApp(); _firebaseMessaging = FirebaseMessaging.instance; firebaseToken = await _firebaseMessaging.getToken(); String? firebaseAPNSToken = await _firebaseMessaging.getAPNSToken(); print("Firebase Token: $firebaseToken"); print("Firebase APNS Token: $firebaseAPNSToken"); AppNotifications().init(firebaseToken, context); checkLoginInfo(); await FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true); } } catch (ex) { Utils.hideLoading(context); Utils.handleException(ex, context, null); await FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true); } } void checkLoginInfo() async { try { loginInfo = await LoginApiClient().getMobileLoginInfoNEW( AppState().getIsHuawei ? AppState().getHuaweiPushToken : firebaseToken ?? "", Platform.isAndroid ? "android" : "ios", memberType: ApiConsts.selectedMemberType.value, ); if (ApiConsts.selectedMemberType.isDependent) { Utils.hideLoading(context); return; } if (loginInfo == null) { await checkPrefs(); _autoLogin = false; Utils.hideLoading(context); return; } else { loginInfo!.deviceToken = firebaseToken; await checkPrefs(); Utils.hideLoading(context); performLogin(); } } catch (ex) { Utils.hideLoading(context); } } Future checkPrefs() async { String username = await Utils.getStringFromPrefs(SharedPrefsConsts.username); if (username.isNotEmpty) { String password = await Utils.getStringFromPrefs(SharedPrefsConsts.password); // String firebaseToken = await Utils.getStringFromPrefs(SharedPrefsConsts.firebaseToken); // print("firebaseToken:$firebaseToken"); this.username.text = username; this.password.text = password; _autoLogin = true; } } void performLogin() async { Utils.showLoading(context); try { _checkMobileAppVersion = await LoginApiClient().checkMobileAppVersion(); _memberLoginList = await LoginApiClient().memberLogin(username.text, password.text); AppState().setMemberLoginListModel = _memberLoginList; AppState().setUserName = username.text; AppState().password = password.text; if (_autoLogin) { AppState().setMemberInformationListModel = (await MemberInformationListModel.getFromPrefs()).first; AppState().setPrivilegeListModel = await PrivilegeListModel.getFromPrefs(); String mohemmWifiSSID = await Utils.getStringFromPrefs(SharedPrefsConsts.mohemmWifiSSID); String mohemmWifiPassword = await Utils.getStringFromPrefs(SharedPrefsConsts.mohemmWifiPassword); AppState().setMohemmWifiSSID = mohemmWifiSSID; AppState().setMohemmWifiPassword = mohemmWifiPassword; } Utils.hideLoading(context); if (_autoLogin) { Navigator.pushReplacementNamed(context, AppRoutes.verifyLastLogin, arguments: loginInfo); } else { Navigator.pushNamed(context, AppRoutes.verifyLogin, arguments: "$firebaseToken"); } Utils.saveStringFromPrefs(SharedPrefsConsts.password, password.text); } catch (ex) { print(ex); print(ex.toString()); Utils.hideLoading(context); Utils.handleException(ex, context, (msg) { Utils.confirmDialog( context, msg, onTap: () async { if (msg.toLowerCase().contains("password has expired")) { Navigator.pop(context); // await Navigator.pushNamed(context, AppRoutes.newPassword, arguments: username.text); performForgotPassword(); } else { Navigator.pop(context); } }, ); }); } } void performForgotPassword() async { // if (username.text.isEmpty) { // return; // } Utils.showLoading(context); try { _basicMemberInformation = await LoginApiClient().getBasicUserInformation("CS", username.text); genericResponseModel = await LoginApiClient().sendPublicActivationCode(_basicMemberInformation?.pMOBILENUMBER, username.text); Utils.hideLoading(context); OtpDialog( context, 1, int.tryParse(_basicMemberInformation?.pMOBILENUMBER ?? ""), (value, TextEditingController _pinPutController) async { Utils.showLoading(context); try { GenericResponseModel? genericResponseModel = await LoginApiClient().checkPublicActivationCode(value, username.text); if (genericResponseModel?.errorMessage != null) { Utils.showToast(genericResponseModel?.errorMessage ?? ""); return; } Utils.hideLoading(context); await Navigator.pushNamed(context, AppRoutes.newPassword, arguments: username.text); Navigator.pop(context); // Navigator.pop(context); } catch (ex) { print(ex); _pinPutController.clear(); otpFieldClear.value = ""; Utils.hideLoading(context); Utils.handleException(ex, context, null); } }, () => { Navigator.pop(context), }, onResendCode: () { performForgotPassword(); }, ).displayDialog(context); } catch (ex) { print(ex); Utils.hideLoading(context); Utils.handleException(ex, context, null); } } void _onTabChanged(MemberType type) { if (ApiConsts.selectedMemberType != type) { setState(() { ApiConsts.selectedMemberType = type; }); checkLoginInfo(); } } Widget _buildTabSwitcher() { bool isEmployee = ApiConsts.selectedMemberType == MemberType.employee; bool isAr = AppState().isArabic(context); return Container( height: 46, decoration: BoxDecoration( color: const Color(0xffF2F4F7), borderRadius: BorderRadius.circular(12), ), padding: const EdgeInsets.all(4), child: Row( children: [ Expanded( child: Container( decoration: BoxDecoration( color: isEmployee ? Colors.white : Colors.transparent, borderRadius: BorderRadius.circular(9), boxShadow: isEmployee ? [ BoxShadow( color: Colors.black.withOpacity(0.06), blurRadius: 4, offset: const Offset(0, 2), ) ] : null, ), alignment: Alignment.center, child: (isAr ? "الموظف" : "Employee").toText14( color: isEmployee ? MyColors.textMixColor : MyColors.grey70Color, isBold: isEmployee, ), ).onPress(() { _onTabChanged(MemberType.employee); }), ), Expanded( child: Container( decoration: BoxDecoration( color: !isEmployee ? Colors.white : Colors.transparent, borderRadius: BorderRadius.circular(9), boxShadow: !isEmployee ? [ BoxShadow( color: Colors.black.withOpacity(0.06), blurRadius: 4, offset: const Offset(0, 2), ) ] : null, ), alignment: Alignment.center, child: (isAr ? "التابع" : "Dependent").toText14( color: !isEmployee ? MyColors.textMixColor : MyColors.grey70Color, isBold: !isEmployee, ), ).onPress(() { _onTabChanged(MemberType.dependent); }), ), ], ), ); } Future _selectDateOfBirth(BuildContext context) async { DateTime initialDate = selectedDob ?? DateTime(2000, 1, 1); DateTime firstDate = DateTime(1920, 1, 1); DateTime lastDate = DateTime.now(); DateTime? picked = await showDatePicker( context: context, initialDate: initialDate.isAfter(lastDate) ? lastDate : initialDate, firstDate: firstDate, lastDate: lastDate, builder: (context, child) { return Theme( data: Theme.of(context).copyWith( colorScheme: const ColorScheme.light( primary: MyColors.textMixColor, onPrimary: Colors.white, onSurface: MyColors.darkTextColor, ), ), child: child!, ); }, ); if (picked != null) { setState(() { selectedDob = picked; dobController.text = DateFormat('yyyy-MM-dd', 'en_US').format(picked); }); } } String getFormattedBirthDate() { DateTime? date = selectedDob; if (date == null && dobController.text.trim().isNotEmpty) { String text = dobController.text.trim(); try { if (text.contains('-')) { List parts = text.split('-'); if (parts[0].length == 4) { // yyyy-MM-dd date = DateTime.utc(int.parse(parts[0]), int.parse(parts[1]), int.parse(parts[2])); } else if (parts[2].length == 4) { // dd-MM-yyyy date = DateTime.utc(int.parse(parts[2]), int.parse(parts[1]), int.parse(parts[0])); } } else if (text.contains('/')) { List parts = text.split('/'); if (parts[0].length == 4) { // yyyy/MM/dd date = DateTime.utc(int.parse(parts[0]), int.parse(parts[1]), int.parse(parts[2])); } else if (parts[2].length == 4) { // dd/MM/yyyy date = DateTime.utc(int.parse(parts[2]), int.parse(parts[1]), int.parse(parts[0])); } } else { DateTime parsed = DateTime.parse(text); date = DateTime.utc(parsed.year, parsed.month, parsed.day); } } catch (_) { return ""; } } if (date != null) { int utcMillis = DateTime.utc(date.year, date.month, date.day).millisecondsSinceEpoch; return "/Date($utcMillis)/"; } return ""; } void performDependentLogin() async { if (nationalId.text.trim().isEmpty) { Utils.showToast(AppState().isArabic(context) ? "الرجاء إدخال رقم الهوية الوطنية" : "Please enter National ID"); return; } String birthDateStr = getFormattedBirthDate(); if (birthDateStr.isEmpty) { Utils.showToast(AppState().isArabic(context) ? "الرجاء تحديد تاريخ الميلاد" : "Please select Date of Birth"); return; } Utils.showLoading(context); try { GenericResponseModel? depLoginResponse = await LoginApiClient().memberLoginDependent( nationalId: nationalId.text.trim(), birthDate: birthDateStr, context: context, ); if (depLoginResponse?.errorMessage != null && depLoginResponse!.errorMessage!.isNotEmpty) { Utils.hideLoading(context); Utils.showToast(depLoginResponse.errorMessage!); return; } String? logInTokenID = depLoginResponse?.logInTokenID; String? mobileNumber = depLoginResponse?.getWalaplusDepInfoModel?.pEmpMobileNumber; if (logInTokenID == null || mobileNumber == null || mobileNumber.isEmpty) { Utils.hideLoading(context); Utils.showToast(AppState().isArabic(context) ? "تعذر الحصول على معلومات التابع" : "Unable to retrieve dependent information"); return; } // Step 2: Send OTP GenericResponseModel? sendOtpResponse = await LoginApiClient().mohemmSendOTPDependent( nationalId: nationalId.text.trim(), mobileNumber: mobileNumber, logInTokenID: logInTokenID, context: context, ); Utils.hideLoading(context); if (sendOtpResponse?.messageStatus == 1) { // Step 3: Open OTP Dialog _showDependentOtpDialog(logInTokenID, mobileNumber); } else { Utils.showToast(sendOtpResponse?.errorMessage ?? (AppState().isArabic(context) ? "فشل إرسال رمز التحقق" : "Failed to send OTP")); } } catch (ex) { print(ex); Utils.hideLoading(context); Utils.handleException(ex, context, null); } } void _showDependentOtpDialog(String logInTokenID, String mobileNumber) { OtpDialog( context, 1, int.tryParse(mobileNumber), (value, TextEditingController _pinPutController) async { Utils.showLoading(context); try { GenericResponseModel? checkOtpResponse = await LoginApiClient().mohemmCheckOTPDependent( logInTokenID: logInTokenID, activationCode: value, nationalId: nationalId.text.trim(), mobileNumber: mobileNumber, context: context, ); Utils.hideLoading(context); if (checkOtpResponse?.errorMessage != null && checkOtpResponse!.errorMessage!.isNotEmpty) { Utils.showToast(checkOtpResponse.errorMessage!); _pinPutController.clear(); otpFieldClear.value = ""; return; } Navigator.pop(context); Utils.showToast(AppState().isArabic(context) ? "تم التحقق بنجاح" : "Verified successfully"); if (ApiConsts.ISDependetLogin) { Navigator.pushNamedAndRemoveUntil(context, AppRoutes.dashboardScreenForDependet, (route) => false); } } catch (ex) { print(ex); _pinPutController.clear(); otpFieldClear.value = ""; Utils.hideLoading(context); Utils.handleException(ex, context, null); } }, () { Navigator.pop(context); }, onResendCode: () async { Utils.showLoading(context); try { await LoginApiClient().mohemmSendOTPDependent( nationalId: nationalId.text.trim(), mobileNumber: mobileNumber, logInTokenID: logInTokenID, context: context, ); Utils.hideLoading(context); Utils.showToast(AppState().isArabic(context) ? "تم إعادة إرسال رمز التحقق" : "Verification code resent"); } catch (ex) { Utils.hideLoading(context); Utils.handleException(ex, context, null); } }, ).displayDialog(context); } @override Widget build(BuildContext context) { if (isAppOpenBySystem == null) { isAppOpenBySystem = (ModalRoute.of(context)!.settings.arguments ?? true) as bool; if (!kReleaseMode) { // username.text = "15444"; // Maha User // username.text = "15153"; // Tamer User // password.text = "Abcd@12345"; // username.text = "206535"; // Hashim User // password.text = "Namira786"; // 13777 // Ab12345cd } if (isAppOpenBySystem!) checkFirebaseToken(); } // username.text = "15444"; return Scaffold( body: Column( children: [ const SizedBox(height: 23), Expanded( child: Padding( padding: const EdgeInsets.all(21.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ // Expanded( // child:SizedBox(child: HmgConnectivityButton(),), // ), Row( children: [ LocaleKeys.english.tr().toText14(color: AppState().isArabic(context) ? null : MyColors.textMixColor).onPress(() { context.setLocale(const Locale("en", "US")); }), Container( width: 1, color: MyColors.darkWhiteColor, height: 16, margin: const EdgeInsets.only(left: 10, right: 10), ), LocaleKeys.arabic.tr().toText14(color: !AppState().isArabic(context) ? null : MyColors.textMixColor).onPress(() { context.setLocale(const Locale("ar", "SA")); }), ], ), ], ), Expanded( child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, children: [ _buildTabSwitcher(), 20.height, LocaleKeys.login.tr().toText24(isBold: true), LocaleKeys.pleaseEnterLoginDetails.tr().toText16(), 16.height, if (ApiConsts.selectedMemberType == MemberType.employee) ...[ InputWidget(LocaleKeys.username.tr(), "123456", username), 12.height, InputWidget(LocaleKeys.password.tr(), "xxxxxx", password, isTextIsPassword: true), 9.height, Align( alignment: Alignment.centerRight, child: LocaleKeys.forgotPassword.tr().toText12(isUnderLine: true, color: MyColors.textMixColor).onPress( () { // Navigator.pushNamed(context, AppRoutes.forgotPassword); performForgotPassword(); }, ), ), 20.height, ] else ...[ InputWidget(AppState().isArabic(context) ? "الهوية الوطنية" : "National ID", "1234567890", nationalId, isInputTypeNum: true), 12.height, GestureDetector( behavior: HitTestBehavior.opaque, onTap: () => _selectDateOfBirth(context), child: Stack( alignment: AlignmentDirectional.centerEnd, children: [ IgnorePointer( child: InputWidget( LocaleKeys.dateOfBirth.tr(), "YYYY-MM-DD", dobController, ), ), Positioned.directional( textDirection: Directionality.of(context), end: 16, child: const Icon( Icons.calendar_today_outlined, size: 20, color: MyColors.grey70Color, ), ), ], ), ), 20.height, ], // DefaultButton( // "Connect HMG Network", // () async { // SystemChannels.textInput.invokeMethod('TextInput.hide'); // connectWithHmgNetwork(); // }, // ), ], ), ) ], ), ), ), DefaultButton(LocaleKeys.login.tr(), () async { SystemChannels.textInput.invokeMethod('TextInput.hide'); if (ApiConsts.ISDependetLogin) { performDependentLogin(); } else { performLogin(); } }).insideContainer ], ), ); } void connectWithHmgNetwork() async { try { bool isConnected = await WiFiForIoTPlugin.connect("MOHEMM-CONNECT", password: "0987654321", joinOnce: Platform.isIOS ? false : true, security: NetworkSecurity.WPA, withInternet: false); if (isConnected) { await WiFiForIoTPlugin.forceWifiUsage(true); // if (Platform.isIOS) { // await closeWifiRequest(); // await Future.delayed(Duration(seconds: 6)); // } else { // await WiFiForIoTPlugin.forceWifiUsage(true); // } } } catch (e) { print("----------------o----"); print(e); } } Future closeWifiRequest() async { if (Platform.isAndroid) { await WiFiForIoTPlugin.forceWifiUsage(false); } return await WiFiForIoTPlugin.disconnect(); } }