From 32d26c3c4b4445c2eff8618ef25bb4c2e9a039e3 Mon Sep 17 00:00:00 2001 From: Elham Rababah Date: Wed, 5 May 2021 17:53:53 +0300 Subject: [PATCH] remove Verification Methods page and move some code to model --- .../viewModel/authentication_view_model.dart | 41 +- lib/routes.dart | 2 +- lib/screens/auth/login_screen.dart | 2 +- .../auth/verification_methods_screen.dart | 591 ++++++++++++++++- lib/widgets/auth/verification_methods.dart | 619 ------------------ 5 files changed, 609 insertions(+), 646 deletions(-) delete mode 100644 lib/widgets/auth/verification_methods.dart diff --git a/lib/core/viewModel/authentication_view_model.dart b/lib/core/viewModel/authentication_view_model.dart index 474b91fe..a8dda45f 100644 --- a/lib/core/viewModel/authentication_view_model.dart +++ b/lib/core/viewModel/authentication_view_model.dart @@ -1,5 +1,6 @@ import 'package:doctor_app_flutter/config/config.dart'; import 'package:doctor_app_flutter/config/shared_pref_kay.dart'; +import 'package:doctor_app_flutter/core/enum/auth_method_types.dart'; import 'package:doctor_app_flutter/core/enum/viewstate.dart'; import 'package:doctor_app_flutter/core/model/hospitals/get_hospitals_request_model.dart'; import 'package:doctor_app_flutter/core/model/hospitals/get_hospitals_response_model.dart'; @@ -88,8 +89,19 @@ class AuthenticationViewModel extends BaseViewModel { setState(ViewState.Idle); } - Future sendActivationCodeVerificationScreen(ActivationCodeForVerificationScreenModel activationCodeModel) async { + Future sendActivationCodeVerificationScreen( AuthMethodTypes authMethodType) async { setState(ViewState.BusyLocal); + ActivationCodeForVerificationScreenModel activationCodeModel = + ActivationCodeForVerificationScreenModel( + iMEI: user.iMEI, + facilityId: user.projectID, + memberID: user.doctorID, + zipCode: user.outSA == true ? '971' : '966', + mobileNumber: user.mobile, + oTPSendType: authMethodType.getTypeIdService(), + isMobileFingerPrint: 1, + vidaAuthTokenID: user.vidaAuthTokenID, + vidaRefreshTokenID: user.vidaRefreshTokenID); await _authService.sendActivationCodeVerificationScreen(activationCodeModel); if (_authService.hasError) { error = _authService.error; @@ -98,8 +110,16 @@ class AuthenticationViewModel extends BaseViewModel { setState(ViewState.Idle); } - Future sendActivationCodeForDoctorApp(ActivationCodeModel activationCodeModel) async { + Future sendActivationCodeForDoctorApp({AuthMethodTypes authMethodType, String password }) async { setState(ViewState.BusyLocal); + int projectID = await sharedPref.getInt(PROJECT_ID); + ActivationCodeModel activationCodeModel = ActivationCodeModel( + facilityId: projectID, + memberID: loggedUser['List_MemberInformation'][0]['MemberID'], + zipCode: loggedUser['ZipCode'], + mobileNumber: loggedUser['MobileNumber'], + otpSendType: authMethodType.getTypeIdService().toString(), + password: password); await _authService.sendActivationCodeForDoctorApp(activationCodeModel); if (_authService.hasError) { error = _authService.error; @@ -108,9 +128,22 @@ class AuthenticationViewModel extends BaseViewModel { setState(ViewState.Idle); } - Future checkActivationCodeForDoctorApp(CheckActivationCodeRequestModel checkActivationCodeRequestModel) async { + Future checkActivationCodeForDoctorApp({String activationCode}) async { setState(ViewState.BusyLocal); - await _authService.checkActivationCodeForDoctorApp(checkActivationCodeRequestModel); + CheckActivationCodeRequestModel checkActivationCodeForDoctorApp = + new CheckActivationCodeRequestModel( + zipCode: + loggedUser != null ? loggedUser['ZipCode'] :user.zipCode, + mobileNumber: + loggedUser != null ? loggedUser['MobileNumber'] : user.mobile, + projectID: await sharedPref.getInt(PROJECT_ID) != null + ? await sharedPref.getInt(PROJECT_ID) + : user.projectID, + logInTokenID: await sharedPref.getString(LOGIN_TOKEN_ID), + activationCode: activationCode ?? '0000', + oTPSendType: await sharedPref.getInt(OTP_TYPE), + generalid: "Cs2020@2016\$2958"); + await _authService.checkActivationCodeForDoctorApp(checkActivationCodeForDoctorApp); if (_authService.hasError) { error = _authService.error; setState(ViewState.ErrorLocal); diff --git a/lib/routes.dart b/lib/routes.dart index 2684cd82..90e061b8 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -14,9 +14,9 @@ import 'package:doctor_app_flutter/screens/prescription/prescriptions_page.dart' import 'package:doctor_app_flutter/screens/procedures/procedure_screen.dart'; import 'package:doctor_app_flutter/screens/sick-leave/add-sickleave.dart'; import 'package:doctor_app_flutter/screens/sick-leave/show-sickleave.dart'; +import 'package:doctor_app_flutter/screens/auth/verification_methods_screen.dart'; import './screens/auth/login_screen.dart'; -import './screens/auth/verification_methods_screen.dart'; import 'screens/patients/profile/profile_screen/patient_profile_screen.dart'; import './screens/patients/profile/vital_sign/vital_sign_details_screen.dart'; import 'landing_page.dart'; diff --git a/lib/screens/auth/login_screen.dart b/lib/screens/auth/login_screen.dart index 707e178c..0048b10c 100644 --- a/lib/screens/auth/login_screen.dart +++ b/lib/screens/auth/login_screen.dart @@ -10,10 +10,10 @@ import 'package:doctor_app_flutter/core/service/authentication_service.dart'; import 'package:doctor_app_flutter/core/viewModel/authentication_view_model.dart'; import 'package:doctor_app_flutter/core/viewModel/project_view_model.dart'; import 'package:doctor_app_flutter/models/doctor/user_model.dart'; -import 'package:doctor_app_flutter/screens/auth/verification_methods_screen.dart'; import 'package:doctor_app_flutter/screens/base/base_view.dart'; import 'package:doctor_app_flutter/util/helpers.dart'; import 'package:doctor_app_flutter/util/translations_delegate_base.dart'; +import 'package:doctor_app_flutter/screens/auth/verification_methods_screen.dart'; import 'package:doctor_app_flutter/widgets/shared/app_loader_widget.dart'; import 'package:doctor_app_flutter/widgets/shared/app_texts_widget.dart'; import 'package:doctor_app_flutter/widgets/shared/buttons/app_buttons_widget.dart'; diff --git a/lib/screens/auth/verification_methods_screen.dart b/lib/screens/auth/verification_methods_screen.dart index e4d2603d..2b906588 100644 --- a/lib/screens/auth/verification_methods_screen.dart +++ b/lib/screens/auth/verification_methods_screen.dart @@ -1,42 +1,591 @@ +import 'dart:io' show Platform; + +import 'package:doctor_app_flutter/config/shared_pref_kay.dart'; +import 'package:doctor_app_flutter/core/enum/auth_method_types.dart'; +import 'package:doctor_app_flutter/core/enum/viewstate.dart'; +import 'package:doctor_app_flutter/core/model/imei_details.dart'; import 'package:doctor_app_flutter/core/viewModel/authentication_view_model.dart'; +import 'package:doctor_app_flutter/core/viewModel/project_view_model.dart'; +import 'package:doctor_app_flutter/models/auth/activation_Code_req_model.dart'; +import 'package:doctor_app_flutter/models/auth/activation_code_for_verification_screen_model.dart'; +import 'package:doctor_app_flutter/models/auth/check_activation_code_request_model.dart'; +import 'package:doctor_app_flutter/models/doctor/clinic_model.dart'; +import 'package:doctor_app_flutter/models/doctor/doctor_profile_model.dart'; +import 'package:doctor_app_flutter/models/doctor/profile_req_Model.dart'; import 'package:doctor_app_flutter/screens/base/base_view.dart'; +import 'package:doctor_app_flutter/util/date-utils.dart'; +import 'package:doctor_app_flutter/util/dr_app_toast_msg.dart'; +import 'package:doctor_app_flutter/util/translations_delegate_base.dart'; +import 'package:doctor_app_flutter/widgets/auth/sms-popup.dart'; import 'package:doctor_app_flutter/widgets/shared/app_scaffold_widget.dart'; +import 'package:doctor_app_flutter/widgets/shared/app_texts_widget.dart'; +import 'package:doctor_app_flutter/widgets/shared/buttons/app_buttons_widget.dart'; +import 'package:doctor_app_flutter/widgets/shared/loader/gif_loader_dialog_utils.dart'; +import 'package:doctor_app_flutter/widgets/transitions/fade_page.dart'; import 'package:flutter/material.dart'; -import 'package:hexcolor/hexcolor.dart'; +import 'package:flutter/services.dart'; +import 'package:local_auth/auth_strings.dart'; +import 'package:local_auth/local_auth.dart'; +import 'package:provider/provider.dart'; -import '../../widgets/auth/verification_methods.dart'; +import '../../config/size_config.dart'; +import '../../core/viewModel/doctor_profile_view_model.dart'; +import '../../landing_page.dart'; +import '../../routes.dart'; +import '../../util/dr_app_shared_pref.dart'; +import '../../util/helpers.dart'; +import '../../widgets/auth/method_card.dart'; -class VerificationMethodsScreen extends StatefulWidget { - const VerificationMethodsScreen({Key key, this.password}) : super(key: key); +DrAppSharedPreferances sharedPref = new DrAppSharedPreferances(); +Helpers helpers = Helpers(); - @override - _VerificationMethodsScreenState createState() => - _VerificationMethodsScreenState(); +class VerificationMethodsScreen extends StatefulWidget { + VerificationMethodsScreen({this.changeLoadingState, this.password}); final password; + final Function changeLoadingState; + + @override + _VerificationMethodsScreenState createState() => _VerificationMethodsScreenState(); } class _VerificationMethodsScreenState extends State { - bool _isLoading = false; + + ProjectViewModel projectsProvider; + bool isMoreOption = false; + bool onlySMSBox = false; + var loginTokenID; + DoctorProfileViewModel doctorProfileViewModel; - void changeLoadingState(isLoading) { - setState(() { - _isLoading = isLoading; - }); + bool authenticated; + + AuthMethodTypes fingerPrintBefore; + + AuthMethodTypes selectedOption; + AuthenticationViewModel model; + + final LocalAuthentication auth = LocalAuthentication(); + + @override + void initState() { + super.initState(); + } + + + @override + void didChangeDependencies() async{ + super.didChangeDependencies(); + } @override Widget build(BuildContext context) { + doctorProfileViewModel = Provider.of(context); + projectsProvider = Provider.of(context); return BaseView( + onModelReady: (model) async { + this.model = model; + await model.getInitUserInfo(); + }, builder: (_, model, w) => AppScaffold( - isLoading: _isLoading, - isShowAppBar: false, - isHomeIcon: false, - backgroundColor: HexColor('#F8F8F8'), - body:VerificationMethods( - password: widget.password, - changeLoadingState: changeLoadingState, - // model:model - ))); + isShowAppBar: false, + baseViewModel: model, + body: SingleChildScrollView( + child: Center( + child: FractionallySizedBox( + // widthFactor: 0.9, + child: Container( + margin: EdgeInsetsDirectional.fromSTEB(30, 0, 30, 0), + + height: SizeConfig.realScreenHeight * .95, + width: SizeConfig.realScreenWidth, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + child: Column( + + children: [ + SizedBox( + height: 100, + ), + model.user != null && isMoreOption == false + ? Column( + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + AppText( + TranslationBase.of(context).welcomeBack), + AppText( + Helpers.capitalize(model.user.doctorName), + fontSize: SizeConfig.textMultiplier * 3.5, + fontWeight: FontWeight.bold, + ), + SizedBox( + height: 20, + ), + AppText( + TranslationBase.of(context).accountInfo, + fontSize: SizeConfig.textMultiplier * 2.5, + fontWeight: FontWeight.w600, + ), + SizedBox( + height: 20, + ), + Card( + color: Colors.white, + child: Row( + children: [ + Flexible( + flex: 3, + child: ListTile( + title: Text( + TranslationBase.of(context) + .lastLoginAt, + overflow: + TextOverflow.ellipsis, + style: TextStyle( + fontFamily: 'Poppins', + fontWeight: + FontWeight.w800, + fontSize: 14), + ), + subtitle: AppText( + model.getType( + model.user.logInTypeID, + context), + fontSize: 14, + ))), + Flexible( + flex: 2, + child: ListTile( + title: AppText( + model.user.editedOn != null + ? model.getDate( + DateUtils + .convertStringToDate( + model.user + .editedOn)) + : model.user.createdOn != null + ? model + .getDate(DateUtils + .convertStringToDate( + model.user.createdOn)) + : '--', + textAlign: TextAlign.right, + fontSize: 14, + fontWeight: FontWeight.w800, + ), + subtitle: AppText( + model.user.editedOn != null + ? model.getTime( + DateUtils + .convertStringToDate( + model.user + .editedOn)) + : model.user.createdOn != null + ? model + .getTime(DateUtils + .convertStringToDate( + model.user.createdOn)) + : '--', + textAlign: TextAlign.right, + fontSize: 14, + ), + )) + ], + )), + ], + ) + : Column( + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + this.onlySMSBox == false + ? AppText( + TranslationBase.of(context) + .verifyLoginWith, + fontSize: + SizeConfig.textMultiplier * 3.5, + textAlign: TextAlign.left, + ) + : AppText( + TranslationBase.of(context) + .verifyFingerprint2, + fontSize: + SizeConfig.textMultiplier * 2.5, + textAlign: TextAlign.start, + ), + ]), + model.user != null && isMoreOption == false + ? Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Expanded( + child: InkWell( + onTap: () => { + // TODO check this logic it seem it will create bug to us + + authenticateUser( + AuthMethodTypes + .Fingerprint, + true) + }, + child: MethodCard( + authMethodType: model.user + .logInTypeID == + 4 + ? AuthMethodTypes.FaceID + : model.user.logInTypeID == 2 + ? AuthMethodTypes + .WhatsApp + : model.user.logInTypeID == + 3 + ? AuthMethodTypes + .Fingerprint + : AuthMethodTypes + .SMS, + authenticateUser: + (AuthMethodTypes + authMethodType, + isActive) => + authenticateUser( + authMethodType, + isActive), + )), + ), + Expanded( + child: MethodCard( + authMethodType: + AuthMethodTypes.MoreOptions, + onShowMore: () { + setState(() { + isMoreOption = true; + }); + }, + )) + ]), + ]) + : Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + onlySMSBox == false + ? Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Expanded( + child: MethodCard( + authMethodType: + AuthMethodTypes.Fingerprint, + authenticateUser: + (AuthMethodTypes + authMethodType, + isActive) => + authenticateUser( + authMethodType, + isActive), + )), + Expanded( + child: MethodCard( + authMethodType: + AuthMethodTypes.FaceID, + authenticateUser: + (AuthMethodTypes + authMethodType, + isActive) => + authenticateUser( + authMethodType, + isActive), + )) + ], + ) + : SizedBox(), + Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Expanded( + child: MethodCard( + authMethodType: AuthMethodTypes.SMS, + authenticateUser: + (AuthMethodTypes authMethodType, + isActive) => + authenticateUser( + authMethodType, isActive), + )), + Expanded( + child: MethodCard( + authMethodType: + AuthMethodTypes.WhatsApp, + authenticateUser: + (AuthMethodTypes authMethodType, + isActive) => + authenticateUser( + authMethodType, isActive), + )) + ], + ), + ]), + + // ) + ], + ), + ), + Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + model.user != null + ? Row( + children: [ + Expanded( + child: AppButton( + title: TranslationBase.of(context) + .useAnotherAccount, + color: Colors.red[700], + onPressed: () { + Navigator.of(context).pushNamed(LOGIN); + }, + )), + ], + ) + : SizedBox(), + ], + ), + ], + ), + ), + ), + ), + ), + )); + } + + sendActivationCodeByOtpNotificationType( + AuthMethodTypes authMethodType) async { + if (authMethodType == AuthMethodTypes.SMS || + authMethodType == AuthMethodTypes.WhatsApp) { + GifLoaderDialogUtils.showMyDialog(context); + + + await model.sendActivationCodeForDoctorApp(authMethodType:authMethodType, password: widget.password ); + if (model.state == ViewState.ErrorLocal) { + Helpers.showErrorToast(model.error); + GifLoaderDialogUtils.hideDialog(context); + } else { + // TODO move it model + print("VerificationCode : " + + model.activationCodeForDoctorAppRes["VerificationCode"]); + sharedPref.setString(VIDA_AUTH_TOKEN_ID, + model.activationCodeForDoctorAppRes["VidaAuthTokenID"]); + sharedPref.setString(VIDA_REFRESH_TOKEN_ID, + model.activationCodeForDoctorAppRes["VidaRefreshTokenID"]); + sharedPref.setString(LOGIN_TOKEN_ID, + model.activationCodeForDoctorAppRes["LogInTokenID"]); + sharedPref.setString(PASSWORD, widget.password); + GifLoaderDialogUtils.hideDialog(context); + this.startSMSService(authMethodType); + } + } else { + // TODO route to this page with parameters to inicate we should present 2 option + if (Platform.isAndroid && authMethodType == AuthMethodTypes.Fingerprint) { + Helpers.showErrorToast('Your device not support this feature'); + } else {} + } + } + + sendActivationCodeVerificationScreen(AuthMethodTypes authMethodType) async { + GifLoaderDialogUtils.showMyDialog(context); + + + await model + .sendActivationCodeVerificationScreen(authMethodType); + + if (model.state == ViewState.ErrorLocal) { + GifLoaderDialogUtils.hideDialog(context); + Helpers.showErrorToast(model.error); + } else { + //TODO Move it to view model + print("VerificationCode : " + + model.activationCodeVerificationScreenRes["VerificationCode"]); + sharedPref.setString(VIDA_AUTH_TOKEN_ID, + model.activationCodeVerificationScreenRes["VidaAuthTokenID"]); + sharedPref.setString( + VIDA_REFRESH_TOKEN_ID, + model.activationCodeVerificationScreenRes["VidaRefreshTokenID"]); + sharedPref.setString(LOGIN_TOKEN_ID, + model.activationCodeVerificationScreenRes["LogInTokenID"]); + if (authMethodType == AuthMethodTypes.SMS || + authMethodType == AuthMethodTypes.WhatsApp) { + GifLoaderDialogUtils.hideDialog(context); + this.startSMSService(authMethodType); + } else { + checkActivationCode(); + } + } + } + + authenticateUser(AuthMethodTypes authMethodType, isActive) { + if (authMethodType == AuthMethodTypes.Fingerprint || + authMethodType == AuthMethodTypes.FaceID) { + fingerPrintBefore = authMethodType; + } + this.selectedOption = + fingerPrintBefore != null ? fingerPrintBefore : authMethodType; + + switch (authMethodType) { + case AuthMethodTypes.SMS: + sendActivationCode(authMethodType); + break; + case AuthMethodTypes.WhatsApp: + sendActivationCode(authMethodType); + break; + case AuthMethodTypes.Fingerprint: + this.loginWithFingerPrintOrFaceID( + AuthMethodTypes.Fingerprint, isActive); + break; + case AuthMethodTypes.FaceID: + this.loginWithFingerPrintOrFaceID(AuthMethodTypes.FaceID, isActive); + break; + default: + break; + } + sharedPref.setInt(OTP_TYPE, selectedOption.getTypeIdService()); + } + + sendActivationCode(AuthMethodTypes authMethodType) async { + if (model.user != null) { + sendActivationCodeVerificationScreen(authMethodType); + } else { + sendActivationCodeByOtpNotificationType(authMethodType); + } + } + + startSMSService(AuthMethodTypes type) { + // TODO improve this logic + new SMSOTP( + context, + type, + model.loggedUser != null ? model.loggedUser['MobileNumber'] : model.user.mobile, + (value) { + showDialog( + context: context, + builder: (BuildContext context) { + return Center( + child: CircularProgressIndicator(), + ); + }); + + this.checkActivationCode(value: value); + }, + () => + { + widget.changeLoadingState(false), + print('Faild..'), + }, + ).displayDialog(context); + } + + loginWithFingerPrintOrFaceID(AuthMethodTypes authMethodTypes, + isActive) async { + if (isActive) { + 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) { + DrAppToastMsg.showErrorToast(e.toString()); + } + if (!mounted) return; + if (model.user != null && (model.user.logInTypeID == 3 || model.user.logInTypeID == 4)) { + this.sendActivationCode(authMethodTypes); + } else { + setState(() { + this.onlySMSBox = true; + }); + } + } + } + + checkActivationCode({value}) async { + + await model + .checkActivationCodeForDoctorApp(activationCode:value ); + + if (model.state == ViewState.ErrorLocal) { + Navigator.pop(context); + Helpers.showErrorToast(model.error); + } else { + sharedPref.setString( + TOKEN, + model + .checkActivationCodeForDoctorAppRes['AuthenticationTokenID']); + if (model.checkActivationCodeForDoctorAppRes['List_DoctorProfile'] != + null) { + loginProcessCompleted(model.checkActivationCodeForDoctorAppRes['List_DoctorProfile'][0]); + sharedPref.setObj( + CLINIC_NAME, + model + .checkActivationCodeForDoctorAppRes['List_DoctorsClinic']); + } else { + sharedPref.setObj( + CLINIC_NAME, + model + .checkActivationCodeForDoctorAppRes['List_DoctorsClinic']); + ClinicModel clinic = ClinicModel.fromJson(model.checkActivationCodeForDoctorAppRes['List_DoctorsClinic'][0]); + getDocProfiles(clinic); + } + } + } + + loginProcessCompleted(Map profile) { + var doctor = DoctorProfileModel.fromJson(profile); + doctorProfileViewModel.setDoctorProfile(doctor); + sharedPref.setObj(DOCTOR_PROFILE, profile); + projectsProvider.isLogin = true; + + Navigator.pushAndRemoveUntil( + context, + FadePage( + page: LandingPage(), + ), + (r) => false); + } + + getDocProfiles(ClinicModel clinicInfo) { + ProfileReqModel docInfo = new ProfileReqModel( + doctorID: clinicInfo.doctorID, + clinicID: clinicInfo.clinicID, + license: true, + projectID: clinicInfo.projectID, + tokenID: '', + languageID: 2); + doctorProfileViewModel.getDocProfiles(docInfo.toJson()).then((res) { + if (res['MessageStatus'] == 1) { + loginProcessCompleted(res['DoctorProfileList'][0]); + } else { + // changeLoadingState(false); + Helpers.showErrorToast(res['ErrorEndUserMessage']); + } + }).catchError((err) { + Helpers.showErrorToast(err); + }); } } diff --git a/lib/widgets/auth/verification_methods.dart b/lib/widgets/auth/verification_methods.dart deleted file mode 100644 index faadbf9e..00000000 --- a/lib/widgets/auth/verification_methods.dart +++ /dev/null @@ -1,619 +0,0 @@ -import 'dart:io' show Platform; - -import 'package:doctor_app_flutter/config/shared_pref_kay.dart'; -import 'package:doctor_app_flutter/core/enum/auth_method_types.dart'; -import 'package:doctor_app_flutter/core/enum/viewstate.dart'; -import 'package:doctor_app_flutter/core/model/imei_details.dart'; -import 'package:doctor_app_flutter/core/viewModel/authentication_view_model.dart'; -import 'package:doctor_app_flutter/core/viewModel/project_view_model.dart'; -import 'package:doctor_app_flutter/models/auth/activation_Code_req_model.dart'; -import 'package:doctor_app_flutter/models/auth/activation_code_for_verification_screen_model.dart'; -import 'package:doctor_app_flutter/models/auth/check_activation_code_request_model.dart'; -import 'package:doctor_app_flutter/models/doctor/clinic_model.dart'; -import 'package:doctor_app_flutter/models/doctor/doctor_profile_model.dart'; -import 'package:doctor_app_flutter/models/doctor/profile_req_Model.dart'; -import 'package:doctor_app_flutter/screens/base/base_view.dart'; -import 'package:doctor_app_flutter/util/date-utils.dart'; -import 'package:doctor_app_flutter/util/dr_app_toast_msg.dart'; -import 'package:doctor_app_flutter/util/translations_delegate_base.dart'; -import 'package:doctor_app_flutter/widgets/auth/sms-popup.dart'; -import 'package:doctor_app_flutter/widgets/shared/app_scaffold_widget.dart'; -import 'package:doctor_app_flutter/widgets/shared/app_texts_widget.dart'; -import 'package:doctor_app_flutter/widgets/shared/buttons/app_buttons_widget.dart'; -import 'package:doctor_app_flutter/widgets/shared/loader/gif_loader_dialog_utils.dart'; -import 'package:doctor_app_flutter/widgets/transitions/fade_page.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:local_auth/auth_strings.dart'; -import 'package:local_auth/local_auth.dart'; -import 'package:provider/provider.dart'; - -import '../../config/size_config.dart'; -import '../../core/viewModel/doctor_profile_view_model.dart'; -import '../../landing_page.dart'; -import '../../routes.dart'; -import '../../util/dr_app_shared_pref.dart'; -import '../../util/helpers.dart'; -import 'method_card.dart'; - -DrAppSharedPreferances sharedPref = new DrAppSharedPreferances(); -Helpers helpers = Helpers(); - -class VerificationMethods extends StatefulWidget { - VerificationMethods({this.changeLoadingState, this.password}); - - final password; - final Function changeLoadingState; - - @override - _VerificationMethodsState createState() => _VerificationMethodsState(); -} - -class _VerificationMethodsState extends State { - - ProjectViewModel projectsProvider; - bool isMoreOption = false; - bool onlySMSBox = false; - var loginTokenID; - DoctorProfileViewModel doctorProfileViewModel; - - bool authenticated; - - AuthMethodTypes fingerPrintBefore; - - AuthMethodTypes selectedOption; - AuthenticationViewModel model; - - final LocalAuthentication auth = LocalAuthentication(); - - @override - void initState() { - super.initState(); - } - - - @override - void didChangeDependencies() async{ - super.didChangeDependencies(); - - } - - @override - Widget build(BuildContext context) { - doctorProfileViewModel = Provider.of(context); - projectsProvider = Provider.of(context); - return BaseView( - onModelReady: (model) async { - this.model = model; - await model.getInitUserInfo(); - }, - builder: (_, model, w) => AppScaffold( - isShowAppBar: false, - baseViewModel: model, - body: SingleChildScrollView( - child: Center( - child: FractionallySizedBox( - // widthFactor: 0.9, - child: Container( - margin: EdgeInsetsDirectional.fromSTEB(30, 0, 30, 0), - - height: SizeConfig.realScreenHeight * .95, - width: SizeConfig.realScreenWidth, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Container( - child: Column( - - children: [ - SizedBox( - height: 100, - ), - model.user != null && isMoreOption == false - ? Column( - mainAxisAlignment: - MainAxisAlignment.spaceEvenly, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - AppText( - TranslationBase.of(context).welcomeBack), - AppText( - Helpers.capitalize(model.user.doctorName), - fontSize: SizeConfig.textMultiplier * 3.5, - fontWeight: FontWeight.bold, - ), - SizedBox( - height: 20, - ), - AppText( - TranslationBase.of(context).accountInfo, - fontSize: SizeConfig.textMultiplier * 2.5, - fontWeight: FontWeight.w600, - ), - SizedBox( - height: 20, - ), - Card( - color: Colors.white, - child: Row( - children: [ - Flexible( - flex: 3, - child: ListTile( - title: Text( - TranslationBase.of(context) - .lastLoginAt, - overflow: - TextOverflow.ellipsis, - style: TextStyle( - fontFamily: 'Poppins', - fontWeight: - FontWeight.w800, - fontSize: 14), - ), - subtitle: AppText( - model.getType( - model.user.logInTypeID, - context), - fontSize: 14, - ))), - Flexible( - flex: 2, - child: ListTile( - title: AppText( - model.user.editedOn != null - ? model.getDate( - DateUtils - .convertStringToDate( - model.user - .editedOn)) - : model.user.createdOn != null - ? model - .getDate(DateUtils - .convertStringToDate( - model.user.createdOn)) - : '--', - textAlign: TextAlign.right, - fontSize: 14, - fontWeight: FontWeight.w800, - ), - subtitle: AppText( - model.user.editedOn != null - ? model.getTime( - DateUtils - .convertStringToDate( - model.user - .editedOn)) - : model.user.createdOn != null - ? model - .getTime(DateUtils - .convertStringToDate( - model.user.createdOn)) - : '--', - textAlign: TextAlign.right, - fontSize: 14, - ), - )) - ], - )), - ], - ) - : Column( - mainAxisAlignment: - MainAxisAlignment.spaceEvenly, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - this.onlySMSBox == false - ? AppText( - TranslationBase.of(context) - .verifyLoginWith, - fontSize: - SizeConfig.textMultiplier * 3.5, - textAlign: TextAlign.left, - ) - : AppText( - TranslationBase.of(context) - .verifyFingerprint2, - fontSize: - SizeConfig.textMultiplier * 2.5, - textAlign: TextAlign.start, - ), - ]), - model.user != null && isMoreOption == false - ? Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment.center, - children: [ - Expanded( - child: InkWell( - onTap: () => { - // TODO check this logic it seem it will create bug to us - - authenticateUser( - AuthMethodTypes - .Fingerprint, - true) - }, - child: MethodCard( - authMethodType: model.user - .logInTypeID == - 4 - ? AuthMethodTypes.FaceID - : model.user.logInTypeID == 2 - ? AuthMethodTypes - .WhatsApp - : model.user.logInTypeID == - 3 - ? AuthMethodTypes - .Fingerprint - : AuthMethodTypes - .SMS, - authenticateUser: - (AuthMethodTypes - authMethodType, - isActive) => - authenticateUser( - authMethodType, - isActive), - )), - ), - Expanded( - child: MethodCard( - authMethodType: - AuthMethodTypes.MoreOptions, - onShowMore: () { - setState(() { - isMoreOption = true; - }); - }, - )) - ]), - ]) - : Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - onlySMSBox == false - ? Row( - mainAxisAlignment: - MainAxisAlignment.center, - children: [ - Expanded( - child: MethodCard( - authMethodType: - AuthMethodTypes.Fingerprint, - authenticateUser: - (AuthMethodTypes - authMethodType, - isActive) => - authenticateUser( - authMethodType, - isActive), - )), - Expanded( - child: MethodCard( - authMethodType: - AuthMethodTypes.FaceID, - authenticateUser: - (AuthMethodTypes - authMethodType, - isActive) => - authenticateUser( - authMethodType, - isActive), - )) - ], - ) - : SizedBox(), - Row( - mainAxisAlignment: - MainAxisAlignment.center, - children: [ - Expanded( - child: MethodCard( - authMethodType: AuthMethodTypes.SMS, - authenticateUser: - (AuthMethodTypes authMethodType, - isActive) => - authenticateUser( - authMethodType, isActive), - )), - Expanded( - child: MethodCard( - authMethodType: - AuthMethodTypes.WhatsApp, - authenticateUser: - (AuthMethodTypes authMethodType, - isActive) => - authenticateUser( - authMethodType, isActive), - )) - ], - ), - ]), - - // ) - ], - ), - ), - Column( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - model.user != null - ? Row( - children: [ - Expanded( - child: AppButton( - title: TranslationBase.of(context) - .useAnotherAccount, - color: Colors.red[700], - onPressed: () { - Navigator.of(context).pushNamed(LOGIN); - }, - )), - ], - ) - : SizedBox(), - ], - ), - ], - ), - ), - ), - ), - ), - )); - } - - sendActivationCodeByOtpNotificationType( - AuthMethodTypes authMethodType) async { - if (authMethodType == AuthMethodTypes.SMS || - authMethodType == AuthMethodTypes.WhatsApp) { - GifLoaderDialogUtils.showMyDialog(context); - - int projectID = await sharedPref.getInt(PROJECT_ID); - // TODO create model for model.loggedUser; - ActivationCodeModel activationCodeModel = ActivationCodeModel( - facilityId: projectID, - memberID: model.loggedUser['List_MemberInformation'][0]['MemberID'], - zipCode: model.loggedUser['ZipCode'], - mobileNumber: model.loggedUser['MobileNumber'], - otpSendType: authMethodType.getTypeIdService().toString(), - password: widget.password); - await model.sendActivationCodeForDoctorApp(activationCodeModel); - if (model.state == ViewState.ErrorLocal) { - Helpers.showErrorToast(model.error); - GifLoaderDialogUtils.hideDialog(context); - } else { - print("VerificationCode : " + - model.activationCodeForDoctorAppRes["VerificationCode"]); - sharedPref.setString(VIDA_AUTH_TOKEN_ID, - model.activationCodeForDoctorAppRes["VidaAuthTokenID"]); - sharedPref.setString(VIDA_REFRESH_TOKEN_ID, - model.activationCodeForDoctorAppRes["VidaRefreshTokenID"]); - sharedPref.setString(LOGIN_TOKEN_ID, - model.activationCodeForDoctorAppRes["LogInTokenID"]); - sharedPref.setString(PASSWORD, widget.password); - GifLoaderDialogUtils.hideDialog(context); - this.startSMSService(authMethodType); - } - } else { - // TODO route to this page with parameters to inicate we should present 2 option - if (Platform.isAndroid && authMethodType == AuthMethodTypes.Fingerprint) { - Helpers.showErrorToast('Your device not support this feature'); - } else {} - } - } - - sendActivationCodeVerificationScreen(AuthMethodTypes authMethodType) async { - GifLoaderDialogUtils.showMyDialog(context); - ActivationCodeForVerificationScreenModel activationCodeModel = - ActivationCodeForVerificationScreenModel( - iMEI: model.user.iMEI, - facilityId: model.user.projectID, - memberID: model.user.doctorID, - zipCode: model.user.outSA == true ? '971' : '966', - mobileNumber: model.user.mobile, - oTPSendType: authMethodType.getTypeIdService(), - isMobileFingerPrint: 1, - vidaAuthTokenID: model.user.vidaAuthTokenID, - vidaRefreshTokenID: model.user.vidaRefreshTokenID); - - await model - .sendActivationCodeVerificationScreen(activationCodeModel); - - if (model.state == ViewState.ErrorLocal) { - GifLoaderDialogUtils.hideDialog(context); - Helpers.showErrorToast(model.error); - } else { - print("VerificationCode : " + - model.activationCodeVerificationScreenRes["VerificationCode"]); - sharedPref.setString(VIDA_AUTH_TOKEN_ID, - model.activationCodeVerificationScreenRes["VidaAuthTokenID"]); - sharedPref.setString( - VIDA_REFRESH_TOKEN_ID, - model.activationCodeVerificationScreenRes["VidaRefreshTokenID"]); - sharedPref.setString(LOGIN_TOKEN_ID, - model.activationCodeVerificationScreenRes["LogInTokenID"]); - if (authMethodType == AuthMethodTypes.SMS || - authMethodType == AuthMethodTypes.WhatsApp) { - GifLoaderDialogUtils.hideDialog(context); - this.startSMSService(authMethodType); - } else { - checkActivationCode(); - } - } - } - - authenticateUser(AuthMethodTypes authMethodType, isActive) { - if (authMethodType == AuthMethodTypes.Fingerprint || - authMethodType == AuthMethodTypes.FaceID) { - fingerPrintBefore = authMethodType; - } - this.selectedOption = - fingerPrintBefore != null ? fingerPrintBefore : authMethodType; - - switch (authMethodType) { - case AuthMethodTypes.SMS: - sendActivationCode(authMethodType); - break; - case AuthMethodTypes.WhatsApp: - sendActivationCode(authMethodType); - break; - case AuthMethodTypes.Fingerprint: - this.loginWithFingerPrintOrFaceID( - AuthMethodTypes.Fingerprint, isActive); - break; - case AuthMethodTypes.FaceID: - this.loginWithFingerPrintOrFaceID(AuthMethodTypes.FaceID, isActive); - break; - default: - break; - } - sharedPref.setInt(OTP_TYPE, selectedOption.getTypeIdService()); - } - - sendActivationCode(AuthMethodTypes authMethodType) async { - if (model.user != null) { - sendActivationCodeVerificationScreen(authMethodType); - } else { - sendActivationCodeByOtpNotificationType(authMethodType); - } - } - - startSMSService(AuthMethodTypes type) { - // TODO improve this logic - new SMSOTP( - context, - type, - model.loggedUser != null ? model.loggedUser['MobileNumber'] : model.user.mobile, - (value) { - showDialog( - context: context, - builder: (BuildContext context) { - return Center( - child: CircularProgressIndicator(), - ); - }); - - this.checkActivationCode(value: value); - }, - () => - { - widget.changeLoadingState(false), - print('Faild..'), - }, - ).displayDialog(context); - } - - loginWithFingerPrintOrFaceID(AuthMethodTypes authMethodTypes, - isActive) async { - if (isActive) { - 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) { - DrAppToastMsg.showErrorToast(e.toString()); - } - if (!mounted) return; - if (model.user != null && (model.user.logInTypeID == 3 || model.user.logInTypeID == 4)) { - this.sendActivationCode(authMethodTypes); - } else { - setState(() { - this.onlySMSBox = true; - }); - } - } - } - - checkActivationCode({value}) async { - CheckActivationCodeRequestModel checkActivationCodeForDoctorApp = - new CheckActivationCodeRequestModel( - zipCode: - model.loggedUser != null ? model.loggedUser['ZipCode'] : model.user.zipCode, - mobileNumber: - model.loggedUser != null ? model.loggedUser['MobileNumber'] : model.user.mobile, - projectID: await sharedPref.getInt(PROJECT_ID) != null - ? await sharedPref.getInt(PROJECT_ID) - : model.user.projectID, - logInTokenID: await sharedPref.getString(LOGIN_TOKEN_ID), - activationCode: value ?? '0000', - oTPSendType: await sharedPref.getInt(OTP_TYPE), - generalid: "Cs2020@2016\$2958"); - await model - .checkActivationCodeForDoctorApp(checkActivationCodeForDoctorApp); - - if (model.state == ViewState.ErrorLocal) { - Navigator.pop(context); - Helpers.showErrorToast(model.error); - } else { - sharedPref.setString( - TOKEN, - model - .checkActivationCodeForDoctorAppRes['AuthenticationTokenID']); - if (model.checkActivationCodeForDoctorAppRes['List_DoctorProfile'] != - null) { - loginProcessCompleted(model.checkActivationCodeForDoctorAppRes['List_DoctorProfile'][0]); - sharedPref.setObj( - CLINIC_NAME, - model - .checkActivationCodeForDoctorAppRes['List_DoctorsClinic']); - } else { - sharedPref.setObj( - CLINIC_NAME, - model - .checkActivationCodeForDoctorAppRes['List_DoctorsClinic']); - ClinicModel clinic = ClinicModel.fromJson(model.checkActivationCodeForDoctorAppRes['List_DoctorsClinic'][0]); - getDocProfiles(clinic); - } - } - } - - loginProcessCompleted(Map profile) { - var doctor = DoctorProfileModel.fromJson(profile); - doctorProfileViewModel.setDoctorProfile(doctor); - sharedPref.setObj(DOCTOR_PROFILE, profile); - projectsProvider.isLogin = true; - - Navigator.pushAndRemoveUntil( - context, - FadePage( - page: LandingPage(), - ), - (r) => false); - } - - getDocProfiles(ClinicModel clinicInfo) { - ProfileReqModel docInfo = new ProfileReqModel( - doctorID: clinicInfo.doctorID, - clinicID: clinicInfo.clinicID, - license: true, - projectID: clinicInfo.projectID, - tokenID: '', - languageID: 2); - doctorProfileViewModel.getDocProfiles(docInfo.toJson()).then((res) { - if (res['MessageStatus'] == 1) { - loginProcessCompleted(res['DoctorProfileList'][0]); - } else { - // changeLoadingState(false); - Helpers.showErrorToast(res['ErrorEndUserMessage']); - } - }).catchError((err) { - Helpers.showErrorToast(err); - }); - } -}