diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index 6a108e7..8dfc92f 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -53,5 +53,6 @@ "hr": "س", "min": "د", "years": "سنة", - "months": "أشهر" + "months": "أشهر", + "userOtherAccount": "مستخدم حساب آخر" } \ No newline at end of file diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 1a15855..a530700 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -53,5 +53,6 @@ "hr": "Hr", "min": "Min", "years": "Years", - "months": "Months" + "months": "Months", + "userOtherAccount": "User Another Account" } \ No newline at end of file diff --git a/lib/classes/enums.dart b/lib/classes/enums.dart index cf55e42..cf27602 100644 --- a/lib/classes/enums.dart +++ b/lib/classes/enums.dart @@ -25,6 +25,5 @@ enum ViewState { enum LoginType { FROM_LOGIN, SILENT_LOGIN, - REGISTER_BIO, - REGISTER_NEW_BIO, + SILENT_WITH_OTP, } diff --git a/lib/classes/utils.dart b/lib/classes/utils.dart index 6f0bf6d..146eb72 100644 --- a/lib/classes/utils.dart +++ b/lib/classes/utils.dart @@ -56,17 +56,33 @@ class Utils { return await Future.delayed(Duration(milliseconds: millis)); } - static void showLoading() { - WidgetsBinding.instance.addPostFrameCallback((_) { - _isLoadingVisible = true; - showDialog( - context: navigatorKey.currentContext!, - barrierColor: Colors.black.withOpacity(0.5), - builder: (BuildContext context) => LoadingDialog(), - ).then((value) { - _isLoadingVisible = false; + static void showLoading({bool isNeedBinding = true}) { + if (isNeedBinding) { + WidgetsBinding.instance.addPostFrameCallback((_) { + showLoadingDialog(); }); - }); + } else { + showLoadingDialog(); + } + } + + static void showLoadingDialog() { + _isLoadingVisible = true; + showDialog( + context: navigatorKey.currentContext!, + barrierColor: Colors.black.withOpacity(0.5), + builder: (BuildContext context) => LoadingDialog(), + ).then((value) { + _isLoadingVisible = false; + }).catchError((e) { + print("--------------catchError---------------"); + print(e); + }).onError( + (error, stackTrace) { + print("--------------onError---------------"); + print(error); + }, + ); } static void hideLoading() { @@ -253,8 +269,6 @@ class Utils { return DateFormat('dd-MMM-yyyy').format(date); } - - static String reverseFormatDate(String date) { String formattedDate; if (date.isNotEmpty) { @@ -340,9 +354,6 @@ class Utils { return selectedDate; } - - - // static void readNFc({required Function(String) onRead}) { // // NfcManager.instance.startSession(onDiscovered: (NfcTag tag) async { diff --git a/lib/config/app_state.dart b/lib/config/app_state.dart index 7155660..2df5feb 100644 --- a/lib/config/app_state.dart +++ b/lib/config/app_state.dart @@ -19,7 +19,9 @@ class AppState { int projectID = 0; int clinicId = 0; - int lastLoginTyp = 0; + + //TODO: Must be -1 before login or logout + int lastLoginTyp = -1; int? doctorUserId; String? password; String? doctorIdFromDB; diff --git a/lib/main.dart b/lib/main.dart index 44c8525..efdce5c 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -10,7 +10,6 @@ import 'package:hmg_nurses/config/routes.dart'; import 'package:hmg_nurses/provider/dashboard_provider_model.dart'; import 'package:hmg_nurses/provider/login_provider_model.dart'; import 'package:hmg_nurses/theme/app_theme.dart'; -import 'package:hmg_nurses/ui/login/login_vm.dart'; import 'package:injector/injector.dart'; import 'package:logger/logger.dart'; import 'package:provider/provider.dart'; @@ -21,7 +20,6 @@ import 'generated/codegen_loader.g.dart'; late AppState appState; -// GlobalKey navigatorKey = GlobalKey(); final navigatorKey = GlobalKey(); Logger logger = Logger( @@ -61,9 +59,6 @@ Future main() async { ChangeNotifierProvider( create: (_) => LoginProviderModel(), ), - ChangeNotifierProvider( - create: (_) => LoginViewModel(), - ), ChangeNotifierProvider( create: (_) => DashboardProviderModel(), ) @@ -89,32 +84,30 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { - return LayoutBuilder( - builder: (context, constraints) { - return Sizer( - builder: ( - BuildContext context, - Orientation orientation, - DeviceType deviceType, - ) { - SizeConfig().init(constraints, orientation); - List> delegates = context.localizationDelegates; - return MaterialApp( - // key: navigatorKey, - navigatorKey: navigatorKey, - theme: AppTheme.getTheme( - EasyLocalization.of(context)?.locale.languageCode == "ar", - ), - debugShowCheckedModeBanner: false, - localizationsDelegates: delegates, - supportedLocales: context.supportedLocales, - locale: context.locale, - initialRoute: AppRoutes.initialPage, - routes: AppRoutes.routes, - ); - }, - ); - } - ); + return LayoutBuilder(builder: (context, constraints) { + return Sizer( + builder: ( + BuildContext context, + Orientation orientation, + DeviceType deviceType, + ) { + SizeConfig().init(constraints, orientation); + List> delegates = context.localizationDelegates; + return MaterialApp( + // key: navigatorKey, + navigatorKey: navigatorKey, + theme: AppTheme.getTheme( + EasyLocalization.of(context)?.locale.languageCode == "ar", + ), + debugShowCheckedModeBanner: false, + localizationsDelegates: delegates, + supportedLocales: context.supportedLocales, + locale: context.locale, + initialRoute: AppRoutes.initialPage, + routes: AppRoutes.routes, + ); + }, + ); + }); } } diff --git a/lib/provider/login_provider_model.dart b/lib/provider/login_provider_model.dart index 802ca02..1712c2d 100644 --- a/lib/provider/login_provider_model.dart +++ b/lib/provider/login_provider_model.dart @@ -1,5 +1,6 @@ import 'dart:convert'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -7,6 +8,7 @@ import 'package:hmg_nurses/classes/consts.dart'; import 'package:hmg_nurses/classes/enums.dart'; import 'package:hmg_nurses/classes/utils.dart'; import 'package:hmg_nurses/config/routes.dart'; +import 'package:hmg_nurses/generated/locale_keys.g.dart'; import 'package:hmg_nurses/main.dart'; import 'package:hmg_nurses/model/base/generic_response_model.dart'; import 'package:hmg_nurses/model/base/generic_response_model2.dart'; @@ -69,13 +71,12 @@ class LoginProviderModel extends BaseViewModel { Future loginWithFaceIDAndBiometrics() async { IOSAuthMessages iosStrings = - const IOSAuthMessages(cancelButton: 'cancel', goToSettingsButton: 'settings', goToSettingsDescription: 'Please set up your Touch ID.', lockOut: 'Please reenable your Touch ID'); + const IOSAuthMessages(cancelButton: 'cancel', goToSettingsButton: 'settings', goToSettingsDescription: 'Please set up your Touch ID.', lockOut: 'Please re-enable your Touch ID'); bool authenticated = false; try { authenticated = await auth.authenticate(localizedReason: 'Scan your fingerprint to authenticate', useErrorDialogs: true, stickyAuth: true, biometricOnly: true, iOSAuthStrings: iosStrings); } on PlatformException catch (e) { print(e); - Utils.hideLoading(); Utils.showToast("Please enable your Touch or Face ID"); } return authenticated; @@ -96,6 +97,21 @@ class LoginProviderModel extends BaseViewModel { } } + String getType(type) { + switch (type) { + case 1: + return LocaleKeys.sms.tr(); + case 3: + return LocaleKeys.fingerPrint.tr(); + case 4: + return LocaleKeys.face.tr(); + case 2: + return LocaleKeys.whatsapp.tr(); + default: + return LocaleKeys.sms.tr(); + } + } + // LoginType getDirectLoginType(type) { // switch (type) { // case 1: @@ -139,8 +155,9 @@ class LoginProviderModel extends BaseViewModel { appState.setMemberBeforeLogin = memberLogin; appState.projectID = branchId; appState.logInTokenID = memberLogin.logInTokenId; + appState.lastLoginTyp=-1; Utils.hideLoading(); - Navigator.pushNamed(navigatorKey.currentContext!, AppRoutes.loginMethodsPage, arguments: LoginType.FROM_LOGIN); + Navigator.pushReplacementNamed(navigatorKey.currentContext!, AppRoutes.loginMethodsPage, arguments: LoginType.FROM_LOGIN); return true; } catch (e) { Utils.hideLoading(); @@ -151,24 +168,27 @@ class LoginProviderModel extends BaseViewModel { } } - Future sendActivationCode(MemberLoginModel memberLoginModel, int facilityID, int sendOtpType, bool isFromSilentLogin) async { + Future sendActivationCode(MemberLoginModel memberLoginModel, int facilityID, int sendOtpType, LoginType loginType, {bool isNeedBinding = true}) async { try { - Utils.showLoading(); + Utils.showLoading(isNeedBinding: isNeedBinding); GenericResponseModel memberLogin; - if (isFromSilentLogin) { - memberLogin = await _loginApiRepo.sendActivationCodeForSlientLogin(memberLoginModel, facilityID, sendOtpType); - } else { - memberLogin = await _loginApiRepo.sendActivationCode(memberLoginModel, facilityID, sendOtpType); - } - appState.logInTokenID = memberLogin.logInTokenId.toString(); - // Utils.showToast(deviceInfo.length.toString()); - Utils.hideLoading(); - // Navigator.pushNamed(navigatorKey.currentContext!, AppRoutes.loginMethodsPage, arguments: LoginType.FROM_LOGIN); - if(isFromSilentLogin){ - checkActivationCode("0000", sendOtpType, isFromSilentLogin); - }else{ - startSMSService(sendOtpType, isFromSilentLogin); + if (loginType == LoginType.FROM_LOGIN) { + memberLogin = await _loginApiRepo.sendActivationCode(memberLoginModel, facilityID, sendOtpType); + appState.logInTokenID = memberLogin.logInTokenId.toString(); + Utils.hideLoading(); + startSMSService(sendOtpType, false); + } else { + if (loginType == LoginType.SILENT_LOGIN) { + memberLogin = await _loginApiRepo.sendActivationCodeForSlientLogin(memberLoginModel, facilityID, sendOtpType); + appState.logInTokenID = memberLogin.logInTokenId.toString(); + checkActivationCode("0000", sendOtpType, true); + } else { + memberLogin = await _loginApiRepo.sendActivationCodeForSlientLogin(memberLoginModel, facilityID, sendOtpType); + appState.logInTokenID = memberLogin.logInTokenId.toString(); + Utils.hideLoading(); + startSMSService(sendOtpType, true); + } } return memberLogin; @@ -178,15 +198,16 @@ class LoginProviderModel extends BaseViewModel { Utils.confirmDialog(navigatorKey.currentContext!, msg); }); } + return null; } Future checkActivationCode(String activationCode, int sendOtpType, bool isFromSilentLogin) async { try { - Utils.showLoading(); + if (!isFromSilentLogin) Utils.showLoading(); GenericResponseModel memberLogin = await _loginApiRepo.checkActivationCode(activationCode, sendOtpType, isFromSilentLogin); Utils.hideLoading(); setSession(memberLogin); - Navigator.pushNamed(navigatorKey.currentContext!, AppRoutes.dashboard); + Navigator.pushReplacementNamed(navigatorKey.currentContext!, AppRoutes.dashboard); return memberLogin; } catch (e) { Utils.hideLoading(); @@ -241,6 +262,7 @@ class LoginProviderModel extends BaseViewModel { String lastLoginDate = await Utils.getStringFromPrefs(SharedPrefsConsts.lastLoginDate); appState.setMemberBeforeLogin = await MemberLoginModel.getFromPrefs(); + appState.lastLoginTyp = -1; appState.doctorUserId = doctorUserId; appState.password = password; appState.logInTokenID = logInTokenID; @@ -251,7 +273,7 @@ class LoginProviderModel extends BaseViewModel { appState.clinicId = clinicId; appState.lastLoginImeiDate = model; appState.lastLoginDate = lastLoginDate; - Navigator.pushNamed(navigatorKey.currentContext!, AppRoutes.loginMethodsPage, arguments: LoginType.SILENT_LOGIN); + Navigator.pushReplacementNamed(navigatorKey.currentContext!, AppRoutes.loginMethodsPage, arguments: LoginType.SILENT_LOGIN); } } } diff --git a/lib/services/api_repo/login_api_repo.dart b/lib/services/api_repo/login_api_repo.dart index 7d49c0f..9242722 100644 --- a/lib/services/api_repo/login_api_repo.dart +++ b/lib/services/api_repo/login_api_repo.dart @@ -116,7 +116,7 @@ class LoginApiRepo implements ILoginApiRepo { postParams.addAll(appState.postParamsJson); postParams["MobileNumber"] = memberLoginModel.mobileNumber; postParams["ZipCode"] = memberLoginModel.zipCode; - postParams["IsMobileFingerPrint"] = sendOtpType; + postParams["IsMobileFingerPrint"] = 1; postParams["IMEI"] = appState.imei; postParams["LoginDoctorID"] = memberLoginModel.doctorId; postParams["DoctorID"] = memberLoginModel.doctorId; diff --git a/lib/ui/dashboard/dashbaord_page.dart b/lib/ui/dashboard/dashbaord_page.dart index db1ce31..8804c11 100644 --- a/lib/ui/dashboard/dashbaord_page.dart +++ b/lib/ui/dashboard/dashbaord_page.dart @@ -1,5 +1,6 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:hmg_nurses/config/routes.dart'; import 'package:hmg_nurses/main.dart'; import 'package:hmg_nurses/provider/dashboard_provider_model.dart'; import 'package:provider/provider.dart'; @@ -21,6 +22,20 @@ class _DashboardPageState extends State { @override Widget build(BuildContext context) { - return Scaffold(); + return Scaffold( + appBar: AppBar( + actions: [ + IconButton( + onPressed: () { + Navigator.pushReplacementNamed(context, AppRoutes.login, arguments: false); + }, + icon: const Icon( + Icons.logout, + color: Colors.white, + ), + ) + ], + ), + ); } } diff --git a/lib/ui/login/login_method_page.dart b/lib/ui/login/login_method_page.dart index 52c631d..fdf8714 100644 --- a/lib/ui/login/login_method_page.dart +++ b/lib/ui/login/login_method_page.dart @@ -4,6 +4,7 @@ import 'package:hexcolor/hexcolor.dart'; import 'package:hmg_nurses/classes/colors.dart'; import 'package:hmg_nurses/classes/date-utils.dart'; import 'package:hmg_nurses/classes/enums.dart'; +import 'package:hmg_nurses/config/routes.dart'; import 'package:hmg_nurses/extensions/int_extensions.dart'; import 'package:hmg_nurses/extensions/string_extensions.dart'; import 'package:hmg_nurses/extensions/util_extensions.dart'; @@ -11,7 +12,6 @@ import 'package:hmg_nurses/extensions/widget_extensions.dart'; import 'package:hmg_nurses/generated/locale_keys.g.dart'; import 'package:hmg_nurses/main.dart'; import 'package:hmg_nurses/provider/login_provider_model.dart'; -import 'package:hmg_nurses/ui/login/login_vm.dart'; import 'package:hmg_nurses/ui/login/widgets/verification_method_card.dart'; import 'package:hmg_nurses/widgets/button/default_button.dart'; import 'package:local_auth/local_auth.dart'; @@ -33,7 +33,7 @@ class LoginMethodsPage extends StatefulWidget { class LoginMethodsPageState extends State { bool isMoreOption = false; bool onlySMSBox = false; - late LoginViewModel loginViewModel; + LoginType? loginType; AuthMethodTypes? selectedAuthType; late LoginProviderModel loginProviderModel; @@ -43,396 +43,241 @@ class LoginMethodsPageState extends State { if (loginType == null) { loginType = ModalRoute.of(context)!.settings.arguments as LoginType; } - loginViewModel = context.read(); + loginProviderModel = context.read(); return Scaffold( - appBar: AppBar( - backgroundColor: Colors.transparent, - leading: IconButton( - icon: const Icon(Icons.arrow_back_ios, color: MyColors.darkIconColor), - onPressed: () => Navigator.pop(context), - ), - // actions: [Center(child: "Employee Digital ID".toText12(color: MyColors.textMixColor, isUnderLine: true).onPress(() {})), 21.width], - ), + // appBar: AppBar( + // backgroundColor: Colors.transparent, + // leading: null, + // // actions: [Center(child: "Employee Digital ID".toText12(color: MyColors.textMixColor, isUnderLine: true).onPress(() {})), 21.width], + // ), body: Container( width: double.infinity, height: double.infinity, padding: const EdgeInsets.all(21), child: Column( children: [ - if (loginType == LoginType.SILENT_LOGIN && appState.lastLoginImeiDate != null) - Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - LocaleKeys.welcomeBack.tr().toText12(), - (appState.lastLoginImeiDate!.titleDescription! + " " + appState.lastLoginImeiDate!.doctorName!).toText20(isBold: true), - heightSpacer3per(), - LocaleKeys.wouldYouLikeToLoginWithCurrentUsername.tr().toText14(), - heightSpacer3per(), - Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: const BorderRadius.all(Radius.circular(10)), - border: Border.all(color: HexColor('#707070'), width: 0.1), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ + Expanded( + child: SafeArea( + child: SingleChildScrollView( + child: Column( + children: [ + 21.height, + if (loginType == LoginType.SILENT_LOGIN && appState.lastLoginImeiDate != null) Column( - mainAxisAlignment: MainAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.start, - children: [ - LocaleKeys.lastLoginDetails.tr().toText13(), - SizedBox( - width: 55.w, + children: [ + LocaleKeys.welcomeBack.tr().toText12(), + (appState.lastLoginImeiDate!.titleDescription! + " " + appState.lastLoginImeiDate!.doctorName!).toText20(isBold: true), + heightSpacer3per(), + LocaleKeys.wouldYouLikeToLoginWithCurrentUsername.tr().toText14(), + heightSpacer3per(), + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: const BorderRadius.all(Radius.circular(10)), + border: Border.all(color: HexColor('#707070'), width: 0.1), + ), child: Row( - children: [ - "${LocaleKeys.verificationType.tr()} : ".toText11(), - loginViewModel.getType(appState.lastLoginImeiDate!.logInTypeID ?? 1).toText11(isBold: true), + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocaleKeys.lastLoginDetails.tr().toText13(), + SizedBox( + width: 55.w, + child: Row( + children: [ + "${LocaleKeys.verificationType.tr()} : ".toText11(), + loginProviderModel.getType(appState.lastLoginImeiDate!.logInTypeID ?? 1).toText11(isBold: true), + ], + ), + ), + ], + ), + Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + (appState.lastLoginImeiDate!.editedOn != null + ? AppDateUtils.getDayMonthYearDateFormatted(AppDateUtils.convertStringToDate(appState.lastLoginImeiDate!.editedOn ?? ""), isMonthShort: true) + : appState.lastLoginImeiDate!.createdOn != null + ? AppDateUtils.getDayMonthYearDateFormatted(AppDateUtils.convertStringToDate(appState.lastLoginImeiDate!.createdOn ?? ""), isMonthShort: true) + : '--') + .toText11(isBold: true), + heightSpacer06per(), + (appState.lastLoginImeiDate!.editedOn != null + ? AppDateUtils.getHour(AppDateUtils.convertStringToDate(appState.lastLoginImeiDate!.editedOn ?? "")) + : appState.lastLoginImeiDate!.createdOn != null + ? AppDateUtils.getHour(AppDateUtils.convertStringToDate(appState.lastLoginImeiDate!.createdOn ?? "")) + : '--') + .toText10() + ], + ) ], ), ), + heightSpacer3per(), + LocaleKeys.pleaseVerify.tr().toText14().paddingOnly(left: 1.w), + heightSpacer2per(), ], ), - Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - (appState.lastLoginImeiDate!.editedOn != null - ? AppDateUtils.getDayMonthYearDateFormatted(AppDateUtils.convertStringToDate(appState.lastLoginImeiDate!.editedOn ?? ""), isMonthShort: true) - : appState.lastLoginImeiDate!.createdOn != null - ? AppDateUtils.getDayMonthYearDateFormatted(AppDateUtils.convertStringToDate(appState.lastLoginImeiDate!.createdOn ?? ""), isMonthShort: true) - : '--') - .toText11(isBold: true), - heightSpacer06per(), - (appState.lastLoginImeiDate!.editedOn != null - ? AppDateUtils.getHour(AppDateUtils.convertStringToDate(appState.lastLoginImeiDate!.editedOn ?? "")) - : appState.lastLoginImeiDate!.createdOn != null - ? AppDateUtils.getHour(AppDateUtils.convertStringToDate(appState.lastLoginImeiDate!.createdOn ?? "")) - : '--') - .toText10() - ], - ) - ], - ), - ), - heightSpacer3per(), - LocaleKeys.pleaseVerify.tr().toText14().paddingOnly(left: 1.w), - heightSpacer2per(), - ], - ), - Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (loginType == LoginType.FROM_LOGIN || loginType == LoginType.REGISTER_NEW_BIO) - Column( - children: [ - LocaleKeys.pleaseVerifyForBio.tr().toText14(), - 21.height, - ], - ), - if (loginType == LoginType.FROM_LOGIN || loginType == LoginType.SILENT_LOGIN) - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded( - child: VerificationMethodsList( - authMethodType: AuthMethodTypes.faceID, - isBioAvailable: loginProviderModel.isFaceBioAvailable, - authenticateUser: (AuthMethodTypes authMethodType, isActive) async { - // loginViewModel.startSMSService(authMethodType, context: context); - // appState.setMemberBeforeLogin - bool isAuthenticated = await loginProviderModel.loginWithFaceIDAndBiometrics(); - if (isAuthenticated) { - appState.lastLoginTyp = loginProviderModel.getLoginMethodId(AuthMethodTypes.faceID); - if (loginType == LoginType.FROM_LOGIN) { - setState(() { - loginType = LoginType.REGISTER_NEW_BIO; - selectedAuthType = AuthMethodTypes.faceID; - }); - } else if (loginType == LoginType.SILENT_LOGIN) { - if (appState.lastLoginImeiDate!.logInTypeID == loginProviderModel.getLoginMethodId(AuthMethodTypes.faceID)) { - loginProviderModel.sendActivationCode( - appState.memberBeforeLogin!, - appState.projectID, - loginProviderModel.getLoginMethodId(AuthMethodTypes.sms), - true, - ); - } else { - setState(() { - loginType = LoginType.REGISTER_NEW_BIO; - selectedAuthType = AuthMethodTypes.faceID; - }); - } - } - } else { - print("Authentaction Failded"); - } - }, - ), - ), - 21.width, - Expanded( - child: VerificationMethodsList( - authMethodType: AuthMethodTypes.fingerPrint, - isBioAvailable: loginProviderModel.isFingerBioAvailable, - onShowMore: () async { - bool isAuthenticated = await loginProviderModel.loginWithFaceIDAndBiometrics(); - if (isAuthenticated) { - if (loginType == LoginType.FROM_LOGIN) { - appState.lastLoginTyp = loginProviderModel.getLoginMethodId(AuthMethodTypes.fingerPrint); - loginType = LoginType.REGISTER_NEW_BIO; - selectedAuthType = AuthMethodTypes.fingerPrint; - setState(() {}); - } - } else { - print("Authentaction Failded"); - } - }, - ), - ), - ], - ), - 21.height, - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded( - child: VerificationMethodsList( - authMethodType: AuthMethodTypes.sms, - authenticateUser: (AuthMethodTypes authMethodType, isActive) { - // loginViewModel.startSMSService(authMethodType, context: context); - if (selectedAuthType == null) { - appState.lastLoginTyp = loginProviderModel.getLoginMethodId(AuthMethodTypes.sms); - } else if (selectedAuthType == AuthMethodTypes.faceID || selectedAuthType == AuthMethodTypes.fingerPrint) { - appState.lastLoginTyp = loginProviderModel.getLoginMethodId(selectedAuthType!); - } - loginProviderModel.sendActivationCode( - appState.memberBeforeLogin!, - appState.projectID, - loginProviderModel.getLoginMethodId(AuthMethodTypes.sms), - false, - ); - }, - ), - ), - 21.width, - Expanded( - child: VerificationMethodsList( - authMethodType: AuthMethodTypes.whatsApp, - authenticateUser: (AuthMethodTypes authMethodType, isActive) { - // loginViewModel.startSMSService(authMethodType, context: context); - if (selectedAuthType == null) { - appState.lastLoginTyp = loginProviderModel.getLoginMethodId(AuthMethodTypes.whatsApp); - } else if (selectedAuthType == AuthMethodTypes.faceID || selectedAuthType == AuthMethodTypes.fingerPrint) { - appState.lastLoginTyp = loginProviderModel.getLoginMethodId(selectedAuthType!); - } - loginProviderModel.sendActivationCode( - appState.memberBeforeLogin!, - appState.projectID, - loginProviderModel.getLoginMethodId(AuthMethodTypes.whatsApp), - false, - ); - }, - ), - ), - ], - ), - ], - ), - ], - ), - ), - ); - return Scaffold( - appBar: AppBar( - backgroundColor: Colors.transparent, - leading: IconButton( - icon: const Icon(Icons.arrow_back_ios, color: MyColors.darkIconColor), - onPressed: () => Navigator.pop(context), - ), - // actions: [Center(child: "Employee Digital ID".toText12(color: MyColors.textMixColor, isUnderLine: true).onPress(() {})), 21.width], - ), - body: SingleChildScrollView( - child: Center( - child: FractionallySizedBox( - widthFactor: 0.9, - child: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - heightSpacer1per(), - if (loginViewModel.isFromLogin) - InkWell( - onTap: () { - // loginViewModel.setUnverified(false, isFromLogin: false); - // loginViewModel.setAppStatus(APPSTATUS.unAuthenticated); - }, - child: const Icon( - Icons.arrow_back_ios, - color: MyColors.darkTextColor, - ), - ), - Column( - children: [ - heightSpacer1per(), - isMoreOption == false - ? Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - LocaleKeys.welcomeBack.tr().toText12(), - "Dr Amal Ahmed".toText20(isBold: true), - heightSpacer3per(), - LocaleKeys.wouldYouLikeToLoginWithCurrentUsername.tr().toText14(), - heightSpacer3per(), - Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: const BorderRadius.all(Radius.circular(10)), - border: Border.all(color: HexColor('#707070'), width: 0.1), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - LocaleKeys.lastLoginDetails.tr().toText13(), - SizedBox( - width: 55.w, - child: Row( - children: [ - "${LocaleKeys.verificationType.tr()} : ".toText11(), - "${loginViewModel.getType(1)}".toText11(isBold: true), - ], - ), - ), - ], - ), - Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.end, - children: ["12 NOV, 2022".toText11(isBold: true), heightSpacer06per(), "09:56 AM".toText10()], - ) - ], - ), - ), - heightSpacer3per(), - LocaleKeys.pleaseVerify.tr().toText14().paddingOnly(left: 1.w), - heightSpacer2per(), - ], - ) - : Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - LocaleKeys.pleaseVerifyForBio.tr().toText14().paddingAll(10), + Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (loginType == LoginType.FROM_LOGIN || loginType == LoginType.SILENT_WITH_OTP) + Column( + children: [ + LocaleKeys.pleaseVerifyForBio.tr().toText14(), + 21.height, ], ), - isMoreOption == false - ? Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Row(mainAxisAlignment: MainAxisAlignment.center, children: [ + if (loginType == LoginType.FROM_LOGIN || loginType == LoginType.SILENT_LOGIN) + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ Expanded( child: VerificationMethodsList( - authMethodType: SelectedAuthMethodTypesService.getMethodsTypeService(1), - authenticateUser: (AuthMethodTypes authMethodType, isActive) { - loginViewModel.startSMSService(authMethodType, context: context); + authMethodType: AuthMethodTypes.faceID, + isBioAvailable: loginProviderModel.isFaceBioAvailable, + authenticateUser: (AuthMethodTypes authMethodType, isActive) async { + bool isAuthenticated = await loginProviderModel.loginWithFaceIDAndBiometrics(); + if (isAuthenticated) { + appState.lastLoginTyp = loginProviderModel.getLoginMethodId(authMethodType); + if (loginType == LoginType.FROM_LOGIN) { + setState(() { + loginType = LoginType.FROM_LOGIN; + }); + } else if (loginType == LoginType.SILENT_LOGIN) { + if (appState.lastLoginImeiDate!.logInTypeID == loginProviderModel.getLoginMethodId(authMethodType)) { + loginProviderModel.sendActivationCode( + appState.memberBeforeLogin!, + appState.projectID, + loginProviderModel.getLoginMethodId(AuthMethodTypes.sms), + loginType ?? LoginType.FROM_LOGIN, + isNeedBinding: false, + ); + } else { + setState(() { + loginType = LoginType.SILENT_WITH_OTP; + }); + } + } + } else { + print("Authentication Failed"); + } }, ), ), + 21.width, Expanded( - child: VerificationMethodsList( - authMethodType: AuthMethodTypes.moreOptions, - onShowMore: () { - setState(() { - isMoreOption = true; - }); - }, - )) - ]), - ]) - : Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ - onlySMSBox == false - ? Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded( - child: VerificationMethodsList( - authMethodType: AuthMethodTypes.fingerPrint, - authenticateUser: (AuthMethodTypes authMethodType, isActive) { - loginViewModel.startSMSService(authMethodType, context: context); - }, - )), - Expanded( - child: VerificationMethodsList( - authMethodType: AuthMethodTypes.faceID, - authenticateUser: (AuthMethodTypes authMethodType, isActive) { - loginViewModel.startSMSService(authMethodType, context: context); - }, - )) - ], - ) - : const SizedBox(), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded( - child: VerificationMethodsList( - authMethodType: AuthMethodTypes.sms, - authenticateUser: (AuthMethodTypes authMethodType, isActive) { - loginViewModel.startSMSService(authMethodType, context: context); - }, - )), - Expanded( - child: VerificationMethodsList( - authMethodType: AuthMethodTypes.whatsApp, - authenticateUser: (AuthMethodTypes authMethodType, isActive) { - loginViewModel.startSMSService(authMethodType, context: context); + child: VerificationMethodsList( + authMethodType: AuthMethodTypes.fingerPrint, + isBioAvailable: loginProviderModel.isFingerBioAvailable, + authenticateUser: (AuthMethodTypes authMethodType, isActive) async { + bool isAuthenticated = await loginProviderModel.loginWithFaceIDAndBiometrics(); + if (isAuthenticated) { + appState.lastLoginTyp = loginProviderModel.getLoginMethodId(authMethodType); + if (loginType == LoginType.FROM_LOGIN) { + setState(() { + loginType = LoginType.FROM_LOGIN; + }); + } else if (loginType == LoginType.SILENT_LOGIN) { + if (appState.lastLoginImeiDate!.logInTypeID == loginProviderModel.getLoginMethodId(authMethodType)) { + loginProviderModel.sendActivationCode( + appState.memberBeforeLogin!, + appState.projectID, + loginProviderModel.getLoginMethodId(AuthMethodTypes.sms), + loginType ?? LoginType.FROM_LOGIN, + isNeedBinding: false, + ); + } else { + setState(() { + loginType = LoginType.SILENT_WITH_OTP; + }); + } + } + } else { + print("Authentication Failed"); + } }, - )) - ], + ), + ), + ], + ), + 21.height, + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: VerificationMethodsList( + authMethodType: AuthMethodTypes.sms, + authenticateUser: (AuthMethodTypes authMethodType, isActive) { + if (loginType == LoginType.FROM_LOGIN || loginType == LoginType.SILENT_LOGIN) { + if (appState.lastLoginTyp == -1) appState.lastLoginTyp = loginProviderModel.getLoginMethodId(authMethodType); + if (loginType == LoginType.SILENT_LOGIN) { + loginType = LoginType.SILENT_WITH_OTP; + } + } + loginProviderModel.sendActivationCode( + appState.memberBeforeLogin!, + appState.projectID, + loginProviderModel.getLoginMethodId(AuthMethodTypes.sms), + loginType ?? LoginType.FROM_LOGIN, + ); + }, + ), ), - ]), - - // ) - ], - ), - ], - ), - ), - ), - ), - ), - bottomSheet: !isMoreOption - ? null - : Container( - height: 10.h, - color: MyColors.backgroundColor, - width: double.infinity, - child: Center( - child: FractionallySizedBox( - widthFactor: 0.9, - child: Column( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Padding( - padding: EdgeInsets.symmetric(horizontal: 4.w), - child: DefaultButton(LocaleKeys.useAnotherAccount.tr(), () {}, colors: const [MyColors.redColor, MyColors.redColor]), + 21.width, + Expanded( + child: VerificationMethodsList( + authMethodType: AuthMethodTypes.whatsApp, + authenticateUser: (AuthMethodTypes authMethodType, isActive) { + if (loginType == LoginType.FROM_LOGIN || loginType == LoginType.SILENT_LOGIN) { + if (appState.lastLoginTyp == -1) appState.lastLoginTyp = loginProviderModel.getLoginMethodId(authMethodType); + if (loginType == LoginType.SILENT_LOGIN) { + loginType = LoginType.SILENT_WITH_OTP; + } + } + loginProviderModel.sendActivationCode( + appState.memberBeforeLogin!, + appState.projectID, + loginProviderModel.getLoginMethodId(AuthMethodTypes.whatsApp), + loginType ?? LoginType.FROM_LOGIN, + ); + }, + ), + ), + ], + ), + ], ), - heightSpacer3per(), + 12.height, ], ), ), ), ), + 21.height, + DefaultButton( + LocaleKeys.useAnotherAccount.tr(), + () async { + Navigator.pushReplacementNamed(context, AppRoutes.login, arguments:false); + }, + colors: const [ + MyColors.redColor, + MyColors.redColor, + ], + ), + ], + ), + ), ); } } diff --git a/lib/ui/login/login_page.dart b/lib/ui/login/login_page.dart index 52fabd8..d11c125 100644 --- a/lib/ui/login/login_page.dart +++ b/lib/ui/login/login_page.dart @@ -23,11 +23,7 @@ import 'package:local_auth/local_auth.dart'; import 'package:provider/provider.dart'; import 'package:sizer/sizer.dart'; -import '../../services/api_repo/login_api_repo.dart'; - class LoginPage extends StatefulWidget { - const LoginPage({Key? key}) : super(key: key); - @override State createState() => _LoginPageState(); } @@ -35,25 +31,36 @@ class LoginPage extends StatefulWidget { class _LoginPageState extends State { int branchID = 0; - late LoginProviderModel provider; + LoginProviderModel? provider; + final loginFormKey = GlobalKey(); + var projectIdController = TextEditingController(); + var userIdController = TextEditingController(); + var passwordController = TextEditingController(); - @override - void initState() { - super.initState(); - provider = Provider.of(navigatorKey.currentContext!); - checkUserSession(); + checkUserSession() async { + provider!.checkLastSession(); } - checkUserSession() async { - provider.checkLastSession(); + setUserSession() async { + await Utils.getStringFromPrefs(SharedPrefsConsts.username); + await Utils.getStringFromPrefs(SharedPrefsConsts.password); } @override Widget build(BuildContext context) { + if (provider == null) { + dynamic? isNeedCheckUserSession = (ModalRoute.of(context)!.settings.arguments); + // setUserSession(); + provider = context.read(); + if (isNeedCheckUserSession == null) { + checkUserSession(); + } + } + return Scaffold( body: SafeArea( child: Column( @@ -96,7 +103,7 @@ class _LoginPageState extends State { isTextIsPassword: true, onChange: (v) { if (v.length == 1) { - provider.getAssignedBranches(userIdController.text); + provider!.getAssignedBranches(userIdController.text); } }, ), @@ -120,11 +127,11 @@ class _LoginPageState extends State { isEnable: false, onClick: () => CustomCupertinoPicker.showCupertinoPicker( context, - provider.assignedBranches, + provider!.assignedBranches, (index) { - projectIdController.text = provider.assignedBranches[index].facilityName!; - branchID = provider.assignedBranches[index].facilityId as int; - provider.notifyListeners(); + projectIdController.text = provider!.assignedBranches[index].facilityName!; + branchID = provider!.assignedBranches[index].facilityId as int; + provider!.notifyListeners(); }, ), ); @@ -144,7 +151,7 @@ class _LoginPageState extends State { LocaleKeys.login.tr(), () async { // provider.checkLastSession(); - bool isSuccess = await provider.performLogin(userIdController.text, passwordController.text, branchID); + bool isSuccess = await provider!.performLogin(userIdController.text, passwordController.text, branchID); if (isSuccess) { appState.password = passwordController.text; appState.doctorUserId = int.parse(userIdController.text); diff --git a/lib/ui/login/login_vm.dart b/lib/ui/login/login_vm.dart deleted file mode 100644 index 4003b2d..0000000 --- a/lib/ui/login/login_vm.dart +++ /dev/null @@ -1,134 +0,0 @@ -import 'package:easy_localization/easy_localization.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:hmg_nurses/provider/base_vm.dart'; -import 'package:hmg_nurses/classes/enums.dart'; -import 'package:hmg_nurses/classes/utils.dart'; - -import 'package:hmg_nurses/generated/locale_keys.g.dart'; -import 'package:hmg_nurses/widgets/dialogs/otp_dialog.dart'; -import 'package:local_auth/local_auth.dart'; - -class LoginViewModel extends BaseViewModel { - bool isLogin = false; - bool unverified = false; - bool isFromLogin = false; - String localToken = ""; - - String nurseProfile = ""; - - final LocalAuthentication auth = LocalAuthentication(); - late List _availableBiometrics; - - LoginViewModel(); - - /// get type name based on id. - String getType(type) { - switch (type) { - case 1: - return LocaleKeys.sms.tr(); - case 3: - return LocaleKeys.fingerPrint.tr(); - case 4: - return LocaleKeys.face.tr(); - case 2: - return LocaleKeys.whatsapp.tr(); - default: - return LocaleKeys.sms.tr(); - } - } - - int getLoginMethodId(AuthMethodTypes authMethodTypes) { - switch (authMethodTypes) { - case AuthMethodTypes.sms: - return 1; - case AuthMethodTypes.whatsApp: - return 2; - case AuthMethodTypes.fingerPrint: - return 3; - case AuthMethodTypes.faceID: - return 4; - default: - return 1; - } - } - /// ask user to add his biometric - showIOSAuthMessages() async { - try { - await auth.authenticate( - localizedReason: 'Scan your fingerprint to authenticate', - ); - } on PlatformException catch (e) { - if (kDebugMode) { - print(e); - } - } - } - - /// check specific biometric if it available or not - 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; - } - - /// get all available biometric on the device for local Auth service - Future _getAvailableBiometrics() async { - try { - _availableBiometrics = await auth.getAvailableBiometrics(); - } on PlatformException catch (e) { - if (kDebugMode) { - print(e); - } - } - } - - /// determine the status of the ap - - setUnverified(bool unverified, {bool isFromLogin = false}) { - this.unverified = unverified; - this.isFromLogin = isFromLogin; - notifyListeners(); - } - - /// logout function - logout({bool isFromLogin = false}) async { - // localToken = ""; - // String lang = await sharedPref.getString(APP_Language); - // await Utils.clearSharedPref(); - // doctorProfile = null; - // sharedPref.setString(APP_Language, lang); - // deleteUser(); - // await getDeviceInfoFromFirebase(); - // this.isFromLogin = isFromLogin; - // appStatus = APPSTATUS.unAuthenticated; - // setState(ViewState.Idle); - } - - deleteUser() { - // user = null; - // unverified = false; - // isLogin = false; - } - - startSMSService(AuthMethodTypes type, {isSilentLogin = false, required BuildContext context}) { - OtpDialog( - type: 1, - mobileNo: "0504278212", - onSuccess: (String otpCode, TextEditingController pinPut) { - Utils.showLoading(); - //TODO: API CALL - // performDirectApiCall(_title, _icon, _flag, value); - }, - onFailure: () => Navigator.pop(context), - onResendCode: () {}, - ).displayDialog(context); - } -} diff --git a/lib/ui/login/widgets/verification_method_card.dart b/lib/ui/login/widgets/verification_method_card.dart index 0199585..556a910 100644 --- a/lib/ui/login/widgets/verification_method_card.dart +++ b/lib/ui/login/widgets/verification_method_card.dart @@ -6,7 +6,7 @@ import 'package:hmg_nurses/classes/colors.dart'; import 'package:hmg_nurses/classes/enums.dart'; import 'package:hmg_nurses/classes/size_config.dart'; import 'package:hmg_nurses/generated/locale_keys.g.dart'; -import 'package:hmg_nurses/ui/login/login_vm.dart'; + import 'package:local_auth/local_auth.dart'; class VerificationMethodsList extends StatelessWidget { diff --git a/lib/widgets/dialogs/otp_dialog.dart b/lib/widgets/dialogs/otp_dialog.dart index 873fad8..0c8f7e1 100644 --- a/lib/widgets/dialogs/otp_dialog.dart +++ b/lib/widgets/dialogs/otp_dialog.dart @@ -216,9 +216,11 @@ class OtpDialog { void startTimer(setState) { remainingTime--; if (stopTimer) return; - setState(() { - displayTime = getSecondsAsDigitalClock(remainingTime); - }); + try { + setState(() { + displayTime = getSecondsAsDigitalClock(remainingTime); + }); + } catch (e) {} timer = Future.delayed(const Duration(seconds: 1), () { if (remainingTime > 0) {