diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 878a1850..2f4607e0 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -322,4 +322,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 649616dc336b3659ac6b2b25159d8e488e042b69 -COCOAPODS: 1.10.1 +COCOAPODS: 1.10.0.rc.1 diff --git a/lib/core/enum/auth_method_types.dart b/lib/core/enum/auth_method_types.dart index 3faff89c..82577eeb 100644 --- a/lib/core/enum/auth_method_types.dart +++ b/lib/core/enum/auth_method_types.dart @@ -21,4 +21,26 @@ extension SelectedAuthMethodTypesService on AuthMethodTypes { } } + + // ignore: missing_return + static getMethodsTypeService( int typeId) { + switch (typeId) { + case 1: + return AuthMethodTypes.SMS; + break; + case 2: + return AuthMethodTypes.WhatsApp; + break; + case 3: + return AuthMethodTypes.Fingerprint; + break; + case 4: + return AuthMethodTypes.FaceID; + break; + case 5: + return AuthMethodTypes.MoreOptions; + break; + + } + } } \ No newline at end of file diff --git a/lib/core/model/auth/check_activation_code_for_doctor_app_response_model.dart b/lib/core/model/auth/check_activation_code_for_doctor_app_response_model.dart index 283e617f..c5ff29e6 100644 --- a/lib/core/model/auth/check_activation_code_for_doctor_app_response_model.dart +++ b/lib/core/model/auth/check_activation_code_for_doctor_app_response_model.dart @@ -1,24 +1,33 @@ +import 'package:doctor_app_flutter/models/doctor/doctor_profile_model.dart'; + class CheckActivationCodeForDoctorAppResponseModel { String authenticationTokenID; List listDoctorsClinic; - List list_DoctorProfile; + List listDoctorProfile; MemberInformation memberInformation; CheckActivationCodeForDoctorAppResponseModel( {this.authenticationTokenID, - this.listDoctorsClinic, - this.memberInformation}); + this.listDoctorsClinic, + this.memberInformation}); CheckActivationCodeForDoctorAppResponseModel.fromJson( Map json) { authenticationTokenID = json['AuthenticationTokenID']; - list_DoctorProfile = json['List_DoctorProfile']; if (json['List_DoctorsClinic'] != null) { listDoctorsClinic = new List(); json['List_DoctorsClinic'].forEach((v) { listDoctorsClinic.add(new ListDoctorsClinic.fromJson(v)); }); } + + if (json['List_DoctorProfile'] != null) { + listDoctorProfile = new List(); + json['List_DoctorProfile'].forEach((v) { + listDoctorProfile.add(new DoctorProfileModel.fromJson(v)); + }); + } + memberInformation = json['memberInformation'] != null ? new MemberInformation.fromJson(json['memberInformation']) : null; @@ -27,11 +36,15 @@ class CheckActivationCodeForDoctorAppResponseModel { Map toJson() { final Map data = new Map(); data['AuthenticationTokenID'] = this.authenticationTokenID; - data['List_DoctorProfile'] = this.list_DoctorProfile; if (this.listDoctorsClinic != null) { data['List_DoctorsClinic'] = this.listDoctorsClinic.map((v) => v.toJson()).toList(); } + + if (this.listDoctorProfile != null) { + data['List_DoctorProfile'] = + this.listDoctorProfile.map((v) => v.toJson()).toList(); + } if (this.memberInformation != null) { data['memberInformation'] = this.memberInformation.toJson(); } @@ -47,13 +60,12 @@ class ListDoctorsClinic { bool isActive; String clinicName; - ListDoctorsClinic( - {this.setupID, - this.projectID, - this.doctorID, - this.clinicID, - this.isActive, - this.clinicName}); + ListDoctorsClinic({this.setupID, + this.projectID, + this.doctorID, + this.clinicID, + this.isActive, + this.clinicName}); ListDoctorsClinic.fromJson(Map json) { setupID = json['SetupID']; @@ -87,16 +99,15 @@ class MemberInformation { String preferredLanguage; List roles; - MemberInformation( - {this.clinics, - this.doctorId, - this.email, - this.employeeId, - this.memberId, - this.memberName, - this.memberNameArabic, - this.preferredLanguage, - this.roles}); + MemberInformation({this.clinics, + this.doctorId, + this.email, + this.employeeId, + this.memberId, + this.memberName, + this.memberNameArabic, + this.preferredLanguage, + this.roles}); MemberInformation.fromJson(Map json) { if (json['clinics'] != null) { diff --git a/lib/core/service/authentication_service.dart b/lib/core/service/authentication_service.dart index 9f67a3b8..d20f5dbf 100644 --- a/lib/core/service/authentication_service.dart +++ b/lib/core/service/authentication_service.dart @@ -10,6 +10,8 @@ import 'package:doctor_app_flutter/core/viewModel/doctor_profile_view_model.dart import 'package:doctor_app_flutter/core/model/auth/activation_code_for_verification_screen_model.dart'; import 'package:doctor_app_flutter/core/model/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/models/doctor/user_model.dart'; import 'package:provider/provider.dart'; @@ -30,6 +32,9 @@ class AuthenticationService extends BaseService { CheckActivationCodeForDoctorAppResponseModel get checkActivationCodeForDoctorAppRes => _checkActivationCodeForDoctorAppRes; Map _insertDeviceImeiRes = {}; + List _doctorProfilesList = []; + List get doctorProfilesList => _doctorProfilesList; + Future selectDeviceImei(imei) async { try { await baseAppClient.post(SELECT_DEVICE_IMEI, @@ -144,4 +149,23 @@ class AuthenticationService extends BaseService { super.error = error; } } + + Future getDoctorProfileBasedOnClinic(ProfileReqModel profileReqModel)async { + hasError = false; + try { + await baseAppClient.post(GET_DOC_PROFILES, + onSuccess: (dynamic response, int statusCode) { + _doctorProfilesList.clear(); + response['DoctorProfileList'].forEach((v) { + _doctorProfilesList.add(DoctorProfileModel.fromJson(v)); + }); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body: profileReqModel.toJson()); + } catch (error) { + hasError = true; + super.error = error; + } + } } diff --git a/lib/core/viewModel/authentication_view_model.dart b/lib/core/viewModel/authentication_view_model.dart index 228a63e7..b5f61b05 100644 --- a/lib/core/viewModel/authentication_view_model.dart +++ b/lib/core/viewModel/authentication_view_model.dart @@ -3,36 +3,62 @@ 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/auth/activation_Code_req_model.dart'; +import 'package:doctor_app_flutter/core/model/auth/activation_code_for_verification_screen_model.dart'; import 'package:doctor_app_flutter/core/model/auth/check_activation_code_for_doctor_app_response_model.dart'; +import 'package:doctor_app_flutter/core/model/auth/check_activation_code_request_model.dart'; +import 'package:doctor_app_flutter/core/model/auth/imei_details.dart'; import 'package:doctor_app_flutter/core/model/auth/insert_imei_model.dart'; import 'package:doctor_app_flutter/core/model/auth/new_login_information_response_model.dart'; import 'package:doctor_app_flutter/core/model/auth/send_activation_code_for_doctor_app_response_model.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'; -import 'package:doctor_app_flutter/core/model/auth/imei_details.dart'; import 'package:doctor_app_flutter/core/service/authentication_service.dart'; import 'package:doctor_app_flutter/core/service/hospitals/hospitals_service.dart'; import 'package:doctor_app_flutter/core/viewModel/base_view_model.dart'; import 'package:doctor_app_flutter/locator.dart'; -import 'package:doctor_app_flutter/core/model/auth/activation_code_for_verification_screen_model.dart'; -import 'package:doctor_app_flutter/core/model/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/models/doctor/user_model.dart'; +import 'package:doctor_app_flutter/util/dr_app_toast_msg.dart'; import 'package:doctor_app_flutter/util/translations_delegate_base.dart'; -import 'package:intl/intl.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 'doctor_profile_view_model.dart'; class AuthenticationViewModel extends BaseViewModel { AuthenticationService _authService = locator(); HospitalsService _hospitalsService = locator(); List get imeiDetails => _authService.dashboardItemsList; + List get hospitals => _hospitalsService.hospitals; + NewLoginInformationModel get loginInfo => _authService.loginInfo; - SendActivationCodeForDoctorAppResponseModel get activationCodeVerificationScreenRes => _authService.activationCodeVerificationScreenRes; - SendActivationCodeForDoctorAppResponseModel get activationCodeForDoctorAppRes => _authService.activationCodeForDoctorAppRes; - CheckActivationCodeForDoctorAppResponseModel get checkActivationCodeForDoctorAppRes => _authService.checkActivationCodeForDoctorAppRes; + List get doctorProfilesList => _authService.doctorProfilesList; + SendActivationCodeForDoctorAppResponseModel + get activationCodeVerificationScreenRes => + _authService.activationCodeVerificationScreenRes; + + SendActivationCodeForDoctorAppResponseModel + get activationCodeForDoctorAppRes => + _authService.activationCodeForDoctorAppRes; + + CheckActivationCodeForDoctorAppResponseModel + get checkActivationCodeForDoctorAppRes => + _authService.checkActivationCodeForDoctorAppRes; NewLoginInformationModel loggedUser; GetIMEIDetailsModel user; + + UserModel userInfo = UserModel(); + final LocalAuthentication auth = LocalAuthentication(); + List _availableBiometrics; + + Future selectDeviceImei(imei) async { setState(ViewState.Busy); await _authService.selectDeviceImei(imei); @@ -88,8 +114,13 @@ class AuthenticationViewModel extends BaseViewModel { if (_authService.hasError) { error = _authService.error; setState(ViewState.ErrorLocal); - } else + } else { + sharedPref.setInt(PROJECT_ID, userInfo.projectID); + saveObjToString(LOGGED_IN_USER, loginInfo); + sharedPref.remove(LAST_LOGIN_USER); + sharedPref.setString(TOKEN, loginInfo.logInTokenID); setState(ViewState.Idle); + } } Future sendActivationCodeVerificationScreen( AuthMethodTypes authMethodType) async { @@ -168,21 +199,6 @@ class AuthenticationViewModel extends BaseViewModel { setState(ViewState.Idle); } - - //TODO Elham remove it - getDate(DateTime date) { - final DateFormat formatter = DateFormat('dd MMM yyyy'); - - return formatter.format(date); - } - //TODO Elham remove it - getTime(DateTime date) { - final DateFormat formatter = DateFormat('HH:mm a'); - - return formatter.format(date); - } - - getType(type, context) { switch (type) { case 1: @@ -214,17 +230,16 @@ class AuthenticationViewModel extends BaseViewModel { var localLoggedUser = await sharedPref.getObj(LOGGED_IN_USER); if(localLoggedUser!= null) { loggedUser = NewLoginInformationModel.fromJson(localLoggedUser); - } var lastLogin = await sharedPref.getObj(LAST_LOGIN_USER); if (lastLogin != null) { user = GetIMEIDetailsModel.fromJson(lastLogin); } setState(ViewState.Idle); - } - setDataAfterSendActivationSuccsess(SendActivationCodeForDoctorAppResponseModel sendActivationCodeForDoctorAppResponseModel){ + setDataAfterSendActivationSuccsess( + SendActivationCodeForDoctorAppResponseModel sendActivationCodeForDoctorAppResponseModel) { print("VerificationCode : " + sendActivationCodeForDoctorAppResponseModel.verificationCode); sharedPref.setString(VIDA_AUTH_TOKEN_ID, @@ -234,4 +249,93 @@ class AuthenticationViewModel extends BaseViewModel { sharedPref.setString(LOGIN_TOKEN_ID, sendActivationCodeForDoctorAppResponseModel.logInTokenID); } + + saveObjToString(String key, value) async { + sharedPref.setObj(key, value); + } + + showIOSAuthMessages() async { + const iosStrings = const IOSAuthMessages( + cancelButton: 'cancel', + goToSettingsButton: 'settings', + goToSettingsDescription: 'Please set up your Touch ID.', + lockOut: 'Please Enable Your Touch ID'); + + try { + await auth.authenticateWithBiometrics( + localizedReason: 'Scan your fingerprint to authenticate', + useErrorDialogs: true, + stickyAuth: true, + iOSAuthStrings: iosStrings); + } on PlatformException catch (e) { + DrAppToastMsg.showErrorToast(e.toString()); + } + } + + localSetDoctorProfile(DoctorProfileModel profile) { + super.setDoctorProfile(profile); + //TODO: Remove it when we remove Doctor Profile View Model and start to use profile form base view model + Provider.of(AppGlobal.CONTEX, listen: false) + .setDoctorProfile(profile); + } + + Future getDoctorProfileBasedOnClinic(ClinicModel clinicInfo) async { + ProfileReqModel docInfo = new ProfileReqModel( + doctorID: clinicInfo.doctorID, + clinicID: clinicInfo.clinicID, + license: true, + projectID: clinicInfo.projectID, + tokenID: '', + languageID: 2); + await _authService.getDoctorProfileBasedOnClinic(docInfo); + if (_authService.hasError) { + error = _authService.error; + setState(ViewState.ErrorLocal); + } else { + localSetDoctorProfile(doctorProfilesList.first); + setState(ViewState.Idle); + } + } + + onCheckActivationCodeSuccess() async { + sharedPref.setString( + TOKEN, + checkActivationCodeForDoctorAppRes.authenticationTokenID); + if (checkActivationCodeForDoctorAppRes.listDoctorProfile != null && + checkActivationCodeForDoctorAppRes.listDoctorProfile + .isNotEmpty) { + localSetDoctorProfile( + checkActivationCodeForDoctorAppRes.listDoctorProfile[0]); + + + } else { + sharedPref.setObj( + CLINIC_NAME, + checkActivationCodeForDoctorAppRes.listDoctorsClinic); + ClinicModel clinic = ClinicModel.fromJson( + checkActivationCodeForDoctorAppRes.listDoctorsClinic[0] + .toJson()); + await getDoctorProfileBasedOnClinic(clinic); + } + } + + Future checkIfBiometricAvailable(BiometricType biometricType) async { + bool isAvailable = false; + await _getAvailableBiometrics(); + if (_availableBiometrics != null) { + for (var i = 0; i < _availableBiometrics.length; i++) { + if (biometricType == _availableBiometrics[i]) isAvailable = true; + } + } + return isAvailable; + } + + Future _getAvailableBiometrics() async { + try { + _availableBiometrics = await auth.getAvailableBiometrics(); + } on PlatformException catch (e) { + print(e); + } + } + } diff --git a/lib/core/viewModel/base_view_model.dart b/lib/core/viewModel/base_view_model.dart index 43e83c9b..fe4dbd22 100644 --- a/lib/core/viewModel/base_view_model.dart +++ b/lib/core/viewModel/base_view_model.dart @@ -45,5 +45,10 @@ class BaseViewModel extends ChangeNotifier { } else { return doctorProfile; } -} + } + + setDoctorProfile(DoctorProfileModel doctorProfile){ + sharedPref.setObj(DOCTOR_PROFILE, doctorProfile); + doctorProfile = doctorProfile; + } } diff --git a/lib/core/viewModel/doctor_profile_view_model.dart b/lib/core/viewModel/doctor_profile_view_model.dart index d336dd8d..4dcaf050 100644 --- a/lib/core/viewModel/doctor_profile_view_model.dart +++ b/lib/core/viewModel/doctor_profile_view_model.dart @@ -1,14 +1,19 @@ import 'package:doctor_app_flutter/client/base_app_client.dart'; import 'package:doctor_app_flutter/config/config.dart'; import 'package:doctor_app_flutter/config/shared_pref_kay.dart'; +import 'package:doctor_app_flutter/core/service/authentication_service.dart'; import 'package:doctor_app_flutter/core/viewModel/base_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 '../../locator.dart'; + enum APP_STATUS { LOADING, UNAUTHENTICATED, AUTHENTICATED } class DoctorProfileViewModel extends BaseViewModel { List doctorsClinicList = []; + AuthenticationService _authService = locator(); + String selectedClinicName; bool isLogin = false; diff --git a/lib/root_page.dart b/lib/root_page.dart index 7df1b7cb..3b47290b 100644 --- a/lib/root_page.dart +++ b/lib/root_page.dart @@ -21,7 +21,7 @@ class RootPage extends StatelessWidget { ); break; case APP_STATUS.UNAUTHENTICATED: - return Loginsreen(); + return LoginScreen(); break; case APP_STATUS.AUTHENTICATED: return LandingPage(); diff --git a/lib/routes.dart b/lib/routes.dart index 90e061b8..5ec36ae3 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -64,7 +64,7 @@ const String RADIOLOGY_PATIENT = 'radiology-patient'; var routes = { ROOT: (_) => RootPage(), HOME: (_) => LandingPage(), - LOGIN: (_) => Loginsreen(), + LOGIN: (_) => LoginScreen(), VERIFICATION_METHODS: (_) => VerificationMethodsScreen(), PATIENTS_PROFILE: (_) => PatientProfileScreen(), LAB_RESULT: (_) => LabsHomePage(), diff --git a/lib/screens/auth/login_screen.dart b/lib/screens/auth/login_screen.dart index 91af7a2f..429aff5a 100644 --- a/lib/screens/auth/login_screen.dart +++ b/lib/screens/auth/login_screen.dart @@ -1,4 +1,3 @@ -import 'dart:async'; import 'dart:io'; import 'package:doctor_app_flutter/config/config.dart'; @@ -9,7 +8,6 @@ import 'package:doctor_app_flutter/core/model/hospitals/get_hospitals_response_m 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'; @@ -24,20 +22,18 @@ import 'package:flutter/material.dart'; import 'package:hexcolor/hexcolor.dart'; import 'package:provider/provider.dart'; -import '../../lookups/auth_lookup.dart'; import '../../util/dr_app_shared_pref.dart'; -import '../../widgets/auth/auth_header.dart'; import '../../widgets/shared/app_scaffold_widget.dart'; + //TODO Elham remove it DrAppSharedPreferances sharedPref = new DrAppSharedPreferances(); -//TODO Elham change the name -class Loginsreen extends StatefulWidget { + +class LoginScreen extends StatefulWidget { @override - _LoginsreenState createState() => _LoginsreenState(); + _LoginScreenState createState() => _LoginScreenState(); } -class _LoginsreenState extends State { - +class _LoginScreenState extends State { String platformImei; final FirebaseMessaging _firebaseMessaging = FirebaseMessaging(); bool _isLoading = true; @@ -50,9 +46,7 @@ class _LoginsreenState extends State { List projectsList = []; FocusNode focusPass = FocusNode(); FocusNode focusProject = FocusNode(); - // HospitalViewModel hospitalViewModel; - //TODO Elham to change it ti UserModel - var userInfo = UserModel(); + @override void initState() { @@ -99,11 +93,7 @@ class _LoginsreenState extends State { @override Widget build(BuildContext context) { projectViewModel = Provider.of(context); - - return BaseView( - //TODO Elham remove it - onModelReady: (model) => {}, builder: (_, model, w) => AppScaffold( baseViewModel: model, @@ -123,7 +113,71 @@ class _LoginsreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ - AuthHeader(loginType.knownUser), + //TODO Use App Text rather than text + Container( + + child: Column( + crossAxisAlignment: CrossAxisAlignment + .start, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment + .start, + children: [ + SizedBox( + height: 30, + ), + ], + ), + Column( + crossAxisAlignment: CrossAxisAlignment + .start, children: [ + SizedBox( + height: 10, + ), + Text( + TranslationBase + .of(context) + .welcomeTo, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight + .w600, + fontFamily: 'Poppins'), + ), + Text( + TranslationBase + .of(context) + .drSulaimanAlHabib, + style: TextStyle( + fontWeight: FontWeight + .w800, + fontSize: SizeConfig + .isMobile + ? 24 + : SizeConfig + .realScreenWidth * + 0.029, + fontFamily: 'Poppins'), + ), + + Text( + "Doctor App", + style: TextStyle( + fontSize: + SizeConfig.isMobile + ? 16 + : SizeConfig + .realScreenWidth * + 0.030, + fontWeight: FontWeight + .w800, + color: HexColor( + '#B8382C')), + ), + ]), + ], + )), SizedBox( height: 40, ), @@ -203,7 +257,7 @@ class _LoginsreenState extends State { onSaved: (value) { if (value != null) setState(() { - userInfo + model.userInfo .userID = value .trim(); @@ -212,7 +266,7 @@ class _LoginsreenState extends State { onChanged: (value) { if (value != null) setState(() { - userInfo + model.userInfo .userID = value .trim(); @@ -276,7 +330,7 @@ class _LoginsreenState extends State { if (value != null) setState(() { - userInfo + model.userInfo .password = value; }); @@ -286,7 +340,7 @@ class _LoginsreenState extends State { if (value != null) setState(() { - userInfo + model.userInfo .password = value; }); @@ -300,11 +354,12 @@ class _LoginsreenState extends State { context, projectsList, 'facilityName', - onSelectProject); + onSelectProject, + model); }, onTap: () { this.getProjects( - userInfo + model.userInfo .userID, model); }, ) @@ -352,7 +407,8 @@ class _LoginsreenState extends State { context, projectsList, 'facilityName', - onSelectProject); + onSelectProject, + model); }, validator: ( value) { @@ -424,9 +480,10 @@ class _LoginsreenState extends State { .login, color: HexColor( '#D02127'), - disabled: userInfo + disabled: model.userInfo .userID == null || - userInfo.password == + model.userInfo + .password == null, fontWeight: FontWeight .bold, @@ -445,7 +502,7 @@ class _LoginsreenState extends State { ]) : Center(child: AppLoaderWidget()), ), - )); + ), ); } SizedBox buildSizedBox() { @@ -459,44 +516,28 @@ class _LoginsreenState extends State { if (loginFormKey.currentState.validate()) { loginFormKey.currentState.save(); GifLoaderDialogUtils.showMyDialog(context); - sharedPref.setInt(PROJECT_ID, userInfo.projectID); - //TODO Elham move the sharedPref to view model - await model.login(userInfo); + await model.login(model.userInfo); if (model.state == ViewState.ErrorLocal) { GifLoaderDialogUtils.hideDialog(context); Helpers.showErrorToast(model.error); - } else { - saveObjToString(LOGGED_IN_USER, model.loginInfo); - sharedPref.remove(LAST_LOGIN_USER); - sharedPref.setString(TOKEN, model.loginInfo.logInTokenID); - //TODO Elham move the sharedPref to view model GifLoaderDialogUtils.hideDialog(context); Navigator.of(context).pushReplacement( MaterialPageRoute( - builder: (BuildContext context) => VerificationMethodsScreen( - password: userInfo.password, + builder: (BuildContext context) => + VerificationMethodsScreen( + password: model.userInfo.password, ), ), ); } } } - //TODO Elham to it view model - Future setSharedPref(key, value) async { - sharedPref.setString(key, value).then((success) { - }); - } - -//TODO Elham to it view model - saveObjToString(String key, value) async { - sharedPref.setObj(key, value); - } - onSelectProject(index) { + onSelectProject(index, AuthenticationViewModel model) { setState(() { - userInfo.projectID = projectsList[index].facilityId; + model.userInfo.projectID = projectsList[index].facilityId; projectIdController.text = projectsList[index].facilityName; }); @@ -510,7 +551,7 @@ class _LoginsreenState extends State { if(model.state == ViewState.Idle) { projectsList = model.hospitals; setState(() { - userInfo.projectID = projectsList[0].facilityId; + model.userInfo.projectID = projectsList[0].facilityId; projectIdController.text = projectsList[0].facilityName; }); } diff --git a/lib/screens/auth/verification_methods_screen.dart b/lib/screens/auth/verification_methods_screen.dart index 5105707a..1c16bda9 100644 --- a/lib/screens/auth/verification_methods_screen.dart +++ b/lib/screens/auth/verification_methods_screen.dart @@ -5,12 +5,8 @@ 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'; @@ -19,9 +15,7 @@ import 'package:doctor_app_flutter/widgets/shared/buttons/app_buttons_widget.dar 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:hexcolor/hexcolor.dart'; import 'package:provider/provider.dart'; import '../../config/size_config.dart'; @@ -30,17 +24,15 @@ import '../../landing_page.dart'; import '../../routes.dart'; import '../../util/dr_app_shared_pref.dart'; import '../../util/helpers.dart'; -import '../../widgets/auth/method_card.dart'; +import '../../widgets/auth/verification_methods_list.dart'; DrAppSharedPreferances sharedPref = new DrAppSharedPreferances(); Helpers helpers = Helpers(); class VerificationMethodsScreen extends StatefulWidget { - VerificationMethodsScreen({this.changeLoadingState, this.password}); + VerificationMethodsScreen({this.password}); final password; - //TODO Elham remove this fun - final Function changeLoadingState; @override _VerificationMethodsScreenState createState() => _VerificationMethodsScreenState(); @@ -51,31 +43,11 @@ 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(); - - //TODO Elham remove this fun - @override - void initState() { - super.initState(); - } - -//TODO Elham remove this fun - @override - void didChangeDependencies() async{ - super.didChangeDependencies(); - - } - @override Widget build(BuildContext context) { doctorProfileViewModel = Provider.of(context); @@ -93,7 +65,6 @@ class _VerificationMethodsScreenState extends State { child: FractionallySizedBox( child: Container( margin: EdgeInsetsDirectional.fromSTEB(30, 0, 30, 0), - height: SizeConfig.realScreenHeight * .95, width: SizeConfig.realScreenWidth, child: Column( @@ -102,7 +73,6 @@ class _VerificationMethodsScreenState extends State { children: [ Container( child: Column( - children: [ SizedBox( height: 100, @@ -146,54 +116,61 @@ class _VerificationMethodsScreenState extends State { 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, - ), - )) - ], - )), + 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 + ? DateUtils.getDayMonthYearDateFormatted( + DateUtils.convertStringToDate( + model.user + .editedOn)) + : model.user.createdOn != + null + ? DateUtils.getDayMonthYearDateFormatted( + DateUtils.convertStringToDate(model + .user + .createdOn)) + : '--', + textAlign: + TextAlign.right, + fontSize: 14, + fontWeight: + FontWeight.w800, + ), + subtitle: AppText( + model.user.editedOn != + null + ? DateUtils.getHour( + DateUtils.convertStringToDate( + model.user + .editedOn)) + : model.user.createdOn != + null + ? DateUtils.getHour( + DateUtils.convertStringToDate(model + .user + .createdOn)) + : '--', + textAlign: + TextAlign.right, + fontSize: 14, + ), + )) + ], + )), ], ) : Column( @@ -228,43 +205,39 @@ class _VerificationMethodsScreenState extends State { 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, + onTap: () => + { + // TODO check this logic it seem it will create bug to us + authenticateUser( + AuthMethodTypes + .Fingerprint, true) + }, + child: VerificationMethodsList( + model: model, + authMethodType: SelectedAuthMethodTypesService + .getMethodsTypeService( + model.user + .logInTypeID), authenticateUser: (AuthMethodTypes - authMethodType, - isActive) => - authenticateUser( - authMethodType, - isActive), + authMethodType, + isActive) => + authenticateUser( + authMethodType, + isActive), )), ), Expanded( - child: MethodCard( - authMethodType: + child: VerificationMethodsList( + model: model, + authMethodType: AuthMethodTypes.MoreOptions, - onShowMore: () { - setState(() { - isMoreOption = true; - }); - }, - )) + onShowMore: () { + setState(() { + isMoreOption = true; + }); + }, + )) ]), ]) : Column( @@ -277,29 +250,31 @@ class _VerificationMethodsScreenState extends State { MainAxisAlignment.center, children: [ Expanded( - child: MethodCard( - authMethodType: + child: VerificationMethodsList( + model: model, + authMethodType: AuthMethodTypes.Fingerprint, - authenticateUser: - (AuthMethodTypes - authMethodType, - isActive) => + authenticateUser: + (AuthMethodTypes + authMethodType, + isActive) => authenticateUser( authMethodType, isActive), - )), + )), Expanded( - child: MethodCard( - authMethodType: + child: VerificationMethodsList( + model: model, + authMethodType: AuthMethodTypes.FaceID, - authenticateUser: - (AuthMethodTypes - authMethodType, - isActive) => + authenticateUser: + (AuthMethodTypes + authMethodType, + isActive) => authenticateUser( authMethodType, isActive), - )) + )) ], ) : SizedBox(), @@ -308,60 +283,79 @@ class _VerificationMethodsScreenState extends State { MainAxisAlignment.center, children: [ Expanded( - child: MethodCard( - authMethodType: AuthMethodTypes.SMS, - authenticateUser: - (AuthMethodTypes authMethodType, - isActive) => + child: VerificationMethodsList( + model: model, + authMethodType: AuthMethodTypes + .SMS, + authenticateUser: + ( + AuthMethodTypes authMethodType, + isActive) => authenticateUser( authMethodType, isActive), - )), + )), Expanded( - child: MethodCard( - authMethodType: + child: VerificationMethodsList( + model: model, + authMethodType: AuthMethodTypes.WhatsApp, - authenticateUser: - (AuthMethodTypes authMethodType, - isActive) => + authenticateUser: + ( + AuthMethodTypes authMethodType, + isActive) => authenticateUser( authMethodType, isActive), - )) + )) ], ), - ]), + ]), // ) ], ), ), - //TODO Elham move it to bottom sheet - 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(), - ], - ), ], ), - ), + ), ), ), ), - )); + bottomSheet: model.user == null ? SizedBox(height: 0,) : Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all( + Radius.circular(0.0), + ), + border: Border.all( + color: HexColor('#707070'), + width: 0), + ), + height: 90, + width: double.infinity, + child: Center( + child: FractionallySizedBox( + widthFactor: 0.9, + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + AppButton( + title: TranslationBase + .of(context) + .useAnotherAccount, + color: Colors.red[700], + onPressed: () { + Navigator.of(context).pushNamed(LOGIN); + }, + ), + + SizedBox(height: 25,) + ], + ), + ), + ),), + ) + + ); } sendActivationCodeByOtpNotificationType( @@ -391,8 +385,6 @@ class _VerificationMethodsScreenState extends State { sendActivationCodeVerificationScreen(AuthMethodTypes authMethodType) async { GifLoaderDialogUtils.showMyDialog(context); - - await model .sendActivationCodeVerificationScreen(authMethodType); @@ -466,32 +458,21 @@ class _VerificationMethodsScreenState extends State { }, () => { - widget.changeLoadingState(false), print('Faild..'), }, ).displayDialog(context); } -//TODO Elham move it to view model 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()); - } + await model.showIOSAuthMessages(); if (!mounted) return; - if (model.user != null && (model.user.logInTypeID == 3 || model.user.logInTypeID == 4)) { + if (model.user != null && + (SelectedAuthMethodTypesService.getMethodsTypeService( + model.user.logInTypeID) == + AuthMethodTypes.Fingerprint || + SelectedAuthMethodTypesService.getMethodsTypeService( + model.user.logInTypeID) == AuthMethodTypes.FaceID)) { this.sendActivationCode(authMethodTypes); } else { setState(() { @@ -502,64 +483,30 @@ class _VerificationMethodsScreenState extends State { } checkActivationCode({value}) async { - - await model.checkActivationCodeForDoctorApp(activationCode:value ); - + await model.checkActivationCodeForDoctorApp(activationCode: value); if (model.state == ViewState.ErrorLocal) { Navigator.pop(context); Helpers.showErrorToast(model.error); } else { - sharedPref.setString( - TOKEN, model.checkActivationCodeForDoctorAppRes.authenticationTokenID); - //TODO Elham check the logic - 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); - } + await model.onCheckActivationCodeSuccess(); + navigateToLandingPage(); } } - //TODO Elham move it to view model - 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); - } -//TODO Elham move it to view model - 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); - }); + navigateToLandingPage() { + if (model.state == ViewState.ErrorLocal) { + Helpers.showErrorToast(model.error); + } else { + projectsProvider.isLogin = true; + + Navigator.pushAndRemoveUntil( + context, + FadePage( + page: LandingPage(), + ), (r) => false); + } } + + } diff --git a/lib/util/helpers.dart b/lib/util/helpers.dart index 6967a8aa..eb702d8d 100644 --- a/lib/util/helpers.dart +++ b/lib/util/helpers.dart @@ -1,6 +1,8 @@ import 'package:connectivity/connectivity.dart'; import 'package:doctor_app_flutter/config/config.dart'; import 'package:doctor_app_flutter/config/shared_pref_kay.dart'; +import 'package:doctor_app_flutter/core/model/hospitals/get_hospitals_response_model.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/list_doctor_working_hours_table_model.dart'; import 'package:doctor_app_flutter/screens/auth/login_screen.dart'; @@ -22,7 +24,7 @@ class Helpers { static int cupertinoPickerIndex = 0; get currentLanguage => null; - static showCupertinoPicker(context, items, decKey, onSelectFun) { + static showCupertinoPicker(context, List items, decKey, onSelectFun, AuthenticationViewModel model) { showModalBottomSheet( isDismissible: false, context: context, @@ -53,7 +55,7 @@ class Helpers { ), onPressed: () { Navigator.pop(context); - onSelectFun(cupertinoPickerIndex); + onSelectFun(cupertinoPickerIndex, model); }, ) ], @@ -63,7 +65,7 @@ class Helpers { height: SizeConfig.realScreenHeight * 0.3, color: Color(0xfff7f7f7), child: - buildPickerItems(context, items, decKey, onSelectFun)) + buildPickerItems(context, items, decKey, onSelectFun, model)) ], ), ); @@ -73,14 +75,14 @@ class Helpers { static TextStyle textStyle(context) => TextStyle(color: Theme.of(context).primaryColor); - static buildPickerItems(context, List items, decKey, onSelectFun) { + static buildPickerItems(context, List items, decKey, onSelectFun, model) { return CupertinoPicker( magnification: 1.5, scrollController: FixedExtentScrollController(initialItem: cupertinoPickerIndex), children: items.map((item) { return Text( - '${item["$decKey"]}', + '${item.facilityName}', style: TextStyle(fontSize: SizeConfig.textMultiplier * 2), ); }).toList(), @@ -151,7 +153,7 @@ class Helpers { Navigator.pushAndRemoveUntil( AppGlobal.CONTEX, FadePage( - page: Loginsreen(), + page: LoginScreen(), ), (r) => false); } diff --git a/lib/widgets/auth/auth_header.dart b/lib/widgets/auth/auth_header.dart deleted file mode 100644 index 27396980..00000000 --- a/lib/widgets/auth/auth_header.dart +++ /dev/null @@ -1,113 +0,0 @@ -import 'package:doctor_app_flutter/util/translations_delegate_base.dart'; -import 'package:doctor_app_flutter/widgets/shared/app_texts_widget.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/rendering.dart'; -import 'package:hexcolor/hexcolor.dart'; - -import '../../config/size_config.dart'; -import '../../lookups/auth_lookup.dart'; -//TODO Elham delete this widget -class AuthHeader extends StatelessWidget { - var userType; - AuthHeader(this.userType); - - @override - Widget build(BuildContext context) { - var screen = Container( - margin: SizeConfig.isMobile - ? null - : EdgeInsetsDirectional.fromSTEB(SizeConfig.realScreenWidth * 0.30, - SizeConfig.realScreenWidth * 0.1, 0, 0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - height: 30, - ), - ], - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: SizeConfig.isMobile - ? [ - SizedBox( - height: 10, - ), - buildWelText(context), - buildDrSulText(context), - ] - : [ - SizedBox( - height: 10, - ), - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - buildWelText(context), - buildDrSulText(context), - ], - ), - ], - ), - buildDrAppContainer(context) - ], - )); - return screen; - } - - - Container buildDrAppContainer(BuildContext context) { - if (userType == loginType.changePassword || - userType == loginType.verifyPassword || - userType == loginType.verificationMethods) { - return Container(); - } - return Container( - child: Text( - "Doctor App", - style: TextStyle( - fontSize: - SizeConfig.isMobile ? 16 : SizeConfig.realScreenWidth * 0.030, - fontWeight: FontWeight.w800, - color: HexColor('#B8382C')), - ), - ); - } - - Text buildDrSulText(BuildContext context) { - if (userType == loginType.changePassword || - userType == loginType.verifyPassword || - userType == loginType.verificationMethods) { - return Text(''); - } - return Text( - TranslationBase.of(context).drSulaimanAlHabib, - style: TextStyle( - fontWeight: FontWeight.w800, - fontSize: - SizeConfig.isMobile ? 24 : SizeConfig.realScreenWidth * 0.029, - fontFamily: 'Poppins'), - ); - } - - Widget buildWelText(BuildContext context) { - String text = TranslationBase.of(context).welcomeTo; - if (userType == loginType.unknownUser) { - text = TranslationBase.of(context).welcomeBackTo; - } - if (userType == loginType.changePassword || - userType == loginType.verifyPassword || - userType == loginType.verificationMethods) { - return Text(''); - } - return AppText( - text, - // style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - ); - } -} diff --git a/lib/widgets/auth/method_card.dart b/lib/widgets/auth/method_card.dart deleted file mode 100644 index 79721381..00000000 --- a/lib/widgets/auth/method_card.dart +++ /dev/null @@ -1,244 +0,0 @@ -import 'package:doctor_app_flutter/core/enum/auth_method_types.dart'; -import 'package:doctor_app_flutter/core/viewModel/project_view_model.dart'; -import 'package:doctor_app_flutter/util/translations_delegate_base.dart'; -import 'package:doctor_app_flutter/widgets/shared/app_texts_widget.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:local_auth/local_auth.dart'; -import 'package:provider/provider.dart'; - -class MethodCard extends StatefulWidget { - final AuthMethodTypes authMethodType; - final Function ( AuthMethodTypes type, bool isActive) authenticateUser; - final Function onShowMore; - - const MethodCard({Key key, this.authMethodType, this.authenticateUser, this.onShowMore}) : super(key: key); - - @override - _MethodCardState createState() => _MethodCardState(); -} - -class _MethodCardState extends State { - - //TODO Elham change it to list Enum - var _availableBiometrics; - - final LocalAuthentication auth = LocalAuthentication(); - ProjectViewModel projectsProvider; - - - - @override - void initState() { - super.initState(); - _getAvailableBiometrics(); - } - - - bool checkIfBiometricAvailable(BiometricType biometricType) { - bool isAvailable = false; - if (_availableBiometrics != null) { - for (var i = 0; i < _availableBiometrics.length; i++) { - if (biometricType == _availableBiometrics[i]) isAvailable = true; - } - } - return isAvailable; - } - - Future _getAvailableBiometrics() async { - var availableBiometrics; - try { - availableBiometrics = await auth.getAvailableBiometrics(); - } on PlatformException catch (e) { - print(e); - } - if (!mounted) return; - - setState(() { - _availableBiometrics = availableBiometrics; - }); - } - @override - Widget build(BuildContext context) { - projectsProvider = Provider.of(context); - - switch (widget.authMethodType) { - case AuthMethodTypes.WhatsApp: - return InkWell( - onTap: () => {widget.authenticateUser(AuthMethodTypes.WhatsApp, true)}, - //TODO Elham change it to widget - child: Container( - margin: EdgeInsets.all(10), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), - color: Colors.white, - ), - child: Padding( - padding: EdgeInsets.fromLTRB(20, 15, 20, 15), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Image.asset( - 'assets/images/verify-whtsapp.png', - height: 60, - width: 60, - ), - ], - ), - SizedBox( - height: 20, - ), - AppText( - TranslationBase.of(context).verifyWhatsApp, - fontSize: 14, - fontWeight: FontWeight.w600, - ) - ], - ), - ))); - break; - case AuthMethodTypes.SMS: - return InkWell( - onTap: () => {widget.authenticateUser(AuthMethodTypes.SMS, true)}, - child: Container( - margin: EdgeInsets.all(10), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), - color: Colors.white, - ), - child: Padding( - padding: EdgeInsets.fromLTRB(20, 15, 20, 15), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Image.asset( - 'assets/images/verify-sms.png', - height: 60, - width: 60, - ), - SizedBox( - height: 20, - ), - AppText( - TranslationBase.of(context).verifySMS, - fontSize: 14, - fontWeight: FontWeight.w600, - ) - ], - ), - ))); - break; - case AuthMethodTypes.Fingerprint: - return InkWell( - onTap: () => { - if (checkIfBiometricAvailable(BiometricType.fingerprint)) - {widget.authenticateUser(AuthMethodTypes.Fingerprint, true)} - }, - child: Container( - margin: EdgeInsets.all(10), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), - color: Colors.white, - ), - child: Padding( - padding: EdgeInsets.fromLTRB(20, 15, 20, 15), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Image.asset( - 'assets/images/verification_fingerprint_icon.png', - height: 60, - width: 60, - ), - SizedBox( - height: 20, - ), - AppText( - TranslationBase.of(context).verifyFingerprint, - fontSize: 14, - fontWeight: FontWeight.w600, - ) - ], - ), - ))); - break; - case AuthMethodTypes.FaceID: - return InkWell( - onTap: () { - if (checkIfBiometricAvailable(BiometricType.face)) { - widget.authenticateUser(AuthMethodTypes.FaceID, true); - } - }, - child: - Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), - color: Colors.white, - ), - margin: EdgeInsets.all(10), - child: Padding( - padding: EdgeInsets.fromLTRB(20, 15, 20, 15), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Image.asset( - 'assets/images/verification_faceid_icon.png', - height: 60, - width: 60, - ), - SizedBox( - height: 20, - ), - AppText( - TranslationBase.of(context).verifyFaceID, - fontSize: 14, - fontWeight: FontWeight.w600, - ) - ], - ), - ))); - break; - - default: - return InkWell( - onTap: widget.onShowMore, - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), - color: Colors.white, - ), - child: Padding( - padding: EdgeInsets.fromLTRB(20, 15, 20, 15), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Image.asset( - 'assets/images/login/more_icon.png', - height: 60, - width: 60, - ), - projectsProvider.isArabic - ? SizedBox( - height: 20, - ) - : SizedBox( - height: 10, - ), - AppText( - TranslationBase.of(context).moreVerification, - fontSize: 14, - fontWeight: FontWeight.w600, - ) - ], - ), - ))); - }; - } -} diff --git a/lib/widgets/auth/method_type_card.dart b/lib/widgets/auth/method_type_card.dart new file mode 100644 index 00000000..45190d2c --- /dev/null +++ b/lib/widgets/auth/method_type_card.dart @@ -0,0 +1,53 @@ +import 'package:doctor_app_flutter/widgets/shared/app_texts_widget.dart'; +import 'package:flutter/material.dart'; + +class MethodTypeCard extends StatelessWidget { + const MethodTypeCard({ + Key key, + this.assetPath, + this.onTap, + this.label, + }) : super(key: key); + final String assetPath; + final Function onTap; + final String label; + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: onTap, + child: Container( + margin: EdgeInsets.all(10), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: Colors.white, + ), + child: Padding( + padding: EdgeInsets.fromLTRB(20, 15, 20, 15), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Image.asset( + assetPath, + height: 60, + width: 60, + ), + ], + ), + SizedBox( + height: 20, + ), + AppText( + label, + fontSize: 14, + fontWeight: FontWeight.w600, + ) + ], + ), + )), + ); + } +} diff --git a/lib/widgets/auth/verification_methods_list.dart b/lib/widgets/auth/verification_methods_list.dart new file mode 100644 index 00000000..e42e33ba --- /dev/null +++ b/lib/widgets/auth/verification_methods_list.dart @@ -0,0 +1,87 @@ +import 'package:doctor_app_flutter/core/enum/auth_method_types.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/util/translations_delegate_base.dart'; +import 'package:doctor_app_flutter/widgets/auth/method_type_card.dart'; +import 'package:flutter/material.dart'; +import 'package:local_auth/local_auth.dart'; +import 'package:provider/provider.dart'; + +class VerificationMethodsList extends StatefulWidget { + final AuthMethodTypes authMethodType; + final Function(AuthMethodTypes type, bool isActive) authenticateUser; + final Function onShowMore; + final AuthenticationViewModel model; + + const VerificationMethodsList( + {Key key, + this.authMethodType, + this.authenticateUser, + this.onShowMore, + this.model}) + : super(key: key); + + @override + _VerificationMethodsListState createState() => + _VerificationMethodsListState(); +} + +class _VerificationMethodsListState extends State { + final LocalAuthentication auth = LocalAuthentication(); + ProjectViewModel projectsProvider; + + @override + Widget build(BuildContext context) { + projectsProvider = Provider.of(context); + + switch (widget.authMethodType) { + case AuthMethodTypes.WhatsApp: + return MethodTypeCard( + assetPath: 'assets/images/verify-whtsapp.png', + onTap: () => + {widget.authenticateUser(AuthMethodTypes.WhatsApp, true)}, + label: TranslationBase.of(context).verifyWhatsApp, + ); + break; + case AuthMethodTypes.SMS: + return MethodTypeCard( + assetPath: "assets/images/verify-sms.png", + onTap: () => {widget.authenticateUser(AuthMethodTypes.SMS, true)}, + label: TranslationBase.of(context).verifySMS, + ); + break; + case AuthMethodTypes.Fingerprint: + return MethodTypeCard( + assetPath: 'assets/images/verification_fingerprint_icon.png', + onTap: () async { + if (await widget.model + .checkIfBiometricAvailable(BiometricType.fingerprint)) { + + widget.authenticateUser(AuthMethodTypes.Fingerprint, true); + } + }, + label: TranslationBase.of(context).verifyFingerprint, + ); + break; + case AuthMethodTypes.FaceID: + return MethodTypeCard( + assetPath: 'assets/images/verification_faceid_icon.png', + onTap: () async { + if (await widget.model + .checkIfBiometricAvailable(BiometricType.face)) { + widget.authenticateUser(AuthMethodTypes.FaceID, true); + } + }, + label: TranslationBase.of(context).verifyFaceID, + ); + break; + + default: + return MethodTypeCard( + assetPath: 'assets/images/login/more_icon.png', + onTap: widget.onShowMore, + label: TranslationBase.of(context).moreVerification, + ); + } + } +}