import 'dart:convert'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:hmg_nurses/classes/consts.dart'; import 'package:hmg_nurses/classes/enums.dart'; import 'package:hmg_nurses/classes/utils.dart'; import 'package:hmg_nurses/config/routes.dart'; import 'package:hmg_nurses/generated/locale_keys.g.dart'; import 'package:hmg_nurses/main.dart'; import 'package:hmg_nurses/model/base/generic_response_model.dart'; import 'package:hmg_nurses/model/base/generic_response_model2.dart'; import 'package:hmg_nurses/model/base/post_params_model.dart'; import 'package:hmg_nurses/model/login/imei_details_model.dart'; import 'package:hmg_nurses/model/login/member_login_model.dart'; import 'package:hmg_nurses/model/login/project_info_model.dart'; import 'package:hmg_nurses/provider/base_vm.dart'; import 'package:hmg_nurses/services/api_repo/login_api_repo.dart'; import 'package:hmg_nurses/widgets/dialogs/otp_dialog.dart'; import 'package:http/http.dart'; import 'package:injector/injector.dart'; import 'package:local_auth/auth_strings.dart'; import 'package:local_auth/local_auth.dart'; class LoginProviderModel extends BaseViewModel { //UI variables late LocalAuthentication auth; late bool isFaceBioAvailable, isFingerBioAvailable; late List _availableBiometrics; //API's variables late List assignedBranches; final ILoginApiRepo _loginApiRepo = Injector.appInstance.get(); LoginProviderModel() { setOnlyState(ViewState.hide); checkBiosAvailblity(); } checkBiosAvailblity() async { auth = LocalAuthentication(); await _getAvailableBiometrics(); isFaceBioAvailable = checkBiometricIsAvailable(BiometricType.face); isFingerBioAvailable = checkBiometricIsAvailable(BiometricType.fingerprint); } /// check specific biometric if it available or not bool checkBiometricIsAvailable(BiometricType biometricType) { bool isAvailable = false; for (int i = 0; i < _availableBiometrics.length; i++) { if (biometricType == _availableBiometrics[i]) { isAvailable = true; break; } } return isAvailable; } /// get all available biometric on the device for local Auth service Future _getAvailableBiometrics() async { try { _availableBiometrics = await auth.getAvailableBiometrics(); print(_availableBiometrics); } on PlatformException catch (e) { // AppToast.showErrorToast(message: e.message); print("_getAvailableBiometrics"); print(e); } } Future loginWithFaceIDAndBiometrics() async { IOSAuthMessages iosStrings = const IOSAuthMessages(cancelButton: 'cancel', goToSettingsButton: 'settings', goToSettingsDescription: 'Please set up your Touch ID.', lockOut: 'Please re-enable your Touch ID'); bool authenticated = false; try { authenticated = await auth.authenticate(localizedReason: 'Scan your fingerprint to authenticate', useErrorDialogs: true, stickyAuth: true, biometricOnly: true, iOSAuthStrings: iosStrings); } on PlatformException catch (e) { print(e); Utils.showToast("Please enable your Touch or Face ID"); } return authenticated; } int getLoginMethodId(AuthMethodTypes authMethodTypes) { switch (authMethodTypes) { case AuthMethodTypes.sms: return 1; case AuthMethodTypes.whatsApp: return 2; case AuthMethodTypes.fingerPrint: return 3; case AuthMethodTypes.faceID: return 4; default: return 1; } } String getType(type) { switch (type) { case 1: return LocaleKeys.sms.tr(); case 3: return LocaleKeys.fingerPrint.tr(); case 4: return LocaleKeys.face.tr(); case 2: return LocaleKeys.whatsapp.tr(); default: return LocaleKeys.sms.tr(); } } // LoginType getDirectLoginType(type) { // switch (type) { // case 1: // return LoginType.DIRECT_LOGIN; // case 3: // return LocaleKeys.fingerPrint.tr(); // case 4: // return LocaleKeys.face.tr(); // case 2: // return LocaleKeys.whatsapp.tr(); // default: // return LocaleKeys.sms.tr(); // } // } //API Calls checkLastSession() async { try { Utils.showLoading(); List deviceInfo = await _loginApiRepo.getDeviceInfoByIMEI(); if (deviceInfo.isNotEmpty) getSession(deviceInfo.first); Utils.showToast(deviceInfo.length.toString()); Utils.hideLoading(); } catch (e) { Utils.hideLoading(); } } getAssignedBranches(String userId) async { setState(ViewState.busy); assignedBranches = await _loginApiRepo.getProjectInfo(userId); print(assignedBranches.length); setState(ViewState.idle); } Future performLogin(String userID, String password, int branchId) async { try { Utils.showLoading(); MemberLoginModel memberLogin = await _loginApiRepo.memberLogin(userID, password, branchId); // Utils.showToast(deviceInfo.length.toString()); appState.memberBeforeLogin = memberLogin; appState.projectID = branchId; appState.logInTokenID = memberLogin.logInTokenId; appState.lastLoginTyp = -1; Utils.hideLoading(); Navigator.pushReplacementNamed(navigatorKey.currentContext!, AppRoutes.loginMethodsPage, arguments: LoginType.FROM_LOGIN); return true; } catch (e) { Utils.hideLoading(); Utils.handleException(e, navigatorKey.currentContext!, (msg) { Utils.confirmDialog(navigatorKey.currentContext!, msg); }); return false; } } Future sendActivationCode(MemberLoginModel memberLoginModel, int facilityID, int sendOtpType, LoginType loginType, {bool isNeedBinding = true}) async { try { Utils.showLoading(isNeedBinding: isNeedBinding); GenericResponseModel memberLogin; if (loginType == LoginType.FROM_LOGIN) { memberLogin = await _loginApiRepo.sendActivationCode(memberLoginModel, facilityID, sendOtpType); appState.logInTokenID = memberLogin.logInTokenId.toString(); Utils.hideLoading(); startSMSService(sendOtpType, false); } else { if (loginType == LoginType.SILENT_LOGIN) { memberLogin = await _loginApiRepo.sendActivationCodeForSlientLogin(memberLoginModel, facilityID, sendOtpType); appState.logInTokenID = memberLogin.logInTokenId.toString(); checkActivationCode("0000", sendOtpType, true); } else { memberLogin = await _loginApiRepo.sendActivationCodeForSlientLogin(memberLoginModel, facilityID, sendOtpType); appState.logInTokenID = memberLogin.logInTokenId.toString(); Utils.hideLoading(); startSMSService(sendOtpType, true); } } return memberLogin; } catch (e) { Utils.hideLoading(); Utils.handleException(e, navigatorKey.currentContext!, (msg) { Utils.confirmDialog(navigatorKey.currentContext!, msg); }); } return null; } Future checkActivationCode(String activationCode, int sendOtpType, bool isFromSilentLogin) async { try { if (!isFromSilentLogin) Utils.showLoading(); GenericResponseModel memberLogin = await _loginApiRepo.checkActivationCode(activationCode, sendOtpType, isFromSilentLogin); Utils.hideLoading(); setSession(memberLogin); Navigator.pushReplacementNamed(navigatorKey.currentContext!, AppRoutes.dashboard); return memberLogin; } catch (e) { Utils.hideLoading(); Utils.handleException(e, navigatorKey.currentContext!, (msg) { Utils.confirmDialog(navigatorKey.currentContext!, msg); }); } return null; } startSMSService(int sendOtpType, bool isFromSilentLogin) { OtpDialog( type: sendOtpType, mobileNo: appState.memberBeforeLogin!.mobileNumber, onSuccess: (String otpCode, TextEditingController pinPut) { Navigator.pop(navigatorKey.currentContext!); Utils.showLoading(); checkActivationCode(otpCode, sendOtpType, isFromSilentLogin); Utils.hideLoading(); }, onFailure: () => Navigator.pop(navigatorKey.currentContext!), onResendCode: () {}, ).displayDialog(navigatorKey.currentContext!); } setSession(GenericResponseModel response) { appState.vidaAuthTokenID = response.vidaAuthTokenId; appState.vidaRefreshTokenID = response.vidaRefreshTokenId; appState.authenticationTokenID = response.authenticationTokenId; appState.listDoctorsClinic = response.listDoctorsClinic; appState.projectID = response.listDoctorsClinic!.first.projectId!; appState.clinicId = response.listDoctorsClinic!.first.clinicId!; appState.employeeId = response.memberInformation!.employeeId; appState.isLogged = true; PostParamsModel? paramsModel = appState.postParamsObject; paramsModel!.doctorId = appState.employeeId; paramsModel.editedBy = appState.employeeId; paramsModel.projectId = appState.projectID; paramsModel.clinicId = appState.clinicId; MemberLoginModel.saveToPrefs(jsonEncode(appState.memberBeforeLogin!.toJson())); Utils.saveIntFromPrefs(SharedPrefsConsts.username, appState.doctorUserId ?? 0); Utils.saveStringFromPrefs(SharedPrefsConsts.password, appState.password ?? ""); Utils.saveStringFromPrefs(SharedPrefsConsts.logInTokenID, appState.logInTokenID ?? ""); Utils.saveStringFromPrefs(SharedPrefsConsts.vidaAuthTokenID, appState.vidaAuthTokenID ?? ""); Utils.saveStringFromPrefs(SharedPrefsConsts.vidaRefreshTokenID, appState.vidaRefreshTokenID ?? ""); Utils.saveStringFromPrefs(SharedPrefsConsts.authenticationTokenID, appState.authenticationTokenID ?? ""); Utils.saveIntFromPrefs(SharedPrefsConsts.projectID, appState.projectID); Utils.saveIntFromPrefs(SharedPrefsConsts.clinicId, appState.clinicId); Utils.saveStringFromPrefs(SharedPrefsConsts.lastLoginDate, Utils.getMonthNamedFormat(DateTime.now())); } getSession(GetIMEIDetailsModel model) async { int doctorUserId = await Utils.getIntFromPrefs(SharedPrefsConsts.username); if (model.doctorID == doctorUserId) { String password = await Utils.getStringFromPrefs(SharedPrefsConsts.password); String logInTokenID = await Utils.getStringFromPrefs(SharedPrefsConsts.logInTokenID); String authenticationTokenID = await Utils.getStringFromPrefs(SharedPrefsConsts.authenticationTokenID); int clinicId = await Utils.getIntFromPrefs(SharedPrefsConsts.clinicId); String lastLoginDate = await Utils.getStringFromPrefs(SharedPrefsConsts.lastLoginDate); appState.memberBeforeLogin = await MemberLoginModel.getFromPrefs(); // print(appState.memberBeforeLogin!.toJson()); appState.lastLoginTyp = -1; appState.doctorUserId = doctorUserId; appState.employeeId = appState.memberBeforeLogin!.listMemberInformation!.first.employeeId; appState.password = password; appState.logInTokenID = logInTokenID; appState.vidaAuthTokenID = model.vidaAuthTokenID; appState.vidaRefreshTokenID = model.vidaRefreshTokenID; appState.authenticationTokenID = authenticationTokenID; appState.projectID = model.projectID ?? 0; appState.clinicId = clinicId; appState.lastLoginImeiDate = model; appState.lastLoginDate = lastLoginDate; Navigator.pushReplacementNamed(navigatorKey.currentContext!, AppRoutes.loginMethodsPage, arguments: LoginType.SILENT_LOGIN); } } }