From d1e1154bdb781fdccf12e0a5b3114285a4380734 Mon Sep 17 00:00:00 2001 From: aamir-csol Date: Tue, 2 Sep 2025 17:00:03 +0300 Subject: [PATCH] changes --- lib/core/utils/utils.dart | 74 +++++-- lib/extensions/string_extensions.dart | 36 ++-- .../authentication/authentication_repo.dart | 6 +- .../authentication_view_model.dart | 193 +++++++++--------- lib/presentation/authentication/login.dart | 9 +- lib/presentation/authentication/register.dart | 4 +- lib/presentation/home/landing_page.dart | 4 +- .../medical_file/medical_file_page.dart | 1 - .../bottomsheet/generic_bottom_sheet.dart | 2 +- .../dropdown/country_dropdown_widget.dart | 8 +- 10 files changed, 193 insertions(+), 144 deletions(-) diff --git a/lib/core/utils/utils.dart b/lib/core/utils/utils.dart index bdca5ff..ed4770d 100644 --- a/lib/core/utils/utils.dart +++ b/lib/core/utils/utils.dart @@ -13,6 +13,7 @@ import 'package:hmg_patient_app_new/core/dependencies.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/generated/locale_keys.g.dart'; +import 'package:hmg_patient_app_new/services/dialog_service.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/dialogs/confirm_dialog.dart'; @@ -59,14 +60,13 @@ class Utils { // )); return !isAddHours ? DateFormat('hh:mm a', appState.isArabic() ? "ar_SA" : "en_US") - .format(DateTime.tryParse(startTime.contains("T") ? startTime : convertStringToDateTime(startTime))!.toLocal()) + .format(DateTime.tryParse(startTime.contains("T") ? startTime : convertStringToDateTime(startTime))!.toLocal()) : DateFormat('hh:mm a', appState.isArabic() ? "ar_SA" : "en_US") - .format(DateTime.tryParse(startTime.contains("T") ? startTime : convertStringToDateTime(startTime))!.add( - Duration( - hours: isAddHours ? 3 : 0, - ), - )); - ; + .format(DateTime.tryParse(startTime.contains("T") ? startTime : convertStringToDateTime(startTime))!.add( + Duration( + hours: isAddHours ? 3 : 0, + ), + )); } static String convertStringToDateTime(String dateTimeString) { @@ -209,12 +209,12 @@ class Utils { builder: (BuildContext context) => LoadingDialog(), ) .then((value) { - _isLoadingVisible = false; - }) + _isLoadingVisible = false; + }) .catchError((e) {}) .onError( (error, stackTrace) {}, - ); + ); } static void hideLoading() { @@ -236,11 +236,12 @@ class Utils { showDialog( barrierDismissible: false, context: context, - builder: (cxt) => ConfirmDialog( - title: title!, - message: message!, - onTap: onTap, - ), + builder: (cxt) => + ConfirmDialog( + title: title!, + message: message!, + onTap: onTap, + ), ); } @@ -371,7 +372,9 @@ class Utils { static String formatHijriDateToDisplay(String hijriDateString) { try { // Assuming hijriDateString is in the format yyyy-MM-dd - final datePart = hijriDateString.split("T").first; + final datePart = hijriDateString + .split("T") + .first; final parts = datePart.split('-'); if (parts.length != 3) return ""; @@ -429,8 +432,14 @@ class Utils { void Function(LottieComposition)? onLoaded, }) { return Lottie.asset(assetPath, - height: height ?? MediaQuery.of(context).size.height * 0.26, - width: width ?? MediaQuery.of(context).size.width, + height: height ?? MediaQuery + .of(context) + .size + .height * 0.26, + width: width ?? MediaQuery + .of(context) + .size + .width, fit: fit, alignment: alignment, repeat: repeat, @@ -487,9 +496,13 @@ class Utils { ], ); } + static Future isGoogleServicesAvailable() async { GooglePlayServicesAvailability availability = await GoogleApiAvailability.instance.checkGooglePlayServicesAvailability(); - String status = availability.toString().split('.').last; + String status = availability + .toString() + .split('.') + .last; if (status == "success") { return true; } @@ -510,3 +523,26 @@ class Utils { return crypto.md5.convert(utf8.encode(input)).toString(); } } + +class ValidationUtils { + static DialogService dialogService = getIt.get(); + + + static bool isValidatePhoneAndId({ + String? nationalId, + String? phoneNumber + }) { + if (nationalId == null || nationalId.isEmpty) { + dialogService.showErrorDialog(message: "Please enter a valid national ID or file number", onOkPressed: () {}); + return false; + } + + if (phoneNumber == null || phoneNumber.isEmpty) { + dialogService.showErrorDialog(message: "Please enter a valid phone number", onOkPressed: () {}); + return false; + } + return true; + } +} + + diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart index 187939e..cbfac11 100644 --- a/lib/extensions/string_extensions.dart +++ b/lib/extensions/string_extensions.dart @@ -235,10 +235,12 @@ extension EmailValidator on String { ); Widget toText36({Color? color, bool isBold = false, bool isCenter = false}) => Text( - this, - textAlign: isCenter ? TextAlign.center : null, - style: TextStyle(height: 47 / 36, color: color ?? AppColors.blackColor, fontSize: 36.fSize, letterSpacing: -1, fontWeight: isBold ? FontWeight.w600 : FontWeight.normal), - ); + this, + textAlign: isCenter ? TextAlign.center : null, + style: TextStyle(height: 47 / 36, color: color ?? AppColors.blackColor, fontSize: 36.fSize, letterSpacing: -1, fontWeight: isBold ? FontWeight.w600 : FontWeight.normal), + ); + + Widget toText44({Color? color, bool isBold = false}) => Text( this, @@ -381,53 +383,55 @@ class FontUtils { } } -extension CountryExtension on Country { + +extension CountryExtension on CountryEnum { String get displayName { switch (this) { - case Country.saudiArabia: + case CountryEnum.saudiArabia: return "Kingdom Of Saudi Arabia"; - case Country.unitedArabEmirates: + case CountryEnum.unitedArabEmirates: return "United Arab Emirates"; } } String get nameArabic { switch (this) { - case Country.saudiArabia: + case CountryEnum.saudiArabia: return "المملكة العربية السعودية"; - case Country.unitedArabEmirates: + case CountryEnum.unitedArabEmirates: return "الإمارات العربية المتحدة"; } } String get iconPath { switch (this) { - case Country.saudiArabia: + case CountryEnum.saudiArabia: return AppAssets.ksa; - case Country.unitedArabEmirates: + case CountryEnum.unitedArabEmirates: return AppAssets.uae; } } String get countryCode { switch (this) { - case Country.saudiArabia: + case CountryEnum.saudiArabia: return "966"; - case Country.unitedArabEmirates: + case CountryEnum.unitedArabEmirates: return "971"; } } - static Country fromDisplayName(String name) { + static CountryEnum fromDisplayName(String name) { switch (name) { case "Kingdom Of Saudi Arabia": case "المملكة العربية السعودية": - return Country.saudiArabia; + return CountryEnum.saudiArabia; case "United Arab Emirates": case "الإمارات العربية المتحدة": - return Country.unitedArabEmirates; + return CountryEnum.unitedArabEmirates; default: throw Exception("Invalid country name"); } } } + diff --git a/lib/features/authentication/authentication_repo.dart b/lib/features/authentication/authentication_repo.dart index 7307013..0be6eaf 100644 --- a/lib/features/authentication/authentication_repo.dart +++ b/lib/features/authentication/authentication_repo.dart @@ -20,8 +20,7 @@ abstract class AuthenticationRepo { required CheckPatientAuthenticationReq checkPatientAuthenticationReq, }); - Future>> sendActivationCodeRegister( - {required CheckPatientAuthenticationReq checkPatientAuthenticationReq, String? languageID}); + Future>> sendActivationCodeRegister({required CheckPatientAuthenticationReq checkPatientAuthenticationReq, String? languageID}); } class AuthenticationRepoImp implements AuthenticationRepo { @@ -114,8 +113,7 @@ class AuthenticationRepoImp implements AuthenticationRepo { } @override - Future>> sendActivationCodeRegister( - {required CheckPatientAuthenticationReq checkPatientAuthenticationReq, String? languageID}) async { + Future>> sendActivationCodeRegister({required CheckPatientAuthenticationReq checkPatientAuthenticationReq, String? languageID}) async { int isOutKsa = (checkPatientAuthenticationReq.zipCode == '966' || checkPatientAuthenticationReq.zipCode == '+966') ? 0 : 1; //TODO : We will use all these from AppState directly in the ApiClient diff --git a/lib/features/authentication/authentication_view_model.dart b/lib/features/authentication/authentication_view_model.dart index ed77aca..f192db2 100644 --- a/lib/features/authentication/authentication_view_model.dart +++ b/lib/features/authentication/authentication_view_model.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/enums.dart'; import 'package:hmg_patient_app_new/core/utils/request_utils.dart'; +import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/features/authentication/authentication_repo.dart'; import 'package:hmg_patient_app_new/features/authentication/models/request_models/check_patient_authentication_request_model.dart'; import 'package:hmg_patient_app_new/services/dialog_service.dart'; @@ -23,9 +24,15 @@ class AuthenticationViewModel extends ChangeNotifier { final TextEditingController nationalIdController = TextEditingController(); final TextEditingController phoneNumberController = TextEditingController(); + void login() { + if (ValidationUtils.isValidatePhoneAndId(nationalId: nationalIdController.text, phoneNumber: phoneNumberController.text)) { + } else { + + } + } + Future selectDeviceImei({Function(dynamic)? onSuccess, Function(String)? onError}) async { - String firebaseToken = - "dOGRRszQQMGe_9wA5Hx3kO:APA91bFV5IcIJXvcCXXk0tc2ddtZgWwCPq7sGSuPr-YW7iiJpQZKgFGN9GAzCVOWL8MfheaP1slE8MdxB7lczdPBGdONQ7WbMmhgHcsUCUktq-hsapGXXqc"; + String firebaseToken = "dOGRRszQQMGe_9wA5Hx3kO:APA91bFV5IcIJXvcCXXk0tc2ddtZgWwCPq7sGSuPr-YW7iiJpQZKgFGN9GAzCVOWL8MfheaP1slE8MdxB7lczdPBGdONQ7WbMmhgHcsUCUktq-hsapGXXqc"; final result = await authenticationRepo.selectDeviceByImei(firebaseToken: firebaseToken); result.fold( @@ -40,96 +47,96 @@ class AuthenticationViewModel extends ChangeNotifier { ); } - // Future checkUserAuthentication({Function(dynamic)? onSuccess, Function(String)? onError}) async { - // CheckPatientAuthenticationReq checkPatientAuthenticationReq = RequestUtils.getCommonRequestWelcome( - // phoneNumber: '0567184134', - // otpTypeEnum: OTPTypeEnum.sms, - // deviceToken: 'dummyDeviceToken123', - // patientOutSA: true, - // loginTokenID: 'dummyLoginToken456', - // registeredData: null, - // patientId: 12345, - // nationIdText: '1234567890', - // countryCode: 'SA', - // ); - // - // final result = await authenticationRepo.checkPatientAuthentication(checkPatientAuthenticationReq: checkPatientAuthenticationReq); - // result.fold( - // (failure) async => await errorHandlerService.handleError(failure: failure), - // (apiResponse) { - // if (apiResponse.data['isSMSSent']) { - // // TODO: set this in AppState - // // sharedPref.setString(LOGIN_TOKEN_ID, value['LogInTokenID']); - // // loginTokenID = value['LogInTokenID'], - // // sharedPref.setObject(REGISTER_DATA_FOR_LOGIIN, request), - // sendActivationCode(type); - // } else { - // if (apiResponse.data['IsAuthenticated']) { - // checkActivationCode(onWrongActivationCode: (String? message) {}); - // } - // } - // }, - // ); - // } +// Future checkUserAuthentication({Function(dynamic)? onSuccess, Function(String)? onError}) async { +// CheckPatientAuthenticationReq checkPatientAuthenticationReq = RequestUtils.getCommonRequestWelcome( +// phoneNumber: '0567184134', +// otpTypeEnum: OTPTypeEnum.sms, +// deviceToken: 'dummyDeviceToken123', +// patientOutSA: true, +// loginTokenID: 'dummyLoginToken456', +// registeredData: null, +// patientId: 12345, +// nationIdText: '1234567890', +// countryCode: 'SA', +// ); +// +// final result = await authenticationRepo.checkPatientAuthentication(checkPatientAuthenticationReq: checkPatientAuthenticationReq); +// result.fold( +// (failure) async => await errorHandlerService.handleError(failure: failure), +// (apiResponse) { +// if (apiResponse.data['isSMSSent']) { +// // TODO: set this in AppState +// // sharedPref.setString(LOGIN_TOKEN_ID, value['LogInTokenID']); +// // loginTokenID = value['LogInTokenID'], +// // sharedPref.setObject(REGISTER_DATA_FOR_LOGIIN, request), +// sendActivationCode(type); +// } else { +// if (apiResponse.data['IsAuthenticated']) { +// checkActivationCode(onWrongActivationCode: (String? message) {}); +// } +// } +// }, +// ); +// } - // Future sendActivationCode({required OTPTypeEnum otpTypeEnum}) async { - // var request = RequestUtils.getCommonRequestAuthProvider( - // otpTypeEnum: otpTypeEnum, - // registeredData: null, - // deviceToken: "dummyLoginToken456", - // mobileNumber: "0567184134", - // zipCode: "SA", - // patientOutSA: true, - // loginTokenID: "dummyLoginToken456", - // selectedOption: selectedOption, - // patientId: 12345, - // ); - // - // request.sMSSignature = await SMSOTP.getSignature(); - // selectedOption = type; - // // GifLoaderDialogUtils.showMyDialog(context); - // if (healthId != null || isDubai) { - // if (!isDubai) { - // request.dob = dob; //isHijri == 1 ? dob : dateFormat2.format(dateFormat.parse(dob)); - // } - // request.healthId = healthId; - // request.isHijri = isHijri; - // await this.apiClient.sendActivationCodeRegister(request).then((result) { - // // GifLoaderDialogUtils.hideDialog(context); - // if (result != null && result['isSMSSent'] == true) { - // this.startSMSService(type); - // } - // }).catchError((r) { - // GifLoaderDialogUtils.hideDialog(context); - // context.showBottomSheet( - // child: ExceptionBottomSheet( - // message: r.toString(), - // onOkPressed: () { - // Navigator.of(context).pop(); - // }, - // )); - // // AppToast.showErrorToast(message: r); - // }); - // } else { - // request.dob = ""; - // request.healthId = ""; - // request.isHijri = 0; - // await this.authService.sendActivationCode(request).then((result) { - // GifLoaderDialogUtils.hideDialog(context); - // if (result != null && result['isSMSSent'] == true) { - // this.startSMSService(type); - // } - // }).catchError((r) { - // GifLoaderDialogUtils.hideDialog(context); - // context.showBottomSheet( - // child: ExceptionBottomSheet( - // message: r.toString(), - // onOkPressed: () { - // Navigator.of(context).pop(); - // }, - // )); - // // AppToast.showErrorToast(message: r.toString()); - // }); - // } - // } +// Future sendActivationCode({required OTPTypeEnum otpTypeEnum}) async { +// var request = RequestUtils.getCommonRequestAuthProvider( +// otpTypeEnum: otpTypeEnum, +// registeredData: null, +// deviceToken: "dummyLoginToken456", +// mobileNumber: "0567184134", +// zipCode: "SA", +// patientOutSA: true, +// loginTokenID: "dummyLoginToken456", +// selectedOption: selectedOption, +// patientId: 12345, +// ); +// +// request.sMSSignature = await SMSOTP.getSignature(); +// selectedOption = type; +// // GifLoaderDialogUtils.showMyDialog(context); +// if (healthId != null || isDubai) { +// if (!isDubai) { +// request.dob = dob; //isHijri == 1 ? dob : dateFormat2.format(dateFormat.parse(dob)); +// } +// request.healthId = healthId; +// request.isHijri = isHijri; +// await this.apiClient.sendActivationCodeRegister(request).then((result) { +// // GifLoaderDialogUtils.hideDialog(context); +// if (result != null && result['isSMSSent'] == true) { +// this.startSMSService(type); +// } +// }).catchError((r) { +// GifLoaderDialogUtils.hideDialog(context); +// context.showBottomSheet( +// child: ExceptionBottomSheet( +// message: r.toString(), +// onOkPressed: () { +// Navigator.of(context).pop(); +// }, +// )); +// // AppToast.showErrorToast(message: r); +// }); +// } else { +// request.dob = ""; +// request.healthId = ""; +// request.isHijri = 0; +// await this.authService.sendActivationCode(request).then((result) { +// GifLoaderDialogUtils.hideDialog(context); +// if (result != null && result['isSMSSent'] == true) { +// this.startSMSService(type); +// } +// }).catchError((r) { +// GifLoaderDialogUtils.hideDialog(context); +// context.showBottomSheet( +// child: ExceptionBottomSheet( +// message: r.toString(), +// onOkPressed: () { +// Navigator.of(context).pop(); +// }, +// )); +// // AppToast.showErrorToast(message: r.toString()); +// }); +// } +// } } diff --git a/lib/presentation/authentication/login.dart b/lib/presentation/authentication/login.dart index f74348f..2771b36 100644 --- a/lib/presentation/authentication/login.dart +++ b/lib/presentation/authentication/login.dart @@ -7,6 +7,7 @@ import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/extensions/context_extensions.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/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/presentation/authentication/register.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; @@ -14,6 +15,7 @@ import 'package:hmg_patient_app_new/widgets/appbar/app_bar_widget.dart'; import 'package:hmg_patient_app_new/widgets/bottomsheet/generic_bottom_sheet.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/input_widget.dart'; +import 'package:provider/provider.dart'; class LoginScreen extends StatefulWidget { @override @@ -33,6 +35,7 @@ class _LoginScreen extends State { @override Widget build(BuildContext context) { + AuthenticationViewModel authVm = context.read(); return Scaffold( backgroundColor: AppColors.bgScaffoldColor, appBar: CustomAppBar( @@ -61,7 +64,7 @@ class _LoginScreen extends State { TextInputWidget( labelText: "${LocaleKeys.nationalId.tr()} / ${LocaleKeys.fileNo.tr()}", hintText: "xxxxxxxxx", - controller: TextEditingController(), + controller: authVm.nationalIdController, keyboardType: TextInputType.number, isEnable: true, prefix: null, @@ -80,7 +83,7 @@ class _LoginScreen extends State { icon: AppAssets.login1, iconColor: Colors.white, onPressed: () { - showLoginModel(context: context); + showLoginModel(context: context, textController: authVm.phoneNumberController); // if (nationIdController.text.isNotEmpty) { // } else { @@ -150,7 +153,7 @@ class _LoginScreen extends State { child: GenericBottomSheet( countryCode: "966", initialPhoneNumber: "", - textController: TextEditingController(), + textController: textController, isEnableCountryDropdown: true, onCountryChange: (value) {}, onChange: (String? value) {}, diff --git a/lib/presentation/authentication/register.dart b/lib/presentation/authentication/register.dart index 0fcad5c..b445631 100644 --- a/lib/presentation/authentication/register.dart +++ b/lib/presentation/authentication/register.dart @@ -85,8 +85,8 @@ class _RegisterNew extends State { child: Column( children: [ CustomCountryDropdown( - countryList: Country.values, - onCountryChange: (Country? value) {}, + countryList: CountryEnum.values, + onCountryChange: (CountryEnum? value) {}, isRtl: Directionality.of(context) == TextDirection.LTR, ).withVerticalPadding(8.h), Divider(height: 1.h), diff --git a/lib/presentation/home/landing_page.dart b/lib/presentation/home/landing_page.dart index 55abb00..f2017b2 100644 --- a/lib/presentation/home/landing_page.dart +++ b/lib/presentation/home/landing_page.dart @@ -51,7 +51,9 @@ class _LandingPageState extends State { CustomButton( text: LocaleKeys.loginOrRegister.tr(context: context), onPressed: () async { - await authenticationViewModel.selectDeviceImei(); + + // await authenticationViewModel.selectDeviceImei(); + Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) => LoginScreen())); }, backgroundColor: Color(0xffFEE9EA), borderColor: Color(0xffFEE9EA), diff --git a/lib/presentation/medical_file/medical_file_page.dart b/lib/presentation/medical_file/medical_file_page.dart index 55ca84b..ba274bf 100644 --- a/lib/presentation/medical_file/medical_file_page.dart +++ b/lib/presentation/medical_file/medical_file_page.dart @@ -40,7 +40,6 @@ class MedicalFilePage extends StatelessWidget { isAllowLeadingIcon: true, padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 8.h), leadingIcon: AppAssets.student_card, - hasError: true, ), SizedBox(height: 16.h), Container( diff --git a/lib/widgets/bottomsheet/generic_bottom_sheet.dart b/lib/widgets/bottomsheet/generic_bottom_sheet.dart index eefb187..1d07099 100644 --- a/lib/widgets/bottomsheet/generic_bottom_sheet.dart +++ b/lib/widgets/bottomsheet/generic_bottom_sheet.dart @@ -17,7 +17,7 @@ class GenericBottomSheet extends StatefulWidget { final List buttons; TextEditingController? textController; final bool isForEmail; - Function(Country)? onCountryChange; + Function(CountryEnum)? onCountryChange; final bool isEnableCountryDropdown; final bool isFromSavedLogin; Function(String?)? onChange; diff --git a/lib/widgets/dropdown/country_dropdown_widget.dart b/lib/widgets/dropdown/country_dropdown_widget.dart index 81ac60a..5e4bddf 100644 --- a/lib/widgets/dropdown/country_dropdown_widget.dart +++ b/lib/widgets/dropdown/country_dropdown_widget.dart @@ -7,8 +7,8 @@ import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; class CustomCountryDropdown extends StatefulWidget { - final List countryList; - final Function(Country)? onCountryChange; + final List countryList; + final Function(CountryEnum)? onCountryChange; final bool isRtl; const CustomCountryDropdown({ @@ -23,14 +23,14 @@ class CustomCountryDropdown extends StatefulWidget { } class _CustomCountryDropdownState extends State { - Country? selectedCountry; + CountryEnum? selectedCountry; late OverlayEntry _overlayEntry; bool _isDropdownOpen = false; @override void initState() { super.initState(); - selectedCountry = Country.saudiArabia; + selectedCountry = CountryEnum.saudiArabia; } @override