diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index 268bf0a3..6df6d8c7 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -1587,5 +1587,7 @@ "ratings": "التقييمات", "hmgPharmacyText": "صيدلية الحبيب، المتجر الصيدلاني الإلكتروني المتكامل الذي تقدمه لكم مجموعة خدمات الدكتور سليمان الحبيب الطبية.", "insuranceRequestSubmittedSuccessfully": "تم إرسال طلب تحديث بيانات التأمين بنجاح. سيتم إعلامك بمجرد الانتهاء.", - "updatingEmailAddress": "جارٍ تحديث عنوان البريد الإلكتروني، يرجى الانتظار..." + "updatingEmailAddress": "جارٍ تحديث عنوان البريد الإلكتروني، يرجى الانتظار...", + "verifyInsurance": "التحقق من التأمين", + "tests": "تحليل" } diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index d1a48222..bedf03fd 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -1581,5 +1581,7 @@ "ratings": "Ratings", "hmgPharmacyText": "Al Habib Pharmacy, the complete online Pharmaceutical store brought to you by Dr. Sulaiman Al Habib Medical Services Group.", "insuranceRequestSubmittedSuccessfully": "Your insurance update request has been successfully submitted. You will be notified once completed.", - "updatingEmailAddress": "Updating email address, Please wait..." + "updatingEmailAddress": "Updating email address, Please wait...", + "verifyInsurance": "Verify Insurance", + "tests": "tests" } diff --git a/lib/core/api/api_client.dart b/lib/core/api/api_client.dart index 0131a938..2de4ce5c 100644 --- a/lib/core/api/api_client.dart +++ b/lib/core/api/api_client.dart @@ -200,7 +200,7 @@ class ApiClientImp implements ApiClient { } // body['TokenID'] = "@dm!n"; - // body['PatientID'] = 4774402; + // body['PatientID'] = 1231755; // body['PatientTypeID'] = 1; // body['PatientOutSA'] = 0; // body['SessionID'] = "45786230487560q"; diff --git a/lib/extensions/widget_extensions.dart b/lib/extensions/widget_extensions.dart index f0897950..866c26a4 100644 --- a/lib/extensions/widget_extensions.dart +++ b/lib/extensions/widget_extensions.dart @@ -1,7 +1,9 @@ import 'package:flutter/material.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/extensions/int_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; +import 'package:hmg_patient_app_new/features/profile_settings/profile_settings_view_model.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:shimmer/shimmer.dart'; import 'package:sizer/sizer.dart'; @@ -166,7 +168,7 @@ extension SmoothContainerExtension on ShapeBorder { ? [ BoxShadow( // color: hasDenseShadow ? const Color(0xff000000).withOpacity(.06) : const Color(0xff000000).withOpacity(.1), - color: const Color(0xffE1E1E1).withOpacity(1.0), + color: getIt.get().isDarkMode ? Color(0xff3a3a3a).withOpacity(1.0) : Color(0xffE1E1E1).withOpacity(1.0), blurRadius: 0, spreadRadius: 0, offset: const Offset(1, 0), diff --git a/lib/features/ask_doctor/ask_doctor_repo.dart b/lib/features/ask_doctor/ask_doctor_repo.dart index 4e4a4006..bd6af5b8 100644 --- a/lib/features/ask_doctor/ask_doctor_repo.dart +++ b/lib/features/ask_doctor/ask_doctor_repo.dart @@ -47,7 +47,7 @@ class AskDoctorRepoImp implements AskDoctorRepo { try { final list = response['PatientDoctorAppointmentResultList']; - final clinicsList = list.map((item) => AskDoctorAppointmentHistoryList.fromJson(item as Map)).toList().cast(); + final clinicsList = list != null ? list.map((item) => AskDoctorAppointmentHistoryList.fromJson(item as Map)).toList().cast() : []; apiResponse = GenericApiModel>( messageStatus: messageStatus, diff --git a/lib/features/ask_doctor/models/ask_doctor_appointments_list.dart b/lib/features/ask_doctor/models/ask_doctor_appointments_list.dart index 7f40d71c..6b337662 100644 --- a/lib/features/ask_doctor/models/ask_doctor_appointments_list.dart +++ b/lib/features/ask_doctor/models/ask_doctor_appointments_list.dart @@ -143,7 +143,7 @@ class AskDoctorAppointmentHistoryList { noOfPatientsRate = json['NoOfPatientsRate']; projectName = json['ProjectName']; qR = json['QR']; - speciality = json['Speciality'].cast(); + // speciality = json['Speciality'].cast(); } Map toJson() { diff --git a/lib/features/insurance/insurance_view_model.dart b/lib/features/insurance/insurance_view_model.dart index d1423113..28210d39 100644 --- a/lib/features/insurance/insurance_view_model.dart +++ b/lib/features/insurance/insurance_view_model.dart @@ -13,6 +13,7 @@ class InsuranceViewModel extends ChangeNotifier { bool isInsuranceHistoryLoading = false; bool isInsuranceDetailsLoading = false; bool isInsuranceUpdateDetailsLoading = false; + bool isInsuranceExpiryBannerShown = false; bool isInsuranceDataToBeLoaded = true; bool isInsuranceApprovalsLoading = false; @@ -49,6 +50,11 @@ class InsuranceViewModel extends ChangeNotifier { notifyListeners(); } + setIsInsuranceExpiryBannerShown(bool isInsuranceExpiryBannerShown) { + this.isInsuranceExpiryBannerShown = isInsuranceExpiryBannerShown; + notifyListeners(); + } + setIsInsuranceHistoryLoading(bool val) { isInsuranceHistoryLoading = val; notifyListeners(); @@ -91,6 +97,7 @@ class InsuranceViewModel extends ChangeNotifier { isInsuranceDataToBeLoaded = true; isInsuranceExpired = false; isInsuranceActive = false; + isInsuranceExpiryBannerShown = false; notifyListeners(); }, (apiResponse) { @@ -111,6 +118,8 @@ class InsuranceViewModel extends ChangeNotifier { debugPrint("InsuranceViewModel: Insurance card expired: $isInsuranceExpired"); } + isInsuranceExpiryBannerShown = isInsuranceExpired; + isInsuranceActive = patientInsuranceList.first.isActive ?? false; // isInsuranceActive = true; @@ -148,6 +157,9 @@ class InsuranceViewModel extends ChangeNotifier { } Future getPatientInsuranceDetailsForUpdate(String patientID, String identificationNo, {Function(dynamic)? onSuccess, Function(String)? onError}) async { + patientInsuranceUpdateResponseModel = null; + notifyListeners(); + final result = await insuranceRepo.getPatientInsuranceDetailsForUpdate(patientId: patientID, identificationNo: identificationNo); result.fold( diff --git a/lib/features/lab/lab_view_model.dart b/lib/features/lab/lab_view_model.dart index 4c689ab7..1af2654e 100644 --- a/lib/features/lab/lab_view_model.dart +++ b/lib/features/lab/lab_view_model.dart @@ -149,21 +149,26 @@ class LabViewModel extends ChangeNotifier { isLabOrdersLoading = false; isLabResultsLoading = false; - // --- Build groups by clinic and by hospital (projectName) --- - final clinicMap = >{}; - final hospitalMap = >{}; - for (var order in patientLabOrders) { - final clinicKey = (order.clinicDescription ?? 'Unknown').trim(); - clinicMap.putIfAbsent(clinicKey, () => []).add(order); - - final hospitalKey = (order.projectName ?? order.projectID ?? 'Unknown').toString().trim(); - hospitalMap.putIfAbsent(hospitalKey, () => []).add(order); + order.testDetails!.sort((a, b) => a.description!.compareTo(b.description!)); } - patientLabOrdersByClinic = clinicMap.values.toList(); - patientLabOrdersByHospital = hospitalMap.values.toList(); - patientLabOrdersViewList = isSortByClinic ? patientLabOrdersByClinic : patientLabOrdersByHospital; + // --- Build groups by clinic and by hospital (projectName) --- + // final clinicMap = >{}; + // final hospitalMap = >{}; + // + // for (var order in patientLabOrders) { + // final clinicKey = (order.clinicDescription ?? 'Unknown').trim(); + // clinicMap.putIfAbsent(clinicKey, () => []).add(order); + // + // final hospitalKey = (order.projectName ?? order.projectID ?? 'Unknown').toString().trim(); + // hospitalMap.putIfAbsent(hospitalKey, () => []).add(order); + // } + + // patientLabOrdersByClinic = clinicMap.values.toList(); + // patientLabOrdersByHospital = hospitalMap.values.toList(); + // patientLabOrdersViewList = isSortByClinic ? patientLabOrdersByClinic : patientLabOrdersByHospital; + // patientLabOrdersViewList = patientLabOrdersByClinic; filterSuggestions(); getUniqueTestDescription(); diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index 031e1be9..ac9f3f7c 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -1582,5 +1582,7 @@ abstract class LocaleKeys { static const hmgPharmacyText = 'hmgPharmacyText'; static const insuranceRequestSubmittedSuccessfully = 'insuranceRequestSubmittedSuccessfully'; static const updatingEmailAddress = 'updatingEmailAddress'; + static const verifyInsurance = 'verifyInsurance'; + static const tests = 'tests'; } diff --git a/lib/presentation/appointments/appointment_details_page.dart b/lib/presentation/appointments/appointment_details_page.dart index 71cf4e16..072cb04a 100644 --- a/lib/presentation/appointments/appointment_details_page.dart +++ b/lib/presentation/appointments/appointment_details_page.dart @@ -14,6 +14,7 @@ import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/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/ask_doctor/ask_doctor_view_model.dart'; import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart'; import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/doctors_list_response_model.dart'; import 'package:hmg_patient_app_new/features/contact_us/contact_us_view_model.dart'; @@ -31,6 +32,8 @@ import 'package:hmg_patient_app_new/presentation/appointments/appointment_paymen import 'package:hmg_patient_app_new/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart'; import 'package:hmg_patient_app_new/presentation/appointments/widgets/appointment_doctor_card.dart'; import 'package:hmg_patient_app_new/presentation/appointments/widgets/ask_doctor_request_type_select.dart'; +import 'package:hmg_patient_app_new/presentation/ask_doctor/ask_doctor_page.dart'; +import 'package:hmg_patient_app_new/presentation/ask_doctor/doctor_response_page.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/widgets/appointment_calendar.dart'; import 'package:hmg_patient_app_new/presentation/contact_us/feedback_page.dart'; import 'package:hmg_patient_app_new/presentation/prescriptions/prescription_detail_page.dart'; @@ -556,6 +559,22 @@ class _AppointmentDetailsPageState extends State { // ), // ); }), + MedicalFileCard( + label: LocaleKeys.doctorResponses.tr(context: context), + textColor: AppColors.blackColor, + backgroundColor: AppColors.whiteColor, + svgIcon: AppAssets.ask_doctor_medical_file_icon, + isLargeText: true, + iconSize: 36.w, + ).onPress(() { + getIt.get().initAskDoctorViewModel(); + getIt.get().getDoctorResponses(); + Navigator.of(context).push( + CustomPageRoute( + page: DoctorResponsePage(), + ), + ); + }), ], ), // Column( @@ -839,8 +858,8 @@ class _AppointmentDetailsPageState extends State { onPressed: () { openDoctorScheduleCalendar(); }, - backgroundColor: AppColors.successColor, - borderColor: AppColors.successColor, + backgroundColor: AppColors.primaryRedColor, + borderColor: AppColors.primaryRedColor, textColor: Colors.white, fontSize: 16.f, fontWeight: FontWeight.w500, diff --git a/lib/presentation/appointments/widgets/appointment_card.dart b/lib/presentation/appointments/widgets/appointment_card.dart index ac63432f..44fcfa86 100644 --- a/lib/presentation/appointments/widgets/appointment_card.dart +++ b/lib/presentation/appointments/widgets/appointment_card.dart @@ -329,12 +329,19 @@ class AppointmentCard extends StatelessWidget { flex: 1, child: Container( height: (isFoldable || isTablet) ? 50.h : 40.h, - decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.textColor, borderRadius: 10.h), + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.transparent, + borderRadius: 10.h, + side: BorderSide( + color: AppColors.textColor, + width: 1.2, + ), + ), child: Transform.flip( flipX: appState.isArabic(), child: Utils.buildSvgWithAssets( icon: AppAssets.forward_arrow_icon, - iconColor: AppColors.whiteColor, + iconColor: AppColors.textColor, width: 24.w, height: 24.h, fit: BoxFit.contain, @@ -401,9 +408,10 @@ class AppointmentCard extends StatelessWidget { return CustomButton( text: LocaleKeys.rebookSameDoctor.tr(context: context), onPressed: () => openDoctorScheduleCalendar(context), - backgroundColor: AppColors.greyColor, - borderColor: AppColors.greyColor, + backgroundColor: AppColors.transparent, + borderColor: AppColors.textColor, textColor: AppColors.blackColor, + borderWidth: 1.h, fontSize: (isFoldable || isTablet) ? 12.f : 14.f, fontWeight: FontWeight.w500, borderRadius: 12.r, diff --git a/lib/presentation/appointments/widgets/appointment_doctor_card.dart b/lib/presentation/appointments/widgets/appointment_doctor_card.dart index ef8c76ee..5a47708e 100644 --- a/lib/presentation/appointments/widgets/appointment_doctor_card.dart +++ b/lib/presentation/appointments/widgets/appointment_doctor_card.dart @@ -155,25 +155,27 @@ class AppointmentDoctorCard extends StatelessWidget { icon: AppAssets.ask_doctor_icon, iconColor: AppColors.primaryRedColor, ) - : !patientAppointmentHistoryResponseModel.isLiveCareAppointment! - ? CustomButton( - text: LocaleKeys.rebookSameDoctor.tr(), - onPressed: () { - onRescheduleTap(); - }, - backgroundColor: AppColors.greyColor, - borderColor: AppColors.greyColor, - textColor: AppColors.blackColor, - fontSize: 12.f, - fontWeight: FontWeight.w500, - borderRadius: 12.r, - padding: EdgeInsets.fromLTRB(10.w, 0, 10.w, 0), - height: 40.h, - icon: AppAssets.rebook_appointment_icon, - iconColor: AppColors.blackColor, - iconSize: 14.h, - ) - : SizedBox.shrink(); + : + // !patientAppointmentHistoryResponseModel.isLiveCareAppointment! + // ? CustomButton( + // text: LocaleKeys.rebookSameDoctor.tr(), + // onPressed: () { + // onRescheduleTap(); + // }, + // backgroundColor: AppColors.greyColor, + // borderColor: AppColors.greyColor, + // textColor: AppColors.blackColor, + // fontSize: 12.f, + // fontWeight: FontWeight.w500, + // borderRadius: 12.r, + // padding: EdgeInsets.fromLTRB(10.w, 0, 10.w, 0), + // height: 40.h, + // icon: AppAssets.rebook_appointment_icon, + // iconColor: AppColors.blackColor, + // iconSize: 14.h, + // ) + // : + SizedBox.shrink(); } else { return patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? CustomButton( diff --git a/lib/presentation/emergency_services/emergency_services_page.dart b/lib/presentation/emergency_services/emergency_services_page.dart index 41597e40..7970d819 100644 --- a/lib/presentation/emergency_services/emergency_services_page.dart +++ b/lib/presentation/emergency_services/emergency_services_page.dart @@ -35,7 +35,7 @@ class EmergencyServicesPage extends StatelessWidget { return CollapsingListView( title: LocaleKeys.emergencyServices.tr(), - requests: () { + history: () { emergencyServicesViewModel.changeOrderDisplayItems(OrderDislpay.ALL); Navigator.of(context).push(CustomPageRoute(page: ErHistoryListing(), direction: AxisDirection.up)); }, diff --git a/lib/presentation/home/landing_page.dart b/lib/presentation/home/landing_page.dart index 768a31d1..14684c0c 100644 --- a/lib/presentation/home/landing_page.dart +++ b/lib/presentation/home/landing_page.dart @@ -48,6 +48,7 @@ import 'package:hmg_patient_app_new/presentation/home/widgets/large_service_card import 'package:hmg_patient_app_new/presentation/home/widgets/small_service_card.dart'; import 'package:hmg_patient_app_new/presentation/home/widgets/welcome_widget.dart'; import 'package:hmg_patient_app_new/presentation/insurance/insurance_home_page.dart'; +import 'package:hmg_patient_app_new/presentation/insurance/widgets/insurance_update_details_card.dart'; import 'package:hmg_patient_app_new/presentation/medical_file/medical_file_page.dart'; import 'package:hmg_patient_app_new/presentation/my_family/my_family.dart'; import 'package:hmg_patient_app_new/presentation/notifications/notifications_list_page.dart'; @@ -171,7 +172,11 @@ class _LandingPageState extends State { return Stack( children: [ SingleChildScrollView( - padding: EdgeInsets.only(top: (!insuranceVM.isInsuranceLoading && insuranceVM.isInsuranceExpired) ? (MediaQuery.paddingOf(context).top + 70.h) : kToolbarHeight + 0.h, bottom: 24), + padding: EdgeInsets.only( + top: (!insuranceVM.isInsuranceLoading && insuranceVM.isInsuranceExpired && insuranceVM.isInsuranceExpiryBannerShown) + ? (MediaQuery.paddingOf(context).top + 70.h) + : kToolbarHeight + 0.h, + bottom: 24), child: Column( spacing: 16.h, children: [ @@ -728,7 +733,7 @@ class _LandingPageState extends State { ], ), ), - (!insuranceVM.isInsuranceLoading && insuranceVM.isInsuranceExpired) + (!insuranceVM.isInsuranceLoading && insuranceVM.isInsuranceExpired && insuranceVM.isInsuranceExpiryBannerShown) ? Container( height: MediaQuery.paddingOf(context).top + 50.h, decoration: ShapeDecoration( @@ -745,27 +750,30 @@ class _LandingPageState extends State { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - LocaleKeys.insuranceExpiredOrInactive.tr(context: context).toText14(color: AppColors.primaryRedColor, weight: FontWeight.w500).paddingSymmetrical(24.h, 0.h), + LocaleKeys.insuranceExpiredOrInactive.tr(context: context).toText14(color: AppColors.primaryRedColor, weight: FontWeight.w500).paddingSymmetrical(0.h, 0.h), Row( children: [ CustomButton( text: LocaleKeys.updateInsurance.tr(context: context), onPressed: () { - Navigator.of(context).push( - CustomPageRoute( - page: InsuranceHomePage(), - ), - ); + insuranceVM.setIsInsuranceUpdateDetailsLoading(true); + insuranceVM.getPatientInsuranceDetailsForUpdate( + appState.getAuthenticatedUser()!.patientId.toString(), appState.getAuthenticatedUser()!.patientIdentificationNo.toString()); + showCommonBottomSheetWithoutHeight(context, + child: PatientInsuranceCardUpdateCard(), callBackFunc: () {}, title: "", isCloseButtonVisible: false, isFullScreen: false); }, backgroundColor: AppColors.primaryRedColor, borderColor: AppColors.secondaryLightRedBorderColor, - textColor: AppColors.whiteColor, - fontSize: 10.f, + textColor: Colors.white, + fontSize: 12.f, fontWeight: FontWeight.bold, borderRadius: 8.r, padding: EdgeInsets.fromLTRB(15, 0, 15, 0), height: 36.h, - ).paddingSymmetrical(24.h, 0.h), + ).paddingSymmetrical(12.h, 0.h), + Icon(Icons.close, color: AppColors.primaryRedColor).onPress(() { + insuranceVM.setIsInsuranceExpiryBannerShown(false); + }), ], ), ], @@ -774,7 +782,7 @@ class _LandingPageState extends State { height: 10.h, ) ], - ), + ).paddingSymmetrical(24.h, 0.h), ) : SizedBox.shrink() ], diff --git a/lib/presentation/insurance/insurance_home_page.dart b/lib/presentation/insurance/insurance_home_page.dart index 519d8306..35e3acb8 100644 --- a/lib/presentation/insurance/insurance_home_page.dart +++ b/lib/presentation/insurance/insurance_home_page.dart @@ -48,11 +48,11 @@ class _InsuranceHomePageState extends State { insuranceViewModel = Provider.of(context, listen: false); return CollapsingListView( title: "${LocaleKeys.insurance.tr(context: context)} ${LocaleKeys.updateInsurance.tr(context: context)}", - history: () { - insuranceViewModel.setIsInsuranceHistoryLoading(true); - insuranceViewModel.getPatientInsuranceCardHistory(); - showCommonBottomSheetWithoutHeight(context, child: InsuranceHistory(), callBackFunc: () {}, title: "", isCloseButtonVisible: false, isFullScreen: false); - }, + // history: () { + // // insuranceViewModel.setIsInsuranceHistoryLoading(true); + // // insuranceViewModel.getPatientInsuranceCardHistory(); + // showCommonBottomSheetWithoutHeight(context, child: InsuranceHistory(), callBackFunc: () {}, title: "", isCloseButtonVisible: false, isFullScreen: false); + // }, child: SingleChildScrollView( child: Consumer(builder: (context, insuranceVM, child) { return Column( @@ -66,12 +66,23 @@ class _InsuranceHomePageState extends State { isLoading: true, ).paddingSymmetrical(24.h, 24.h) : insuranceVM.patientInsuranceList.isNotEmpty - ? Padding( - padding: EdgeInsets.only(top: 24.h), - child: PatientInsuranceCard( - insuranceCardDetailsModel: insuranceVM.patientInsuranceList.first, - isInsuranceExpired: DateTime.now().isAfter(DateUtil.convertStringToDate(insuranceVM.patientInsuranceList.first.cardValidTo))) - .paddingSymmetrical(24.w, 0.h), + ? ListView.builder( + shrinkWrap: true, + padding: EdgeInsets.all(16.h), + physics: const BouncingScrollPhysics(), + itemBuilder: (context, index) { + return Column( + children: [ + PatientInsuranceCard( + insuranceCardDetailsModel: insuranceVM.patientInsuranceList[index], + isInsuranceExpired: DateTime.now().isAfter(DateUtil.convertStringToDate(insuranceVM.patientInsuranceList.first.cardValidTo))), + SizedBox( + height: 12.h, + ) + ], + ); + }, + itemCount: insuranceVM.patientInsuranceList.length, ) : Padding( padding: EdgeInsets.only(top: MediaQuery.of(context).size.height * 0.12), diff --git a/lib/presentation/insurance/widgets/insurance_update_details_card.dart b/lib/presentation/insurance/widgets/insurance_update_details_card.dart index 2136f0cb..770f4da2 100644 --- a/lib/presentation/insurance/widgets/insurance_update_details_card.dart +++ b/lib/presentation/insurance/widgets/insurance_update_details_card.dart @@ -105,49 +105,51 @@ class PatientInsuranceCardUpdateCard extends StatelessWidget { iconSize: 20.w, text: "${LocaleKeys.updateInsurance.tr(context: context)} ${LocaleKeys.updateInsuranceSubtitle.tr(context: context)}", onPressed: () { - LoaderBottomSheet.showLoader(); - getIt().sendPatientUpdateRequest(onSuccess: (val) { - LoaderBottomSheet.hideLoader(); - insuranceViewModel.setIsInsuranceDataToBeLoaded(true); - insuranceViewModel.initInsuranceProvider(); - Navigator.pop(context); - }, onError: (err) { - insuranceViewModel.updatePatientInsuranceCard( - patientID: appState.getAuthenticatedUser()!.patientId!, - patientType: appState.getAuthenticatedUser()!.patientType!, - patientIdentificationID: appState.getAuthenticatedUser()!.patientIdentificationNo!, - mobileNo: appState.getAuthenticatedUser()!.mobileNumber!, - insuranceCardImage: "", - onSuccess: (val) { - LoaderBottomSheet.hideLoader(); - showCommonBottomSheetWithoutHeight( - title: LocaleKeys.success.tr(context: context), - context, - child: Utils.getSuccessWidget(loadingText: LocaleKeys.insuranceRequestSubmittedSuccessfully.tr(context: context)), - callBackFunc: () { - Navigator.pop(context); - }, - isFullScreen: false, - isCloseButtonVisible: false, - ); - // Future.delayed(Duration(milliseconds: 2000)).then((value) async { - // Navigator.pop(context); - // }); - }, - onError: (err) { - LoaderBottomSheet.hideLoader(); - showCommonBottomSheetWithoutHeight( - title: LocaleKeys.notice.tr(context: context), - context, - child: Utils.getErrorWidget(loadingText: err.toString()), - callBackFunc: () { - Navigator.pop(context); - }, - isFullScreen: false, - isCloseButtonVisible: true, - ); - }); - }); + if (insuranceViewModel.patientInsuranceUpdateResponseModel != null) { + LoaderBottomSheet.showLoader(); + getIt().sendPatientUpdateRequest(onSuccess: (val) { + LoaderBottomSheet.hideLoader(); + insuranceViewModel.setIsInsuranceDataToBeLoaded(true); + insuranceViewModel.initInsuranceProvider(); + Navigator.pop(context); + }, onError: (err) { + insuranceViewModel.updatePatientInsuranceCard( + patientID: appState.getAuthenticatedUser()!.patientId!, + patientType: appState.getAuthenticatedUser()!.patientType!, + patientIdentificationID: appState.getAuthenticatedUser()!.patientIdentificationNo!, + mobileNo: appState.getAuthenticatedUser()!.mobileNumber!, + insuranceCardImage: "", + onSuccess: (val) { + LoaderBottomSheet.hideLoader(); + showCommonBottomSheetWithoutHeight( + title: LocaleKeys.success.tr(context: context), + context, + child: Utils.getSuccessWidget(loadingText: LocaleKeys.insuranceRequestSubmittedSuccessfully.tr(context: context)), + callBackFunc: () { + Navigator.pop(context); + }, + isFullScreen: false, + isCloseButtonVisible: false, + ); + // Future.delayed(Duration(milliseconds: 2000)).then((value) async { + // Navigator.pop(context); + // }); + }, + onError: (err) { + LoaderBottomSheet.hideLoader(); + showCommonBottomSheetWithoutHeight( + title: LocaleKeys.notice.tr(context: context), + context, + child: Utils.getErrorWidget(loadingText: err.toString()), + callBackFunc: () { + Navigator.pop(context); + }, + isFullScreen: false, + isCloseButtonVisible: true, + ); + }); + }); + } }, backgroundColor: insuranceViewModel.patientInsuranceUpdateResponseModel != null ? AppColors.successColor : AppColors.lightGrayBGColor, borderColor: AppColors.successColor.withOpacity(0.01), diff --git a/lib/presentation/insurance/widgets/patient_insurance_card.dart b/lib/presentation/insurance/widgets/patient_insurance_card.dart index d6bb204f..1607a7c6 100644 --- a/lib/presentation/insurance/widgets/patient_insurance_card.dart +++ b/lib/presentation/insurance/widgets/patient_insurance_card.dart @@ -53,26 +53,30 @@ class PatientInsuranceCard extends StatelessWidget { SizedBox( width: MediaQuery.of(context).size.width * 0.4, child: "${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}".toText18(isBold: true, textOverflow: TextOverflow.clip, isEnglishOnly: true)), - LocaleKeys.policyNumber.tr(namedArgs: {'number': insuranceCardDetailsModel.insurancePolicyNo ?? ''}, context: context).toText12(isBold: true, color: AppColors.lightGrayColor), + Row( + children: [ + "${LocaleKeys.policyNumber.tr(context: context)}${insuranceCardDetailsModel.insurancePolicyNo}".toText12(isBold: true, color: AppColors.lightGrayColor), + ], + ), ], ), AppCustomChipWidget( - icon: insuranceViewModel.isInsuranceExpired + icon: isCurrentPatientInsuranceExpired(insuranceCardDetailsModel.cardValidTo!) ? AppAssets.cancel_circle_icon : insuranceViewModel.isInsuranceActive ? AppAssets.insurance_active_icon : AppAssets.alertSquare, - labelText: insuranceViewModel.isInsuranceExpired + labelText: isCurrentPatientInsuranceExpired(insuranceCardDetailsModel.cardValidTo!) ? LocaleKeys.insuranceExpired.tr(context: context) : insuranceViewModel.isInsuranceActive ? LocaleKeys.insuranceActive.tr(context: context) : LocaleKeys.insuranceInActive.tr(context: context), - iconColor: insuranceViewModel.isInsuranceExpired + iconColor: isCurrentPatientInsuranceExpired(insuranceCardDetailsModel.cardValidTo!) ? AppColors.primaryRedColor : insuranceViewModel.isInsuranceActive ? AppColors.successColor : AppColors.warningColorYellow, - textColor: insuranceViewModel.isInsuranceExpired + textColor: isCurrentPatientInsuranceExpired(insuranceCardDetailsModel.cardValidTo!) ? AppColors.primaryRedColor : insuranceViewModel.isInsuranceActive ? AppColors.successColor @@ -110,7 +114,7 @@ class PatientInsuranceCard extends StatelessWidget { // ); } }, - backgroundColor: insuranceViewModel.isInsuranceExpired + backgroundColor: isCurrentPatientInsuranceExpired(insuranceCardDetailsModel.cardValidTo!) ? AppColors.primaryRedColor.withOpacity(0.1) : insuranceViewModel.isInsuranceActive ? AppColors.successColor.withOpacity(0.1) @@ -130,7 +134,23 @@ class PatientInsuranceCard extends StatelessWidget { ), SizedBox(height: 12.h), insuranceCardDetailsModel.groupName!.toText12(isBold: true), - insuranceCardDetailsModel.companyName!.toText12(isBold: true), + Row( + children: [ + insuranceCardDetailsModel.companyName!.toText12(isBold: true), + SizedBox( + width: 6.h, + ), + Container( + padding: EdgeInsets.symmetric(horizontal: 6.h, vertical: 4.h), + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.infoColor, + borderRadius: 50.r, + ), + child: (insuranceCardDetailsModel.subCategoryDesc!.length > 5 ? insuranceCardDetailsModel.subCategoryDesc!.substring(0, 12) : insuranceCardDetailsModel.subCategoryDesc!) + .toText8(isBold: true, color: AppColors.whiteColor), + ), + ], + ), SizedBox(height: 8.h), Wrap( direction: Axis.horizontal, @@ -150,9 +170,10 @@ class PatientInsuranceCard extends StatelessWidget { isInsuranceExpired ? CustomButton( icon: AppAssets.update_insurance_card_icon, - iconColor: AppColors.successColor, + iconColor: AppColors.warningColorYellow, iconSize: 15.h, - text: "${LocaleKeys.updateInsurance.tr(context: context)} ${LocaleKeys.updateInsuranceSubtitle.tr(context: context)}", + // text: "${LocaleKeys.updateInsurance.tr(context: context)} ${LocaleKeys.updateInsuranceSubtitle.tr(context: context)}", + text: LocaleKeys.verifyInsurance.tr(context: context), onPressed: () { insuranceViewModel.setIsInsuranceUpdateDetailsLoading(true); insuranceViewModel.getPatientInsuranceDetailsForUpdate( @@ -165,9 +186,9 @@ class PatientInsuranceCard extends StatelessWidget { isCloseButtonVisible: false, isFullScreen: false); }, - backgroundColor: AppColors.bgGreenColor.withOpacity(0.20), - borderColor: AppColors.bgGreenColor.withOpacity(0.0), - textColor: AppColors.bgGreenColor, + backgroundColor: AppColors.warningColorYellow.withOpacity(0.20), + borderColor: AppColors.warningColorYellow.withOpacity(0.0), + textColor: AppColors.warningColorYellow, fontSize: 14, fontWeight: FontWeight.w500, borderRadius: 12, @@ -180,4 +201,10 @@ class PatientInsuranceCard extends StatelessWidget { ), ).paddingSymmetrical(0.h, 0.h); } + + bool isCurrentPatientInsuranceExpired(String cardValidTo) { + return DateTime.now().isAfter( + DateUtil.convertStringToDate(cardValidTo), + ); + } } diff --git a/lib/presentation/lab/lab_orders_page.dart b/lib/presentation/lab/lab_orders_page.dart index bb2c3034..b38ad737 100644 --- a/lib/presentation/lab/lab_orders_page.dart +++ b/lib/presentation/lab/lab_orders_page.dart @@ -1 +1 @@ -import 'dart:async'; import 'dart:convert'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; import 'package:hmg_patient_app_new/core/app_state.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/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/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/lab/lab_view_model.dart'; import 'package:hmg_patient_app_new/features/lab/models/resp_models/patient_lab_orders_response_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/presentation/lab/lab_result_item_view.dart'; import 'package:hmg_patient_app_new/presentation/lab/lab_result_via_clinic/LabResultByClinic.dart'; import 'package:hmg_patient_app_new/presentation/lab/search_lab_report.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/utils/date_util.dart'; import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/appbar/collapsing_toolbar.dart'; import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/chip/custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart'; import 'package:hmg_patient_app_new/widgets/date_range_selector/viewmodel/date_range_view_model.dart'; import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import 'package:provider/provider.dart'; import 'alphabeticScroll.dart'; import 'dart:ui' as ui; class LabOrdersPage extends StatefulWidget { const LabOrdersPage({super.key}); @override State createState() => _LabOrdersPageState(); } class _LabOrdersPageState extends State { late LabViewModel labProvider; late DateRangeSelectorRangeViewModel rangeViewModel; late AppState _appState; List?> labSuggestions = []; int? expandedIndex; String? selectedFilterText = ''; int activeIndex = 0; @override void initState() { scheduleMicrotask(() { labProvider.initLabProvider(); }); super.initState(); } @override Widget build(BuildContext context) { labProvider = Provider.of(context, listen: false); rangeViewModel = Provider.of(context); _appState = getIt(); return CollapsingListView( title: LocaleKeys.labResults.tr(context: context), search: () async { if (labProvider.isLabOrdersLoading) { return; } else { String? value = await Navigator.of(context).push( CustomPageRoute( page: SearchLabResultsContent(labSuggestionsList: labProvider.labSuggestions), fullScreenDialog: true, direction: AxisDirection.down, ), ); if (value != null) { selectedFilterText = value; labProvider.filterLabReports(value); } } }, child: Consumer( builder: (context, labViewModel, child) { return SingleChildScrollView( physics: NeverScrollableScrollPhysics(), padding: EdgeInsets.all(24.h), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: CustomTabBar( activeTextColor: Color(0xffED1C2B), activeBackgroundColor: Color(0xffED1C2B).withValues(alpha: .1), tabs: [ CustomTabBarModel(null, LocaleKeys.byVisit.tr()), CustomTabBarModel(null, LocaleKeys.byTest.tr()), // CustomTabBarModel(null, "Completed".needTranslation), ], onTabChange: (index) { activeIndex = index; setState(() {}); }, ), ), ], ), if (activeIndex == 0) Padding( padding: EdgeInsets.symmetric(vertical: 10.h), child: Row( children: [ CustomButton( text: LocaleKeys.byClinic.tr(context: context), onPressed: () { labViewModel.setIsSortByClinic(true); }, backgroundColor: labViewModel.isSortByClinic ? AppColors.bgRedLightColor : AppColors.whiteColor, borderColor: labViewModel.isSortByClinic ? AppColors.primaryRedColor : AppColors.textColor.withValues(alpha: 0.2), textColor: labViewModel.isSortByClinic ? AppColors.primaryRedColor : AppColors.blackColor, fontSize: 12.f, fontWeight: FontWeight.w500, borderRadius: 10, padding: EdgeInsets.fromLTRB(10, 0, 10, 0), height: 40.h, ), SizedBox(width: 8.h), CustomButton( text: LocaleKeys.byHospital.tr(context: context), onPressed: () { labViewModel.setIsSortByClinic(false); }, backgroundColor: labViewModel.isSortByClinic ? AppColors.whiteColor : AppColors.bgRedLightColor, borderColor: labViewModel.isSortByClinic ? AppColors.textColor.withValues(alpha: 0.2) : AppColors.primaryRedColor, textColor: labViewModel.isSortByClinic ? AppColors.blackColor : AppColors.primaryRedColor, fontSize: 12, fontWeight: FontWeight.w500, borderRadius: 10, padding: EdgeInsets.fromLTRB(10, 0, 10, 0), height: 40.h, ), ], ), ), SizedBox(height: 8.h), selectedFilterText!.isNotEmpty ? Column( children: [ AppCustomChipWidget( labelText: selectedFilterText!, backgroundColor: AppColors.alertColor, textColor: AppColors.whiteColor, deleteIcon: AppAssets.close_bottom_sheet_icon, deleteIconColor: AppColors.whiteColor, deleteIconHasColor: true, onDeleteTap: () { selectedFilterText = ""; labProvider.filterLabReports(""); }, ), SizedBox(height: 8.h), ], ) : SizedBox(), activeIndex == 0 ? // By Visit - show grouped view when available labViewModel.isLabOrdersLoading ? ListView.builder( shrinkWrap: true, physics: AlwaysScrollableScrollPhysics(), padding: EdgeInsets.zero, itemCount: 5, itemBuilder: (context, index) => LabResultItemView( onTap: () {}, labOrder: null, index: index, isLoading: true, ), ) : (labViewModel.patientLabOrdersViewList.isNotEmpty ? ListView.builder( shrinkWrap: true, physics: NeverScrollableScrollPhysics(), padding: EdgeInsets.zero, itemCount: labViewModel.patientLabOrdersViewList.length, itemBuilder: (context, index) { final group = labViewModel.patientLabOrdersViewList[index]; final isExpanded = expandedIndex == index; return AnimationConfiguration.staggeredList( position: index, duration: const Duration(milliseconds: 500), child: SlideAnimation( verticalOffset: 100.0, child: FadeInAnimation( child: AnimatedContainer( duration: Duration(milliseconds: 300), curve: Curves.easeInOut, margin: EdgeInsets.symmetric(vertical: 8.h), decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.h, hasShadow: true), child: InkWell( onTap: () { setState(() { expandedIndex = isExpanded ? null : index; }); }, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: EdgeInsets.all(16.h), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ AppCustomChipWidget(labelText: "${group.length} ${LocaleKeys.results.tr(context: context)}"), Icon(isExpanded ? Icons.expand_less : Icons.expand_more), ], ), SizedBox(height: 8.h), Text( labViewModel.isSortByClinic ? (group.first.clinicDescription ?? 'Unknown') : (group.first.projectName ?? 'Unknown'), style: TextStyle(fontSize: 16.h, fontWeight: FontWeight.w600), overflow: TextOverflow.ellipsis, ), ], ), ), AnimatedSwitcher( duration: Duration(milliseconds: 500), switchInCurve: Curves.easeIn, switchOutCurve: Curves.easeOut, transitionBuilder: (Widget child, Animation animation) { return FadeTransition( opacity: animation, child: SizeTransition( sizeFactor: animation, axisAlignment: 0.0, child: child, ), ); }, child: isExpanded ? Container( key: ValueKey(index), padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 0.h), child: ListView.separated( shrinkWrap: true, physics: NeverScrollableScrollPhysics(), padding: EdgeInsets.zero, itemBuilder: (cxt, index) { PatientLabOrdersResponseModel order = group[index]; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisSize: MainAxisSize.min, children: [ Image.network( order.doctorImageURL ?? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png", width: 24.w, height: 24.h, fit: BoxFit.cover, ).circle(100), SizedBox(width: 8.h), Expanded(child: (order.doctorName ?? order.doctorNameEnglish ?? "").toString().toText14(weight: FontWeight.w500)), ], ), SizedBox(height: 8.h), Wrap( direction: Axis.horizontal, spacing: 4.h, runSpacing: 4.h, children: [ AppCustomChipWidget( labelText: ("${LocaleKeys.orderNo.tr(context: context)}: ${order.orderNo!}"), isEnglishOnly: true, ), Directionality( textDirection: ui.TextDirection.ltr, child: AppCustomChipWidget( labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(order.orderDate ?? ""), false), isEnglishOnly: true, )), AppCustomChipWidget( labelText: labViewModel.isSortByClinic ? (order.projectName ?? "") : (order.clinicDescription ?? ""), ), ], ), // Row( // children: [ // CustomButton( // text: ("Order No: ".needTranslation + order.orderNo!), // onPressed: () {}, // backgroundColor: AppColors.greyColor, // borderColor: AppColors.greyColor, // textColor: AppColors.blackColor, // fontSize: 10, // fontWeight: FontWeight.w500, // borderRadius: 8, // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // height: 24.h, // ), // SizedBox(width: 8.h), // CustomButton( // text: DateUtil.formatDateToDate(DateUtil.convertStringToDate(order.orderDate ?? ""), false), // onPressed: () {}, // backgroundColor: AppColors.greyColor, // borderColor: AppColors.greyColor, // textColor: AppColors.blackColor, // fontSize: 10, // fontWeight: FontWeight.w500, // borderRadius: 8, // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // height: 24.h, // ), // ], // ), // SizedBox(height: 8.h), // Row( // children: [ // CustomButton( // text: model.isSortByClinic ? (order.clinicDescription ?? "") : (order.projectName ?? ""), // onPressed: () {}, // backgroundColor: AppColors.greyColor, // borderColor: AppColors.greyColor, // textColor: AppColors.blackColor, // fontSize: 10, // fontWeight: FontWeight.w500, // borderRadius: 8, // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // height: 24.h, // ), // ], // ), SizedBox(height: 12.h), Row( children: [ Expanded(flex: 2, child: SizedBox()), // Expanded( // flex: 1, // child: Container( // height: 40.h, // width: 40.w, // decoration: RoundedRectangleBorder().toSmoothCornerDecoration( // color: AppColors.textColor, // borderRadius: 12, // ), // child: Padding( // padding: EdgeInsets.all(12.h), // child: Transform.flip( // flipX: _appState.isArabic(), // child: Utils.buildSvgWithAssets( // icon: AppAssets.forward_arrow_icon_small, // iconColor: AppColors.whiteColor, // fit: BoxFit.contain, // ), // ), // ), // ).onPress(() { // model.currentlySelectedPatientOrder = order; // labProvider.getPatientLabResultByHospital(order); // labProvider.getPatientSpecialResult(order); // Navigator.of(context).push( // CustomPageRoute(page: LabResultByClinic(labOrder: order)), // ); // }), // ) Expanded( flex: 2, child: CustomButton( icon: AppAssets.view_report_icon, iconColor: AppColors.primaryRedColor, iconSize: 16.h, text: LocaleKeys.viewResults.tr(context: context), onPressed: () { labViewModel.currentlySelectedPatientOrder = order; labProvider.getPatientLabResultByHospital(order); labProvider.getPatientSpecialResult(order); Navigator.of(context).push( CustomPageRoute(page: LabResultByClinic(labOrder: order)), ); }, backgroundColor: AppColors.secondaryLightRedColor, borderColor: AppColors.secondaryLightRedColor, textColor: AppColors.primaryRedColor, fontSize: 14, fontWeight: FontWeight.w500, borderRadius: 12, padding: EdgeInsets.fromLTRB(10, 0, 10, 0), height: 40.h, ), ) ], ), // SizedBox(height: 12.h), // Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h), // SizedBox(height: 12.h), ], ).paddingOnly(top: 16, bottom: 16); }, separatorBuilder: (cxt, index) => Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h), itemCount: group.length)) : SizedBox.shrink(), ), ], ), ), ), ), )); }, ) : Utils.getNoDataWidget(context, noDataText: LocaleKeys.noLabResults.tr(context: context))) : // By Test or other tabs keep existing behavior (labViewModel.isLabOrdersLoading) ? Column( children: List.generate( 5, (index) => LabResultItemView( onTap: () {}, labOrder: null, index: index, isLoading: true, )), ) : AlphabeticScroll( alpahbetsAvailable: labViewModel.indexedCharacterForUniqueTest, details: labViewModel.uniqueTestsList, labViewModel: labViewModel, rangeViewModel: rangeViewModel, appState: _appState, ) ], )); }, ), ); } Color getLabOrderStatusColor(num status) { switch (status) { case 44: return AppColors.warningColorYellow; case 45: return AppColors.warningColorYellow; case 16: return AppColors.successColor; case 17: return AppColors.successColor; default: return AppColors.greyColor; } } String getLabOrderStatusText(num status) { switch (status) { case 44: return LocaleKeys.resultsPending.tr(context: context); case 45: return LocaleKeys.resultsPending.tr(context: context); case 16: return LocaleKeys.resultsAvailable.tr(context: context); case 17: return LocaleKeys.resultsAvailable.tr(context: context); default: return ""; } } getLabSuggestions(LabViewModel model) { if (model.patientLabOrders.isEmpty) { return []; } return model.patientLabOrders.map((m) => m.testDetails).toList(); } } \ No newline at end of file +import 'dart:async'; import 'dart:convert'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; import 'package:hmg_patient_app_new/core/app_state.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/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/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/lab/lab_view_model.dart'; import 'package:hmg_patient_app_new/features/lab/models/resp_models/patient_lab_orders_response_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/presentation/lab/lab_result_item_view.dart'; import 'package:hmg_patient_app_new/presentation/lab/lab_result_via_clinic/LabResultByClinic.dart'; import 'package:hmg_patient_app_new/presentation/lab/search_lab_report.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/utils/date_util.dart'; import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/appbar/collapsing_toolbar.dart'; import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/chip/custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart'; import 'package:hmg_patient_app_new/widgets/date_range_selector/viewmodel/date_range_view_model.dart'; import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import 'package:provider/provider.dart'; import 'alphabeticScroll.dart'; import 'dart:ui' as ui; class LabOrdersPage extends StatefulWidget { const LabOrdersPage({super.key}); @override State createState() => _LabOrdersPageState(); } class _LabOrdersPageState extends State { late LabViewModel labProvider; late DateRangeSelectorRangeViewModel rangeViewModel; late AppState _appState; List?> labSuggestions = []; int? expandedIndex; String? selectedFilterText = ''; int activeIndex = 0; @override void initState() { scheduleMicrotask(() { labProvider.initLabProvider(); }); super.initState(); } @override Widget build(BuildContext context) { labProvider = Provider.of(context, listen: false); rangeViewModel = Provider.of(context); _appState = getIt(); return CollapsingListView( title: LocaleKeys.labResults.tr(context: context), search: () async { if (labProvider.isLabOrdersLoading) { return; } else { String? value = await Navigator.of(context).push( CustomPageRoute( page: SearchLabResultsContent(labSuggestionsList: labProvider.labSuggestions), fullScreenDialog: true, direction: AxisDirection.down, ), ); if (value != null) { selectedFilterText = value; labProvider.filterLabReports(value); } } }, child: Consumer( builder: (context, labViewModel, child) { return SingleChildScrollView( physics: NeverScrollableScrollPhysics(), padding: EdgeInsets.all(24.h), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: CustomTabBar( activeTextColor: Color(0xffED1C2B), activeBackgroundColor: Color(0xffED1C2B).withValues(alpha: .1), tabs: [ CustomTabBarModel(null, LocaleKeys.byVisit.tr()), CustomTabBarModel(null, LocaleKeys.byTest.tr()), // CustomTabBarModel(null, "Completed".needTranslation), ], onTabChange: (index) { activeIndex = index; setState(() {}); }, ), ), ], ), if (activeIndex == 0) Padding( padding: EdgeInsets.symmetric(vertical: 10.h), child: Row( children: [ // CustomButton( // text: LocaleKeys.byClinic.tr(context: context), // onPressed: () { // labViewModel.setIsSortByClinic(true); // }, // backgroundColor: labViewModel.isSortByClinic ? AppColors.bgRedLightColor : AppColors.whiteColor, // borderColor: labViewModel.isSortByClinic ? AppColors.primaryRedColor : AppColors.textColor.withValues(alpha: 0.2), // textColor: labViewModel.isSortByClinic ? AppColors.primaryRedColor : AppColors.blackColor, // fontSize: 12.f, // fontWeight: FontWeight.w500, // borderRadius: 10, // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // height: 40.h, // ), // SizedBox(width: 8.h), // CustomButton( // text: LocaleKeys.byHospital.tr(context: context), // onPressed: () { // labViewModel.setIsSortByClinic(false); // }, // backgroundColor: labViewModel.isSortByClinic ? AppColors.whiteColor : AppColors.bgRedLightColor, // borderColor: labViewModel.isSortByClinic ? AppColors.textColor.withValues(alpha: 0.2) : AppColors.primaryRedColor, // textColor: labViewModel.isSortByClinic ? AppColors.blackColor : AppColors.primaryRedColor, // fontSize: 12, // fontWeight: FontWeight.w500, // borderRadius: 10, // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // height: 40.h, // ), ], ), ), SizedBox(height: 8.h), selectedFilterText!.isNotEmpty ? Column( children: [ AppCustomChipWidget( labelText: selectedFilterText!, backgroundColor: AppColors.alertColor, textColor: AppColors.whiteColor, deleteIcon: AppAssets.close_bottom_sheet_icon, deleteIconColor: AppColors.whiteColor, deleteIconHasColor: true, onDeleteTap: () { selectedFilterText = ""; labProvider.filterLabReports(""); }, ), SizedBox(height: 8.h), ], ) : SizedBox(), activeIndex == 0 ? // By Visit - show grouped view when available labViewModel.isLabOrdersLoading ? ListView.builder( shrinkWrap: true, physics: AlwaysScrollableScrollPhysics(), padding: EdgeInsets.zero, itemCount: 5, itemBuilder: (context, index) => LabResultItemView( onTap: () {}, labOrder: null, index: index, isLoading: true, ), ) : (labViewModel.patientLabOrders.isNotEmpty ? ListView.builder( shrinkWrap: true, physics: NeverScrollableScrollPhysics(), padding: EdgeInsets.zero, itemCount: labViewModel.patientLabOrders.length, itemBuilder: (context, index) { final group = labViewModel.patientLabOrders[index]; final isExpanded = expandedIndex == index; return AnimationConfiguration.staggeredList( position: index, duration: const Duration(milliseconds: 500), child: SlideAnimation( verticalOffset: 100.0, child: FadeInAnimation( child: AnimatedContainer( duration: Duration(milliseconds: 300), curve: Curves.easeInOut, margin: EdgeInsets.symmetric(vertical: 8.h), decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.h, hasShadow: true), child: InkWell( onTap: () { setState(() { expandedIndex = isExpanded ? null : index; }); }, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: EdgeInsets.all(16.h), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ AppCustomChipWidget( labelText: "${group.testDetails!.length} ${LocaleKeys.tests.tr(context: context)}", backgroundColor: AppColors.successColor.withOpacity(0.1), textColor: AppColors.successColor, ), Icon(isExpanded ? Icons.expand_less : Icons.expand_more), ], ), SizedBox(height: 8.h), Row( mainAxisSize: MainAxisSize.min, children: [ Image.network( group.doctorImageURL ?? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png", width: 24.w, height: 24.h, fit: BoxFit.cover, ).circle(100), SizedBox(width: 8.h), Expanded(child: (group.doctorName ?? group.doctorNameEnglish ?? "").toString().toText14(weight: FontWeight.w500)), ], ), SizedBox(height: 8.h), Wrap( direction: Axis.horizontal, spacing: 4.h, runSpacing: 4.h, children: [ Directionality( textDirection: ui.TextDirection.ltr, child: AppCustomChipWidget( labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(group.orderDate ?? ""), false), isEnglishOnly: true, )), AppCustomChipWidget( labelText: (group.projectName ?? ""), ), AppCustomChipWidget( labelText: (group.clinicDescription ?? ""), ), ], ), ], ), ), AnimatedSwitcher( duration: Duration(milliseconds: 500), switchInCurve: Curves.easeIn, switchOutCurve: Curves.easeOut, transitionBuilder: (Widget child, Animation animation) { return FadeTransition( opacity: animation, child: SizeTransition( sizeFactor: animation, axisAlignment: 0.0, child: child, ), ); }, child: isExpanded ? Container( key: ValueKey(index), padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 0.h), child: Column( children: [ ListView.separated( shrinkWrap: true, physics: NeverScrollableScrollPhysics(), padding: EdgeInsets.zero, itemBuilder: (cxt, index) { PatientLabOrdersResponseModel order = group; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ "• ${order.testDetails![index].description!}".toText14(weight: FontWeight.w500), SizedBox(height: 4.h), order.testDetails![index].testDescriptionEn!.toText12(fontWeight: FontWeight.w500, color: AppColors.textColorLight), // Row( // mainAxisSize: MainAxisSize.min, // children: [ // Image.network( // order.doctorImageURL ?? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png", // width: 24.w, // height: 24.h, // fit: BoxFit.cover, // ).circle(100), // SizedBox(width: 8.h), // Expanded(child: (order.doctorName ?? order.doctorNameEnglish ?? "").toString().toText14(weight: FontWeight.w500)), // ], // ), // SizedBox(height: 8.h), // Wrap( // direction: Axis.horizontal, // spacing: 4.h, // runSpacing: 4.h, // children: [ // AppCustomChipWidget( // labelText: ("${LocaleKeys.orderNo.tr(context: context)}: ${order.orderNo!}"), isEnglishOnly: true, // ), // Directionality( // textDirection: ui.TextDirection.ltr, // child: AppCustomChipWidget( // labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(order.orderDate ?? ""), false), // isEnglishOnly: true, // )), // AppCustomChipWidget( // labelText: labViewModel.isSortByClinic ? (order.projectName ?? "") : (order.clinicDescription ?? ""), // ), // ], // ), // // Row( // // children: [ // // CustomButton( // // text: ("Order No: ".needTranslation + order.orderNo!), // // onPressed: () {}, // // backgroundColor: AppColors.greyColor, // // borderColor: AppColors.greyColor, // // textColor: AppColors.blackColor, // // fontSize: 10, // // fontWeight: FontWeight.w500, // // borderRadius: 8, // // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // // height: 24.h, // // ), // // SizedBox(width: 8.h), // // CustomButton( // // text: DateUtil.formatDateToDate(DateUtil.convertStringToDate(order.orderDate ?? ""), false), // // onPressed: () {}, // // backgroundColor: AppColors.greyColor, // // borderColor: AppColors.greyColor, // // textColor: AppColors.blackColor, // // fontSize: 10, // // fontWeight: FontWeight.w500, // // borderRadius: 8, // // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // // height: 24.h, // // ), // // ], // // ), // // SizedBox(height: 8.h), // // Row( // // children: [ // // CustomButton( // // text: model.isSortByClinic ? (order.clinicDescription ?? "") : (order.projectName ?? ""), // // onPressed: () {}, // // backgroundColor: AppColors.greyColor, // // borderColor: AppColors.greyColor, // // textColor: AppColors.blackColor, // // fontSize: 10, // // fontWeight: FontWeight.w500, // // borderRadius: 8, // // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // // height: 24.h, // // ), // // ], // // ), // SizedBox(height: 12.h), // Row( // children: [ // Expanded(flex: 2, child: SizedBox()), // // Expanded( // // flex: 1, // // child: Container( // // height: 40.h, // // width: 40.w, // // decoration: RoundedRectangleBorder().toSmoothCornerDecoration( // // color: AppColors.textColor, // // borderRadius: 12, // // ), // // child: Padding( // // padding: EdgeInsets.all(12.h), // // child: Transform.flip( // // flipX: _appState.isArabic(), // // child: Utils.buildSvgWithAssets( // // icon: AppAssets.forward_arrow_icon_small, // // iconColor: AppColors.whiteColor, // // fit: BoxFit.contain, // // ), // // ), // // ), // // ).onPress(() { // // model.currentlySelectedPatientOrder = order; // // labProvider.getPatientLabResultByHospital(order); // // labProvider.getPatientSpecialResult(order); // // Navigator.of(context).push( // // CustomPageRoute(page: LabResultByClinic(labOrder: order)), // // ); // // }), // // ) // // Expanded( // flex: 2, // child: CustomButton( // icon: AppAssets.view_report_icon, // iconColor: AppColors.primaryRedColor, // iconSize: 16.h, // text: LocaleKeys.viewResults.tr(context: context), // onPressed: () { // labViewModel.currentlySelectedPatientOrder = order; // labProvider.getPatientLabResultByHospital(order); // labProvider.getPatientSpecialResult(order); // Navigator.of(context).push( // CustomPageRoute(page: LabResultByClinic(labOrder: order)), // ); // }, // backgroundColor: AppColors.secondaryLightRedColor, // borderColor: AppColors.secondaryLightRedColor, // textColor: AppColors.primaryRedColor, // fontSize: 14, // fontWeight: FontWeight.w500, // borderRadius: 12, // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // height: 40.h, // ), // ) // ], // ), // SizedBox(height: 12.h), // Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h), // SizedBox(height: 12.h), ], ).paddingOnly(top: 16, bottom: 16); }, separatorBuilder: (cxt, index) => Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h), itemCount: group.testDetails!.length > 3 ? 3 : group.testDetails!.length), SizedBox(height: 16.h), CustomButton( text: "${LocaleKeys.viewResults.tr()} (${group.testDetails!.length})", onPressed: () { labProvider.currentlySelectedPatientOrder = group; labProvider.getPatientLabResultByHospital(group); labProvider.getPatientSpecialResult(group); Navigator.of(context).push( CustomPageRoute( page: LabResultByClinic(labOrder: group), ), ); }, backgroundColor: AppColors.infoColor.withAlpha(20), borderColor: AppColors.infoColor.withAlpha(0), textColor: AppColors.infoColor, fontSize: (isFoldable || isTablet) ? 12.f : 14.f, fontWeight: FontWeight.w500, borderRadius: 12.r, padding: EdgeInsets.fromLTRB(10.w, 0, 10.w, 0), height: 40.h, iconSize: 14.h, icon: AppAssets.view_report_icon, iconColor: AppColors.infoColor, ), SizedBox(height: 16.h), ], ), ) : SizedBox.shrink(), ), ], ), ), ), ), )); }, ) : Utils.getNoDataWidget(context, noDataText: LocaleKeys.noLabResults.tr(context: context))) : // By Test or other tabs keep existing behavior (labViewModel.isLabOrdersLoading) ? Column( children: List.generate( 5, (index) => LabResultItemView( onTap: () {}, labOrder: null, index: index, isLoading: true, )), ) : AlphabeticScroll( alpahbetsAvailable: labViewModel.indexedCharacterForUniqueTest, details: labViewModel.uniqueTestsList, labViewModel: labViewModel, rangeViewModel: rangeViewModel, appState: _appState, ) ], )); }, ), ); } Color getLabOrderStatusColor(num status) { switch (status) { case 44: return AppColors.warningColorYellow; case 45: return AppColors.warningColorYellow; case 16: return AppColors.successColor; case 17: return AppColors.successColor; default: return AppColors.greyColor; } } String getLabOrderStatusText(num status) { switch (status) { case 44: return LocaleKeys.resultsPending.tr(context: context); case 45: return LocaleKeys.resultsPending.tr(context: context); case 16: return LocaleKeys.resultsAvailable.tr(context: context); case 17: return LocaleKeys.resultsAvailable.tr(context: context); default: return ""; } } getLabSuggestions(LabViewModel model) { if (model.patientLabOrders.isEmpty) { return []; } return model.patientLabOrders.map((m) => m.testDetails).toList(); } } \ No newline at end of file diff --git a/lib/presentation/lab/lab_result_via_clinic/lab_order_result_item.dart b/lib/presentation/lab/lab_result_via_clinic/lab_order_result_item.dart index cf6ce97b..1a97d48d 100644 --- a/lib/presentation/lab/lab_result_via_clinic/lab_order_result_item.dart +++ b/lib/presentation/lab/lab_result_via_clinic/lab_order_result_item.dart @@ -114,15 +114,15 @@ class LabOrderResultItem extends StatelessWidget { ), CustomButton( icon: AppAssets.view_report_icon, - iconColor: AppColors.primaryRedColor, + iconColor: AppColors.infoColor, iconSize: 16.h, text: LocaleKeys.viewReport.tr(context: context), onPressed: () { onTap(); }, - backgroundColor: AppColors.secondaryLightRedColor, - borderColor: AppColors.secondaryLightRedColor, - textColor: AppColors.primaryRedColor, + backgroundColor: AppColors.infoColor.withAlpha(20), + borderColor: AppColors.infoColor.withAlpha(0), + textColor: AppColors.infoColor, fontSize: 14, fontWeight: FontWeight.w500, borderRadius: 12, diff --git a/lib/presentation/medical_file/medical_file_page.dart b/lib/presentation/medical_file/medical_file_page.dart index 5301d2e0..cddc4757 100644 --- a/lib/presentation/medical_file/medical_file_page.dart +++ b/lib/presentation/medical_file/medical_file_page.dart @@ -522,7 +522,7 @@ class _MedicalFilePageState extends State { ], ), ExpandableListItem( - title: LocaleKeys.trackerAndOthers.tr(context: context).toText18(weight: FontWeight.w600), + title: LocaleKeys.healthTrackers.tr(context: context).toText18(weight: FontWeight.w600), expandedBackgroundColor: Colors.transparent, children: [ SizedBox(height: 10.h), @@ -1347,12 +1347,12 @@ class _MedicalFilePageState extends State { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Row( - children: [ - LocaleKeys.healthTrackers.tr(context: context).toText16(weight: FontWeight.w500, color: AppColors.textColor), - ], - ), - SizedBox(height: 16.h), + // Row( + // children: [ + // LocaleKeys.healthTrackers.tr(context: context).toText16(weight: FontWeight.w500, color: AppColors.textColor), + // ], + // ), + // SizedBox(height: 16.h), GridView( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, @@ -1391,11 +1391,11 @@ class _MedicalFilePageState extends State { ], ).paddingSymmetrical(0.w, 0.0), SizedBox(height: 16.h), - Row( - children: [ - LocaleKeys.others.tr(context: context).toText16(weight: FontWeight.w500, color: AppColors.textColor), - ], - ), + // Row( + // children: [ + // LocaleKeys.others.tr(context: context).toText16(weight: FontWeight.w500, color: AppColors.textColor), + // ], + // ), SizedBox(height: 16.h), GridView( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( @@ -1408,21 +1408,22 @@ class _MedicalFilePageState extends State { padding: EdgeInsets.zero, shrinkWrap: true, children: [ - MedicalFileCard( - label: LocaleKeys.askYourDoctor.tr(context: context), - textColor: AppColors.blackColor, - backgroundColor: AppColors.whiteColor, - svgIcon: AppAssets.ask_doctor_medical_file_icon, - isLargeText: true, - iconSize: 36.w, - ).onPress(() { - getIt.get().initAskDoctorViewModel(); - Navigator.of(context).push( - CustomPageRoute( - page: AskDoctorPage(), - ), - ); - }), + // MedicalFileCard( + // label: LocaleKeys.askYourDoctor.tr(context: context), + // textColor: AppColors.blackColor, + // backgroundColor: AppColors.whiteColor, + // svgIcon: AppAssets.ask_doctor_medical_file_icon, + // isLargeText: true, + // iconSize: 36.w, + // ).onPress(() { + // getIt.get().initAskDoctorViewModel(); + // Navigator.of(context).push( + // CustomPageRoute( + // page: AskDoctorPage(), + // ), + // ); + // }), + // MedicalFileCard( // label: LocaleKeys.internetPairing.tr(context: context), // textColor: AppColors.blackColor,