From c416d84a3a3de72d40f324979f07e48c176b4180 Mon Sep 17 00:00:00 2001 From: Sultan khan Date: Thu, 12 Feb 2026 15:11:15 +0300 Subject: [PATCH 1/3] register insurance in progress. --- .../hmg_services/hmg_services_repo.dart | 30 +++- .../insurance/insurance_view_model.dart | 22 ++- .../authentication/register_step2.dart | 154 ++++++++++++------ .../vital_sign/vital_sign_details_page.dart | 22 ++- .../vital_sign/vital_sign_page.dart | 31 +++- 5 files changed, 189 insertions(+), 70 deletions(-) diff --git a/lib/features/hmg_services/hmg_services_repo.dart b/lib/features/hmg_services/hmg_services_repo.dart index e4b9a030..89285339 100644 --- a/lib/features/hmg_services/hmg_services_repo.dart +++ b/lib/features/hmg_services/hmg_services_repo.dart @@ -918,7 +918,10 @@ class HmgServicesRepoImp implements HmgServicesRepo { @override Future>>> getPatientVitalSign() async { - Map requestBody = {}; + Map requestBody = { + + + }; try { GenericApiModel>? apiResponse; @@ -942,12 +945,29 @@ class HmgServicesRepoImp implements HmgServicesRepo { if (vitalSignJson is Map) { final vitalSign = VitalSignResModel.fromJson(vitalSignJson); - // Only add records where BOTH height AND weight are greater than 0 + // Debug logging for blood pressure + print('=== Repository Blood Pressure Check ==='); + print('bloodPressureHigher: ${vitalSign.bloodPressureHigher}'); + print('bloodPressureLower: ${vitalSign.bloodPressureLower}'); + print('weightKg: ${vitalSign.weightKg}'); + print('heightCm: ${vitalSign.heightCm}'); + + // Check if the record has at least one valid vital sign measurement final hasValidWeight = _isValidValue(vitalSign.weightKg); final hasValidHeight = _isValidValue(vitalSign.heightCm); - - // Only add if both height and weight are valid (> 0) - if (hasValidWeight && hasValidHeight) { + final hasValidBMI = _isValidValue(vitalSign.bodyMassIndex); + final hasValidTemperature = _isValidValue(vitalSign.temperatureCelcius); + final hasValidHeartRate = _isValidValue(vitalSign.heartRate) || _isValidValue(vitalSign.pulseBeatPerMinute); + final hasValidRespiration = _isValidValue(vitalSign.respirationBeatPerMinute); + final hasValidBloodPressure = _isValidValue(vitalSign.bloodPressureHigher) || _isValidValue(vitalSign.bloodPressureLower); + + print('hasValidBloodPressure: $hasValidBloodPressure'); + print('Will add to list: ${hasValidWeight || hasValidHeight || hasValidBMI || hasValidTemperature || hasValidHeartRate || hasValidRespiration || hasValidBloodPressure}'); + print('====================================='); + + // Add if ANY vital sign has valid data + if (hasValidWeight || hasValidHeight || hasValidBMI || hasValidTemperature || + hasValidHeartRate || hasValidRespiration || hasValidBloodPressure) { vitalSignList.add(vitalSign); } } diff --git a/lib/features/insurance/insurance_view_model.dart b/lib/features/insurance/insurance_view_model.dart index 0bbdda20..8573ae9d 100644 --- a/lib/features/insurance/insurance_view_model.dart +++ b/lib/features/insurance/insurance_view_model.dart @@ -30,10 +30,14 @@ class InsuranceViewModel extends ChangeNotifier { InsuranceViewModel({required this.insuranceRepo, required this.errorHandlerService}); initInsuranceProvider() { + debugPrint("InsuranceViewModel: initInsuranceProvider called, isInsuranceDataToBeLoaded=$isInsuranceDataToBeLoaded"); if (isInsuranceDataToBeLoaded) { patientInsuranceList.clear(); isInsuranceLoading = true; + debugPrint("InsuranceViewModel: Calling getPatientInsuranceDetails API"); getPatientInsuranceDetails(); + } else { + debugPrint("InsuranceViewModel: Skipping API call, isInsuranceDataToBeLoaded is false"); } patientInsuranceCardHistoryList.clear(); isInsuranceHistoryLoading = true; @@ -69,29 +73,39 @@ class InsuranceViewModel extends ChangeNotifier { } Future getPatientInsuranceDetails({Function(dynamic)? onSuccess, Function(String)? onError}) async { - if (!isInsuranceDataToBeLoaded) return; + if (!isInsuranceDataToBeLoaded) { + debugPrint("InsuranceViewModel: getPatientInsuranceDetails - skipping, flag is false"); + return; + } + debugPrint("InsuranceViewModel: getPatientInsuranceDetails - making API call"); final result = await insuranceRepo.getPatientInsuranceDetails(); result.fold( // (failure) async => await errorHandlerService.handleError(failure: failure), (failure) async { + debugPrint("InsuranceViewModel: API call failed - ${failure.toString()}"); isInsuranceLoading = false; isInsuranceDataToBeLoaded = false; notifyListeners(); }, (apiResponse) { if (apiResponse.messageStatus == 2) { + debugPrint("InsuranceViewModel: API returned error status"); isInsuranceDataToBeLoaded = false; // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {}); } else if (apiResponse.messageStatus == 1) { + debugPrint("InsuranceViewModel: API success - received ${apiResponse.data?.length ?? 0} insurance records"); patientInsuranceList = apiResponse.data!; isInsuranceLoading = false; isInsuranceDataToBeLoaded = false; - isInsuranceExpired = DateTime.now().isAfter( - DateUtil.convertStringToDate(patientInsuranceList.first.cardValidTo), - ); + if (patientInsuranceList.isNotEmpty) { + isInsuranceExpired = DateTime.now().isAfter( + DateUtil.convertStringToDate(patientInsuranceList.first.cardValidTo), + ); + debugPrint("InsuranceViewModel: Insurance card expired: $isInsuranceExpired"); + } notifyListeners(); if (onSuccess != null) { diff --git a/lib/presentation/authentication/register_step2.dart b/lib/presentation/authentication/register_step2.dart index 71cef960..fdb0f42e 100644 --- a/lib/presentation/authentication/register_step2.dart +++ b/lib/presentation/authentication/register_step2.dart @@ -5,12 +5,15 @@ import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/common_models/nationality_country_model.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/enums.dart'; +import 'package:hmg_patient_app_new/core/utils/date_util.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/validation_utils.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart'; +import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; +import 'package:hmg_patient_app_new/presentation/insurance/widgets/patient_insurance_card.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/appbar/app_bar_widget.dart'; import 'package:hmg_patient_app_new/widgets/bottomsheet/generic_bottom_sheet.dart'; @@ -28,11 +31,22 @@ class RegisterNewStep2 extends StatefulWidget { class _RegisterNew extends State { AuthenticationViewModel? authVM; + InsuranceViewModel? insuranceVM; @override void initState() { super.initState(); authVM = context.read(); + insuranceVM = context.read(); + + // Call insurance API to fetch data + WidgetsBinding.instance.addPostFrameCallback((_) { + debugPrint("Registration Step 2: Calling insurance API"); + // Reset the flag to ensure API gets called + insuranceVM?.setIsInsuranceDataToBeLoaded(true); + insuranceVM?.initInsuranceProvider(); + debugPrint("Registration Step 2: Insurance API call initiated"); + }); } @override @@ -59,6 +73,59 @@ class _RegisterNew extends State { onLanguageChanged: (lang) {}, hideLogoAndLang: true, ), + bottomSheet: Container( + // height: 200.h, + width: MediaQuery.of(context).size.width, + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + customBorder: BorderRadius.only(topLeft: Radius.circular(24), topRight: Radius.circular(24)), + hasShadow: true, + ), + child: Row( + children: [ + Expanded( + child: CustomButton( + text: LocaleKeys.cancel.tr(), + icon: AppAssets.cancel, + onPressed: () { + Navigator.of(context).pop(); + // authVM!.clearDefaultInputValues(); + }, + backgroundColor: AppColors.secondaryLightRedColor, + borderColor: AppColors.secondaryLightRedColor, + textColor: AppColors.primaryRedColor, + iconColor: AppColors.primaryRedColor, + ), + ), + SizedBox(width: 16.w), + Expanded( + child: CustomButton( + backgroundColor: AppColors.primaryRedColor, + borderColor: AppColors.primaryRedColor, + textColor: AppColors.whiteColor, + text: LocaleKeys.confirm.tr(), + icon: AppAssets.confirm, + iconColor: AppColors.whiteColor, + onPressed: () { + if (appState.getUserRegistrationPayload.zipCode != CountryEnum.saudiArabia.countryCode) { + if (ValidationUtils.validateUaeRegistration( + name: authVM!.nameController.text, + gender: authVM!.genderType, + country: authVM!.pickedCountryByUAEUser, + maritalStatus: authVM!.maritalStatus, + onOkPress: () { + Navigator.of(context).pop(); + })) { + showModel(context: context); + } + } else { + showModel(context: context); + } + }, + ), + ) + ], + ).paddingAll(16.h),), body: GestureDetector( onTap: () { FocusScope.of(context).unfocus(); @@ -75,6 +142,29 @@ class _RegisterNew extends State { children: [ LocaleKeys.personalDetailsVerification.tr().toText26(color: AppColors.textColor, weight: FontWeight.w600, letterSpacing: -2), SizedBox(height: 24.h), + + // Insurance Card Section + Consumer( + builder: (context, insuranceVM, child) { + // Only show if insurance data is available and not loading + if (!insuranceVM.isInsuranceLoading && insuranceVM.patientInsuranceList.isNotEmpty) { + return Column( + children: [ + PatientInsuranceCard( + insuranceCardDetailsModel: insuranceVM.patientInsuranceList.first, + isInsuranceExpired: DateTime.now().isAfter( + DateUtil.convertStringToDate(insuranceVM.patientInsuranceList.first.cardValidTo), + ), + ), + SizedBox(height: 24.h), + ], + ); + } + // Don't show anything if loading or no data + return SizedBox.shrink(); + }, + ), + Container( decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(24)), padding: EdgeInsets.only(left: 16.h, right: 16.h), @@ -97,7 +187,7 @@ class _RegisterNew extends State { isReadOnly: authVM!.isUserFromUAE() ? false : true, leadingIcon: AppAssets.user_circle, labelColor: AppColors.textColor, - ).paddingSymmetrical(0.h, 16.h), + ).paddingSymmetrical(0.h, 8.h), Divider(height: 1.h, color: AppColors.greyColor), TextInputWidget( labelText: LocaleKeys.nationalIdNumber.tr(), @@ -111,7 +201,7 @@ class _RegisterNew extends State { isReadOnly: true, labelColor: AppColors.textColor, leadingIcon: AppAssets.student_card) - .paddingSymmetrical(0.h, 16.h), + .paddingSymmetrical(0.h, 8.h), Divider(height: 1, color: AppColors.greyColor), authVM!.isUserFromUAE() ? Selector( @@ -148,7 +238,7 @@ class _RegisterNew extends State { leadingIcon: AppAssets.user_full, labelColor: AppColors.textColor, onChange: (value) {}) - .paddingSymmetrical(0.h, 16.h), + .paddingSymmetrical(0.h, 8.h), Divider(height: 1, color: AppColors.greyColor), authVM!.isUserFromUAE() ? Selector( @@ -187,7 +277,7 @@ class _RegisterNew extends State { labelColor: AppColors.textColor, leadingIcon: AppAssets.smart_phone, onChange: (value) {}) - .paddingSymmetrical(0.h, 16.h), + .paddingSymmetrical(0.h, 8.h), Divider(height: 1.h, color: AppColors.greyColor), authVM!.isUserFromUAE() ? Selector? countriesList, NationalityCountries? selectedCountry, bool isArabic})>( @@ -237,14 +327,14 @@ class _RegisterNew extends State { labelColor: AppColors.textColor, leadingIcon: AppAssets.globe, onChange: (value) {}) - .paddingSymmetrical(0.h, 16.h), + .paddingSymmetrical(0.h, 8.h), Divider( height: 1, color: AppColors.greyColor, ), TextInputWidget( labelText: LocaleKeys.mobileNumber.tr(), - hintText: (appState.getUserRegistrationPayload.patientMobileNumber.toString() ?? ""), + hintText: appState.getUserRegistrationPayload.patientMobileNumber.toString(), controller: null, isEnable: false, prefix: null, @@ -254,7 +344,7 @@ class _RegisterNew extends State { labelColor: AppColors.textColor, isReadOnly: true, leadingIcon: AppAssets.call) - .paddingSymmetrical(0.h, 16.h), + .paddingSymmetrical(0.h, 8.h), Divider( height: 1.h, color: AppColors.greyColor, @@ -271,56 +361,12 @@ class _RegisterNew extends State { labelColor: AppColors.textColor, leadingIcon: AppAssets.birthday_cake, selectionType: null, - ).paddingSymmetrical(0.h, 16.h), + ).paddingSymmetrical(0.h, 8.h), ], ), ), - SizedBox(height: 50.h), - Row( - children: [ - Expanded( - child: CustomButton( - text: LocaleKeys.cancel.tr(), - icon: AppAssets.cancel, - onPressed: () { - Navigator.of(context).pop(); - // authVM!.clearDefaultInputValues(); - }, - backgroundColor: AppColors.secondaryLightRedColor, - borderColor: AppColors.secondaryLightRedColor, - textColor: AppColors.primaryRedColor, - iconColor: AppColors.primaryRedColor, - ), - ), - SizedBox(width: 16.w), - Expanded( - child: CustomButton( - backgroundColor: AppColors.primaryRedColor, - borderColor: AppColors.primaryRedColor, - textColor: AppColors.whiteColor, - text: LocaleKeys.confirm.tr(), - icon: AppAssets.confirm, - iconColor: AppColors.whiteColor, - onPressed: () { - if (appState.getUserRegistrationPayload.zipCode != CountryEnum.saudiArabia.countryCode) { - if (ValidationUtils.validateUaeRegistration( - name: authVM!.nameController.text, - gender: authVM!.genderType, - country: authVM!.pickedCountryByUAEUser, - maritalStatus: authVM!.maritalStatus, - onOkPress: () { - Navigator.of(context).pop(); - })) { - showModel(context: context); - } - } else { - showModel(context: context); - } - }, - ), - ) - ], - ), + SizedBox(height: 120.h), + ], ), ), diff --git a/lib/presentation/vital_sign/vital_sign_details_page.dart b/lib/presentation/vital_sign/vital_sign_details_page.dart index f6325029..f7aafa48 100644 --- a/lib/presentation/vital_sign/vital_sign_details_page.dart +++ b/lib/presentation/vital_sign/vital_sign_details_page.dart @@ -216,12 +216,21 @@ class _VitalSignDetailsPageState extends State { } Widget _historyCard(BuildContext context, {required List history}) { + // For graph display, use only the last 5 data points to avoid performance issues + final graphHistory = _isGraphVisible && history.length > 5 + ? history.sublist(history.length - 5) + : history; + // For blood pressure, we need both systolic and diastolic series List? secondaryHistory; if (args.metric == VitalSignMetric.bloodPressure) { - secondaryHistory = _buildBloodPressureDiastolicSeries( + final fullSecondaryHistory = _buildBloodPressureDiastolicSeries( context.read().vitalSignList, ); + // Also limit secondary history to last 5 for graph + secondaryHistory = _isGraphVisible && fullSecondaryHistory.length > 5 + ? fullSecondaryHistory.sublist(fullSecondaryHistory.length - 5) + : fullSecondaryHistory; } return Container( @@ -290,7 +299,7 @@ class _VitalSignDetailsPageState extends State { if (history.isEmpty) Utils.getNoDataWidget(context, noDataText: 'No history available'.needTranslation, isSmallWidget: true) else if (_isGraphVisible) - _buildHistoryGraph(history, secondaryHistory: secondaryHistory) + _buildHistoryGraph(graphHistory, secondaryHistory: secondaryHistory) else _buildHistoryList(context, history), ], @@ -591,8 +600,13 @@ class _VitalSignDetailsPageState extends State { double? _toDouble(dynamic v) { if (v == null) return null; - if (v is num) return v.toDouble(); - return double.tryParse(v.toString()); + if (v is num) { + // Treat 0 as invalid for vital signs + return v == 0 ? null : v.toDouble(); + } + final parsed = double.tryParse(v.toString()); + // Treat 0 as invalid for vital signs + return (parsed == null || parsed == 0) ? null : parsed; } String _latestValueText(VitalSignResModel? latest) { diff --git a/lib/presentation/vital_sign/vital_sign_page.dart b/lib/presentation/vital_sign/vital_sign_page.dart index fbf9fc6d..04d36bd9 100644 --- a/lib/presentation/vital_sign/vital_sign_page.dart +++ b/lib/presentation/vital_sign/vital_sign_page.dart @@ -24,6 +24,19 @@ class VitalSignPage extends StatefulWidget { } class _VitalSignPageState extends State { + + // Helper function to check if a value is valid (not null, not 0, not empty string) + bool _isValidValue(dynamic value) { + if (value == null) return false; + if (value is num) return value > 0; + if (value is String) { + if (value.trim().isEmpty) return false; + final parsed = double.tryParse(value); + return parsed != null && parsed > 0; + } + return false; + } + void _openDetails(VitalSignDetailsArgs args) { Navigator.of(context).push( CustomPageRoute( @@ -51,6 +64,18 @@ class _VitalSignPageState extends State { ? viewModel.vitalSignList.first : null; + // Debug logging for blood pressure + if (latestVitalSign != null) { + print('=== Blood Pressure Debug ==='); + print('bloodPressureHigher: ${latestVitalSign.bloodPressureHigher}'); + print('bloodPressureLower: ${latestVitalSign.bloodPressureLower}'); + print('bloodPressureHigher type: ${latestVitalSign.bloodPressureHigher.runtimeType}'); + print('bloodPressureLower type: ${latestVitalSign.bloodPressureLower.runtimeType}'); + print('bloodPressureHigher == 0: ${latestVitalSign.bloodPressureHigher == 0}'); + print('bloodPressureLower == 0: ${latestVitalSign.bloodPressureLower == 0}'); + print('========================'); + } + return SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -125,9 +150,9 @@ class _VitalSignPageState extends State { _buildVitalSignCard( icon: AppAssets.bloodPressure, label: 'Blood Pressure', - value: latestVitalSign != null && - latestVitalSign.bloodPressureHigher != null && - latestVitalSign.bloodPressureLower != null + value: (latestVitalSign != null && + _isValidValue(latestVitalSign.bloodPressureHigher) && + _isValidValue(latestVitalSign.bloodPressureLower)) ? '${latestVitalSign.bloodPressureHigher}/${latestVitalSign.bloodPressureLower}' : '--', unit: '', -- 2.30.2 From acfab432cc004a59bcc7a56aa1d5befc6609d1e1 Mon Sep 17 00:00:00 2001 From: Sultan khan Date: Thu, 5 Mar 2026 11:08:47 +0300 Subject: [PATCH 2/3] multiple submit button commented --- .../authentication/register_step2.dart | 90 +++++++++---------- lib/splashPage.dart | 2 +- 2 files changed, 46 insertions(+), 46 deletions(-) diff --git a/lib/presentation/authentication/register_step2.dart b/lib/presentation/authentication/register_step2.dart index c83226ca..0262f129 100644 --- a/lib/presentation/authentication/register_step2.dart +++ b/lib/presentation/authentication/register_step2.dart @@ -366,51 +366,51 @@ class _RegisterNew extends State { ), ), SizedBox(height: 50.h), - Row( - children: [ - Expanded( - child: CustomButton( - text: LocaleKeys.cancel.tr(context: context), - icon: AppAssets.cancel, - onPressed: () { - Navigator.of(context).pop(); - // authVM!.clearDefaultInputValues(); - }, - backgroundColor: AppColors.secondaryLightRedColor, - borderColor: AppColors.secondaryLightRedColor, - textColor: AppColors.primaryRedColor, - iconColor: AppColors.primaryRedColor, - ), - ), - SizedBox(width: 16.w), - Expanded( - child: CustomButton( - backgroundColor: AppColors.primaryRedColor, - borderColor: AppColors.primaryRedColor, - textColor: AppColors.whiteColor, - text: LocaleKeys.confirm.tr(context: context), - icon: AppAssets.confirm, - iconColor: AppColors.whiteColor, - onPressed: () { - if (appState.getUserRegistrationPayload.zipCode != CountryEnum.saudiArabia.countryCode) { - if (ValidationUtils.validateUaeRegistration( - name: authVM!.nameController.text, - gender: authVM!.genderType, - country: authVM!.pickedCountryByUAEUser, - maritalStatus: authVM!.maritalStatus, - onOkPress: () { - Navigator.of(context).pop(); - })) { - showModel(context: context); - } - } else { - showModel(context: context); - } - }, - ), - ) - ], - ), + // Row( + // children: [ + // Expanded( + // child: CustomButton( + // text: LocaleKeys.cancel.tr(context: context), + // icon: AppAssets.cancel, + // onPressed: () { + // Navigator.of(context).pop(); + // // authVM!.clearDefaultInputValues(); + // }, + // backgroundColor: AppColors.secondaryLightRedColor, + // borderColor: AppColors.secondaryLightRedColor, + // textColor: AppColors.primaryRedColor, + // iconColor: AppColors.primaryRedColor, + // ), + // ), + // SizedBox(width: 16.w), + // Expanded( + // child: CustomButton( + // backgroundColor: AppColors.primaryRedColor, + // borderColor: AppColors.primaryRedColor, + // textColor: AppColors.whiteColor, + // text: LocaleKeys.confirm.tr(context: context), + // icon: AppAssets.confirm, + // iconColor: AppColors.whiteColor, + // onPressed: () { + // if (appState.getUserRegistrationPayload.zipCode != CountryEnum.saudiArabia.countryCode) { + // if (ValidationUtils.validateUaeRegistration( + // name: authVM!.nameController.text, + // gender: authVM!.genderType, + // country: authVM!.pickedCountryByUAEUser, + // maritalStatus: authVM!.maritalStatus, + // onOkPress: () { + // Navigator.of(context).pop(); + // })) { + // showModel(context: context); + // } + // } else { + // showModel(context: context); + // } + // }, + // ), + // ) + // ], + // ), ], ), ), diff --git a/lib/splashPage.dart b/lib/splashPage.dart index dc7a7c98..1107c6b6 100644 --- a/lib/splashPage.dart +++ b/lib/splashPage.dart @@ -57,7 +57,7 @@ class _SplashScreenState extends State { await notificationService.initialize(onNotificationClick: (payload) { // Handle notification click here }); - ZoomService().initializeZoomSDK(); + //ZoomService().initializeZoomSDK(); if (isAppOpenedFromCall) { navigateToTeleConsult(); } else { -- 2.30.2 From 4f303d8496f271cd295d3cfb15331e179a5afe31 Mon Sep 17 00:00:00 2001 From: Sultan khan Date: Thu, 12 Mar 2026 14:30:46 +0300 Subject: [PATCH 3/3] other country login done. --- assets/langs/ar-SA.json | 1 + assets/langs/en-US.json | 1 + lib/core/api/api_client.dart | 44 +++++------ lib/core/api_consts.dart | 4 + lib/core/app_assets.dart | 1 + lib/core/app_state.dart | 1 + lib/core/enums.dart | 2 +- lib/core/utils/request_utils.dart | 46 +++++++---- lib/core/utils/validation_utils.dart | 14 +++- lib/extensions/string_extensions.dart | 11 +++ .../authentication/authentication_repo.dart | 56 ++++++++++++-- .../authentication_view_model.dart | 62 +++++++++------ ...ctivation_code_register_request_model.dart | 16 +++- .../patient_insert_device_imei_request.dart | 6 +- .../send_activation_request_model.dart | 14 +++- .../resp_models/select_device_by_imei.dart | 5 +- lib/generated/locale_keys.g.dart | 1 + lib/presentation/authentication/login.dart | 77 +++++++++++-------- lib/presentation/authentication/register.dart | 2 +- .../authentication/saved_login_screen.dart | 60 ++++++++++----- lib/presentation/home/landing_page.dart | 2 + .../bottomsheet/generic_bottom_sheet.dart | 2 +- .../dropdown/country_dropdown_widget.dart | 20 +++-- .../family_files/family_file_add_widget.dart | 2 +- 24 files changed, 307 insertions(+), 143 deletions(-) diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index 0886f376..f929b1ae 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -814,6 +814,7 @@ "ready": "جاهز", "enterValidNationalId": "الرجاء إدخال رقم الهوية الوطنية أو رقم الملف الصحيح", "enterValidPhoneNumber": "الرجاء إدخال رقم هاتف صالح", + "cannotEnterSaudiOrUAENumber": "لا يمكنك إدخال أرقام هواتف السعودية (00966) أو الإمارات (00971) عند اختيار دولة 'أخرى'", "medicalCentersWithCount": "{count} مراكز طبية", "medicalCenters": "مراكز طبية", "hospitalsWithCount": "{count} مستشفيات", diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 294201db..b1cc5b08 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -804,6 +804,7 @@ "awaitingApproval": "Awaiting Approval", "enterValidNationalId": "Please enter a valid national ID or file number", "enterValidPhoneNumber": "Please enter a valid phone number", + "cannotEnterSaudiOrUAENumber": "You cannot enter Saudi Arabia (00966) or UAE (00971) phone numbers when 'Others' country is selected", "ready": "Ready", "medicalCentersWithCount": "{count} Medical Centers", "medicalCenters": " Medical Centers", diff --git a/lib/core/api/api_client.dart b/lib/core/api/api_client.dart index b17db626..916f9b89 100644 --- a/lib/core/api/api_client.dart +++ b/lib/core/api/api_client.dart @@ -129,8 +129,7 @@ class ApiClientImp implements ApiClient { } else {} if (body.containsKey('isDentalAllowedBackend')) { - body['isDentalAllowedBackend'] = - body.containsKey('isDentalAllowedBackend') ? body['isDentalAllowedBackend'] ?? IS_DENTAL_ALLOWED_BACKEND : IS_DENTAL_ALLOWED_BACKEND; + body['isDentalAllowedBackend'] = body.containsKey('isDentalAllowedBackend') ? body['isDentalAllowedBackend'] ?? IS_DENTAL_ALLOWED_BACKEND : IS_DENTAL_ALLOWED_BACKEND; } if (!body.containsKey('IsPublicRequest')) { @@ -194,6 +193,11 @@ class ApiClientImp implements ApiClient { body['TokenID'] = "@dm!n"; } + if (url == 'https://uat.hmgwebservices.com/Services/NHIC.svc/REST/GetPatientInfo') { + url = "https://hmgwebservices.com/Services/NHIC.svc/REST/GetPatientInfo"; + body['TokenID'] = "@dm!n"; + } + // body['TokenID'] = "@dm!n"; // body['PatientID'] = 4773715; // body['PatientTypeID'] = 1; @@ -207,7 +211,7 @@ class ApiClientImp implements ApiClient { // body['PatientID'] = 809289; } - if(!url.contains("/paymentApi")) { + if (!url.contains("/paymentApi")) { body['IsNewFlutterApp'] = true; } @@ -261,10 +265,9 @@ class ApiClientImp implements ApiClient { ApiClient._navigationService.pushAndRemoveUntil( CustomPageRoute( page: AppUpdatePage( - appUpdateMessage: parsed['ErrorEndUserMessage'], - )), - ModalRoute.withName("/appUpdate") - ); + appUpdateMessage: parsed['ErrorEndUserMessage'], + )), + ModalRoute.withName("/appUpdate")); logApiEndpointError(endPoint, parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode); } if (parsed['ErrorType'] == 2) { @@ -272,24 +275,19 @@ class ApiClientImp implements ApiClient { onFailure( parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode, - failureType: - UnAuthenticatedUserFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'] ?? "User is not Authenticated", url: url), + failureType: UnAuthenticatedUserFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'] ?? "User is not Authenticated", url: url), ); // logApiEndpointError(endPoint, "session logged out", statusCode); } if (isAllowAny) { - onSuccess(parsed, statusCode, - messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']); + onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']); } else if (parsed['IsAuthenticated'] == null) { if (parsed['isSMSSent'] == true) { - onSuccess(parsed, statusCode, - messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']); + onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']); } else if (parsed['MessageStatus'] == 1) { - onSuccess(parsed, statusCode, - messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']); + onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']); } else if (parsed['Result'] == 'OK') { - onSuccess(parsed, statusCode, - messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']); + onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']); } else { onFailure( parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], @@ -299,19 +297,16 @@ class ApiClientImp implements ApiClient { logApiEndpointError(endPoint, parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode); } } else if (parsed['MessageStatus'] == 1 || parsed['SMSLoginRequired'] == true) { - onSuccess(parsed, statusCode, - messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']); + onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']); } else if (parsed['IsAuthenticated'] == false) { onFailure( "User is not Authenticated", statusCode, - failureType: - UnAuthenticatedUserFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'] ?? "User is not Authenticated", url: url), + failureType: UnAuthenticatedUserFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'] ?? "User is not Authenticated", url: url), ); } else if (parsed['MessageStatus'] == 2 && parsed['IsAuthenticated']) { if (parsed['SameClinicApptList'] != null) { - onSuccess(parsed, statusCode, - messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']); + onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']); } else { if (parsed['message'] == null && parsed['ErrorEndUserMessage'] == null) { if (parsed['ErrorSearchMsg'] == null) { @@ -340,8 +335,7 @@ class ApiClientImp implements ApiClient { } } else { if (parsed['SameClinicApptList'] != null) { - onSuccess(parsed, statusCode, - messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']); + onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']); } else { if (parsed['message'] != null) { onFailure( diff --git a/lib/core/api_consts.dart b/lib/core/api_consts.dart index ecfbc70a..a529c740 100644 --- a/lib/core/api_consts.dart +++ b/lib/core/api_consts.dart @@ -112,10 +112,13 @@ class ApiConsts { static final String selectDeviceImei = 'Services/Patients.svc/REST/Patient_SELECTDeviceIMEIbyIMEI'; static final String checkPatientAuth = 'Services/Authentication.svc/REST/CheckPatientAuthentication'; + static final String checkPatientAuthOthers = 'Services/Authentication.svc/REST/CheckPatientAuthentication_Others'; static final String sendActivationCode = 'Services/Authentication.svc/REST/SendActivationCodebyOTPNotificationType'; + static final String sendActivationCodeOthers = 'Services/Authentication.svc/REST/SendActivationCodebyOTPNotificationType_Others'; static final String sendActivationCodeRegister = 'Services/Authentication.svc/REST/SendActivationCodebyOTPNotificationTypeForRegistration'; static final String checkActivationCode = 'Services/Authentication.svc/REST/CheckActivationCode'; + static final String checkActivationCodeOthers = 'Services/Authentication.svc/REST/CheckActivationCode_Others'; static final String checkActivationCodeRegister = 'Services/Authentication.svc/REST/CheckActivationCodeForRegistration'; static final String checkUsageAgreement = 'Services/Patients.svc/REST/CheckForUsageAgreement'; static final String getUserAgreementContent = 'Services/Patients.svc/REST/GetUsageAgreementText'; @@ -124,6 +127,7 @@ class ApiConsts { static final String checkUserStatus = 'Services/NHIC.svc/REST/GetPatientInfo'; static final String insertPatientDeviceIMEIData = 'Services/Patients.svc/REST/Patient_INSERTDeviceIMEI'; + static final String insertPatientDeviceIMEIDataOthers = 'Services/Patients.svc/REST/Patient_INSERTDeviceIMEI_Others'; static final String insertPatientMobileData = 'Services/MobileNotifications.svc/REST/Insert_PatientMobileDeviceInfo'; static final String getPatientMobileData = '/Services/Authentication.svc/REST/GetMobileLoginInfo'; static final String getPrivileges = 'Services/Patients.svc/REST/Service_Privilege'; diff --git a/lib/core/app_assets.dart b/lib/core/app_assets.dart index efe62775..fdd32814 100644 --- a/lib/core/app_assets.dart +++ b/lib/core/app_assets.dart @@ -16,6 +16,7 @@ class AppAssets { static const String call = '$svgBasePath/call.svg'; static const String email = '$svgBasePath/email.svg'; static const String globe = '$svgBasePath/globe.svg'; + static const String globeOther = '$svgBasePath/globe_other.svg'; static const String cancel = '$svgBasePath/cancel.svg'; static const String bell = '$svgBasePath/bell.svg'; static const String login1 = '$svgBasePath/login1.svg'; diff --git a/lib/core/app_state.dart b/lib/core/app_state.dart index e1d6e05b..b95b883f 100644 --- a/lib/core/app_state.dart +++ b/lib/core/app_state.dart @@ -116,6 +116,7 @@ class AppState { set setIsAuthenticated(v) => isAuthenticated = v; + String deviceTypeID = ""; set setDeviceTypeID(v) => deviceTypeID = v; diff --git a/lib/core/enums.dart b/lib/core/enums.dart index 66137021..8bb8330c 100644 --- a/lib/core/enums.dart +++ b/lib/core/enums.dart @@ -12,7 +12,7 @@ enum AuthMethodTypesEnum { sms, whatsApp, fingerPrint, faceID, moreOptions } enum ViewStateEnum { hide, idle, busy, error, busyLocal, errorLocal } -enum CountryEnum { saudiArabia, unitedArabEmirates } +enum CountryEnum { saudiArabia, unitedArabEmirates, others } enum CalenderEnum { gregorian, hijri } diff --git a/lib/core/utils/request_utils.dart b/lib/core/utils/request_utils.dart index dd81a13c..bb947398 100644 --- a/lib/core/utils/request_utils.dart +++ b/lib/core/utils/request_utils.dart @@ -27,14 +27,21 @@ class RequestUtils { }) { bool fileNo = false; if (nationId.isNotEmpty) { - fileNo = nationId.length < 10; + final numericRegex = RegExp(r'^[0-9]+$'); + fileNo = nationId.length < 10 && numericRegex.hasMatch(nationId); + //fileNo = nationId.length < 10 && nationId.isNumericOnly() ; if (fileNo) { patientId = int.tryParse(nationId); } } var request = SendActivationRequest(); if (phoneNumber.isNotEmpty) { - request.patientMobileNumber = int.parse(phoneNumber); + // If zipCode is "0", it means "Others" country is selected + if (zipCode == "0") { + request.patientMobileNumberOthers = phoneNumber; + } else { + request.patientMobileNumber = int.parse(phoneNumber); + } } request.oTPSendType = otpTypeEnum.toInt(); // could map OTPTypeEnum if needed request.zipCode = zipCode; // or countryCode if defined elsewhere @@ -53,9 +60,9 @@ class RequestUtils { request.patientIdentificationID = request.nationalID; request.searchType = 2; } else { - request.patientID = 0; + request.patientID = 0; request.searchType = 1; - request.patientIdentificationID = request.nationalID = nationId.isNotEmpty ? int.parse(nationId) : 0; + request.patientIdentificationID = request.nationalID = nationId.isNotEmpty ? nationId : '0'; } request.isRegister = false; } @@ -75,11 +82,18 @@ class RequestUtils { required int loginType}) { bool fileNo = false; if (nationIdText.isNotEmpty) { - fileNo = nationIdText.length < 10; + final numericRegex = RegExp(r'^[0-9]+$'); + fileNo = nationIdText.length < 10 && numericRegex.hasMatch(nationIdText); } var request = SendActivationRequest(); - request.patientMobileNumber = int.parse(phoneNumber); - request.mobileNo = '0$phoneNumber'; + // If countryCode is "0", it means "Others" country is selected + if (countryCode == "0") { + request.patientMobileNumberOthers = phoneNumber; + request.mobileNo = phoneNumber; + } else { + request.patientMobileNumber = int.parse(phoneNumber); + request.mobileNo = '0$phoneNumber'; + } request.deviceToken = deviceToken; request.projectOutSA = patientOutSA; request.loginType = loginType; @@ -102,14 +116,14 @@ class RequestUtils { } else { if (fileNo) { request.patientID = patientId ?? int.parse(nationIdText); - request.patientIdentificationID = request.nationalID = 0; + request.patientIdentificationID = request.nationalID = '0'; request.searchType = 2; //TODO: Issue HEre is Not Login } else { request.patientID = 0; request.searchType = 1; //TODO: Issue HEre is Not Login - request.patientIdentificationID = request.nationalID = (nationIdText.isNotEmpty ? int.parse(nationIdText) : 0); + request.patientIdentificationID = request.nationalID = (nationIdText.isNotEmpty ? nationIdText : '0'); } request.isRegister = false; } @@ -123,7 +137,7 @@ class RequestUtils { required String mobileNumber, required String zipCode, required int? patientId, - required int? nationalId, + required dynamic nationalId, required bool patientOutSA, required int selectedLoginType, required bool isForRegister, @@ -136,9 +150,15 @@ class RequestUtils { AppState _appState = getIt.get(); var request = SendActivationRequest(); if (mobileNumber.isNotEmpty) { - request.patientMobileNumber = int.parse(mobileNumber); + // If zipCode is "0", it means "Others" country is selected + if (zipCode == "0") { + request.patientMobileNumberOthers = mobileNumber; + request.mobileNo = mobileNumber; + } else { + request.patientMobileNumber = int.parse(mobileNumber); + request.mobileNo = '0$mobileNumber'; + } } - request.mobileNo = '0$mobileNumber'; request.projectOutSA = patientOutSA; request.loginType = selectedLoginType; request.oTPSendType = otpTypeEnum.toInt(); //this.selectedOption == 1 ? 1 : 2; @@ -159,7 +179,7 @@ class RequestUtils { request.searchType = isFileNo ? 2 : 1; request.patientID = patientId ?? 0; request.nationalID = nationalId ?? 0; - request.patientIdentificationID = (nationalId ?? '0') as int?; + request.patientIdentificationID = (nationalId ?? '0'); request.isRegister = false; } request.deviceTypeID = request.searchType; diff --git a/lib/core/utils/validation_utils.dart b/lib/core/utils/validation_utils.dart index abba4477..a8bc03d3 100644 --- a/lib/core/utils/validation_utils.dart +++ b/lib/core/utils/validation_utils.dart @@ -60,11 +60,23 @@ class ValidationUtils { return isCorrectID; } - static bool isValidatePhone({String? phoneNumber, required Function() onOkPress}) { + static bool isValidatePhone({String? phoneNumber, required Function() onOkPress, CountryEnum? selectedCountry}) { if (phoneNumber == null || phoneNumber.isEmpty) { _dialogService.showExceptionBottomSheet(message: LocaleKeys.enterValidPhoneNumber.tr(), onOkPressed: onOkPress); return false; } + + // Check if "Others" country is selected and phone number starts with restricted codes + if (selectedCountry == CountryEnum.others) { + if (phoneNumber.startsWith('00966') || phoneNumber.startsWith('00971')) { + _dialogService.showExceptionBottomSheet( + message: LocaleKeys.cannotEnterSaudiOrUAENumber.tr(), + onOkPressed: onOkPress + ); + return false; + } + } + return true; } diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart index ba646cd2..3f9327fc 100644 --- a/lib/extensions/string_extensions.dart +++ b/lib/extensions/string_extensions.dart @@ -470,6 +470,8 @@ extension CountryExtension on CountryEnum { return "Kingdom Of Saudi Arabia"; case CountryEnum.unitedArabEmirates: return "United Arab Emirates"; + case CountryEnum.others: + return "Others"; } } @@ -479,6 +481,8 @@ extension CountryExtension on CountryEnum { return "المملكة العربية السعودية"; case CountryEnum.unitedArabEmirates: return "الإمارات العربية المتحدة"; + case CountryEnum.others: + return "آخرون"; } } @@ -488,6 +492,8 @@ extension CountryExtension on CountryEnum { return AppAssets.ksa; case CountryEnum.unitedArabEmirates: return AppAssets.uae; + case CountryEnum.others: + return AppAssets.globeOther; } } @@ -497,6 +503,8 @@ extension CountryExtension on CountryEnum { return "966"; case CountryEnum.unitedArabEmirates: return "971"; + case CountryEnum.others: + return "0"; } } @@ -508,6 +516,9 @@ extension CountryExtension on CountryEnum { case "United Arab Emirates": case "الإمارات العربية المتحدة": return CountryEnum.unitedArabEmirates; + case "Others": + case "آخرون": + return CountryEnum.others; default: throw Exception("Invalid country name"); } diff --git a/lib/features/authentication/authentication_repo.dart b/lib/features/authentication/authentication_repo.dart index 9b09c43c..f3b14c67 100644 --- a/lib/features/authentication/authentication_repo.dart +++ b/lib/features/authentication/authentication_repo.dart @@ -102,11 +102,16 @@ class AuthenticationRepoImp implements AuthenticationRepo { Future>> checkPatientAuthentication({required dynamic checkPatientAuthenticationReq, String? languageID}) async { int isOutKsa = (checkPatientAuthenticationReq.zipCode == '966' || checkPatientAuthenticationReq.zipCode == '+966') ? 0 : 1; checkPatientAuthenticationReq.patientOutSA = isOutKsa; + + // Determine which API to use based on zipCode + final isOthersCountry = checkPatientAuthenticationReq.zipCode == '0'; + final apiEndpoint = isOthersCountry ? ApiConsts.checkPatientAuthOthers : ApiConsts.checkPatientAuth; + try { GenericApiModel? apiResponse; Failure? failure; await apiClient.post( - ApiConsts.checkPatientAuth, + apiEndpoint, body: checkPatientAuthenticationReq.toJson(), onFailure: (error, statusCode, {messageStatus, failureType}) { failure = failureType; @@ -150,16 +155,25 @@ class AuthenticationRepoImp implements AuthenticationRepo { // payload.remove("ResponseID"); } + // Determine which API to use based on zipCode + final isOthersCountry = sendActivationCodeReq.zipCode == '0'; + String apiEndpoint; + if (isFormFamilyFile) { + apiEndpoint = ApiConsts.sendFamilyFileActivation; + } else if (isRegister) { + apiEndpoint = ApiConsts.sendActivationCodeRegister; + } else if (isOthersCountry) { + apiEndpoint = ApiConsts.sendActivationCodeOthers; + } else { + apiEndpoint = ApiConsts.sendActivationCode; + } + try { GenericApiModel? apiResponse; Failure? failure; await apiClient.post( - isFormFamilyFile - ? ApiConsts.sendFamilyFileActivation - : isRegister - ? ApiConsts.sendActivationCodeRegister - : ApiConsts.sendActivationCode, + apiEndpoint, body: isFormFamilyFile ? payload : sendActivationCodeReq.toJson(), onFailure: (error, statusCode, {messageStatus, failureType}) { failure = failureType; @@ -186,6 +200,8 @@ class AuthenticationRepoImp implements AuthenticationRepo { } } + + @override Future>> checkActivationCodeRepo( {required dynamic newRequest, // could be CheckActivationCodeReq or CheckActivationCodeRegisterReq @@ -304,11 +320,16 @@ class AuthenticationRepoImp implements AuthenticationRepo { } } + // Determine which API to use based on zipCode + final zipCode = _getZipCodeFromRequest(newRequest); + final isOthersCountry = zipCode == '0'; final endpoint = isFormFamilyFile ? ApiConsts.checkActivationCodeForFamily : isRegister ? ApiConsts.checkActivationCodeRegister - : ApiConsts.checkActivationCode; + : isOthersCountry + ? ApiConsts.checkActivationCodeOthers + : ApiConsts.checkActivationCode; try { GenericApiModel? apiResponse; @@ -521,8 +542,14 @@ class AuthenticationRepoImp implements AuthenticationRepo { try { GenericApiModel? apiResponse; Failure? failure; + + // Determine which API to use based on zipCode + final zipCode = patientIMEIDataRequest['ZipCode']; + final isOthersCountry = zipCode == '0'; + final apiEndpoint = isOthersCountry ? ApiConsts.insertPatientDeviceIMEIDataOthers : ApiConsts.insertPatientDeviceIMEIData; + return apiClient.post( - ApiConsts.insertPatientDeviceIMEIData, + apiEndpoint, body: patientIMEIDataRequest, onFailure: (error, statusCode, {messageStatus, failureType}) { failure = failureType; @@ -648,4 +675,17 @@ class AuthenticationRepoImp implements AuthenticationRepo { return Future.value(Left(UnknownFailure(e.toString()))); } } + + /// Helper method to safely get zipCode from dynamic request (Map or Object) + String _getZipCodeFromRequest(dynamic request) { + if (request is Map) { + return request['ZipCode']?.toString() ?? request['zipCode']?.toString() ?? ''; + } else { + try { + return request.zipCode?.toString() ?? ''; + } catch (e) { + return ''; + } + } + } } diff --git a/lib/features/authentication/authentication_view_model.dart b/lib/features/authentication/authentication_view_model.dart index 6fc36191..ce54c69f 100644 --- a/lib/features/authentication/authentication_view_model.dart +++ b/lib/features/authentication/authentication_view_model.dart @@ -70,7 +70,7 @@ class AuthenticationViewModel extends ChangeNotifier { _errorHandlerService = errorHandlerService, _appState = appState, _authenticationRepo = authenticationRepo, - _localAuthService = localAuthService; + _localAuthService = localAuthService {} final TextEditingController nationalIdController = TextEditingController(), phoneNumberController = TextEditingController(), dobController = TextEditingController(), @@ -182,6 +182,17 @@ class AuthenticationViewModel extends ChangeNotifier { void onPhoneNumberChange(String? phoneNumber) { phoneNumberController.text = phoneNumber!; + + // Real-time validation for Others country - prevent entering Saudi/UAE numbers + if (selectedCountrySignup == CountryEnum.others) { + if (phoneNumber.startsWith('00966') || phoneNumber.startsWith('00971')) { + // Remove the restricted prefix + phoneNumberController.text = phoneNumber.replaceAll(RegExp(r'^(00966|00971)'), ''); + phoneNumberController.selection = TextSelection.fromPosition( + TextPosition(offset: phoneNumberController.text.length), + ); + } + } } void onTermAccepted() { @@ -301,9 +312,11 @@ class AuthenticationViewModel extends ChangeNotifier { patientOutSA: false, otpTypeEnum: otpTypeEnum, patientId: 0, - zipCode: _appState.getSelectDeviceByImeiRespModelElement != null && _appState.getSelectDeviceByImeiRespModelElement!.outSa == true - ? CountryEnum.unitedArabEmirates.countryCode - : selectedCountrySignup.countryCode, + zipCode: selectedCountrySignup == CountryEnum.others + ? "0" + : (_appState.getSelectDeviceByImeiRespModelElement != null && _appState.getSelectDeviceByImeiRespModelElement!.outSa == true + ? CountryEnum.unitedArabEmirates.countryCode + : selectedCountrySignup.countryCode), calenderType: calenderType); final result = await _authenticationRepo.checkPatientAuthentication(checkPatientAuthenticationReq: checkPatientAuthenticationReq); @@ -368,7 +381,7 @@ class AuthenticationViewModel extends ChangeNotifier { mobileNumber: phoneNumber, selectedLoginType: otpTypeEnum.toInt(), zipCode: selectedCountrySignup.countryCode, - nationalId: int.parse(nationalIdOrFileNumber), + nationalId:nationalIdOrFileNumber, isFileNo: isForRegister ? isPatientHasFile(request: payload) : false, patientId: isFormFamilyFile ? _appState.getAuthenticatedUser()!.patientId : 0, isForRegister: isForRegister, @@ -607,6 +620,7 @@ class AuthenticationViewModel extends ChangeNotifier { activation.list!.first.isParentUser = true; } activation.list!.first.bloodGroup = activation.patientBlodType; + activation.list!.first.zipCode = selectedCountrySignup == CountryEnum.others ? '0' : selectedCountrySignup.countryCode; _appState.setAuthenticatedUser(activation.list!.first); _appState.setPrivilegeModelList(activation.list!.first.listPrivilege!); _appState.setUserBloodGroup = activation.patientBlodType ?? "N/A"; @@ -854,7 +868,9 @@ class AuthenticationViewModel extends ChangeNotifier { await clearDefaultInputValues(); // This will Clear All Default Values Of User. Future.delayed(Duration(seconds: 1), () { LoadingUtils.hideFullScreenLoader(); - _navigationService.pushAndReplace(AppRoutes.loginScreen); + // _navigationService.pushAndReplace(AppRoutes.loginScreen); + _navigationService.pushAndRemoveUntil(CustomPageRoute(page: LandingNavigation()), (r) => false); + _navigationService.push(CustomPageRoute(page: LoginScreen())); }); } } @@ -948,22 +964,24 @@ class AuthenticationViewModel extends ChangeNotifier { Future insertPatientIMEIData(int loginType) async { final resultEither = await _authenticationRepo.insertPatientIMEIData( patientIMEIDataRequest: PatientInsertDeviceImei( - imei: _appState.deviceToken, - deviceTypeId: _appState.getDeviceTypeID(), - patientId: _appState.getAuthenticatedUser()!.patientId!, - patientIdentificationNo: _appState.getAuthenticatedUser()!.patientIdentificationNo!, - identificationNo: _appState.getAuthenticatedUser()!.patientIdentificationNo!, - firstName: _appState.getAuthenticatedUser()!.firstName!, - lastName: _appState.getAuthenticatedUser()!.lastName!, - patientTypeId: _appState.getAuthenticatedUser()!.patientType, - mobileNo: _appState.getAuthenticatedUser()!.mobileNumber!, - logInTypeId: loginType, - patientOutSa: _appState.getAuthenticatedUser()!.outSa!, - outSa: _appState.getAuthenticatedUser()!.outSa == 1 ? true : false, - biometricEnabled: loginType == 1 || loginType == 2 ? false : true, - firstNameN: _appState.getAuthenticatedUser()!.firstNameN, - lastNameN: _appState.getAuthenticatedUser()!.lastNameN, - ).toJson()); + imei: _appState.deviceToken, + deviceTypeId: _appState.getDeviceTypeID(), + patientId: _appState.getAuthenticatedUser()!.patientId!, + patientIdentificationNo: _appState.getAuthenticatedUser()!.patientIdentificationNo!, + identificationNo: _appState.getAuthenticatedUser()!.patientIdentificationNo!, + firstName: _appState.getAuthenticatedUser()!.firstName!, + lastName: _appState.getAuthenticatedUser()!.lastName!, + patientTypeId: _appState.getAuthenticatedUser()!.patientType, + mobileNo: _appState.getAuthenticatedUser()!.mobileNumber!, + logInTypeId: loginType, + patientOutSa: _appState.getAuthenticatedUser()!.outSa!, + outSa: _appState.getAuthenticatedUser()!.outSa == 1 ? true : false, + biometricEnabled: loginType == 1 || loginType == 2 ? false : true, + firstNameN: _appState.getAuthenticatedUser()!.firstNameN, + lastNameN: _appState.getAuthenticatedUser()!.lastNameN, + zipCode: _appState.getAuthenticatedUser()!.zipCode //selectedCountrySignup == CountryEnum.others ? '0': selectedCountrySignup.countryCode, + ) + .toJson()); resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) async { if (apiResponse.messageStatus == 1) { log("Insert IMEI Success"); diff --git a/lib/features/authentication/models/request_models/check_activation_code_register_request_model.dart b/lib/features/authentication/models/request_models/check_activation_code_register_request_model.dart index ebae7bc8..be9b8994 100644 --- a/lib/features/authentication/models/request_models/check_activation_code_register_request_model.dart +++ b/lib/features/authentication/models/request_models/check_activation_code_register_request_model.dart @@ -1,5 +1,6 @@ class CheckActivationCodeRegisterReq { int? patientMobileNumber; + String? patientMobileNumberOthers; String? mobileNo; String? deviceToken; bool? projectOutSA; @@ -9,8 +10,8 @@ class CheckActivationCodeRegisterReq { String? logInTokenID; int? searchType; int? patientID; - int? nationalID; - int? patientIdentificationID; + dynamic nationalID; + dynamic patientIdentificationID; String? activationCode; bool? isSilentLogin; double? versionID; @@ -29,6 +30,7 @@ class CheckActivationCodeRegisterReq { CheckActivationCodeRegisterReq({ this.patientMobileNumber, + this.patientMobileNumberOthers, this.mobileNo, this.deviceToken, this.projectOutSA, @@ -59,6 +61,7 @@ class CheckActivationCodeRegisterReq { CheckActivationCodeRegisterReq.fromJson(Map json) { patientMobileNumber = json['PatientMobileNumber']; + patientMobileNumberOthers = json['PatientMobileNumber_Others']; mobileNo = json['MobileNo']; deviceToken = json['DeviceToken']; projectOutSA = json['ProjectOutSA']; @@ -89,9 +92,14 @@ class CheckActivationCodeRegisterReq { Map toJson() { final Map data = {}; - data['PatientMobileNumber'] = patientMobileNumber; - data['MobileNo'] = mobileNo; + // Only send PatientMobileNumber_Others if it's set, otherwise send PatientMobileNumber + if (patientMobileNumberOthers != null) { + data['PatientMobileNumber_Others'] = patientMobileNumberOthers; + } else if (patientMobileNumber != null) { + data['PatientMobileNumber'] = patientMobileNumber; + } data['DeviceToken'] = deviceToken; + data['MobileNo'] = mobileNo; data['ProjectOutSA'] = projectOutSA; data['LoginType'] = loginType; data['ZipCode'] = zipCode; diff --git a/lib/features/authentication/models/request_models/patient_insert_device_imei_request.dart b/lib/features/authentication/models/request_models/patient_insert_device_imei_request.dart index 0b2a99f3..09e262e7 100644 --- a/lib/features/authentication/models/request_models/patient_insert_device_imei_request.dart +++ b/lib/features/authentication/models/request_models/patient_insert_device_imei_request.dart @@ -28,6 +28,7 @@ class PatientInsertDeviceImei { int? patientOutSa; String? sessionId; String? lastName; + String? zipCode; PatientInsertDeviceImei({ this.setupId, @@ -56,7 +57,8 @@ class PatientInsertDeviceImei { this.patientTypeId, this.patientOutSa, this.sessionId, - this.lastName + this.lastName, + this.zipCode, }); factory PatientInsertDeviceImei.fromRawJson(String str) => PatientInsertDeviceImei.fromJson(json.decode(str)); @@ -91,6 +93,7 @@ class PatientInsertDeviceImei { patientOutSa: json["PatientOutSA"], sessionId: json["SessionID"], lastName: json["LastName"], + zipCode: json["ZipCode"], ); @@ -122,5 +125,6 @@ class PatientInsertDeviceImei { "PatientOutSA": patientOutSa, "SessionID": sessionId, "LastName": lastName, + "ZipCode": zipCode, }; } diff --git a/lib/features/authentication/models/request_models/send_activation_request_model.dart b/lib/features/authentication/models/request_models/send_activation_request_model.dart index 6bd48b44..2908f7ec 100644 --- a/lib/features/authentication/models/request_models/send_activation_request_model.dart +++ b/lib/features/authentication/models/request_models/send_activation_request_model.dart @@ -1,5 +1,6 @@ class SendActivationRequest { int? patientMobileNumber; + String? patientMobileNumberOthers; String? mobileNo; String? deviceToken; bool? projectOutSA; @@ -9,8 +10,8 @@ class SendActivationRequest { String? logInTokenID; int? searchType; int? patientID; - int? nationalID; - int? patientIdentificationID; + dynamic nationalID; + dynamic patientIdentificationID; int? oTPSendType; int? languageID; double? versionID; @@ -32,6 +33,7 @@ class SendActivationRequest { SendActivationRequest( {this.patientMobileNumber, + this.patientMobileNumberOthers, this.mobileNo, this.deviceToken, this.projectOutSA, @@ -64,6 +66,7 @@ class SendActivationRequest { SendActivationRequest.fromJson(Map json) { patientMobileNumber = json['PatientMobileNumber']; + patientMobileNumberOthers = json['PatientMobileNumber_Others']; mobileNo = json['MobileNo']; deviceToken = json['DeviceToken']; projectOutSA = json['ProjectOutSA']; @@ -97,7 +100,12 @@ class SendActivationRequest { Map toJson() { final Map data = new Map(); - data['PatientMobileNumber'] = patientMobileNumber; + // Only send PatientMobileNumber_Others if it's set, otherwise send PatientMobileNumber + if (patientMobileNumberOthers != null) { + data['PatientMobileNumber_Others'] = patientMobileNumberOthers; + } else if (patientMobileNumber != null) { + data['PatientMobileNumber'] = patientMobileNumber; + } data['MobileNo'] = mobileNo; data['DeviceToken'] = deviceToken; data['ProjectOutSA'] = projectOutSA; diff --git a/lib/features/authentication/models/resp_models/select_device_by_imei.dart b/lib/features/authentication/models/resp_models/select_device_by_imei.dart index 398f7918..20a876f4 100644 --- a/lib/features/authentication/models/resp_models/select_device_by_imei.dart +++ b/lib/features/authentication/models/resp_models/select_device_by_imei.dart @@ -19,7 +19,7 @@ class SelectDeviceByImeiRespModelElement { bool? biometricEnabled; int? patientType; int? preferredLanguage; - + bool? isOther; SelectDeviceByImeiRespModelElement({ this.id, this.imei, @@ -35,6 +35,7 @@ class SelectDeviceByImeiRespModelElement { this.biometricEnabled, this.patientType, this.preferredLanguage, + this.isOther }); factory SelectDeviceByImeiRespModelElement.fromJson(Map json) => SelectDeviceByImeiRespModelElement( @@ -52,6 +53,7 @@ class SelectDeviceByImeiRespModelElement { biometricEnabled: json["BiometricEnabled"] as bool?, patientType: json["PatientType"] as int?, preferredLanguage: json["PreferredLanguage"] as int?, + isOther: json["IsOther"] as bool? ); Map toJson() => { @@ -69,5 +71,6 @@ class SelectDeviceByImeiRespModelElement { "BiometricEnabled": biometricEnabled, "PatientType": patientType, "PreferredLanguage": preferredLanguage, + "IsOther": isOther, }; } diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index 58639f9c..1a33df93 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -812,6 +812,7 @@ abstract class LocaleKeys { static const ready = 'ready'; static const enterValidNationalId = 'enterValidNationalId'; static const enterValidPhoneNumber = 'enterValidPhoneNumber'; + static const cannotEnterSaudiOrUAENumber = 'cannotEnterSaudiOrUAENumber'; static const medicalCentersWithCount = 'medicalCentersWithCount'; static const medicalCenters = 'medicalCenters'; static const hospitalsWithCount = 'hospitalsWithCount'; diff --git a/lib/presentation/authentication/login.dart b/lib/presentation/authentication/login.dart index 28b47304..62b207ac 100644 --- a/lib/presentation/authentication/login.dart +++ b/lib/presentation/authentication/login.dart @@ -79,7 +79,7 @@ class LoginScreenState extends State { hintText: "xxxxxxxxx", controller: authVm.nationalIdController, focusNode: _nationalIdFocusNode, - keyboardType: TextInputType.number, + keyboardType: TextInputType.text, isEnable: true, prefix: null, autoFocus: true, @@ -165,51 +165,60 @@ class LoginScreenState extends State { child: SingleChildScrollView( child: GenericBottomSheet( countryCode: authViewModel.selectedCountrySignup.countryCode, + initialPhoneNumber: "", textController: phoneNumberController, isEnableCountryDropdown: true, - onCountryChange: authViewModel.onCountryChange, + onCountryChange: (country) { + authViewModel.onCountryChange(country); + setModalState(() {}); + }, onChange: authViewModel.onPhoneNumberChange, buttons: [ - Padding( - padding: EdgeInsets.only(bottom: 10.h), - child: CustomButton( - text: LocaleKeys.sendOTPSMS.tr(context: context), - onPressed: () async { - if (ValidationUtils.isValidatePhone( - phoneNumber: phoneNumberController!.text, - onOkPress: () { - Navigator.of(context).pop(); - })) { - Navigator.of(context).pop(); - appState.setSelectDeviceByImeiRespModelElement(null); - await authViewModel.checkUserAuthentication(otpTypeEnum: OTPTypeEnum.sms); - } - }, - backgroundColor: AppColors.primaryRedColor, - borderColor: AppColors.primaryRedBorderColor, - textColor: Colors.white, - iconColor: Colors.white, - icon: AppAssets.message, - ), - ), - Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Padding( - padding: EdgeInsets.symmetric(horizontal: 8.h), - child: LocaleKeys.oR.tr(context: context).toText16(color: AppColors.textColor), + if (authViewModel.selectedCountrySignup != CountryEnum.others) + Padding( + padding: EdgeInsets.only(bottom: 10.h), + child: CustomButton( + text: LocaleKeys.sendOTPSMS.tr(context: context), + onPressed: () async { + if (ValidationUtils.isValidatePhone( + phoneNumber: phoneNumberController!.text, + selectedCountry: authViewModel.selectedCountrySignup, + onOkPress: () { + Navigator.of(context).pop(); + })) { + Navigator.of(context).pop(); + appState.setSelectDeviceByImeiRespModelElement(null); + await authViewModel.checkUserAuthentication(otpTypeEnum: OTPTypeEnum.sms); + } + }, + backgroundColor: AppColors.primaryRedColor, + borderColor: AppColors.primaryRedBorderColor, + textColor: Colors.white, + iconColor: Colors.white, + icon: AppAssets.message, ), - ], - ), + ), + if (authViewModel.selectedCountrySignup != CountryEnum.others) + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: EdgeInsets.symmetric(horizontal: 8.h), + child: LocaleKeys.oR.tr(context: context).toText16(color: AppColors.textColor), + ), + ], + ), Padding( padding: EdgeInsets.only(bottom: 10.h, top: 10.h), child: CustomButton( text: LocaleKeys.sendOTPWHATSAPP.tr(context: context), + onPressed: () async { if (ValidationUtils.isValidatePhone( phoneNumber: phoneNumberController!.text, + selectedCountry: authViewModel.selectedCountrySignup, onOkPress: () { Navigator.of(context).pop(); })) { @@ -220,7 +229,7 @@ class LoginScreenState extends State { }, backgroundColor: Colors.white, borderColor: AppColors.borderOnlyColor, - textColor: AppColors.whiteColor, + textColor: AppColors.borderOnlyColor, icon: AppAssets.whatsapp, iconColor: null, applyThemeColor: false, diff --git a/lib/presentation/authentication/register.dart b/lib/presentation/authentication/register.dart index 9d67920f..535cdff1 100644 --- a/lib/presentation/authentication/register.dart +++ b/lib/presentation/authentication/register.dart @@ -90,7 +90,7 @@ class _RegisterNew extends State { child: Column( children: [ CustomCountryDropdown( - countryList: CountryEnum.values, + countryList: CountryEnum.values.where((c) => c != CountryEnum.others).toList(), onCountryChange: authVm.onCountryChange, // isRtl: Directionality.of(context) == TextDirection.LTR, ).withVerticalPadding(8.h), diff --git a/lib/presentation/authentication/saved_login_screen.dart b/lib/presentation/authentication/saved_login_screen.dart index 231d7d14..00673cd7 100644 --- a/lib/presentation/authentication/saved_login_screen.dart +++ b/lib/presentation/authentication/saved_login_screen.dart @@ -31,7 +31,7 @@ class _SavedLogin extends State { LoginTypeEnum loginType = LoginTypeEnum.sms; late AuthenticationViewModel authVm; late AppState appState; - + bool? isOther; @override void initState() { authVm = context.read(); @@ -43,6 +43,15 @@ class _SavedLogin extends State { : appState.getSelectDeviceByImeiRespModelElement!.mobile!; authVm.nationalIdController.text = appState.getSelectDeviceByImeiRespModelElement!.identificationNo!; + // Check if this is an "Others" country user + isOther = appState.getSelectDeviceByImeiRespModelElement!.isOther == true; + + // Set country to Others if isOther flag is true - this ensures _Others APIs are called + if (isOther!) { + authVm.phoneNumberController.text = appState.getSelectDeviceByImeiRespModelElement!.mobile!; + authVm.selectedCountrySignup = CountryEnum.others; + } + if (loginType == LoginTypeEnum.fingerprint || loginType == LoginTypeEnum.face) { authVm.loginWithFingerPrintFace(() {}); } @@ -90,9 +99,9 @@ class _SavedLogin extends State { ), child: Column( children: [ - // Last login info + // Last login info - show WhatsApp only if isOther AND loginType is SMS - ("${LocaleKeys.lastLoginBy.tr()} ${loginType.displayName}") + ("${LocaleKeys.lastLoginBy.tr()} ${(isOther == true && loginType == LoginTypeEnum.sms) ? LoginTypeEnum.whatsapp.displayName : loginType.displayName}") .toText14(isBold: true, color: AppColors.greyTextColor, letterSpacing: -1), Directionality( textDirection: ui.TextDirection.ltr, @@ -108,20 +117,27 @@ class _SavedLogin extends State { ? Container( margin: EdgeInsets.all(16.h), child: Utils.buildSvgWithAssets( - icon: getTypeIcons(appState.getSelectDeviceByImeiRespModelElement!.logInType!), + icon: (isOther == true && loginType == LoginTypeEnum.sms) ? AppAssets.whatsapp : getTypeIcons(appState.getSelectDeviceByImeiRespModelElement!.logInType!), height: 54.h, width: 54.w, - iconColor: loginType.toInt == 4 ? null : AppColors.primaryRedColor)) + iconColor: (isOther == true && loginType == LoginTypeEnum.sms) || loginType.toInt == 4 ? null : AppColors.primaryRedColor)) : SizedBox(), - // Face ID login button + // Main login button - for isOther with SMS, show WhatsApp, otherwise keep original login type CustomButton( - text: "${LocaleKeys.loginBy.tr()} ${loginType.displayName}", + text: (isOther == true && loginType == LoginTypeEnum.sms) + ? "${LocaleKeys.loginBy.tr()} ${LoginTypeEnum.whatsapp.displayName}" + : "${LocaleKeys.loginBy.tr()} ${loginType.displayName}", onPressed: () { if (loginType == LoginTypeEnum.fingerprint || loginType == LoginTypeEnum.face) { authVm.loginWithFingerPrintFace(() {}); } else { - authVm.checkUserAuthentication(otpTypeEnum: loginType == LoginTypeEnum.sms ? OTPTypeEnum.sms : OTPTypeEnum.whatsapp); + // For isOther with SMS, use WhatsApp; otherwise use the original login type + authVm.checkUserAuthentication( + otpTypeEnum: (isOther == true && loginType == LoginTypeEnum.sms) + ? OTPTypeEnum.whatsapp + : (loginType == LoginTypeEnum.sms ? OTPTypeEnum.sms : OTPTypeEnum.whatsapp), + ); } }, backgroundColor: AppColors.primaryRedColor, @@ -132,24 +148,25 @@ class _SavedLogin extends State { borderRadius: 12.r, height: 40.h, padding: EdgeInsets.symmetric(vertical: 10.h), - icon: getTypeIcons(loginType.toInt), - //loginType == LoginTypeEnum.sms ? AppAssets.sms :AppAssets.whatsapp, - iconColor: loginType != LoginTypeEnum.whatsapp ? Colors.white : null, + icon: (isOther == true && loginType == LoginTypeEnum.sms) ? AppAssets.whatsapp : getTypeIcons(loginType.toInt), + iconColor: (isOther == true && loginType == LoginTypeEnum.sms) || loginType == LoginTypeEnum.whatsapp ? null : Colors.white, ), ], ), ), SizedBox(height: 24.h), - Padding( - padding: EdgeInsets.symmetric(horizontal: 16.w), - child: Text( - LocaleKeys.oR.tr(), - style: context.dynamicTextStyle(fontSize: 16.f, fontWeight: FontWeight.w500), + // Hide OR + OTP login options entirely when isOther is true + if (isOther != true) ...[ + Padding( + padding: EdgeInsets.symmetric(horizontal: 16.w), + child: Text( + LocaleKeys.oR.tr(), + style: context.dynamicTextStyle(fontSize: 16.f, fontWeight: FontWeight.w500), + ), ), - ), - SizedBox(height: 24.h), - // OTP login button - loginType.toInt != 1 + SizedBox(height: 24.h), + // OTP login button + loginType.toInt != 1 ? Column( children: [ loginType.toInt != 1 @@ -256,9 +273,10 @@ class _SavedLogin extends State { borderWidth: 2.w, padding: EdgeInsets.fromLTRB(0, 14.h, 0, 14.h), ), + ], + const Spacer(flex: 2), // OR divider - SizedBox(height: 24.h), // Guest and Switch account Row( diff --git a/lib/presentation/home/landing_page.dart b/lib/presentation/home/landing_page.dart index 607a47f7..a7ae78b9 100644 --- a/lib/presentation/home/landing_page.dart +++ b/lib/presentation/home/landing_page.dart @@ -10,6 +10,7 @@ import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/cache_consts.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart'; +import 'package:hmg_patient_app_new/core/enums.dart'; import 'package:hmg_patient_app_new/core/utils/date_util.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart'; @@ -1051,6 +1052,7 @@ class _LandingPageState extends State { isDone: isDone, onPressed: () { // sharedPref.setBool(HAS_ENABLED_QUICK_LOGIN, true); + authVM.loginWithFingerPrintFace(() async { isDone = true; cacheService.saveBool(key: CacheConst.quickLoginEnabled, value: true); diff --git a/lib/widgets/bottomsheet/generic_bottom_sheet.dart b/lib/widgets/bottomsheet/generic_bottom_sheet.dart index fd79b7c1..21cc076f 100644 --- a/lib/widgets/bottomsheet/generic_bottom_sheet.dart +++ b/lib/widgets/bottomsheet/generic_bottom_sheet.dart @@ -158,7 +158,7 @@ class GenericBottomSheetState extends State { prefix: widget.isForEmail ? null : widget.countryCode, isBorderAllowed: false, isAllowLeadingIcon: true, - fontSize: 18.f, + fontSize: 14.f, isCountryDropDown: widget.isEnableCountryDropdown, leadingIcon: widget.isForEmail ? AppAssets.email : AppAssets.smart_phone, fontFamily: "Poppins", diff --git a/lib/widgets/dropdown/country_dropdown_widget.dart b/lib/widgets/dropdown/country_dropdown_widget.dart index bc4b5edf..c0efbc98 100644 --- a/lib/widgets/dropdown/country_dropdown_widget.dart +++ b/lib/widgets/dropdown/country_dropdown_widget.dart @@ -98,11 +98,12 @@ class CustomCountryDropdownState extends State { Row( mainAxisAlignment: MainAxisAlignment.start, children: [ - Text( - selectedCountry!.countryCode, - style: TextStyle(fontSize: 12.f, fontWeight: FontWeight.w600, letterSpacing: -0.4, height: 1.5, fontFamily: "Poppins"), - ), - SizedBox(width: 4.h), + if (selectedCountry != CountryEnum.others) + Text( + selectedCountry!.countryCode, + style: TextStyle(fontSize: 12.f, fontWeight: FontWeight.w600, letterSpacing: -0.4, height: 1.5, fontFamily: "Poppins"), + ), + if (selectedCountry != CountryEnum.others) SizedBox(width: 4.h), if (widget.isEnableTextField) SizedBox( height: 20.h, @@ -112,7 +113,14 @@ class CustomCountryDropdownState extends State { child: TextField( focusNode: textFocusNode, style: TextStyle(fontSize: 12.f, fontWeight: FontWeight.w600, letterSpacing: -0.4, height: 1.5, fontFamily: "Poppins"), - decoration: InputDecoration(hintText: "", isDense: true, border: InputBorder.none, contentPadding: EdgeInsets.zero), + + decoration: InputDecoration( + hintText: selectedCountry == CountryEnum.others ? "001*******" : "", + isDense: true, + border: InputBorder.none, + contentPadding: EdgeInsets.zero, + + ), keyboardType: TextInputType.phone, onChanged: widget.onPhoneNumberChanged, ), diff --git a/lib/widgets/family_files/family_file_add_widget.dart b/lib/widgets/family_files/family_file_add_widget.dart index d8b4d13e..c4f43248 100644 --- a/lib/widgets/family_files/family_file_add_widget.dart +++ b/lib/widgets/family_files/family_file_add_widget.dart @@ -44,7 +44,7 @@ class _FamilyFileAddWidgetState extends State { child: Column( children: [ CustomCountryDropdown( - countryList: CountryEnum.values, + countryList: CountryEnum.values.where((c) => c != CountryEnum.others).toList(), onCountryChange: authVm.onCountryChange, ).paddingOnly(top: 8.h, bottom: 16.h), Divider(height: 1.h, color: AppColors.spacerLineColor), -- 2.30.2