From 4d2efee297e505e8550f000f1fbf861997e0ea57 Mon Sep 17 00:00:00 2001 From: Sultan khan Date: Wed, 9 Jul 2025 12:12:20 +0300 Subject: [PATCH] quick login enable --- lib/pages/landing/landing_page.dart | 65 ++++++++++++++-- lib/pages/livecare/incoming_call.dart | 5 +- lib/pages/login/confirm-login.dart | 64 ++++++++-------- lib/pages/login/welcome.dart | 14 ++-- .../authentication/auth_provider.dart | 30 ++++++++ lib/widgets/quick_login.dart | 76 +++++++++++++++++++ 6 files changed, 205 insertions(+), 49 deletions(-) create mode 100644 lib/widgets/quick_login.dart diff --git a/lib/pages/landing/landing_page.dart b/lib/pages/landing/landing_page.dart index 18171bf1..2d686531 100644 --- a/lib/pages/landing/landing_page.dart +++ b/lib/pages/landing/landing_page.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'dart:io'; +import 'package:flutter/services.dart'; import 'package:hmg_patient_app/config/config.dart'; import 'package:hmg_patient_app/config/shared_pref_kay.dart'; import 'package:hmg_patient_app/core/model/ImagesInfo.dart'; @@ -9,6 +10,8 @@ import 'package:hmg_patient_app/core/viewModels/appointment_rate_view_model.dart import 'package:hmg_patient_app/core/viewModels/project_view_model.dart'; import 'package:hmg_patient_app/models/Appointments/toDoCountProviderModel.dart'; import 'package:hmg_patient_app/models/Authentication/authenticated_user.dart'; +import 'package:hmg_patient_app/models/Authentication/check_paitent_authentication_req.dart'; +import 'package:hmg_patient_app/models/Authentication/select_device_imei_res.dart'; import 'package:hmg_patient_app/models/LiveCare/IncomingCallData.dart'; import 'package:hmg_patient_app/pages/BookAppointment/Search.dart'; import 'package:hmg_patient_app/pages/DrawerPages/family/my-family.dart'; @@ -41,6 +44,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_zoom_videosdk/native/zoom_videosdk.dart'; +import 'package:hmg_patient_app/widgets/quick_login.dart'; +import 'package:local_auth/local_auth.dart'; import 'package:provider/provider.dart'; import '../../locator.dart'; @@ -69,7 +74,7 @@ class LandingPage extends StatefulWidget { class _LandingPageState extends State with WidgetsBindingObserver { var authProvider = new AuthProvider(); AppointmentRateViewModel appointmentRateViewModel = locator(); - + final LocalAuthentication auth = LocalAuthentication(); int currentTab = 0; late PageController pageController; late ProjectViewModel projectViewModel; @@ -77,7 +82,7 @@ class _LandingPageState extends State with WidgetsBindingObserver { var notificationCount = ''; var themeNotifier; DateTime? currentBackPressTime; - + bool authenticated = false; // SignalRUtil signalRUtil; late ToDoCountProviderModel toDoProvider; @@ -651,7 +656,7 @@ class _LandingPageState extends State with WidgetsBindingObserver { if (authenticatedUserObject.isLogin) { var data = AuthenticatedUser.fromJson(await sharedPref.getObject(USER_PROFILE)); if (data != null) { - authService.registeredAuthenticatedUser(data, token, 0, 0).then((res) => {}); + // authService.registeredAuthenticatedUser(data, token, 0, 0).then((res) => {}); authService.getDashboard().then((value) async { setState(() { if (value != null) { @@ -659,7 +664,7 @@ class _LandingPageState extends State with WidgetsBindingObserver { notificationCount = value['List_PatientDashboard'][0]['UnreadPatientNotificationCount'] > 99 ? '99+' : value['List_PatientDashboard'][0]['UnreadPatientNotificationCount'].toString(); model.setState(model.count, model.ancillaryCount, true, notificationCount); sharedPref.setString(NOTIFICATION_COUNT, notificationCount); - checkLastLoginStatus(); + checkLastLoginStatus(data, token); } }); // if (await AppSharedPreferences().getBool(IS_LAST_APPOINTMENT_RATE_SHOWN) == null || !await AppSharedPreferences().getBool(IS_LAST_APPOINTMENT_RATE_SHOWN)) { @@ -706,12 +711,58 @@ class _LandingPageState extends State with WidgetsBindingObserver { sharedPref.setString(IS_COVID_CONSENT_SHOWN, "true"); } - checkLastLoginStatus() async{ + checkLastLoginStatus(AuthenticatedUser user, String deviceToken) async{ int lastLoginStatus = await sharedPref.getInt(LAST_LOGIN) != null ? await sharedPref.getInt(LAST_LOGIN) : 1; if(lastLoginStatus == 1 || lastLoginStatus == 2){ - print("SMS or Whatsapp Consent"); + showQuickLoginBottomSheet(context, user, deviceToken); } } -} + + void showQuickLoginBottomSheet(BuildContext context, AuthenticatedUser user, String deviceToken) { + showModalBottomSheet( + context: context, + backgroundColor: Colors.transparent, + isScrollControlled: true, + builder: (context) => QuickLoginBottomSheet(onPressed: (){ + loginWithFingerPrintFace(3, 1, user, deviceToken); + },), + ); + } + loginWithFingerPrintFace(type, int isActive, AuthenticatedUser user, String deviceToken ) async { + try { + authenticated = await auth.authenticate( + localizedReason: 'Scan your fingerprint to authenticate', + options: AuthenticationOptions( + useErrorDialogs: true, + stickyAuth: true, + ), + authMessages: [ + // IOSAuthMessages( + // cancelButton: 'cancel', + // goToSettingsButton: 'settings', + // goToSettingsDescription: 'Please set up your Touch ID.', + // lockOut: 'Please reenable your Touch ID'), + ], + ); + } on PlatformException catch (e) { + GifLoaderDialogUtils.hideDialog(context); + AppToast.showErrorToast(message: 'Please enable your Touch or Face ID'); + } + if (authenticated == true) { + int lastLogin = 1; + List availableBiometrics = []; + if (availableBiometrics.contains(BiometricType.face)) { + lastLogin = 3; + } else if (availableBiometrics.contains(BiometricType.fingerprint)) { + lastLogin = 2; + } else { + lastLogin = 1; + } + await sharedPref.setInt(LAST_LOGIN, lastLogin); + authService.registeredAuthenticatedUser(user, deviceToken, 0, 0).then(( + res) => {}); + } + } + } diff --git a/lib/pages/livecare/incoming_call.dart b/lib/pages/livecare/incoming_call.dart index 2c0a1ef7..229a2c32 100644 --- a/lib/pages/livecare/incoming_call.dart +++ b/lib/pages/livecare/incoming_call.dart @@ -1,13 +1,10 @@ import 'dart:ui'; -import 'package:camera/camera.dart'; import 'package:hmg_patient_app/models/LiveCare/IncomingCallData.dart'; import 'package:hmg_patient_app/pages/conference/widgets/platform_exception_alert_dialog.dart'; import 'package:hmg_patient_app/pages/conference/zoom/call_screen.dart'; import 'package:hmg_patient_app/pages/landing/landing_page.dart'; -import 'package:hmg_patient_app/pages/videocall-webrtc-rnd/webrtc/start_video_call.dart'; import 'package:hmg_patient_app/pages/webRTC/OpenTok/OpenTok.dart'; -import 'package:hmg_patient_app/pages/webRTC/signaling.dart'; import 'package:hmg_patient_app/services/livecare_services/livecare_provider.dart'; import 'package:hmg_patient_app/uitl/translations_delegate_base.dart'; import 'package:hmg_patient_app/uitl/utils_new.dart'; @@ -31,7 +28,7 @@ class _IncomingCallState extends State with SingleTickerProviderSt bool openCallInWeb = true; final player = AudioPlayer(); - late CameraController _controller; + // late CameraController _controller; late Future _initializeControllerFuture; bool isCameraReady = false; diff --git a/lib/pages/login/confirm-login.dart b/lib/pages/login/confirm-login.dart index 595a6a8b..422955ba 100644 --- a/lib/pages/login/confirm-login.dart +++ b/lib/pages/login/confirm-login.dart @@ -369,7 +369,7 @@ class _ConfirmLogin extends State { checkUserAuthentication(type) { showLoader(true); - var req = getCommonRequest(type: type); + var req = authService.getCommonRequest(type: type, registerd_data: this.registerd_data, deviceToken: this.deviceToken, mobileNumber: this.mobileNumber, zipCode: this.zipCode, patientOutSA: this.patientOutSA, loginTokenID: this.loginTokenID, selectedOption: this.selectedOption, user: this.user!); req.logInTokenID = ""; var request = CheckPatientAuthenticationReq.fromJson(req.toJson()); @@ -400,7 +400,7 @@ class _ConfirmLogin extends State { } sendActivationCode(type) async { - var request = this.getCommonRequest(type: type); + var request = this.authService.getCommonRequest(type: type, registerd_data: this.registerd_data, deviceToken: this.deviceToken, mobileNumber: this.mobileNumber, zipCode: this.zipCode, patientOutSA: this.patientOutSA, loginTokenID: this.loginTokenID, selectedOption: this.selectedOption, user: this.user!); request.sMSSignature = await SMSOTP.getSignature(); GifLoaderDialogUtils.showMyDialog(context); if (healthId != null || widget.isDubai) { @@ -478,7 +478,7 @@ class _ConfirmLogin extends State { // this.checkActivationCode(); // } else { - var request = this.getCommonRequest(type: type); + var request = this.authService.getCommonRequest(type: type, registerd_data: this.registerd_data, deviceToken: this.deviceToken, mobileNumber: this.mobileNumber, zipCode: this.zipCode, patientOutSA: this.patientOutSA, loginTokenID: this.loginTokenID, selectedOption: this.selectedOption, user: this.user!); this.getMobileInfo(request); //} } @@ -563,39 +563,39 @@ class _ConfirmLogin extends State { //this.cs.sharedService.getStorage(AuthenticationService.LAST_LOGIN); } - getCommonRequest({type}) { - var request = SendActivationRequest(); - request.patientMobileNumber = this.mobileNumber; - request.mobileNo = '0' + this.mobileNumber.toString(); - request.deviceToken = this.deviceToken; - request.projectOutSA = this.patientOutSA == true ? true : false; - request.loginType = this.selectedOption; - request.oTPSendType = type == 1 ? type : 2; //this.selectedOption == 1 ? 1 : 2; - request.zipCode = this.zipCode; - - request.logInTokenID = this.loginTokenID ?? ""; - - if (this.registerd_data != null) { - request.searchType = this.registerd_data.searchType != null ? this.registerd_data.searchType : 1; - request.patientID = this.registerd_data.patientID != null ? this.registerd_data.patientID : 0; - request.patientIdentificationID = request.nationalID = this.registerd_data.patientIdentificationID != null ? this.registerd_data.patientIdentificationID : '0'; - request.dob = this.registerd_data.dob; - request.isRegister = this.registerd_data.isRegister; - } else { - request.searchType = request.searchType != null ? request.searchType : 2; - request.patientID = this.user!.patientID != null ? this.user!.patientID : 0; - request.nationalID = request.nationalID != null ? request.nationalID : '0'; - request.patientIdentificationID = request.patientIdentificationID != null ? request.patientIdentificationID : '0'; - request.isRegister = false; - } - request.deviceTypeID = request.searchType; - return request; - } + // getCommonRequest({type}) { + // var request = SendActivationRequest(); + // request.patientMobileNumber = this.mobileNumber; + // request.mobileNo = '0' + this.mobileNumber.toString(); + // request.deviceToken = this.deviceToken; + // request.projectOutSA = this.patientOutSA == true ? true : false; + // request.loginType = this.selectedOption; + // request.oTPSendType = type == 1 ? type : 2; //this.selectedOption == 1 ? 1 : 2; + // request.zipCode = this.zipCode; + // + // request.logInTokenID = this.loginTokenID ?? ""; + // + // if (this.registerd_data != null) { + // request.searchType = this.registerd_data.searchType != null ? this.registerd_data.searchType : 1; + // request.patientID = this.registerd_data.patientID != null ? this.registerd_data.patientID : 0; + // request.patientIdentificationID = request.nationalID = this.registerd_data.patientIdentificationID != null ? this.registerd_data.patientIdentificationID : '0'; + // request.dob = this.registerd_data.dob; + // request.isRegister = this.registerd_data.isRegister; + // } else { + // request.searchType = request.searchType != null ? request.searchType : 2; + // request.patientID = this.user!.patientID != null ? this.user!.patientID : 0; + // request.nationalID = request.nationalID != null ? request.nationalID : '0'; + // request.patientIdentificationID = request.patientIdentificationID != null ? request.patientIdentificationID : '0'; + // request.isRegister = false; + // } + // request.deviceTypeID = request.searchType; + // return request; + // } checkActivationCode({value}) async { // Navigator.pop(context); GifLoaderDialogUtils.showMyDialog(context); - var request = this.getCommonRequest().toJson(); + var request = authService.getCommonRequest(registerd_data: this.registerd_data, deviceToken: this.deviceToken, mobileNumber: this.mobileNumber, zipCode: this.zipCode, patientOutSA: this.patientOutSA, loginTokenID: this.loginTokenID, selectedOption: this.selectedOption, user: this.user! ).toJson(); dynamic res; if (healthId != null || widget.isDubai) { if (!widget.isDubai) { diff --git a/lib/pages/login/welcome.dart b/lib/pages/login/welcome.dart index 3ab54304..06595504 100644 --- a/lib/pages/login/welcome.dart +++ b/lib/pages/login/welcome.dart @@ -307,10 +307,10 @@ class _WelcomeLogin extends State { Utils.showErrorToast("Please enter your phone number."); return; } - if (type == OTPType.whatsapp && !phoneController.text.startsWith("+966")) { - Utils.showErrorToast("WhatsApp OTP requires a phone number starting with +966."); - return; - } + // if (type == OTPType.whatsapp && !phoneController.text.startsWith("+966")) { + // Utils.showErrorToast("WhatsApp OTP requires a phone number starting with +966."); + // return; + // } print("Requesting OTP for ${phoneController.text} via ${type == OTPType.whatsapp ? "WhatsApp" : "SMS"} and ${nationIdController.text}"); // Navigator.pop(context); @@ -346,7 +346,8 @@ class _WelcomeLogin extends State { } checkUserAuthentication(type) { - showLoader(true); + // showLoader(true); + GifLoaderDialogUtils.showMyDialog(context); var req = getCommonRequest(type: type); req.logInTokenID = ""; @@ -587,7 +588,8 @@ class _WelcomeLogin extends State { ? user!.logInType : null; - showLoader(false); + // showLoader(false); + GifLoaderDialogUtils.hideDialog(context); //this.cs.sharedService.getStorage(AuthenticationService.LAST_LOGIN); } diff --git a/lib/services/authentication/auth_provider.dart b/lib/services/authentication/auth_provider.dart index 6c03f9e9..8e338426 100644 --- a/lib/services/authentication/auth_provider.dart +++ b/lib/services/authentication/auth_provider.dart @@ -18,6 +18,7 @@ import 'package:hmg_patient_app/models/Authentication/insert_device_imei_request import 'package:hmg_patient_app/models/Authentication/register_user_requet.dart'; import 'package:hmg_patient_app/models/Authentication/registered_authenticated_user_req.dart'; import 'package:hmg_patient_app/models/Authentication/select_device_imei_res.dart'; +import 'package:hmg_patient_app/models/Authentication/send_activation_request.dart'; import 'package:hmg_patient_app/models/Request.dart'; import 'package:hmg_patient_app/routes.dart'; import 'package:hmg_patient_app/uitl/app_shared_preferences.dart'; @@ -1937,4 +1938,33 @@ class AuthProvider with ChangeNotifier { model.setState(0, 0, false, null); Navigator.of(AppGlobal.context).pushReplacementNamed(HOME); } + + SendActivationRequest getCommonRequest({type, required registerd_data,required deviceToken,required mobileNumber,required zipCode,required patientOutSA, required loginTokenID, required selectedOption, required SelectDeviceIMEIRES user} ) { + var request = SendActivationRequest(); + request.patientMobileNumber = mobileNumber; + request.mobileNo = '0' + mobileNumber.toString(); + request.deviceToken = deviceToken; + request.projectOutSA = patientOutSA == true ? true : false; + request.loginType = selectedOption; + request.oTPSendType = type == 1 ? type : 2; //this.selectedOption == 1 ? 1 : 2; + request.zipCode = zipCode; + + request.logInTokenID = loginTokenID ?? ""; + + if (registerd_data != null) { + request.searchType = registerd_data.searchType != null ? registerd_data.searchType : 1; + request.patientID = registerd_data.patientID != null ? registerd_data.patientID : 0; + request.patientIdentificationID = request.nationalID = registerd_data.patientIdentificationID != null ? registerd_data.patientIdentificationID : '0'; + request.dob = registerd_data.dob; + request.isRegister = registerd_data.isRegister; + } else { + request.searchType = request.searchType != null ? request.searchType : 2; + request.patientID = user!.patientID != null ? user!.patientID : 0; + request.nationalID = request.nationalID != null ? request.nationalID : '0'; + request.patientIdentificationID = request.patientIdentificationID != null ? request.patientIdentificationID : '0'; + request.isRegister = false; + } + request.deviceTypeID = request.searchType; + return request; + } } diff --git a/lib/widgets/quick_login.dart b/lib/widgets/quick_login.dart new file mode 100644 index 00000000..ad73642d --- /dev/null +++ b/lib/widgets/quick_login.dart @@ -0,0 +1,76 @@ +import 'package:flutter/material.dart'; +import 'package:hmg_patient_app/new_ui/otp/otp_validation_bootmsheet_widget.dart'; +import 'package:hmg_patient_app/uitl/translations_delegate_base.dart'; +import 'package:hmg_patient_app/widgets/buttons/defaultButton.dart'; + + + +class QuickLoginBottomSheet extends StatelessWidget { + final VoidCallback onPressed; + const QuickLoginBottomSheet({required this.onPressed}); + + @override + Widget build(BuildContext context) { + return Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(24), + topRight: Radius.circular(24), + ), + ), + padding: const EdgeInsets.all(24), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Header + const Text( + 'Enable Quick Login', + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + + const SizedBox(height: 16), + + // Description + const Text( + 'Enabling the quick login will verify through your existing device Face ID / Biometric', + style: TextStyle( + fontSize: 16, + color: Color(0xFF666666), + height: 1.5, + ), + ), + + const SizedBox(height: 24), + + // Divider + const Divider(height: 1, thickness: 1), + + const SizedBox(height: 24), + + // Buttons + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Expanded(child: + + CustomButton( + text: "Enable Quick Login", + onPressed: onPressed, + backgroundColor: Colors.red, + borderColor: Colors.red, + textColor: Colors.white, + icon: "assets/images/svg/apple_finder.svg", + )), + ], + ), + ], + ), + ); + } +} \ No newline at end of file