diff --git a/android/app/build.gradle b/android/app/build.gradle index 4e4b395..596d981 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -23,6 +23,7 @@ if (flutterVersionName == null) { apply plugin: 'com.android.application' apply plugin: 'kotlin-android' +apply plugin: 'com.google.gms.google-services' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { @@ -43,8 +44,8 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.mohem_flutter_app" - minSdkVersion 16 + applicationId "hmg.cloudSolutions.mohem" + minSdkVersion 21 targetSdkVersion 30 versionCode flutterVersionCode.toInteger() versionName flutterVersionName diff --git a/android/app/google-services.json b/android/app/google-services.json new file mode 100644 index 0000000..62fbaea --- /dev/null +++ b/android/app/google-services.json @@ -0,0 +1,40 @@ +{ + "project_info": { + "project_number": "679409052782", + "firebase_url": "https://mohemm-dce93.firebaseio.com", + "project_id": "mohemm-dce93", + "storage_bucket": "mohemm-dce93.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:679409052782:android:dba155ac0859d7fea78a7f", + "android_client_info": { + "package_name": "hmg.cloudSolutions.mohem" + } + }, + "oauth_client": [ + { + "client_id": "679409052782-mtd6d8rjltucnm9uatn6g7et08sm6lbv.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyDgWjuSBIKGghWxYg_KGBRIZTi-O_UA8mU" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "679409052782-mtd6d8rjltucnm9uatn6g7et08sm6lbv.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 472e794..8d53eaf 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,8 +1,9 @@ + _instance; + Future getMobileLoginInfoNEW(String deviceToken, String deviceType) async { + String url = "${ApiConsts.erpRest}Mohemm_GetMobileLoginInfo_NEW"; + Map postParams = {}; + postParams["DeviceToken"] = deviceToken; + postParams["DeviceType"] = deviceType; + return await ApiClient().postJsonForObject((json) { + GenericResponseModel? responseData = GenericResponseModel.fromJson(json); + return (responseData.mohemmGetMobileLoginInfoList?.length ?? 0) > 0 ? responseData.mohemmGetMobileLoginInfoList!.first : null; + }, url, postParams); + } + + Future insertMobileLoginInfoNEW( + String email, int sessionId, String employeeName, int loginType, String mobileNumber, String userName, String deviceToken, String deviceType) async { + String url = "${ApiConsts.erpRest}Mohemm_InsertMobileLoginInfo"; + Map postParams = { + "MobileNumber": mobileNumber, + "P_USER_NAME": userName, + "UserName": userName, + "CompanyID": 1, // todo 'sikander' @discuss umer for companyID + "DeviceToken": deviceToken, + "LoginType": loginType, + "EmployeeName": employeeName, + "P_SESSION_ID": sessionId, + "P_EMAIL_ADDRESS": email + }; + postParams["DeviceToken"] = deviceToken; + postParams["DeviceType"] = deviceType; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject((json) { + GenericResponseModel? responseData = GenericResponseModel.fromJson(json); + return responseData; + }, url, postParams); + } + Future checkMobileAppVersion() async { String url = "${ApiConsts.utilitiesRest}CheckMobileAppVersion"; Map postParams = {}; @@ -84,7 +119,7 @@ class LoginApiClient { postParams.addAll(AppState().postParamsJson); return await ApiClient().postJsonForObject((json) { GenericResponseModel responseData = GenericResponseModel.fromJson(json); - AppState().setForgetPasswordTokenID = responseData.tokenID; + AppState().setForgetPasswordTokenID = responseData.forgetPasswordTokenID; return responseData; }, url, postParams); } diff --git a/lib/app_state/app_state.dart b/lib/app_state/app_state.dart index 65d5184..50aff0a 100644 --- a/lib/app_state/app_state.dart +++ b/lib/app_state/app_state.dart @@ -1,5 +1,8 @@ +import 'package:easy_localization/easy_localization.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/post_params_model.dart'; +import 'package:mohem_flutter_app/models/privilege_list_model.dart'; class AppState { static final AppState _instance = AppState._internal(); @@ -30,15 +33,34 @@ class AppState { this._postParams = _postParams; } + bool isArabic(context) => EasyLocalization.of(context)?.locale.languageCode == "ar"; + String? _username; + // todo ''sikander' added password for now, later will remove & improve + String? password; set setUserName(v) => _username = v; String? get getUserName => _username; + + set setUserPassword(_password) => password = _password; + MemberLoginListModel? _memberLoginList; MemberLoginListModel? get memberLoginList => _memberLoginList; set setMemberLoginListModel(MemberLoginListModel? _memberLoginList) => this._memberLoginList = _memberLoginList; + + MemberInformationListModel? _memberInformationList; + + MemberInformationListModel? get memberInformationList => _memberInformationList; + + set setMemberInformationListModel(MemberInformationListModel? _memberInformationList) => this._memberInformationList = _memberInformationList; + + List? _privilegeListModel; + + List? get privilegeListModel => _privilegeListModel; + + set setPrivilegeListModel(List? _privilegeListModel) => this._privilegeListModel = _privilegeListModel; } diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 4bad83c..a11edec 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -9,14 +9,13 @@ class ApiConsts { static String cocRest = baseUrlServices + "COCWS.svc/REST/"; } - - -class GlobalConsts { +class SharedPrefsConsts { static String isRememberMe = "remember_me"; - static String email = "email"; + static String username = "username"; static String password = "password"; - static String bookmark = "bookmark"; - static String fontZoomSize = "font_zoom_size"; + static String privilegeList = "privilegeList"; + static String firebaseToken = "firebaseToken"; + static String memberInformation = "memberInformation"; static String welcomeVideoUrl = "welcomeVideoUrl"; static String doNotShowWelcomeVideo = "doNotShowWelcomeVideo"; } diff --git a/lib/classes/utils.dart b/lib/classes/utils.dart index d80fdf5..ae8041f 100644 --- a/lib/classes/utils.dart +++ b/lib/classes/utils.dart @@ -3,7 +3,9 @@ import 'package:fluttertoast/fluttertoast.dart'; // import 'package:fluttertoast/fluttertoast.dart'; import 'package:mohem_flutter_app/exceptions/api_exception.dart'; +import 'package:mohem_flutter_app/widgets/dialogs/confirm_dialog.dart'; import 'package:mohem_flutter_app/widgets/loading_dialog.dart'; +import 'package:shared_preferences/shared_preferences.dart'; class Utils { static bool _isLoadingVisible = false; @@ -52,6 +54,16 @@ class Utils { _isLoadingVisible = false; } + static Future getStringFromPrefs(String key) async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + return prefs.getString(key) ?? ""; + } + + static Future saveStringFromPrefs(String key, String value) async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + return await prefs.setString(key, value); + } + static void handleException(dynamic exception, Function(String)? onErrorMessage) { String errorMessage; if (exception is APIException) { @@ -69,4 +81,13 @@ class Utils { showToast(errorMessage); } } + + static void confirmDialog(cxt, String message) { + showDialog( + context: cxt, + builder: (cxt) => ConfirmDialog( + message: message, + ), + ); + } } diff --git a/lib/config/routes.dart b/lib/config/routes.dart index 8e5a64e..3eba985 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -4,6 +4,7 @@ import 'package:mohem_flutter_app/ui/landing/today_attendance_screen.dart'; import 'package:mohem_flutter_app/ui/login/forgot_password_screen.dart'; import 'package:mohem_flutter_app/ui/login/login_screen.dart'; import 'package:mohem_flutter_app/ui/login/new_password_screen.dart'; +import 'package:mohem_flutter_app/ui/login/verify_last_login_screen.dart'; import 'package:mohem_flutter_app/ui/login/verify_login_screen.dart'; import 'package:mohem_flutter_app/ui/work_list/missing_swipe/missing_swipe_screen.dart'; import 'package:mohem_flutter_app/ui/work_list/work_list_screen.dart'; @@ -14,6 +15,7 @@ class AppRoutes { static const String loginVerifyAccount = "/loginVerifyAccount"; static const String login = "/login"; static const String verifyLogin = "/verifyLogin"; + static const String verifyLastLogin = "/verifyLastLogin"; static const String forgotPassword = "/forgotPassword"; static const String newPassword = "/newPassword"; static const String loginVerification = "/loginVerification"; @@ -28,6 +30,7 @@ class AppRoutes { static final Map routes = { login: (context) => LoginScreen(), verifyLogin: (context) => VerifyLoginScreen(), + verifyLastLogin: (context) => VerifyLastLoginScreen(), dashboard: (context) => DashboardScreen(), newPassword: (context) => NewPasswordScreen(), forgotPassword: (context) => ForgotPasswordScreen(), diff --git a/lib/generated/codegen_loader.g.dart b/lib/generated/codegen_loader.g.dart index b43f3bd..3d67def 100644 --- a/lib/generated/codegen_loader.g.dart +++ b/lib/generated/codegen_loader.g.dart @@ -64,7 +64,18 @@ class CodegenLoader extends AssetLoader{ "employeeId": "هوية الموظف", "loginCodeWillSentToMobileNumber": "الرجاء إدخال معرف الموظف الخاص بك ، وسيتم إرسال رمز تسجيل الدخول إلى رقم هاتفك المحمول", "changePassword": "تغيير كلمة المرور", + "ok": "موافق", + "confirm": "تؤكد", + "passwordChangedSuccessfully": "تم تغيير الرقم السري بنجاح", "itemsForSale": "سلع للبيع", + "doNotUseRecentPassword": "لا تستخدم كلمة مرور حديثة", + "atLeastOneLowercase": "حرف صغير واحد على الأقل", + "atLeastOneUppercase": "حرف كبير واحد على الأقل", + "atLeastOneNumeric": "رقم واحد على الأقل", + "minimum8Characters": "8 أحرف على الأقل", + "doNotAddRepeatingLetters": "لا تقم بإضافة أحرف متكررة", + "itShouldContainSpecialCharacter": "يجب أن يحتوي على طابع خاص", + "confirmPasswordMustMatch": "يجب أن يتطابق تأكيد كلمة المرور", "msg": "Hello {} in the {} world ", "msg_named": "{} are written in the {lang} language", "clickMe": "Click me", @@ -153,7 +164,18 @@ static const Map en_US = { "employeeId": "Employee ID", "loginCodeWillSentToMobileNumber": "Please Enter your Employee ID, A login code will be sent to your mobile number", "changePassword": "Change Password", + "ok": "OK", + "confirm": "Confirm", + "passwordChangedSuccessfully": "Password changed successfully", "itemsForSale": "Items for Sale", + "doNotUseRecentPassword": "Do not use recent password", + "atLeastOneLowercase": "At least one lowercase", + "atLeastOneUppercase": "At least one uppercase", + "atLeastOneNumeric": "At least one numeric", + "minimum8Characters": "Minimum 8 characters", + "doNotAddRepeatingLetters": "Do not add repeating letters", + "itShouldContainSpecialCharacter": "It should contain special character", + "confirmPasswordMustMatch": "Confirm password must match", "msg": "Hello {} in the {} world ", "msg_named": "{} are written in the {lang} language", "clickMe": "Click me", diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index 24d7171..b5ecc57 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -49,7 +49,18 @@ abstract class LocaleKeys { static const employeeId = 'employeeId'; static const loginCodeWillSentToMobileNumber = 'loginCodeWillSentToMobileNumber'; static const changePassword = 'changePassword'; + static const ok = 'ok'; + static const confirm = 'confirm'; + static const passwordChangedSuccessfully = 'passwordChangedSuccessfully'; static const itemsForSale = 'itemsForSale'; + static const doNotUseRecentPassword = 'doNotUseRecentPassword'; + static const atLeastOneLowercase = 'atLeastOneLowercase'; + static const atLeastOneUppercase = 'atLeastOneUppercase'; + static const atLeastOneNumeric = 'atLeastOneNumeric'; + static const minimum8Characters = 'minimum8Characters'; + static const doNotAddRepeatingLetters = 'doNotAddRepeatingLetters'; + static const itShouldContainSpecialCharacter = 'itShouldContainSpecialCharacter'; + static const confirmPasswordMustMatch = 'confirmPasswordMustMatch'; static const msg = 'msg'; static const msg_named = 'msg_named'; static const clickMe = 'clickMe'; diff --git a/lib/main.dart b/lib/main.dart index 1146ff0..49b0e35 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -10,9 +10,9 @@ import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart'; import 'package:mohem_flutter_app/theme/app_theme.dart'; import 'package:provider/provider.dart'; import 'package:sizer/sizer.dart'; -import 'package:logger/logger.dart'; - +import 'package:firebase_core/firebase_core.dart'; import 'config/routes.dart'; +import 'package:logger/logger.dart'; var logger = Logger( @@ -25,6 +25,7 @@ var logger = Logger( Future main() async { WidgetsFlutterBinding.ensureInitialized(); await EasyLocalization.ensureInitialized(); + await Firebase.initializeApp(); runApp( EasyLocalization( supportedLocales: const [ diff --git a/lib/models/generic_response_model.dart b/lib/models/generic_response_model.dart index 8ac68bb..a9781d1 100644 --- a/lib/models/generic_response_model.dart +++ b/lib/models/generic_response_model.dart @@ -1,6 +1,7 @@ import 'package:mohem_flutter_app/models/member_login_list_model.dart'; import 'basic_member_information_model.dart'; +import 'get_mobile_login_info_list_model.dart'; import 'dashboard/get_accrual_balances_list_model.dart'; import 'dashboard/get_attendance_tracking_list_model.dart'; import 'dashboard/get_open_missing_swipes_list_model.dart'; @@ -180,7 +181,7 @@ class GenericResponseModel { String? mohemmGetBusinessCardEnabledList; List? mohemmGetFavoriteReplacementsList; String? mohemmGetMobileDeviceInfobyEmpInfoList; - String? mohemmGetMobileLoginInfoList; + List? mohemmGetMobileLoginInfoList; String? mohemmGetPatientIDList; String? mohemmITGResponseItem; bool? mohemmIsChangeIsActiveBusinessCardEnable; @@ -691,7 +692,12 @@ class GenericResponseModel { mohemmGetBusinessCardEnabledList = json['Mohemm_GetBusinessCardEnabledList']; mohemmGetFavoriteReplacementsList = json['Mohemm_GetFavoriteReplacementsList']; mohemmGetMobileDeviceInfobyEmpInfoList = json['Mohemm_GetMobileDeviceInfobyEmpInfoList']; - mohemmGetMobileLoginInfoList = json['Mohemm_GetMobileLoginInfoList']; + if (json['Mohemm_GetMobileLoginInfoList'] != null) { + mohemmGetMobileLoginInfoList = []; + json['Mohemm_GetMobileLoginInfoList'].forEach((v) { + mohemmGetMobileLoginInfoList!.add(new GetMobileLoginInfoListModel.fromJson(v)); + }); + } mohemmGetPatientIDList = json['Mohemm_GetPatientID_List']; mohemmITGResponseItem = json['Mohemm_ITG_ResponseItem']; mohemmIsChangeIsActiveBusinessCardEnable = json['Mohemm_IsChangeIsActiveBusinessCardEnable']; @@ -957,7 +963,9 @@ class GenericResponseModel { data['Mohemm_GetBusinessCardEnabledList'] = this.mohemmGetBusinessCardEnabledList; data['Mohemm_GetFavoriteReplacementsList'] = this.mohemmGetFavoriteReplacementsList; data['Mohemm_GetMobileDeviceInfobyEmpInfoList'] = this.mohemmGetMobileDeviceInfobyEmpInfoList; - data['Mohemm_GetMobileLoginInfoList'] = this.mohemmGetMobileLoginInfoList; + if (this.mohemmGetMobileLoginInfoList != null) { + data['Mohemm_GetMobileLoginInfoList'] = this.mohemmGetMobileLoginInfoList!.map((v) => v.toJson()).toList(); + } data['Mohemm_GetPatientID_List'] = this.mohemmGetPatientIDList; data['Mohemm_ITG_ResponseItem'] = this.mohemmITGResponseItem; data['Mohemm_IsChangeIsActiveBusinessCardEnable'] = this.mohemmIsChangeIsActiveBusinessCardEnable; diff --git a/lib/models/get_mobile_login_info_list_model.dart b/lib/models/get_mobile_login_info_list_model.dart new file mode 100644 index 0000000..ff419f2 --- /dev/null +++ b/lib/models/get_mobile_login_info_list_model.dart @@ -0,0 +1,64 @@ +class GetMobileLoginInfoListModel { + int? iD; + int? employeeID; + int? channelID; + int? companyID; + String? deviceType; + String? deviceToken; + int? language; + int? gender; + int? loginType; + String? createdOn; + String? editedOn; + String? employeeName; + bool? businessCardPrivilege; + + GetMobileLoginInfoListModel( + {this.iD, + this.employeeID, + this.channelID, + this.companyID, + this.deviceType, + this.deviceToken, + this.language, + this.gender, + this.loginType, + this.createdOn, + this.editedOn, + this.employeeName, + this.businessCardPrivilege}); + + GetMobileLoginInfoListModel.fromJson(Map json) { + iD = json['ID']; + employeeID = json['EmployeeID']; + channelID = json['ChannelID']; + companyID = json['CompanyID']; + deviceType = json['DeviceType']; + deviceToken = json['DeviceToken']; + language = json['Language']; + gender = json['Gender']; + loginType = json['LoginType']; + createdOn = json['CreatedOn']; + editedOn = json['EditedOn']; + employeeName = json['EmployeeName']; + businessCardPrivilege = json['BusinessCardPrivilege']; + } + + Map toJson() { + final Map data = Map(); + data['ID'] = iD; + data['EmployeeID'] = employeeID; + data['ChannelID'] = channelID; + data['CompanyID'] = companyID; + data['DeviceType'] = deviceType; + data['DeviceToken'] = deviceToken; + data['Language'] = language; + data['Gender'] = gender; + data['LoginType'] = loginType; + data['CreatedOn'] = createdOn; + data['EditedOn'] = editedOn; + data['EmployeeName'] = employeeName; + data['BusinessCardPrivilege'] = businessCardPrivilege; + return data; + } +} diff --git a/lib/models/member_information_list_model.dart b/lib/models/member_information_list_model.dart index a3bc05f..da95ed0 100644 --- a/lib/models/member_information_list_model.dart +++ b/lib/models/member_information_list_model.dart @@ -1,3 +1,8 @@ +import 'dart:convert'; + +import 'package:mohem_flutter_app/classes/consts.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + class MemberInformationListModel { String? aCTUALTERMINATIONDATE; String? aSSIGNMENTENDDATE; @@ -333,4 +338,16 @@ class MemberInformationListModel { data['USER_STATUS'] = this.uSERSTATUS; return data; } + + static Future> getFromPrefs() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + List encodedList = prefs.getStringList(SharedPrefsConsts.memberInformation) ?? []; + return encodedList.map((e) => MemberInformationListModel.fromJson(jsonDecode(e))).toList(); + } + + static void saveToPrefs(List list) async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + List encodedList = list.map((e) => jsonEncode(e.toJson())).toList(); + await prefs.setStringList(SharedPrefsConsts.memberInformation, encodedList); + } } \ No newline at end of file diff --git a/lib/models/privilege_list_model.dart b/lib/models/privilege_list_model.dart index 3ef3954..ad83500 100644 --- a/lib/models/privilege_list_model.dart +++ b/lib/models/privilege_list_model.dart @@ -1,3 +1,8 @@ +import 'dart:convert'; + +import 'package:mohem_flutter_app/classes/consts.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + class PrivilegeListModel { int? iD; String? serviceName; @@ -18,4 +23,16 @@ class PrivilegeListModel { data['Previlege'] = this.previlege; return data; } + + static Future> getFromPrefs() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + List encodedList = prefs.getStringList(SharedPrefsConsts.privilegeList) ?? []; + return encodedList.map((e) => PrivilegeListModel.fromJson(jsonDecode(e))).toList(); + } + + static void saveToPrefs(List list) async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + List encodedList = list.map((e) => jsonEncode(e.toJson())).toList(); + await prefs.setStringList(SharedPrefsConsts.privilegeList, encodedList); + } } diff --git a/lib/ui/login/forgot_password_screen.dart b/lib/ui/login/forgot_password_screen.dart index 89bd66e..17b105f 100644 --- a/lib/ui/login/forgot_password_screen.dart +++ b/lib/ui/login/forgot_password_screen.dart @@ -37,24 +37,30 @@ class _ForgotPasswordScreenState extends State { super.dispose(); } - void performLogin() async { - // Utils.showLoading(context); + void performForgotPassword() async { + if (employeeId.text.isEmpty) { + return; + } + Utils.showLoading(context); try { _basicMemberInformation = await LoginApiClient().getBasicUserInformation("CS", employeeId.text); genericResponseModel = await LoginApiClient().sendPublicActivationCode(_basicMemberInformation?.pMOBILENUMBER, employeeId.text); + Utils.hideLoading(context); OtpDialog( context, 1, int.tryParse(_basicMemberInformation?.pMOBILENUMBER ?? ""), (value) async { + Utils.showLoading(context); GenericResponseModel? genericResponseModel = await LoginApiClient().checkPublicActivationCode(value, employeeId.text); if (genericResponseModel?.errorMessage != null) { Utils.showToast(genericResponseModel?.errorMessage ?? ""); return; } - - Navigator.pushNamed(context, AppRoutes.newPassword); - // this.checkActivationCode(value: value); + Utils.hideLoading(context); + await Navigator.pushNamed(context, AppRoutes.newPassword, arguments: employeeId.text); + Navigator.pop(context); + Navigator.pop(context); }, () => { Navigator.pop(context), @@ -62,8 +68,8 @@ class _ForgotPasswordScreenState extends State { ).displayDialog(context); } catch (ex) { print(ex); + Utils.hideLoading(context); Utils.handleException(ex, null); - // Utils.hideLoading(context); } } @@ -95,7 +101,14 @@ class _ForgotPasswordScreenState extends State { LocaleKeys.forgotPassword.tr().toText24(isBold: true), LocaleKeys.loginCodeWillSentToMobileNumber.tr().toText16(), 16.height, - InputWidget(LocaleKeys.employeeId.tr(), "123456", employeeId), + InputWidget( + LocaleKeys.employeeId.tr(), + "123456", + employeeId, + onChange: (value) { + setState(() {}); + }, + ), ], ), ) @@ -103,9 +116,13 @@ class _ForgotPasswordScreenState extends State { ), ), ), - DefaultButton(LocaleKeys.changePassword.tr(), () async { - //Navigator.pushNamed(context, AppRoutes.verifyLogin); - }) + DefaultButton( + LocaleKeys.changePassword.tr(), + employeeId.text.isEmpty + ? null + : () async { + performForgotPassword(); + }) .insideContainer ], ), diff --git a/lib/ui/login/login_screen.dart b/lib/ui/login/login_screen.dart index fe7f118..533e9ee 100644 --- a/lib/ui/login/login_screen.dart +++ b/lib/ui/login/login_screen.dart @@ -1,11 +1,15 @@ +import 'dart:io'; + import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/src/public_ext.dart'; +import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:mohem_flutter_app/api/login_api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/classes/consts.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; @@ -13,7 +17,10 @@ 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/check_mobile_app_version_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'; @@ -33,9 +40,15 @@ class _LoginScreenState extends State { CheckMobileAppVersionModel? _checkMobileAppVersion; MemberLoginListModel? _memberLoginList; + final FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance; + + bool _autoLogin = false; + @override void initState() { super.initState(); + checkFirebaseToken(); + //checkPrefs(); } @override @@ -43,6 +56,48 @@ class _LoginScreenState extends State { super.dispose(); } + 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; + } + } + + String? firebaseToken; + + Future checkFirebaseToken() async { + try { + Utils.showLoading(context); + firebaseToken = await _firebaseMessaging.getToken(); + GetMobileLoginInfoListModel? loginInfo = await LoginApiClient().getMobileLoginInfoNEW(firebaseToken ?? "", Platform.isAndroid ? "android" : "ios"); + if (loginInfo == null) { + Utils.hideLoading(context); + print("Device token not found"); + return; + } else { + await checkPrefs(); + Utils.hideLoading(context); + performLogin(); + } + } catch (ex) { + print(ex); + Utils.hideLoading(context); + Utils.handleException(ex, null); + } + } + + // Future getFirebaseToken() async { + // String? firebaseToken = await _firebaseMessaging.getToken(); + // if (firebaseToken != null) { + // await Utils.saveStringFromPrefs(SharedPrefsConsts.firebaseToken, firebaseToken); + // } + // } + void performLogin() async { Utils.showLoading(context); try { @@ -50,20 +105,30 @@ class _LoginScreenState extends State { _memberLoginList = await LoginApiClient().memberLogin(username.text, password.text); AppState().setMemberLoginListModel = _memberLoginList; AppState().setUserName = username.text; - print(_memberLoginList?.toJson()); + AppState().password = password.text; + if (_autoLogin) { + AppState().setMemberInformationListModel = (await MemberInformationListModel.getFromPrefs()).first; + AppState().setPrivilegeListModel = await PrivilegeListModel.getFromPrefs(); + } Utils.hideLoading(context); - Navigator.pushNamed(context, AppRoutes.verifyLogin); + if (_autoLogin) { + Navigator.pushNamed(context, AppRoutes.verifyLastLogin); + } else { + Navigator.pushNamed(context, AppRoutes.verifyLogin, arguments: "$firebaseToken"); + } } catch (ex) { print(ex); - Utils.handleException(ex, null); Utils.hideLoading(context); + Utils.handleException(ex, (msg) { + Utils.confirmDialog(context, msg); + }); } } @override Widget build(BuildContext context) { username.text="15153"; - password.text="s12s12s12"; + password.text="Riyadh@1234"; return Scaffold( body: Column( children: [ @@ -79,7 +144,7 @@ class _LoginScreenState extends State { Expanded(child: SizedBox()), Row( children: [ - LocaleKeys.english.tr().toText14(color: MyColors.textMixColor).onPress(() { + LocaleKeys.english.tr().toText14(color: AppState().isArabic(context) ? null : MyColors.textMixColor).onPress(() { context.setLocale(const Locale("en", "US")); }), Container( @@ -88,7 +153,7 @@ class _LoginScreenState extends State { height: 16, margin: const EdgeInsets.only(left: 10, right: 10), ), - LocaleKeys.arabic.tr().toText14().onPress(() { + LocaleKeys.arabic.tr().toText14(color: !AppState().isArabic(context) ? null : MyColors.textMixColor).onPress(() { context.setLocale(const Locale("ar", "SA")); }), ], diff --git a/lib/ui/login/new_password_screen.dart b/lib/ui/login/new_password_screen.dart index 3fc37f1..e0a8f94 100644 --- a/lib/ui/login/new_password_screen.dart +++ b/lib/ui/login/new_password_screen.dart @@ -1,7 +1,9 @@ import 'package:easy_localization/src/public_ext.dart'; import 'package:flutter/material.dart'; +import 'package:mohem_flutter_app/api/login_api_client.dart'; +import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; -import 'package:mohem_flutter_app/config/routes.dart'; +import 'package:mohem_flutter_app/classes/utils.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'; @@ -22,6 +24,8 @@ class _NewPasswordScreenState extends State { TextEditingController password = TextEditingController(); TextEditingController confirmPassword = TextEditingController(); + String? userName; + @override void initState() { super.initState(); @@ -32,8 +36,26 @@ class _NewPasswordScreenState extends State { super.dispose(); } + void setNewPassword() async { + Utils.showLoading(context); + try { + var genericResponseModel = await LoginApiClient().changePasswordForget(AppState().getForgetPasswordTokenID ?? "", password.text, confirmPassword.text, userName); + Utils.hideLoading(context); + Utils.showToast(LocaleKeys.passwordChangedSuccessfully.tr()); + Navigator.pop(context); + } catch (ex) { + print(ex); + Utils.hideLoading(context); + Utils.handleException(ex, (msg) { + Utils.confirmDialog(context, msg); + }); + } + } + @override Widget build(BuildContext context) { + userName ??= ModalRoute.of(context)!.settings.arguments as String; + return Scaffold( appBar: AppBar( backgroundColor: Colors.transparent, @@ -46,53 +68,125 @@ class _NewPasswordScreenState extends State { 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()), - // Row( - // children: [ - // LocaleKeys.english.tr().toText14(color: MyColors.textMixColor).onPress(() {}), - // Container( - // width: 1, - // color: MyColors.darkWhiteColor, - // height: 16, - // margin: const EdgeInsets.only(left: 10, right: 10), - // ), - // LocaleKeys.arabic.tr().toText14().onPress(() {}), - // ], - // ), - // ], - // ), - Expanded( - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - LocaleKeys.setTheNewPassword.tr().toText24(isBold: true), - LocaleKeys.typeYourNewPasswordBelow.tr().toText16(), - 16.height, - InputWidget(LocaleKeys.password.tr(), "**********", password), - 12.height, - InputWidget(LocaleKeys.confirmPassword.tr(), "**********", confirmPassword, isObscureText: true) - ], - ), - ) - ], - ), - ), + child: ListView( + // mainAxisSize: MainAxisSize.min, + // crossAxisAlignment: CrossAxisAlignment.start, + // mainAxisAlignment: MainAxisAlignment.center, + children: [ + LocaleKeys.setTheNewPassword.tr().toText24(isBold: true), + LocaleKeys.typeYourNewPasswordBelow.tr().toText16(), + 16.height, + InputWidget( + LocaleKeys.password.tr(), + "**********", + password, + onChange: (value) { + setState(() {}); + }, + ), + 12.height, + InputWidget( + LocaleKeys.confirmPassword.tr(), + "**********", + confirmPassword, + isObscureText: true, + onChange: (value) { + setState(() {}); + }, + ), + 12.height, + passwordConstraintsUI(LocaleKeys.doNotUseRecentPassword.tr(), true), + 8.height, + passwordConstraintsUI(LocaleKeys.atLeastOneLowercase.tr(), checkRegEx(r'[a-z]')), + 8.height, + passwordConstraintsUI(LocaleKeys.atLeastOneUppercase.tr(), checkRegEx(r'[A-Z]')), + 8.height, + passwordConstraintsUI(LocaleKeys.atLeastOneNumeric.tr(), checkRegEx(r'[0-9]')), + 8.height, + passwordConstraintsUI(LocaleKeys.minimum8Characters.tr(), password.text.length >= 8), + 8.height, + passwordConstraintsUI(LocaleKeys.doNotAddRepeatingLetters.tr(), checkRepeatedChars(password.text)), + 8.height, + passwordConstraintsUI(LocaleKeys.itShouldContainSpecialCharacter.tr(), checkRegEx(r'[!@#$%^&*(),.?":{}|<>]')), + 8.height, + passwordConstraintsUI(LocaleKeys.confirmPasswordMustMatch.tr(), password.text.isNotEmpty && password.text == confirmPassword.text), + 12.height, + ], + ).paddingAll(21), ), - DefaultButton(LocaleKeys.update.tr(), () async { - - // Navigator.pushNamed(context, AppRoutes.verifyLogin); - }).insideContainer + DefaultButton( + LocaleKeys.update.tr(), + (!isPasswordCompliant(password.text, 8)) + ? null + : () async { + setNewPassword(); + }) + .insideContainer ], ), ); } + + bool checkRegEx(String pattern) { + return RegExp(pattern).hasMatch(password.text); + } + + String recentPassword = ""; + + bool checkRepeatedCharacters(String value) { + if (value.isEmpty) { + return false; + } + for (int i = 0; i < value.length; i++) { + //if(i) + } + + return true; + } + + bool isPasswordCompliant(String? password, int minLength) { + if (password == null || password.isEmpty) { + return false; + } + + bool hasUppercase = password.contains(RegExp(r'[A-Z]')); + bool hasDigits = password.contains(RegExp(r'[0-9]')); + bool hasLowercase = password.contains(RegExp(r'[a-z]')); + bool hasSpecialCharacters = password.contains(RegExp(r'[!@#$%^&*(),.?":{}|<>]')); + bool hasMinLength = password.length >= minLength; + bool isMatched = password == confirmPassword.text; + + return hasDigits && hasUppercase && hasLowercase && hasSpecialCharacters && hasMinLength && isMatched && checkRepeatedChars(password); + } + + bool checkRepeatedChars(String password) { + bool isNonRepeatedLetters = true; + if (password.length > 2) { + for (int i = 0; i < password.length; i++) { + String char = password[i]; + try { + if (char == password[i + 1]) { + isNonRepeatedLetters = false; + break; + } + } catch (ex) {} + } + } + return isNonRepeatedLetters; + } + + Widget passwordConstraintsUI(String description, bool check) { + return Row( + children: [ + 4.width, + SizedBox( + width: 12, + height: 12, + child: Checkbox(fillColor: MaterialStateProperty.all(MyColors.gradiantEndColor), shape: const CircleBorder(), value: check, onChanged: null), + ), + 8.width, + description.toText14() + ], + ); + } } diff --git a/lib/ui/login/verify_last_login_screen.dart b/lib/ui/login/verify_last_login_screen.dart new file mode 100644 index 0000000..282c7a5 --- /dev/null +++ b/lib/ui/login/verify_last_login_screen.dart @@ -0,0 +1,750 @@ +import 'package:easy_localization/src/public_ext.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:local_auth/auth_strings.dart'; +import 'package:local_auth/local_auth.dart'; +import 'package:mohem_flutter_app/api/login_api_client.dart'; +import 'package:mohem_flutter_app/app_state/app_state.dart'; +import 'package:mohem_flutter_app/classes/colors.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/generic_response_model.dart'; +import 'package:mohem_flutter_app/widgets/button/default_button.dart'; + +class VerifyLastLoginScreen extends StatefulWidget { + VerifyLastLoginScreen({Key? key}) : super(key: key); + + @override + _VerifyLastLoginScreenState createState() { + return _VerifyLastLoginScreenState(); + } +} + +class _VerifyLastLoginScreenState extends State { + final LocalAuthentication auth = LocalAuthentication(); + List _availableBioMetricType = []; + + @override + void initState() { + _getAvailableBiometrics(); + // setDefault(); + super.initState(); + } + + @override + Widget build(BuildContext context) { + String empName = AppState().isArabic(context) ? AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr! : AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn!; + return Scaffold( + appBar: AppBar( + backgroundColor: Colors.transparent, + leading: IconButton( + icon: const Icon(Icons.arrow_back_ios, color: MyColors.darkIconColor), + onPressed: () => Navigator.pop(context), + ), + actions: [Center(child: "Employee Digital ID".toText12(color: MyColors.textMixColor, isUnderLine: true).onPress(() {})), 21.width], + ), + body: Column( + children: [ + Expanded( + child: ListView( + padding: const EdgeInsets.all(21), + physics: const BouncingScrollPhysics(), + children: [ + //12.height, + if (true) + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocaleKeys.welcomeBack.tr().toText12(), + empName.toText24(isBold: true), + 10.height, + LocaleKeys.wouldYouLikeToLoginWithCurrentUsername.tr().toText16(), + Container( + height: 72, + margin: const EdgeInsets.only(top: 23, bottom: 23), + alignment: Alignment.center, + padding: const EdgeInsets.only(left: 17, right: 12), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: Colors.white, + border: Border.all( + color: const Color(0xffefefef), + width: 1, + ), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + LocaleKeys.lastLoginDetails.tr().toText16(), + // Text( + // user.editedOn != null + // ? DateUtil.getDayMonthYearDateFormatted(DateUtil.convertStringToDate(user.editedOn)) + // : user.createdOn != null + // ? DateUtil.getDayMonthYearDateFormatted(DateUtil.convertStringToDate(user.createdOn)) + // : '--', + // style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.48), + // ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + LocaleKeys.verificationType.tr().toText10(color: MyColors.grey57Color), + Text( + "SMS", + // " " + getType(user.logInType, context), + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xff2B353E), + ), + ), + Expanded(child: SizedBox()), + // Text( + // user.editedOn != null + // ? DateUtil.formatDateToTimeLang(DateUtil.convertStringToDate(user.editedOn), false) + // : user.createdOn != null + // ? DateUtil.formatDateToTimeLang(DateUtil.convertStringToDate(user.createdOn), false) + // : '--', + // style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xff575757), letterSpacing: -0.48), + // ), + ], + ) + ], + ), + ), + LocaleKeys.pleaseVerify.tr().toText16(), + GridView( + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, crossAxisSpacing: 13, mainAxisSpacing: 9), + physics: const NeverScrollableScrollPhysics(), + padding: const EdgeInsets.only(top: 9), + shrinkWrap: true, + children: [ + getButton(3), + getButton(2), + getButton(1), + getButton(4), + ], + ) + ], + ) + // else + // Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ + // Image.asset( + // 'assets/images/habib-logo.png', + // height: 90, + // width: 90, + // ), + // SizedBox(height: 23), + // this.onlySMSBox == false + // ? Text( + // TranslationBase.of(context).verifyLoginWith, + // style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.64, height: 25 / 16), + // ) + // : Text( + // TranslationBase.of(context).verifyFingerprint2, + // style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.64, height: 25 / 16), + // ), + // SizedBox(height: 23), + // Text( + // TranslationBase.of(context).pleaseVerify, + // style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xff2E303A), letterSpacing: -0.64), + // ), + // GridView( + // gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, crossAxisSpacing: 13, mainAxisSpacing: 9), + // physics: NeverScrollableScrollPhysics(), + // padding: EdgeInsets.only(top: 9), + // shrinkWrap: true, + // children: [ + // if (onlySMSBox == false) getButton(3), + // if (onlySMSBox == false) getButton(2), + // getButton(1), + // getButton(4), + // ], + // ), + // ]), + ], + ), + ), + 12.height, + DefaultButton( + LocaleKeys.useAnotherAccount.tr(), + () => { + //Navigator.of(context).pushNamed(LOGIN_TYPE) + }, + ).insideContainer, + ], + ), + ); + } + + Future _getAvailableBiometrics() async { + try { + _availableBioMetricType = await auth.getAvailableBiometrics(); + } on PlatformException catch (e) { + // AppToast.showErrorToast(message: e.message); + print(e); + } + if (mounted) setState(() {}); + } + + // authenticateUser(int type, {int isActive}) { + // GifLoaderDialogUtils.showMyDialog(context); + // if (type == 2 || type == 3) { + // fingrePrintBefore = type; + // } + // this.selectedOption = fingrePrintBefore != null ? fingrePrintBefore : type; + // + // switch (type) { + // case 1: + // this.loginWithSMS(type); + // break; + // case 2: + // this.loginWithFingurePrintFace(type, isActive); + // break; + // case 3: + // this.loginWithFingurePrintFace(type, isActive); + // break; + // case 4: + // this.loginWithSMS(type); + // break; + // default: + // break; + // } + // sharedPref.setInt(LAST_LOGIN, this.selectedOption); //this.cs.sharedService.setStorage(this.selectedOption, AuthenticationService.LAST_LOGIN); + // } +// +// loginWithSMS(type) { +// //if (!el.disabled) { +// if (this.user != null && this.registerd_data == null) { +// this.checkUserAuthentication(type); +// } else { +// if (this.loginTokenID != null) { +// // Future.delayed(Duration(seconds: 1), () { +// this.sendActivationCode(type); +// // }); +// } else { +// this.checkUserAuthentication(type); +// } +// } +// } +// +// checkUserAuthentication(type) { +// showLoader(true); +// var req = getCommonRequest(type: type); +// req.logInTokenID = ""; +// +// var request = CheckPatientAuthenticationReq.fromJson(req.toJson()); +// +// sharedPref.setObject(REGISTER_DATA_FOR_REGISTER, request); +// authService +// .checkPatientAuthentication(request) +// .then((value) => { +// GifLoaderDialogUtils.hideDialog(context), +// if (value['isSMSSent']) +// { +// sharedPref.setString(LOGIN_TOKEN_ID, value['LogInTokenID']), +// this.loginTokenID = value['LogInTokenID'], +// sharedPref.setObject(REGISTER_DATA_FOR_LOGIIN, request), +// // Future.delayed(Duration(seconds: 1), () { +// this.sendActivationCode(type) +// // }) +// } +// else +// { +// if (value['IsAuthenticated']) {this.checkActivationCode()} +// } +// }) +// .catchError((err) { +// print(err); +// GifLoaderDialogUtils.hideDialog(context); +// }); +// } +// +// sendActivationCode(type) async { +// var request = this.getCommonRequest(type: type); +// request.sMSSignature = await SMSOTP.getSignature(); +// GifLoaderDialogUtils.showMyDialog(context); +// if (healthId != null) { +// // final DateFormat dateFormat = DateFormat('MM/dd/yyyy'); +// // final DateFormat dateFormat2 = DateFormat('dd/MM/yyyy'); +// request.dob = dob; //isHijri == 1 ? dob : dateFormat2.format(dateFormat.parse(dob)); +// request.healthId = healthId; +// request.isHijri = isHijri; +// await this.authService.sendActivationCodeRegister(request).then((result) { +// GifLoaderDialogUtils.hideDialog(context); +// if (result != null && result['isSMSSent'] == true) { +// this.startSMSService(type); +// } +// }).catchError((r) { +// GifLoaderDialogUtils.hideDialog(context); +// }); +// } else { +// request.dob = ""; +// request.healthId = ""; +// request.isHijri = 0; +// await this.authService.sendActivationCode(request).then((result) { +// GifLoaderDialogUtils.hideDialog(context); +// if (result != null && result['isSMSSent'] == true) { +// this.startSMSService(type); +// } +// }).catchError((r) { +// GifLoaderDialogUtils.hideDialog(context); +// }); +// } +// } +// +// var tempType; +// +// startSMSService(type) { +// tempType = type; +// new SMSOTP( +// context, +// type, +// this.mobileNumber, +// (value) { +// this.checkActivationCode(value: value); +// }, +// () => { +// Navigator.pop(context), +// }, +// ).displayDialog(context); +// } +// +// loginWithFingurePrintFace(type, int isActive) async { +// if (isActive == 1 || isActive == 0) { +// const iosStrings = +// const IOSAuthMessages(cancelButton: 'cancel', goToSettingsButton: 'settings', goToSettingsDescription: 'Please set up your Touch ID.', lockOut: 'Please reenable your Touch ID'); +// +// try { +// authenticated = await auth.authenticateWithBiometrics(localizedReason: 'Scan your fingerprint to authenticate', useErrorDialogs: true, stickyAuth: true, iOSAuthStrings: iosStrings); +// } on PlatformException catch (e) { +// GifLoaderDialogUtils.hideDialog(context); +// AppToast.showErrorToast(message: 'Please enable your Touch or Face ID'); +// } +// +// if (authenticated == true) { +// // if (user != null && (user.logInType == 2 || user.logInType == 3)) { +// // this.checkActivationCode(); +// // } else { +// +// var request = this.getCommonRequest(type: type); +// this.getMobileInfo(request); +// //} +// } +// } +// } +// +// getMobileInfo(request) { +// // GifLoaderDialogUtils.showMyDialog(context); +// this.authService.getLoginInfo(request).then((result) { +// GifLoaderDialogUtils.hideDialog(context); +// if (result['SMSLoginRequired'] == false) { +// this.loginTokenID = result['LogInTokenID']; +// this.patientOutSA = result['PatientOutSA']; +// // sms for register the biometric +// if (result['isSMSSent']) { +// setState(() { +// isMoreOption = true; +// this.onlySMSBox = true; +// // this.fingrePrintBefore = true; +// }); +// //this.button(); +// } else { +// setDefault(); +// checkActivationCode(); +// } +// } else { +// if (result['IsAuthenticated'] == true) { +// setState(() { +// isMoreOption = true; +// this.onlySMSBox = true; +// // this.fingrePrintBefore = true; +// }); +// } +// } +// }).catchError((err) { +// GifLoaderDialogUtils.hideDialog(context); +// print(err); +// }); +// } +// +// setDefault() async { +// if (await sharedPref.getObject(IMEI_USER_DATA) != null) user = SelectDeviceIMEIRES.fromJson(await sharedPref.getObject(IMEI_USER_DATA)); +// +// if (await sharedPref.getObject(REGISTER_DATA_FOR_LOGIIN) != null) { +// isMoreOption = true; +// this.registerd_data = CheckPatientAuthenticationReq.fromJson(await sharedPref.getObject(REGISTER_DATA_FOR_LOGIIN)); +// } +// +// this.mobileNumber = this.registerd_data != null ? this.registerd_data.patientMobileNumber : int.parse(this.user.mobile); +// this.zipCode = this.registerd_data != null +// ? this.registerd_data.zipCode +// : this.user.outSA == true +// ? "971" +// : "966"; +// this.patientOutSA = this.registerd_data != null +// ? this.registerd_data.zipCode == "966" +// ? 0 +// : 1 +// : this.user.outSA; +// if (this.registerd_data != null) { +// this.loginTokenID = await sharedPref.getString(LOGIN_TOKEN_ID); +// this.loginType = this.registerd_data.searchType; +// } +// var nhic = await sharedPref.getObject(NHIC_DATA); +// if (nhic != null) { +// final DateFormat dateFormat = DateFormat('MM/dd/yyyy'); +// final DateFormat dateFormat2 = DateFormat('dd/MM/yyyy'); +// dob = nhic['IsHijri'] ? nhic['DateOfBirth'] : dateFormat2.format(dateFormat.parse(nhic['DateOfBirth'])); +// +// isHijri = nhic['IsHijri'] ? 1 : 0; +// healthId = nhic['HealthId']; +// } +// this.deviceToken = await sharedPref.getString(PUSH_TOKEN); +// this.lastLogin = await sharedPref.getInt(LAST_LOGIN) != null +// ? await sharedPref.getInt(LAST_LOGIN) +// : user != null +// ? user.logInType +// : null; +// +// //this.cs.sharedService.getStorage(AuthenticationService.LAST_LOGIN); +// } +// +// getCommonRequest({type}) { +// var request = SendActivationRequest(); +// request.patientMobileNumber = this.mobileNumber; +// request.mobileNo = '0' + this.mobileNumber.toString(); +// request.deviceToken = this.deviceToken; +// request.projectOutSA = this.patientOutSA == true ? true : false; +// request.loginType = this.selectedOption; +// request.oTPSendType = type == 1 ? type : 2; //this.selectedOption == 1 ? 1 : 2; +// request.zipCode = this.zipCode; +// +// request.logInTokenID = this.loginTokenID ?? ""; +// +// if (this.registerd_data != null) { +// request.searchType = this.registerd_data.searchType != null ? this.registerd_data.searchType : 1; +// request.patientID = this.registerd_data.patientID != null ? this.registerd_data.patientID : 0; +// request.patientIdentificationID = request.nationalID = this.registerd_data.patientIdentificationID != null ? this.registerd_data.patientIdentificationID : '0'; +// +// request.isRegister = this.registerd_data.isRegister; +// } else { +// request.searchType = request.searchType != null ? request.searchType : 2; +// request.patientID = this.user.patientID != null ? this.user.patientID : 0; +// request.nationalID = request.nationalID != null ? request.nationalID : '0'; +// request.patientIdentificationID = request.patientIdentificationID != null ? request.patientIdentificationID : '0'; +// request.isRegister = false; +// } +// request.deviceTypeID = request.searchType; +// return request; +// } +// +// // checkActivationCode({value}) async { +// // // Navigator.pop(context); +// // GifLoaderDialogUtils.showMyDialog(context); +// // var request = this.getCommonRequest().toJson(); +// // dynamic res; +// // if (healthId != null) { +// // request['DOB'] = dob; +// // request['HealthId'] = healthId; +// // request['IsHijri'] = isHijri; +// // +// // authService +// // .checkActivationCodeRegister(request, value) +// // .then((result) => { +// // res = result, +// // if (result is Map) +// // { +// // result = CheckActivationCode.fromJson(result), +// // if (this.registerd_data != null && this.registerd_data.isRegister == true) +// // { +// // widget.changePageViewIndex(1), +// // Navigator.popUntil(context, (route) => Utils.route(route, equalsTo: RegisterNew)), +// // } +// // } +// // else +// // { +// // // Navigator.of(context).pop(), +// // GifLoaderDialogUtils.hideDialog(context), +// // Future.delayed(Duration(seconds: 1), () { +// // AppToast.showErrorToast(message: result); +// // }), +// // } +// // }) +// // .catchError((err) { +// // print(err); +// // GifLoaderDialogUtils.hideDialog(context); +// // Future.delayed(Duration(seconds: 1), () { +// // AppToast.showErrorToast(message: err); +// // startSMSService(tempType); +// // }); +// // }); +// // } else { +// // authService +// // .checkActivationCode(request, value) +// // .then((result) => { +// // res = result, +// // if (result is Map) +// // { +// // result = CheckActivationCode.fromJson(result), +// // if (this.registerd_data != null && this.registerd_data.isRegister == true) +// // { +// // widget.changePageViewIndex(1), +// // Navigator.popUntil(context, (route) => Utils.route(route, equalsTo: RegisterNew)), +// // } +// // else +// // { +// // sharedPref.remove(FAMILY_FILE), +// // result.list.isFamily = false, +// // userData = result.list, +// // sharedPref.setString(BLOOD_TYPE, result.patientBloodType), +// // authenticatedUserObject.user = result.list, +// // projectViewModel.setPrivilege(privilegeList: res), +// // sharedPref.setObject(MAIN_USER, result.list), +// // sharedPref.setObject(USER_PROFILE, result.list), +// // loginTokenID = result.logInTokenID, +// // sharedPref.setObject(LOGIN_TOKEN_ID, result.logInTokenID), +// // sharedPref.setString(TOKEN, result.authenticationTokenID), +// // checkIfUserAgreedBefore(result), +// // } +// // } +// // else +// // { +// // // // Navigator.of(context).pop(), +// // // GifLoaderDialogUtils.hideDialog(context), +// // // Future.delayed(Duration(seconds: 1), () { +// // // AppToast.showErrorToast(message: result); +// // // startSMSService(tempType); +// // // }), +// // } +// // }) +// // .catchError((err) { +// // // print(err); +// // // GifLoaderDialogUtils.hideDialog(context); +// // // Future.delayed(Duration(seconds: 1), () { +// // // AppToast.showErrorToast(message: err); +// // // startSMSService(tempType); +// // // }); +// // }); +// // } +// // } +// +// // checkIfUserAgreedBefore(CheckActivationCode result) { +// // if (result.isNeedUserAgreement == true) { +// // //move to agreement page. +// // } else { +// // goToHome(); +// // } +// // } +// +// insertIMEI() { +// authService.insertDeviceImei(selectedOption).then((value) => {}).catchError((err) { +// print(err); +// }); +// } +// +// // getToDoCount() { +// // toDoProvider.setState(0, true, "0"); +// // ClinicListService service = new ClinicListService(); +// // service.getActiveAppointmentNo(context).then((res) { +// // if (res['MessageStatus'] == 1) { +// // toDoProvider.setState(res['AppointmentActiveNumber'], true, "0"); +// // } else {} +// // }).catchError((err) { +// // print(err); +// // }); +// // } +// +// // goToHome() async { +// // authenticatedUserObject.isLogin = true; +// // appointmentRateViewModel.isLogin = true; +// // projectViewModel.isLogin = true; +// // projectViewModel.user = authenticatedUserObject.user; +// // await authenticatedUserObject.getUser(getUser: true); +// // +// // // getToDoCount(); +// // +// // appointmentRateViewModel +// // .getIsLastAppointmentRatedList() +// // .then((value) => { +// // getToDoCount(), +// // GifLoaderDialogUtils.hideDialog(AppGlobal.context), +// // if (appointmentRateViewModel.isHaveAppointmentNotRate) +// // { +// // Navigator.pushAndRemoveUntil( +// // context, +// // FadePage( +// // page: RateAppointmentDoctor(), +// // ), +// // (r) => false) +// // } +// // else +// // { +// // Navigator.pushAndRemoveUntil( +// // context, +// // FadePage( +// // page: LandingPage(), +// // ), +// // (r) => false) +// // }, +// // insertIMEI() +// // }) +// // .catchError((err) { +// // print(err); +// // }); +// // } +// +// loading(flag) { +// // setState(() { +// // isLoading = flag; +// // }); +// } +// + + Future loginWithFaceIDAndBiometrics() async { + IOSAuthMessages iosStrings = + const IOSAuthMessages(cancelButton: 'cancel', goToSettingsButton: 'settings', goToSettingsDescription: 'Please set up your Touch ID.', lockOut: 'Please reenable your Touch ID'); + bool authenticated = false; + try { + authenticated = await auth.authenticate(localizedReason: 'Scan your fingerprint to authenticate', useErrorDialogs: true, stickyAuth: true, iOSAuthStrings: iosStrings); + } on PlatformException catch (e) { + print(e); + Utils.hideLoading(context); + Utils.showToast("Please enable your Touch or Face ID"); + } + return authenticated; + } + + Widget _loginOptionButton(String _title, String _icon, int _flag, int? _loginIndex) { + bool isDisable = ((_flag == 3 && !checkBiometricIsAvailable(BiometricType.face)) || (_flag == 2 && !checkBiometricIsAvailable(BiometricType.fingerprint))); + print("$_title:$isDisable"); + return InkWell( + onTap: isDisable + ? null + : () async { + if (_flag == 0) { + setState(() { + // isMoreOption = true; + }); + } else { + Utils.showLoading(context); + if (_flag == 2 || _flag == 3) { + bool authenticateWithFaceAndTouchID = await loginWithFaceIDAndBiometrics(); + if (authenticateWithFaceAndTouchID) { + Navigator.pushNamedAndRemoveUntil(context, AppRoutes.dashboard, (Route route) => false); + return; + } else { + Utils.hideLoading(context); + return; + } + } + await LoginApiClient().checkMobileAppVersion(); + await LoginApiClient().memberLogin(AppState().getUserName!, AppState().password!); + BasicMemberInformationModel? memberInformationModel = await LoginApiClient() + .mohemmSendActivationCodeByOTPNotificationType(checkBiometricIsAvailable(BiometricType.fingerprint) ? 1 : 0, AppState().memberLoginList?.pMOBILENUMBER, _flag, AppState().getUserName); + Utils.hideLoading(context); + OtpDialog( + context, + _flag, + int.tryParse(AppState().memberLoginList?.pMOBILENUMBER ?? ""), + (value) async { + Utils.showLoading(context); + try { + GenericResponseModel? genericResponseModel = await LoginApiClient().checkActivationCode(false, AppState().memberLoginList?.pMOBILENUMBER, value, AppState().getUserName); + if (genericResponseModel?.errorMessage != null) { + Utils.showToast(genericResponseModel?.errorMessage ?? ""); + // Navigator.pop(context); + } + Utils.hideLoading(context); + Navigator.pop(context); + Navigator.pushNamedAndRemoveUntil(context, AppRoutes.dashboard, (Route route) => false); + } catch (ex) { + print(ex); + Utils.hideLoading(context); + Utils.handleException(ex, null); + } + }, + () => { + Navigator.pop(context), + }, + ).displayDialog(context); + + // authenticateUser(_flag, isActive: _loginIndex); + } + }, + child: Container( + padding: const EdgeInsets.only(left: 20, right: 20, bottom: 15, top: 28), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(15), + color: isDisable ? Colors.grey.withOpacity(0.3) : Colors.white, + border: Border.all(color: MyColors.lightGreyEFColor, width: 1), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SvgPicture.asset( + _icon, + height: 38, + width: 38, + color: isDisable ? MyColors.darkTextColor.withOpacity(0.7) : null, + ), + _title.toText16() + ], + ), + ), + ); + } + + Widget getButton(int flag) { + switch (flag) { + case 4: + return _loginOptionButton(LocaleKeys.verifyThroughWhatsapp.tr(), 'assets/images/login/verify_whatsapp.svg', flag, null); + case 1: + return _loginOptionButton(LocaleKeys.verifyThroughSMS.tr(), 'assets/images/login/verify_sms.svg', flag, null); + case 2: + return _loginOptionButton(LocaleKeys.verifyThroughFingerprint.tr(), 'assets/images/login/verify_thumb.svg', flag, BiometricType.fingerprint.index); + case 3: + return _loginOptionButton(LocaleKeys.verifyThroughFace.tr(), 'assets/images/login/verify_face.svg', flag, BiometricType.face.index); + default: + return const SizedBox(); + } + } + + bool checkBiometricIsAvailable(BiometricType biometricType) { + bool isAvailable = false; + for (int i = 0; i < _availableBioMetricType.length; i++) { + if (biometricType == _availableBioMetricType[i]) { + isAvailable = true; + break; + } + } + return isAvailable; + } +// +// formatDate(date) { +// return date; +// return DateFormat('MMM dd, yyy, kk:mm').format(date); +// } +// +// showLoader(bool isTrue) { +// setState(() { +// // isLoading = isTrue; +// }); +// } + +} diff --git a/lib/ui/login/verify_login_screen.dart b/lib/ui/login/verify_login_screen.dart index ba0eb98..8e9255f 100644 --- a/lib/ui/login/verify_login_screen.dart +++ b/lib/ui/login/verify_login_screen.dart @@ -1,20 +1,25 @@ +import 'dart:io'; + import 'package:easy_localization/src/public_ext.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:local_auth/auth_strings.dart'; import 'package:local_auth/local_auth.dart'; import 'package:mohem_flutter_app/api/login_api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/classes/consts.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/generic_response_model.dart'; +import 'package:mohem_flutter_app/models/member_information_list_model.dart'; +import 'package:mohem_flutter_app/models/privilege_list_model.dart'; import 'package:mohem_flutter_app/widgets/button/default_button.dart'; class VerifyLoginScreen extends StatefulWidget { @@ -30,6 +35,8 @@ class _VerifyLoginScreenState extends State { final LocalAuthentication auth = LocalAuthentication(); List _availableBioMetricType = []; + String? firebaseToken; + @override void initState() { _getAvailableBiometrics(); @@ -39,6 +46,7 @@ class _VerifyLoginScreenState extends State { @override Widget build(BuildContext context) { + firebaseToken ??= ModalRoute.of(context)!.settings.arguments as String; return Scaffold( appBar: AppBar( backgroundColor: Colors.transparent, @@ -46,7 +54,7 @@ class _VerifyLoginScreenState extends State { icon: const Icon(Icons.arrow_back_ios, color: MyColors.darkIconColor), onPressed: () => Navigator.pop(context), ), - actions: [Center(child: "Employee Digital ID".toText12(color: MyColors.textMixColor, isUnderLine: true).onPress(() {})), 21.width], + // actions: [Center(child: "Employee Digital ID".toText12(color: MyColors.textMixColor, isUnderLine: true).onPress(() {})), 21.width], ), body: Column( children: [ @@ -61,69 +69,69 @@ class _VerifyLoginScreenState extends State { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - LocaleKeys.welcomeBack.tr().toText12(), - "Mohammad Hussain".toText24(isBold: true), - 10.height, - LocaleKeys.wouldYouLikeToLoginWithCurrentUsername.tr().toText16(), - Container( - height: 72, - margin: const EdgeInsets.only(top: 23, bottom: 23), - alignment: Alignment.center, - padding: EdgeInsets.only(left: 17, right: 12), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), - color: Colors.white, - border: Border.all( - color: Color(0xffefefef), - width: 1, - ), - ), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - LocaleKeys.lastLoginDetails.tr().toText16(), - // Text( - // user.editedOn != null - // ? DateUtil.getDayMonthYearDateFormatted(DateUtil.convertStringToDate(user.editedOn)) - // : user.createdOn != null - // ? DateUtil.getDayMonthYearDateFormatted(DateUtil.convertStringToDate(user.createdOn)) - // : '--', - // style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.48), - // ), - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - LocaleKeys.verificationType.tr().toText10(color: MyColors.grey57Color), - Text( - "SMS", - // " " + getType(user.logInType, context), - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xff2B353E), - ), - ), - Expanded(child: SizedBox()), - // Text( - // user.editedOn != null - // ? DateUtil.formatDateToTimeLang(DateUtil.convertStringToDate(user.editedOn), false) - // : user.createdOn != null - // ? DateUtil.formatDateToTimeLang(DateUtil.convertStringToDate(user.createdOn), false) - // : '--', - // style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xff575757), letterSpacing: -0.48), - // ), - ], - ) - ], - ), - ), + // LocaleKeys.welcomeBack.tr().toText12(), + // "Mohammad Hussain".toText24(isBold: true), + // 10.height, + // LocaleKeys.wouldYouLikeToLoginWithCurrentUsername.tr().toText16(), + // Container( + // height: 72, + // margin: const EdgeInsets.only(top: 23, bottom: 23), + // alignment: Alignment.center, + // padding: EdgeInsets.only(left: 17, right: 12), + // decoration: BoxDecoration( + // borderRadius: BorderRadius.circular(10), + // color: Colors.white, + // border: Border.all( + // color: Color(0xffefefef), + // width: 1, + // ), + // ), + // child: Column( + // mainAxisSize: MainAxisSize.min, + // children: [ + // Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // crossAxisAlignment: CrossAxisAlignment.center, + // children: [ + // LocaleKeys.lastLoginDetails.tr().toText16(), + // // Text( + // // user.editedOn != null + // // ? DateUtil.getDayMonthYearDateFormatted(DateUtil.convertStringToDate(user.editedOn)) + // // : user.createdOn != null + // // ? DateUtil.getDayMonthYearDateFormatted(DateUtil.convertStringToDate(user.createdOn)) + // // : '--', + // // style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.48), + // // ), + // ], + // ), + // Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // crossAxisAlignment: CrossAxisAlignment.center, + // children: [ + // LocaleKeys.verificationType.tr().toText10(color: MyColors.grey57Color), + // Text( + // "SMS", + // // " " + getType(user.logInType, context), + // style: TextStyle( + // fontSize: 12, + // fontWeight: FontWeight.w600, + // color: Color(0xff2B353E), + // ), + // ), + // Expanded(child: SizedBox()), + // // Text( + // // user.editedOn != null + // // ? DateUtil.formatDateToTimeLang(DateUtil.convertStringToDate(user.editedOn), false) + // // : user.createdOn != null + // // ? DateUtil.formatDateToTimeLang(DateUtil.convertStringToDate(user.createdOn), false) + // // : '--', + // // style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xff575757), letterSpacing: -0.48), + // // ), + // ], + // ) + // ], + // ), + // ), LocaleKeys.pleaseVerify.tr().toText16(), GridView( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, crossAxisSpacing: 13, mainAxisSpacing: 9), @@ -612,9 +620,23 @@ class _VerifyLoginScreenState extends State { // // }); // } // + + Future loginWithFaceIDAndBiometrics() async { + IOSAuthMessages iosStrings = + const IOSAuthMessages(cancelButton: 'cancel', goToSettingsButton: 'settings', goToSettingsDescription: 'Please set up your Touch ID.', lockOut: 'Please reenable your Touch ID'); + bool authenticated = false; + try { + authenticated = await auth.authenticate(localizedReason: 'Scan your fingerprint to authenticate', useErrorDialogs: true, stickyAuth: true, iOSAuthStrings: iosStrings); + } on PlatformException catch (e) { + print(e); + Utils.hideLoading(context); + Utils.showToast("Please enable your Touch or Face ID"); + } + return authenticated; + } + Widget _loginOptionButton(String _title, String _icon, int _flag, int? _loginIndex) { bool isDisable = ((_flag == 3 && !checkBiometricIsAvailable(BiometricType.face)) || (_flag == 2 && !checkBiometricIsAvailable(BiometricType.fingerprint))); - print("$_title:$isDisable"); return InkWell( onTap: isDisable ? null @@ -624,37 +646,64 @@ class _VerifyLoginScreenState extends State { // isMoreOption = true; }); } else { - Utils.showLoading(context); - BasicMemberInformationModel? memberInformationModel = await LoginApiClient() - .mohemmSendActivationCodeByOTPNotificationType(checkBiometricIsAvailable(BiometricType.fingerprint) ? 1 : 0, AppState().memberLoginList?.pMOBILENUMBER, _flag, AppState().getUserName); - Utils.hideLoading(context); - OtpDialog( - context, - _flag, - int.tryParse(AppState().memberLoginList?.pMOBILENUMBER ?? ""), - (value) async { - Utils.showLoading(context); - try { - GenericResponseModel? genericResponseModel = await LoginApiClient().checkActivationCode(false, AppState().memberLoginList?.pMOBILENUMBER, value, AppState().getUserName); - if (genericResponseModel?.errorMessage != null) { - Utils.showToast(genericResponseModel?.errorMessage ?? ""); - // Navigator.pop(context); - } - Utils.hideLoading(context); - Navigator.pop(context); - Navigator.pushNamedAndRemoveUntil(context, AppRoutes.dashboard, (Route route) => false); - } catch (ex) { - print(ex); - Utils.hideLoading(context); - Utils.handleException(ex, null); + try { + Utils.showLoading(context); + if (_flag == 2 || _flag == 3) { + bool authenticateWithFaceAndTouchID = await loginWithFaceIDAndBiometrics(); + if (!authenticateWithFaceAndTouchID) { + return; } - }, - () => { - Navigator.pop(context), - }, - ).displayDialog(context); - - // authenticateUser(_flag, isActive: _loginIndex); + } + await LoginApiClient().checkMobileAppVersion(); + await LoginApiClient().memberLogin(AppState().getUserName!, AppState().password!); + BasicMemberInformationModel? memberInformationModel = await LoginApiClient().mohemmSendActivationCodeByOTPNotificationType( + checkBiometricIsAvailable(BiometricType.fingerprint) ? 1 : 0, AppState().memberLoginList?.pMOBILENUMBER, _flag, AppState().getUserName); + Utils.hideLoading(context); + OtpDialog( + context, + _flag, + int.tryParse(AppState().memberLoginList?.pMOBILENUMBER ?? ""), + (value) async { + Utils.showLoading(context); + try { + GenericResponseModel? genericResponseModel = await LoginApiClient().checkActivationCode(false, AppState().memberLoginList?.pMOBILENUMBER, value, AppState().getUserName); + GenericResponseModel? genericResponseModel1 = await LoginApiClient().insertMobileLoginInfoNEW( + AppState().memberLoginList?.pEMAILADDRESS ?? "", + genericResponseModel?.pSESSIONID ?? 0, + genericResponseModel?.memberInformationList![0].eMPLOYEENAME ?? "", + _flag, + AppState().memberLoginList?.pMOBILENUMBER ?? "", + AppState().getUserName!, + firebaseToken!, + Platform.isAndroid ? "android" : "ios"); + if (genericResponseModel?.errorMessage != null) { + Utils.showToast(genericResponseModel?.errorMessage ?? ""); + } else { + AppState().setPrivilegeListModel = genericResponseModel!.privilegeList ?? []; + AppState().setMemberInformationListModel = genericResponseModel.memberInformationList?.first; + MemberInformationListModel.saveToPrefs(genericResponseModel.memberInformationList ?? []); + PrivilegeListModel.saveToPrefs(genericResponseModel.privilegeList ?? []); + Utils.saveStringFromPrefs(SharedPrefsConsts.username, AppState().getUserName!); + Utils.saveStringFromPrefs(SharedPrefsConsts.password, AppState().password!); + } + Utils.hideLoading(context); + Navigator.pop(context); + Navigator.pushNamedAndRemoveUntil(context, AppRoutes.dashboard, (Route route) => false); + } catch (ex) { + print(ex); + Utils.hideLoading(context); + Utils.handleException(ex, null); + } + }, + () => { + Navigator.pop(context), + }, + ).displayDialog(context); + } catch (ex) { + print(ex); + Utils.hideLoading(context); + Utils.handleException(ex, null); + } } }, child: Container( diff --git a/lib/widgets/dialogs/confirm_dialog.dart b/lib/widgets/dialogs/confirm_dialog.dart new file mode 100644 index 0000000..7264a9b --- /dev/null +++ b/lib/widgets/dialogs/confirm_dialog.dart @@ -0,0 +1,66 @@ +import 'package:easy_localization/src/public_ext.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; +import 'package:mohem_flutter_app/widgets/button/default_button.dart'; + +class ConfirmDialog extends StatelessWidget { + final String? title; + final String? message; + final String? okTitle; + final VoidCallback? onTap; + + const ConfirmDialog({Key? key, this.title, @required this.message, this.okTitle, this.onTap}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Dialog( + backgroundColor: Colors.white, + shape: RoundedRectangleBorder(), + insetPadding: EdgeInsets.only(left: 21, right: 21), + child: Padding( + padding: EdgeInsets.only(left: 20, right: 20, top: 18, bottom: 28), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.only(top: 16.0), + child: Text( + title ?? LocaleKeys.confirm.tr(), + style: TextStyle(fontSize: 24, fontWeight: FontWeight.w600, color: Color(0xff2B353E), height: 35 / 24, letterSpacing: -0.96), + ), + ), + ), + IconButton( + padding: EdgeInsets.zero, + icon: Icon(Icons.close), + color: Color(0xff2B353E), + constraints: BoxConstraints(), + onPressed: () { + Navigator.pop(context); + }, + ) + ], + ), + Text( + message ?? "", + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xff808080), letterSpacing: -0.48), + ), + SizedBox(height: 28), + DefaultButton( + okTitle ?? LocaleKeys.ok.tr(), + onTap == null ? () => Navigator.pop(context) : onTap, + textColor: Colors.white, + //color: Ap.green, + ), + ], + ), + ), + ); + } +} diff --git a/lib/widgets/input_widget.dart b/lib/widgets/input_widget.dart index 8b248e4..7761816 100644 --- a/lib/widgets/input_widget.dart +++ b/lib/widgets/input_widget.dart @@ -12,15 +12,10 @@ class InputWidget extends StatelessWidget { final bool isInputTypeNum; final bool isObscureText; final bool isBackgroundEnable; + final Function(String)? onChange; InputWidget(this.labelText, this.hintText, this.controller, - {this.isObscureText = false, - this.suffixTap, - this.isEnable = true, - this.hasSelection = false, - this.lines = 1, - this.isInputTypeNum = false, - this.isBackgroundEnable = false}); + {this.isObscureText = false, this.suffixTap, this.isEnable = true, this.hasSelection = false, this.lines = 1, this.onChange, this.isInputTypeNum = false, this.isBackgroundEnable = false}); @override Widget build(BuildContext context) { @@ -56,14 +51,12 @@ class InputWidget extends StatelessWidget { TextField( enabled: isEnable, scrollPadding: EdgeInsets.zero, - keyboardType: isInputTypeNum - ? TextInputType.number - : TextInputType.text, + keyboardType: isInputTypeNum ? TextInputType.number : TextInputType.text, controller: controller, maxLines: lines, obscuringCharacter: "*", obscureText: isObscureText, - onChanged: (value) => {}, + onChanged: onChange, style: const TextStyle( fontSize: 14, height: 21 / 14, @@ -82,12 +75,7 @@ class InputWidget extends StatelessWidget { letterSpacing: -0.56, ), suffixIconConstraints: const BoxConstraints(minWidth: 50), - suffixIcon: suffixTap == null - ? null - : IconButton( - icon: const Icon(Icons.mic, - color: MyColors.darkTextColor), - onPressed: suffixTap), + suffixIcon: suffixTap == null ? null : IconButton(icon: const Icon(Icons.mic, color: MyColors.darkTextColor), onPressed: suffixTap), contentPadding: EdgeInsets.zero, border: InputBorder.none, focusedBorder: InputBorder.none, diff --git a/pubspec.yaml b/pubspec.yaml index e7d1182..ca8fe9c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -44,6 +44,8 @@ dependencies: sizer: ^2.0.15 local_auth: ^1.1.9 fluttertoast: ^8.0.8 + shared_preferences: ^2.0.12 + firebase_messaging: ^11.2.6 shimmer: ^2.0.0 logger: ^1.1.0 flutter_countdown_timer: ^4.1.0