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/viewModel/authentication_view_model.dart'; import 'package:doctor_app_flutter/core/viewModel/project_view_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 '../../widgets/auth/method_card.dart'; DrAppSharedPreferances sharedPref = new DrAppSharedPreferances(); Helpers helpers = Helpers(); class VerificationMethodsScreen extends StatefulWidget { VerificationMethodsScreen({this.changeLoadingState, this.password}); final password; final Function changeLoadingState; @override _VerificationMethodsScreenState createState() => _VerificationMethodsScreenState(); } class _VerificationMethodsScreenState 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); await model.sendActivationCodeForDoctorApp(authMethodType:authMethodType, password: widget.password ); if (model.state == ViewState.ErrorLocal) { Helpers.showErrorToast(model.error); GifLoaderDialogUtils.hideDialog(context); } else { model.setDataAfterSendActivationSuccsess(model.activationCodeForDoctorAppRes); 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 { model.setDataAfterSendActivationSuccsess(model.activationCodeVerificationScreenRes); 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.listDoctorsClinic.isNotEmpty) { loginProcessCompleted(model.checkActivationCodeForDoctorAppRes.list_DoctorProfile[0]); sharedPref.setObj( CLINIC_NAME, model .checkActivationCodeForDoctorAppRes.listDoctorsClinic); } else { sharedPref.setObj( CLINIC_NAME, model .checkActivationCodeForDoctorAppRes.listDoctorsClinic); ClinicModel clinic = ClinicModel.fromJson(model.checkActivationCodeForDoctorAppRes.listDoctorsClinic[0].toJson()); 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 { Helpers.showErrorToast(res['ErrorEndUserMessage']); } }).catchError((err) { Helpers.showErrorToast(err); }); } }