From 796aeb03d3cd997188de02859d28026414911cc4 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Thu, 11 Dec 2025 16:54:14 +0300 Subject: [PATCH] Ancillary order fixes, QLine API integrated & other enhancements --- .../images/svg/ancillary_orders_list_icon.svg | 5 + assets/images/svg/insurance_approval_icon.svg | 4 + assets/images/svg/invoices_list_icon.svg | 4 + assets/images/svg/medical_reports_icon.svg | 5 + assets/images/svg/monthly_reports_icon.svg | 4 + assets/images/svg/my_doctors_icon.svg | 4 + assets/images/svg/my_radiology_icon.svg | 3 + assets/images/svg/my_sick_leave_icon.svg | 5 + assets/images/svg/sick_leave_report_icon.svg | 5 + assets/images/svg/update_insurance_icon.svg | 5 + lib/core/api_consts.dart | 8 ++ lib/core/app_assets.dart | 10 ++ lib/core/utils/utils.dart | 6 +- .../authentication_view_model.dart | 1 + .../patient_queue_details_response_model.dart | 40 ++++++ .../my_appointments/my_appointments_repo.dart | 34 +++++ .../my_appointments_view_model.dart | 54 ++++++- .../appointment_details_page.dart | 4 +- .../appointments/appointment_queue_page.dart | 73 +++++----- .../widgets/appointment_card.dart | 3 + .../appointment_checkin_bottom_sheet.dart | 1 + .../widgets/appointment_doctor_card.dart | 2 + .../laser/widgets/body_type_listing.dart | 20 +-- .../home/data/landing_page_data.dart | 6 +- lib/presentation/home/landing_page.dart | 31 ++-- .../medical_file/medical_file_page.dart | 27 ++-- .../patient_sickleaves_list_page.dart | 2 + .../ancillary_order_payment_page.dart | 7 +- .../ancillary_procedures_details_page.dart | 132 +++++++++++++----- lib/presentation/todo_section/todo_page.dart | 6 +- .../widgets/ancillary_orders_list.dart | 2 +- 31 files changed, 396 insertions(+), 117 deletions(-) create mode 100644 assets/images/svg/ancillary_orders_list_icon.svg create mode 100644 assets/images/svg/insurance_approval_icon.svg create mode 100644 assets/images/svg/invoices_list_icon.svg create mode 100644 assets/images/svg/medical_reports_icon.svg create mode 100644 assets/images/svg/monthly_reports_icon.svg create mode 100644 assets/images/svg/my_doctors_icon.svg create mode 100644 assets/images/svg/my_radiology_icon.svg create mode 100644 assets/images/svg/my_sick_leave_icon.svg create mode 100644 assets/images/svg/sick_leave_report_icon.svg create mode 100644 assets/images/svg/update_insurance_icon.svg create mode 100644 lib/features/my_appointments/models/resp_models/patient_queue_details_response_model.dart diff --git a/assets/images/svg/ancillary_orders_list_icon.svg b/assets/images/svg/ancillary_orders_list_icon.svg new file mode 100644 index 0000000..f0497d8 --- /dev/null +++ b/assets/images/svg/ancillary_orders_list_icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/images/svg/insurance_approval_icon.svg b/assets/images/svg/insurance_approval_icon.svg new file mode 100644 index 0000000..b46a54a --- /dev/null +++ b/assets/images/svg/insurance_approval_icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/svg/invoices_list_icon.svg b/assets/images/svg/invoices_list_icon.svg new file mode 100644 index 0000000..f123096 --- /dev/null +++ b/assets/images/svg/invoices_list_icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/svg/medical_reports_icon.svg b/assets/images/svg/medical_reports_icon.svg new file mode 100644 index 0000000..862b813 --- /dev/null +++ b/assets/images/svg/medical_reports_icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/images/svg/monthly_reports_icon.svg b/assets/images/svg/monthly_reports_icon.svg new file mode 100644 index 0000000..5e786e2 --- /dev/null +++ b/assets/images/svg/monthly_reports_icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/svg/my_doctors_icon.svg b/assets/images/svg/my_doctors_icon.svg new file mode 100644 index 0000000..c5fc541 --- /dev/null +++ b/assets/images/svg/my_doctors_icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/svg/my_radiology_icon.svg b/assets/images/svg/my_radiology_icon.svg new file mode 100644 index 0000000..7b5ebe4 --- /dev/null +++ b/assets/images/svg/my_radiology_icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/svg/my_sick_leave_icon.svg b/assets/images/svg/my_sick_leave_icon.svg new file mode 100644 index 0000000..f488cff --- /dev/null +++ b/assets/images/svg/my_sick_leave_icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/images/svg/sick_leave_report_icon.svg b/assets/images/svg/sick_leave_report_icon.svg new file mode 100644 index 0000000..521c063 --- /dev/null +++ b/assets/images/svg/sick_leave_report_icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/images/svg/update_insurance_icon.svg b/assets/images/svg/update_insurance_icon.svg new file mode 100644 index 0000000..684d672 --- /dev/null +++ b/assets/images/svg/update_insurance_icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/lib/core/api_consts.dart b/lib/core/api_consts.dart index b92461e..3e8c512 100644 --- a/lib/core/api_consts.dart +++ b/lib/core/api_consts.dart @@ -728,6 +728,8 @@ class ApiConsts { static String GET_TAMARA_INSTALLMENTS_URL = "https://mdlaboratories.com/tamaralive/Home/GetInstallments"; static String GET_TAMARA_PAYMENT_STATUS = 'https://mdlaboratories.com/tamaralive/api/OnlineTamara/order_status?orderid='; + static String QLINE_URL = "https://ms.hmg.com/nscapi/api/PatientCall/PatientInQueue_Detail"; + // static String GET_TAMARA_INSTALLMENTS_URL = "https://epharmacy.hmg.com/tamara/Home/getinstallments"; // var payFortEnvironment = FortEnvironment.test; @@ -744,6 +746,7 @@ class ApiConsts { GET_TAMARA_INSTALLMENTS_URL = "https://mdlaboratories.com/tamaralive/Home/GetInstallments"; GET_TAMARA_PAYMENT_STATUS = 'https://mdlaboratories.com/tamaralive/api/OnlineTamara/order_status?orderid='; rcBaseUrl = 'https://rc.hmg.com/'; + QLINE_URL = "https://ms.hmg.com/nscapi/api/PatientCall/PatientInQueue_Detail"; break; case AppEnvironmentTypeEnum.dev: baseUrl = "https://uat.hmgwebservices.com/"; @@ -754,6 +757,7 @@ class ApiConsts { GET_TAMARA_INSTALLMENTS_URL = "https://epharmacy.hmg.com/tamara/Home/getinstallments"; GET_TAMARA_PAYMENT_STATUS = 'https://epharmacy.hmg.com/tamara/api/OnlineTamara/order_status?orderid='; rcBaseUrl = 'https://rc.hmg.com/uat/'; + QLINE_URL = "https://ms.hmg.com/nscapi/api/PatientCall/PatientInQueue_Detail"; break; case AppEnvironmentTypeEnum.uat: baseUrl = "https://uat.hmgwebservices.com/"; @@ -764,6 +768,7 @@ class ApiConsts { GET_TAMARA_INSTALLMENTS_URL = "https://epharmacy.hmg.com/tamara/Home/getinstallments"; GET_TAMARA_PAYMENT_STATUS = 'https://epharmacy.hmg.com/tamara/api/OnlineTamara/order_status?orderid='; rcBaseUrl = 'https://rc.hmg.com/uat/'; + QLINE_URL = "https://ms.hmg.com/nscapi/api/PatientCall/PatientInQueue_Detail"; break; case AppEnvironmentTypeEnum.preProd: baseUrl = "https://webservices.hmg.com/"; @@ -774,6 +779,7 @@ class ApiConsts { GET_TAMARA_INSTALLMENTS_URL = "https://epharmacy.hmg.com/tamara/Home/getinstallments"; GET_TAMARA_PAYMENT_STATUS = 'https://epharmacy.hmg.com/tamara/api/OnlineTamara/order_status?orderid='; rcBaseUrl = 'https://rc.hmg.com/'; + QLINE_URL = "https://ms.hmg.com/nscapi/api/PatientCall/PatientInQueue_Detail"; break; case AppEnvironmentTypeEnum.qa: baseUrl = "https://uat.hmgwebservices.com/"; @@ -784,6 +790,7 @@ class ApiConsts { GET_TAMARA_INSTALLMENTS_URL = "https://epharmacy.hmg.com/tamara/Home/getinstallments"; GET_TAMARA_PAYMENT_STATUS = 'https://epharmacy.hmg.com/tamara/api/OnlineTamara/order_status?orderid='; rcBaseUrl = 'https://rc.hmg.com/uat/'; + QLINE_URL = "https://ms.hmg.com/nscapi/api/PatientCall/PatientInQueue_Detail"; break; case AppEnvironmentTypeEnum.staging: baseUrl = "https://uat.hmgwebservices.com/"; @@ -794,6 +801,7 @@ class ApiConsts { GET_TAMARA_INSTALLMENTS_URL = "https://epharmacy.hmg.com/tamara/Home/getinstallments"; GET_TAMARA_PAYMENT_STATUS = 'https://epharmacy.hmg.com/tamara/api/OnlineTamara/order_status?orderid='; rcBaseUrl = 'https://rc.hmg.com/uat/'; + QLINE_URL = "https://ms.hmg.com/nscapi/api/PatientCall/PatientInQueue_Detail"; break; } } diff --git a/lib/core/app_assets.dart b/lib/core/app_assets.dart index 9b6f4b1..05bb7a9 100644 --- a/lib/core/app_assets.dart +++ b/lib/core/app_assets.dart @@ -192,6 +192,16 @@ class AppAssets { static const String weight_tracker_icon = '$svgBasePath/weight_tracker_icon.svg'; static const String ask_doctor_medical_file_icon = '$svgBasePath/ask_doctor_medical_file_icon.svg'; static const String internet_pairing_icon = '$svgBasePath/internet_pairing_icon.svg'; + static const String my_doctors_icon = '$svgBasePath/my_doctors_icon.svg'; + static const String my_sick_leave_icon = '$svgBasePath/my_sick_leave_icon.svg'; + static const String my_radiology_icon = '$svgBasePath/my_radiology_icon.svg'; + static const String monthly_reports_icon = '$svgBasePath/monthly_reports_icon.svg'; + static const String medical_reports_icon = '$svgBasePath/medical_reports_icon.svg'; + static const String sick_leave_report_icon = '$svgBasePath/sick_leave_report_icon.svg'; + static const String update_insurance_icon = '$svgBasePath/update_insurance_icon.svg'; + static const String insurance_approval_icon = '$svgBasePath/insurance_approval_icon.svg'; + static const String invoices_list_icon = '$svgBasePath/invoices_list_icon.svg'; + static const String ancillary_orders_list_icon = '$svgBasePath/ancillary_orders_list_icon.svg'; //bottom navigation// diff --git a/lib/core/utils/utils.dart b/lib/core/utils/utils.dart index df8cdcb..87dee02 100644 --- a/lib/core/utils/utils.dart +++ b/lib/core/utils/utils.dart @@ -913,14 +913,14 @@ class Utils { return AppColors.primaryRedColor; } - static String getCardButtonText(int currentQueueStatus) { + static String getCardButtonText(int currentQueueStatus, String roomNumber) { switch (currentQueueStatus) { case 0: return "Please wait! you will be called for vital signs".needTranslation; case 1: - return "Please visit Room S5 for vital signs".needTranslation; + return "Please visit Room $roomNumber for vital signs".needTranslation; case 2: - return "Please visit Room S5 to the Doctor".needTranslation; + return "Please visit Room $roomNumber to the Doctor".needTranslation; } return ""; } diff --git a/lib/features/authentication/authentication_view_model.dart b/lib/features/authentication/authentication_view_model.dart index fa16423..faedcd8 100644 --- a/lib/features/authentication/authentication_view_model.dart +++ b/lib/features/authentication/authentication_view_model.dart @@ -586,6 +586,7 @@ class AuthenticationViewModel extends ChangeNotifier { activation.list!.first.bloodGroup = activation.patientBlodType; _appState.setAuthenticatedUser(activation.list!.first); _appState.setPrivilegeModelList(activation.list!.first.listPrivilege!); + _appState.setUserBloodGroup = activation.patientBlodType ?? "N/A"; } // _appState.setUserBloodGroup = (activation.patientBlodType ?? ""); _appState.setAppAuthToken = activation.authenticationTokenId; diff --git a/lib/features/my_appointments/models/resp_models/patient_queue_details_response_model.dart b/lib/features/my_appointments/models/resp_models/patient_queue_details_response_model.dart new file mode 100644 index 0000000..c36b9ec --- /dev/null +++ b/lib/features/my_appointments/models/resp_models/patient_queue_details_response_model.dart @@ -0,0 +1,40 @@ +class PatientQueueDetails { + int? patientID; + String? patientName; + String? queueNo; + int? callType; + String? roomNo; + String? calledOn; + bool? servingNow; + + PatientQueueDetails( + {this.patientID, + this.patientName, + this.queueNo, + this.callType, + this.roomNo, + this.calledOn, + this.servingNow}); + + PatientQueueDetails.fromJson(Map json) { + patientID = json['patientID']; + patientName = json['patientName']; + queueNo = json['queueNo']; + callType = json['callType']; + roomNo = json['roomNo']; + calledOn = json['calledOn']; + servingNow = json['servingNow']; + } + + Map toJson() { + final Map data = new Map(); + data['patientID'] = this.patientID; + data['patientName'] = this.patientName; + data['queueNo'] = this.queueNo; + data['callType'] = this.callType; + data['roomNo'] = this.roomNo; + data['calledOn'] = this.calledOn; + data['servingNow'] = this.servingNow; + return data; + } +} diff --git a/lib/features/my_appointments/my_appointments_repo.dart b/lib/features/my_appointments/my_appointments_repo.dart index 87ec10d..3308f93 100644 --- a/lib/features/my_appointments/my_appointments_repo.dart +++ b/lib/features/my_appointments/my_appointments_repo.dart @@ -13,6 +13,7 @@ import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/ import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/hospital_model.dart' show HospitalsModel; import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_share_response_model.dart'; +import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_queue_details_response_model.dart'; import 'package:hmg_patient_app_new/services/logger_service.dart'; abstract class MyAppointmentsRepo { @@ -58,6 +59,8 @@ abstract class MyAppointmentsRepo { Future>> sendAskDocCallRequest( {required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel, required String requestType, required String remarks, required String userMobileNumber}); + + Future>>> getPatientAppointmentQueueDetails({required int appointmentNo, required int patientID}); } class MyAppointmentsRepoImp implements MyAppointmentsRepo { @@ -746,4 +749,35 @@ class MyAppointmentsRepoImp implements MyAppointmentsRepo { return Left(UnknownFailure(e.toString())); } } + + @override + Future>>> getPatientAppointmentQueueDetails({required int appointmentNo, required int patientID}) async { + Map mapDevice = {"appointmentNo": appointmentNo, "patientID": patientID, "apiKey": "EE17D21C7943485D9780223CCE55DCE5"}; + try { + GenericApiModel>? apiResponse; + Failure? failure; + await apiClient.post(ApiConsts.QLINE_URL, onFailure: (error, statusCode, {messageStatus, failureType}) { + failure = failureType; + }, onSuccess: (response, statusCode, {messageStatus, errorMessage}) { + try { + final list = response['data']; + final queueList = list.map((item) => PatientQueueDetails.fromJson(item as Map)).toList().cast(); + + apiResponse = GenericApiModel>( + messageStatus: messageStatus, + statusCode: statusCode, + errorMessage: null, + data: queueList, + ); + } catch (e) { + failure = DataParsingFailure(e.toString()); + } + }, body: mapDevice, isExternal: true, isAllowAny: true); + if (failure != null) return Left(failure!); + if (apiResponse == null) return Left(ServerFailure("Unknown error")); + return Right(apiResponse!); + } catch (e) { + return Left(UnknownFailure(e.toString())); + } + } } diff --git a/lib/features/my_appointments/my_appointments_view_model.dart b/lib/features/my_appointments/my_appointments_view_model.dart index 71e0312..c4b8687 100644 --- a/lib/features/my_appointments/my_appointments_view_model.dart +++ b/lib/features/my_appointments/my_appointments_view_model.dart @@ -6,6 +6,7 @@ import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/ import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/get_tamara_installments_details_response_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_share_response_model.dart'; +import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_queue_details_response_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_repo.dart'; import 'package:hmg_patient_app_new/features/my_appointments/utils/appointment_type.dart'; import 'package:hmg_patient_app_new/services/error_handler_service.dart'; @@ -37,8 +38,11 @@ class MyAppointmentsViewModel extends ChangeNotifier { DateTime? start = null; DateTime? end = null; + bool isAppointmentQueueDetailsLoading = false; bool isPatientHasQueueAppointment = false; int currentQueueStatus = 0; + List patientQueueDetailsList = []; + late PatientQueueDetails currentPatientQueueDetails; List patientAppointmentsHistoryList = []; List filteredAppointmentList = []; @@ -88,7 +92,7 @@ class MyAppointmentsViewModel extends ChangeNotifier { isTamaraDetailsLoading = true; isAppointmentPatientShareLoading = true; isEyeMeasurementsAppointmentsLoading = true; - isPatientHasQueueAppointment = false; + isAppointmentQueueDetailsLoading = true; notifyListeners(); } @@ -218,6 +222,10 @@ class MyAppointmentsViewModel extends ChangeNotifier { patientAppointmentsHistoryList.addAll(patientArrivedAppointmentsHistoryList); filteredAppointmentList.addAll(patientAppointmentsHistoryList); + if (patientArrivedAppointmentsHistoryList.isNotEmpty) { + getPatientAppointmentQueueDetails(appointmentNo: patientArrivedAppointmentsHistoryList.first.appointmentNo, patientID: patientArrivedAppointmentsHistoryList.first.patientID); + } + print('Upcoming Appointments: ${patientUpcomingAppointmentsHistoryList.length}'); print('Arrived Appointments: ${patientArrivedAppointmentsHistoryList.length}'); print('All Appointments: ${patientAppointmentsHistoryList.length}'); @@ -659,6 +667,50 @@ class MyAppointmentsViewModel extends ChangeNotifier { ); } + Future getPatientAppointmentQueueDetails({required int appointmentNo, required int patientID, Function(dynamic)? onSuccess, Function(String)? onError}) async { + isAppointmentQueueDetailsLoading = true; + notifyListeners(); + final result = await myAppointmentsRepo.getPatientAppointmentQueueDetails(appointmentNo: appointmentNo, patientID: patientID); + + isAppointmentQueueDetailsLoading = false; + + result.fold( + // (failure) async => await errorHandlerService.handleError(failure: failure), + (failure) async { + if (onError != null) { + onError(failure.message); + } + }, + (apiResponse) { + if (apiResponse.messageStatus == 2) { + onError!(apiResponse.errorMessage!); + } else if (apiResponse.messageStatus == 1) { + if (apiResponse.data != null && apiResponse.data!.isNotEmpty) { + isPatientHasQueueAppointment = true; + patientQueueDetailsList = apiResponse.data!; + for (var element in patientQueueDetailsList) { + if (element.patientID == patientID) { + currentPatientQueueDetails = element; + currentQueueStatus = element.callType!; + // currentQueueStatus = 2; + break; + } + } + // patientQueueDetailsList.first.callType = 1; + + patientQueueDetailsList.removeWhere((element) => element.patientID == patientID); + } else { + isPatientHasQueueAppointment = false; + } + notifyListeners(); + if (onSuccess != null) { + onSuccess(apiResponse.data); + } + } + }, + ); + } + Future sendAskDocCallRequest({ required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel, required String requestType, diff --git a/lib/presentation/appointments/appointment_details_page.dart b/lib/presentation/appointments/appointment_details_page.dart index 7f863a1..54d654a 100644 --- a/lib/presentation/appointments/appointment_details_page.dart +++ b/lib/presentation/appointments/appointment_details_page.dart @@ -70,7 +70,6 @@ class _AppointmentDetailsPageState extends State { scheduleMicrotask(() async { CalenderUtilsNew calendarUtils = await CalenderUtilsNew.instance; var doesExist = await calendarUtils.checkIfEventExist("${widget.patientAppointmentHistoryResponseModel.appointmentNo}"); - print("the appointment reminder exist $doesExist"); myAppointmentsViewModel.setAppointmentReminder(doesExist, widget.patientAppointmentHistoryResponseModel); setState((){ @@ -82,7 +81,6 @@ class _AppointmentDetailsPageState extends State { @override Widget build(BuildContext context) { - AppState appState = getIt.get(); myAppointmentsViewModel = Provider.of(context, listen: false); prescriptionsViewModel = Provider.of(context, listen: false); bookAppointmentsViewModel = Provider.of(context, listen: false); @@ -390,7 +388,7 @@ class _AppointmentDetailsPageState extends State { label: "${LocaleKeys.radiology.tr(context: context)} ${LocaleKeys.radiologySubtitle.tr(context: context)}", textColor: AppColors.blackColor, backgroundColor: AppColors.whiteColor, - svgIcon: AppAssets.allergy_info_icon, + svgIcon: AppAssets.radiology_icon, isLargeText: true, iconSize: 36.w, ).onPress(() async { diff --git a/lib/presentation/appointments/appointment_queue_page.dart b/lib/presentation/appointments/appointment_queue_page.dart index f48f1eb..d9e5832 100644 --- a/lib/presentation/appointments/appointment_queue_page.dart +++ b/lib/presentation/appointments/appointment_queue_page.dart @@ -42,7 +42,8 @@ class AppointmentQueuePage extends StatelessWidget { color: AppColors.whiteColor, borderRadius: 20.h, hasShadow: false, - side: BorderSide(color: Utils.getCardBorderColor(myAppointmentsVM.currentQueueStatus), width: 2.w), + side: + BorderSide(color: myAppointmentsVM.isAppointmentQueueDetailsLoading ? AppColors.whiteColor : Utils.getCardBorderColor(myAppointmentsVM.currentQueueStatus), width: 2.w), ), child: Padding( padding: EdgeInsets.all(16.h), @@ -59,16 +60,19 @@ class AppointmentQueuePage extends StatelessWidget { ), Utils.buildSvgWithAssets(icon: AppAssets.waiting_icon, width: 24.h, height: 24.h), ], - ), + ).toShimmer2(isShow: myAppointmentsVM.isAppointmentQueueDetailsLoading), SizedBox(height: 10.h), - "Hala ${appState!.getAuthenticatedUser()!.firstName}!!!".needTranslation.toText16(isBold: true), + "Hala ${appState!.getAuthenticatedUser()!.firstName}!!!".needTranslation.toText16(isBold: true).toShimmer2(isShow: myAppointmentsVM.isAppointmentQueueDetailsLoading), SizedBox(height: 8.h), - "Thank you for your patience, here is your queue number.".needTranslation.toText12(fontWeight: FontWeight.w500, color: AppColors.textColorLight), + "Thank you for your patience, here is your queue number." + .needTranslation + .toText12(fontWeight: FontWeight.w500, color: AppColors.textColorLight) + .toShimmer2(isShow: myAppointmentsVM.isAppointmentQueueDetailsLoading), SizedBox(height: 8.h), - "IMD W-A-5".needTranslation.toText32(isBold: true), + myAppointmentsVM.currentPatientQueueDetails.queueNo!.toText32(isBold: true).toShimmer2(isShow: myAppointmentsVM.isAppointmentQueueDetailsLoading), SizedBox(height: 8.h), CustomButton( - text: Utils.getCardButtonText(myAppointmentsVM.currentQueueStatus), + text: Utils.getCardButtonText(myAppointmentsVM.currentQueueStatus, myAppointmentsVM.currentPatientQueueDetails.roomNo!), onPressed: () {}, backgroundColor: Utils.getCardButtonColor(myAppointmentsVM.currentQueueStatus), borderColor: Utils.getCardButtonColor(myAppointmentsVM.currentQueueStatus).withValues(alpha: 0.01), @@ -80,15 +84,16 @@ class AppointmentQueuePage extends StatelessWidget { height: 40.h, iconColor: AppColors.whiteColor, iconSize: 18.h, - ), + ).toShimmer2(isShow: myAppointmentsVM.isAppointmentQueueDetailsLoading), ], ), ), ), SizedBox(height: 16.h), - Container( - decoration: RoundedRectangleBorder().toSmoothCornerDecoration( - color: AppColors.whiteColor, + myAppointmentsVM.patientQueueDetailsList.isNotEmpty + ? Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, borderRadius: 20.h, hasShadow: true, ), @@ -97,14 +102,14 @@ class AppointmentQueuePage extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - "Serving Now".needTranslation.toText16(isBold: true), - SizedBox(height: 18.h), - ListView.separated( + "Serving Now".needTranslation.toText16(isBold: true).toShimmer2(isShow: myAppointmentsVM.isAppointmentQueueDetailsLoading), + SizedBox(height: 18.h), + ListView.separated( padding: EdgeInsets.zero, shrinkWrap: true, - itemCount: 3, - physics: NeverScrollableScrollPhysics(), - itemBuilder: (BuildContext context, int index) { + itemCount: myAppointmentsVM.patientQueueDetailsList.length, + physics: NeverScrollableScrollPhysics(), + itemBuilder: (BuildContext context, int index) { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, @@ -113,28 +118,32 @@ class AppointmentQueuePage extends StatelessWidget { Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ - "Room: S2".toText12(fontWeight: FontWeight.w500), - SizedBox(width: 8.w), - AppCustomChipWidget( - deleteIcon: AppAssets.call_for_vitals, - labelText: "Call for vital signs".needTranslation, - iconColor: AppColors.primaryRedColor, - textColor: AppColors.primaryRedColor, - iconSize: 14.w, - backgroundColor: AppColors.primaryRedColor.withValues(alpha: 0.1), - labelPadding: EdgeInsetsDirectional.only(start: 8.h, end: -2.h), - ), + "Room: ${myAppointmentsVM.patientQueueDetailsList[index].roomNo}".toText12(fontWeight: FontWeight.w500), + SizedBox(width: 8.w), + AppCustomChipWidget( + deleteIcon: myAppointmentsVM.patientQueueDetailsList[index].callType == 1 ? AppAssets.call_for_vitals : AppAssets.call_for_doctor, + labelText: + myAppointmentsVM.patientQueueDetailsList[index].callType == 1 ? "Call for vital signs".needTranslation : "Call for Doctor".needTranslation, + iconColor: myAppointmentsVM.patientQueueDetailsList[index].callType == 1 ? AppColors.primaryRedColor : AppColors.successColor, + textColor: myAppointmentsVM.patientQueueDetailsList[index].callType == 1 ? AppColors.primaryRedColor : AppColors.successColor, + iconSize: 14.w, + backgroundColor: myAppointmentsVM.patientQueueDetailsList[index].callType == 1 + ? AppColors.primaryRedColor.withValues(alpha: 0.1) + : AppColors.successColor.withValues(alpha: 0.1), + labelPadding: EdgeInsetsDirectional.only(start: 8.h, end: -2.h), + ), ], ), ], ); }, separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 8.h), - ), - ], - ), + ).toShimmer2(isShow: myAppointmentsVM.isAppointmentQueueDetailsLoading), + ], + ), ), - ), + ) + : SizedBox.shrink(), SizedBox(height: 16.h), Container( decoration: RoundedRectangleBorder().toSmoothCornerDecoration( @@ -174,7 +183,7 @@ class AppointmentQueuePage extends StatelessWidget { SizedBox(height: 16.h), ], - ), + ).toShimmer2(isShow: myAppointmentsVM.isAppointmentQueueDetailsLoading), ), ), ], diff --git a/lib/presentation/appointments/widgets/appointment_card.dart b/lib/presentation/appointments/widgets/appointment_card.dart index e6b974e..3d59907 100644 --- a/lib/presentation/appointments/widgets/appointment_card.dart +++ b/lib/presentation/appointments/widgets/appointment_card.dart @@ -17,6 +17,7 @@ import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_vie import 'package:hmg_patient_app_new/features/my_appointments/utils/appointment_type.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/presentation/appointments/appointment_details_page.dart'; +import 'package:hmg_patient_app_new/presentation/appointments/appointment_queue_page.dart'; import 'package:hmg_patient_app_new/presentation/appointments/widgets/ask_doctor_request_type_select.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/widgets/appointment_calendar.dart'; import 'package:hmg_patient_app_new/presentation/medical_file/eye_measurement_details_page.dart'; @@ -180,12 +181,14 @@ class AppointmentCard extends StatelessWidget { ).toShimmer2(isShow: isLoading), AppCustomChipWidget(labelText: isLoading ? 'Olaya' : patientAppointmentHistoryResponseModel.projectName!).toShimmer2(isShow: isLoading), AppCustomChipWidget( + labelPadding: EdgeInsetsDirectional.only(start: -4.w, end: 6.w), icon: AppAssets.appointment_calendar_icon, labelText: isLoading ? 'Cardiology' : "${DateUtil.formatDateToDate(DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate), false)} ${DateUtil.formatDateToTimeLang(DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate), false)}", ).toShimmer2(isShow: isLoading), AppCustomChipWidget( + labelPadding: EdgeInsetsDirectional.only(start: -2.w, end: 6.w), isIconPNG: true, icon: getIt.get().getAuthenticatedUser()?.gender == 1 ? AppAssets.male_img : AppAssets.femaleImg, iconSize: 18.h, diff --git a/lib/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart b/lib/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart index f430447..cd43b17 100644 --- a/lib/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart +++ b/lib/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart @@ -149,6 +149,7 @@ class AppointmentCheckinBottomSheet extends StatelessWidget { onSuccess: (apiResponse) { LoaderBottomSheet.hideLoader(); showCommonBottomSheetWithoutHeight(context, title: "Success".needTranslation, child: Utils.getSuccessWidget(loadingText: LocaleKeys.success.tr()), callBackFunc: () { + myAppointmentsViewModel.getPatientAppointmentQueueDetails(appointmentNo: patientAppointmentHistoryResponseModel.appointmentNo, patientID: patientAppointmentHistoryResponseModel.patientID); Navigator.of(context).pop(); Navigator.pushAndRemoveUntil( context, diff --git a/lib/presentation/appointments/widgets/appointment_doctor_card.dart b/lib/presentation/appointments/widgets/appointment_doctor_card.dart index 96d538b..405aa14 100644 --- a/lib/presentation/appointments/widgets/appointment_doctor_card.dart +++ b/lib/presentation/appointments/widgets/appointment_doctor_card.dart @@ -99,6 +99,7 @@ class AppointmentDoctorCard extends StatelessWidget { labelPadding: EdgeInsetsDirectional.only(start: 6.w, end: 6.w), ), AppCustomChipWidget( + labelPadding: EdgeInsetsDirectional.only(start: -4.w, end: 6.w), icon: AppAssets.doctor_calendar_icon, labelText: "${DateUtil.formatDateToDate(DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate), false)} ${DateUtil.formatDateToTimeLang( DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate), @@ -106,6 +107,7 @@ class AppointmentDoctorCard extends StatelessWidget { )}", ), AppCustomChipWidget( + labelPadding: EdgeInsetsDirectional.only(start: -4.w, end: 6.w), icon: !patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? AppAssets.walkin_appointment_icon : AppAssets.small_livecare_icon, diff --git a/lib/presentation/book_appointment/laser/widgets/body_type_listing.dart b/lib/presentation/book_appointment/laser/widgets/body_type_listing.dart index d8fa736..46047ff 100644 --- a/lib/presentation/book_appointment/laser/widgets/body_type_listing.dart +++ b/lib/presentation/book_appointment/laser/widgets/body_type_listing.dart @@ -45,20 +45,22 @@ class BodyTypeListing extends StatelessWidget { ? AppColors.chipPrimaryRedBorderColor : AppColors.blackColor, iconSize: 16, - labelPadding: - EdgeInsetsDirectional.only(start: 8.h, end: 0.h), - padding: - EdgeInsets.symmetric(vertical: 16.h, horizontal: 12.h), - deleteIconSize: Size(18.h, 18.h), - shape: SmoothRectangleBorder( - borderRadius: BorderRadius.circular(10), - smoothness: 10, + labelPadding: EdgeInsetsDirectional.only(start: 8.w, end: 8.w), + padding: EdgeInsets.symmetric(vertical: 16.h, horizontal: 12.w), + deleteIconSize: Size(18.w, 18.h), + shape: SmoothRectangleBorder( + borderRadius: BorderRadius.circular(10.r), + smoothness: 10, side: BorderSide( color: index == selectedBodyAreaIndex ? AppColors.chipPrimaryRedBorderColor : AppColors.borderGrayColor, width: 1), - )).onPress(() => onCategoryChanged(index)))) + )).onPress( + () => onCategoryChanged(index), + ), + ), + ) ], ), ); diff --git a/lib/presentation/home/data/landing_page_data.dart b/lib/presentation/home/data/landing_page_data.dart index 3d74cfd..82c423a 100644 --- a/lib/presentation/home/data/landing_page_data.dart +++ b/lib/presentation/home/data/landing_page_data.dart @@ -90,7 +90,7 @@ class LandingPageData { ), ServiceCardData( serviceName: "radiology_results", - icon: AppAssets.home_lab_result_icon, + icon: AppAssets.my_radiology_icon, title: "Radiology", subtitle: "Results", backgroundColor: AppColors.whiteColor, @@ -120,7 +120,7 @@ class LandingPageData { ), ServiceCardData( serviceName: "my_doctors", - icon: AppAssets.insurance_update_icon, + icon: AppAssets.my_doctors_icon, title: "My", subtitle: "Doctors", backgroundColor: AppColors.whiteColor, @@ -130,7 +130,7 @@ class LandingPageData { ), ServiceCardData( serviceName: "sick_leaves", - icon: AppAssets.insurance_update_icon, + icon: AppAssets.my_sick_leave_icon, title: "Sick", subtitle: "Leaves", backgroundColor: AppColors.whiteColor, diff --git a/lib/presentation/home/landing_page.dart b/lib/presentation/home/landing_page.dart index 88b9274..a43aa18 100644 --- a/lib/presentation/home/landing_page.dart +++ b/lib/presentation/home/landing_page.dart @@ -25,6 +25,7 @@ import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/ import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart'; import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_view_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; +import 'package:hmg_patient_app_new/presentation/appointments/appointment_queue_page.dart'; import 'package:hmg_patient_app_new/presentation/appointments/my_appointments_page.dart'; import 'package:hmg_patient_app_new/presentation/appointments/widgets/appointment_card.dart'; import 'package:hmg_patient_app_new/presentation/authentication/quick_login.dart'; @@ -291,15 +292,15 @@ class _LandingPageState extends State { ], ), SizedBox(height: 10.h), - "Hala ${appState!.getAuthenticatedUser()!.firstName}!!!".needTranslation.toText16(isBold: true), + "Hala ${appState.getAuthenticatedUser()!.firstName}!!!".needTranslation.toText16(isBold: true), SizedBox(height: 8.h), "Thank you for your patience, here is your queue number." .needTranslation .toText12(fontWeight: FontWeight.w500, color: AppColors.textColorLight), SizedBox(height: 8.h), - "IMD W-A-5".needTranslation.toText28(isBold: true), + myAppointmentsVM.currentPatientQueueDetails.queueNo!.toText28(isBold: true), SizedBox(height: 12.h), - Row( + myAppointmentsVM.patientQueueDetailsList.isNotEmpty ? Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ @@ -307,24 +308,24 @@ class _LandingPageState extends State { Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ - "IMD W-A-2".needTranslation.toText12(isBold: true), + myAppointmentsVM.patientQueueDetailsList.first.queueNo!.toText12(isBold: true), SizedBox(width: 8.w), AppCustomChipWidget( - deleteIcon: AppAssets.call_for_vitals, - labelText: "Call for vital signs".needTranslation, - iconColor: AppColors.primaryRedColor, - textColor: AppColors.primaryRedColor, + deleteIcon: myAppointmentsVM.patientQueueDetailsList.first.callType == 1 ? AppAssets.call_for_vitals : AppAssets.call_for_doctor, + labelText: myAppointmentsVM.patientQueueDetailsList.first.callType == 1 ? "Call for vital signs".needTranslation : "Call for Doctor".needTranslation, + iconColor: myAppointmentsVM.patientQueueDetailsList.first.callType == 1 ? AppColors.primaryRedColor : AppColors.successColor, + textColor: myAppointmentsVM.patientQueueDetailsList.first.callType == 1 ? AppColors.primaryRedColor : AppColors.successColor, iconSize: 14.w, - backgroundColor: AppColors.primaryRedColor.withValues(alpha: 0.1), + backgroundColor: myAppointmentsVM.patientQueueDetailsList.first.callType == 1 ? AppColors.primaryRedColor.withValues(alpha: 0.1) : AppColors.successColor.withValues(alpha: 0.1), labelPadding: EdgeInsetsDirectional.only(start: 8.h, end: -2.h), ), ], ), ], - ), + ) : SizedBox(height: 12.h), SizedBox(height: 8.h), CustomButton( - text: Utils.getCardButtonText(myAppointmentsVM.currentQueueStatus), + text: Utils.getCardButtonText(myAppointmentsVM.currentQueueStatus, myAppointmentsVM.currentPatientQueueDetails.roomNo!), onPressed: () {}, backgroundColor: Utils.getCardButtonColor(myAppointmentsVM.currentQueueStatus), borderColor: Utils.getCardButtonColor(myAppointmentsVM.currentQueueStatus).withValues(alpha: 0.01), @@ -340,7 +341,13 @@ class _LandingPageState extends State { ], ), ), - ) + ).onPress(() { + Navigator.of(context).push( + CustomPageRoute( + page: AppointmentQueuePage(), + ), + ); + }) : (immediateLiveCareVM.patientHasPendingLiveCareRequest && index == 0) ? Column( children: [ diff --git a/lib/presentation/medical_file/medical_file_page.dart b/lib/presentation/medical_file/medical_file_page.dart index d735bd9..8b6b19d 100644 --- a/lib/presentation/medical_file/medical_file_page.dart +++ b/lib/presentation/medical_file/medical_file_page.dart @@ -192,20 +192,21 @@ class _MedicalFilePageState extends State { AppCustomChipWidget( icon: AppAssets.file_icon, labelText: "${LocaleKeys.fileno.tr(context: context)}: ${appState.getAuthenticatedUser()!.patientId}", - labelPadding: EdgeInsetsDirectional.only(end: 6.w), + labelPadding: EdgeInsetsDirectional.only(start: -4.w, end: 6.w), onChipTap: () { navigationService.pushPage( page: FamilyMedicalScreen( profiles: medicalFileViewModel.patientFamilyFiles, onSelect: (FamilyFileResponseModelLists p1) {}, - )); + ), + ); }, ), AppCustomChipWidget( icon: AppAssets.checkmark_icon, labelText: LocaleKeys.verified.tr(context: context), iconColor: AppColors.successColor, - labelPadding: EdgeInsetsDirectional.only(end: 6.w), + labelPadding: EdgeInsetsDirectional.only(start: -4.w, end: 6.w), ), ], ), @@ -227,9 +228,9 @@ class _MedicalFilePageState extends State { ), AppCustomChipWidget( icon: AppAssets.blood_icon, - labelText: "Blood: ${appState.getUserBloodGroup.isEmpty ? "N/A" : appState.getUserBloodGroup.isEmpty}", + labelText: "Blood: ${appState.getUserBloodGroup.isEmpty ? "N/A" : appState.getUserBloodGroup}", iconColor: AppColors.primaryRedColor, - labelPadding: EdgeInsetsDirectional.only(end: 4.w), + labelPadding: EdgeInsetsDirectional.only(start: -4.w, end: 6.w), padding: EdgeInsets.zero, ), Consumer(builder: (context, insuranceVM, child) { @@ -240,7 +241,7 @@ class _MedicalFilePageState extends State { textColor: insuranceVM.isInsuranceExpired ? AppColors.primaryRedColor : AppColors.successColor, iconSize: 12.w, backgroundColor: insuranceVM.isInsuranceExpired ? AppColors.primaryRedColor.withOpacity(0.1) : AppColors.successColor.withOpacity(0.1), - labelPadding: EdgeInsetsDirectional.only(end: 8.w), + labelPadding: EdgeInsetsDirectional.only(start: -4.w, end: 6.w), ); }), ], @@ -939,7 +940,7 @@ class _MedicalFilePageState extends State { label: "Update Insurance".needTranslation, textColor: AppColors.blackColor, backgroundColor: AppColors.whiteColor, - svgIcon: AppAssets.eye_result_icon, + svgIcon: AppAssets.update_insurance_icon, isLargeText: true, iconSize: 36.w, ).onPress(() { @@ -949,7 +950,7 @@ class _MedicalFilePageState extends State { label: "${LocaleKeys.insurance.tr(context: context)} ${LocaleKeys.approvals.tr(context: context)}", textColor: AppColors.blackColor, backgroundColor: AppColors.whiteColor, - svgIcon: AppAssets.eye_result_icon, + svgIcon: AppAssets.insurance_approval_icon, isLargeText: true, iconSize: 36.w, ).onPress(() { @@ -963,7 +964,7 @@ class _MedicalFilePageState extends State { label: "My Invoices List".needTranslation, textColor: AppColors.blackColor, backgroundColor: AppColors.whiteColor, - svgIcon: AppAssets.eye_result_icon, + svgIcon: AppAssets.invoices_list_icon, isLargeText: true, iconSize: 36.w, ), @@ -971,7 +972,7 @@ class _MedicalFilePageState extends State { label: "Ancillary Orders List".needTranslation, textColor: AppColors.blackColor, backgroundColor: AppColors.whiteColor, - svgIcon: AppAssets.eye_result_icon, + svgIcon: AppAssets.ancillary_orders_list_icon, isLargeText: true, iconSize: 36.w, ), @@ -1026,7 +1027,7 @@ class _MedicalFilePageState extends State { label: LocaleKeys.monthlyReports.tr(context: context), textColor: AppColors.blackColor, backgroundColor: AppColors.whiteColor, - svgIcon: AppAssets.eye_result_icon, + svgIcon: AppAssets.monthly_reports_icon, isLargeText: true, iconSize: 36.h, ), @@ -1034,7 +1035,7 @@ class _MedicalFilePageState extends State { label: "Medical Reports".needTranslation, textColor: AppColors.blackColor, backgroundColor: AppColors.whiteColor, - svgIcon: AppAssets.allergy_info_icon, + svgIcon: AppAssets.medical_reports_icon, isLargeText: true, iconSize: 36.h, ).onPress(() { @@ -1050,7 +1051,7 @@ class _MedicalFilePageState extends State { label: "Sick Leave Report".needTranslation, textColor: AppColors.blackColor, backgroundColor: AppColors.whiteColor, - svgIcon: AppAssets.vaccine_info_icon, + svgIcon: AppAssets.sick_leave_report_icon, isLargeText: true, iconSize: 36.h, ).onPress(() { diff --git a/lib/presentation/medical_file/patient_sickleaves_list_page.dart b/lib/presentation/medical_file/patient_sickleaves_list_page.dart index a28f518..709e4e3 100644 --- a/lib/presentation/medical_file/patient_sickleaves_list_page.dart +++ b/lib/presentation/medical_file/patient_sickleaves_list_page.dart @@ -47,7 +47,9 @@ class _PatientSickleavesListPageState extends State { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ + SizedBox(height: 24.h), ListView.separated( + padding: EdgeInsets.zero, scrollDirection: Axis.vertical, itemCount: medicalFileVM.isPatientSickLeaveListLoading ? 3 diff --git a/lib/presentation/todo_section/ancillary_order_payment_page.dart b/lib/presentation/todo_section/ancillary_order_payment_page.dart index f9995dc..5263643 100644 --- a/lib/presentation/todo_section/ancillary_order_payment_page.dart +++ b/lib/presentation/todo_section/ancillary_order_payment_page.dart @@ -180,7 +180,6 @@ class _AncillaryOrderPaymentPageState extends State { ), ), ), - // Payment Summary Footer todoVM.isProcessingPayment ? SizedBox.shrink() : _buildPaymentSummary() ], @@ -220,7 +219,7 @@ class _AncillaryOrderPaymentPageState extends State { children: [ "Amount before tax".needTranslation.toText14(isBold: true), Utils.getPaymentAmountWithSymbol( - amountBeforeTax.toString().toText16(isBold: true), + amountBeforeTax.toStringAsFixed(2).toText16(isBold: true), AppColors.blackColor, 13, isSaudiCurrency: true, @@ -234,7 +233,7 @@ class _AncillaryOrderPaymentPageState extends State { children: [ "VAT 15%".needTranslation.toText14(isBold: true, color: AppColors.greyTextColor), Utils.getPaymentAmountWithSymbol( - taxAmount.toString().toText14(isBold: true, color: AppColors.greyTextColor), + taxAmount.toStringAsFixed(2).toText14(isBold: true, color: AppColors.greyTextColor), AppColors.greyTextColor, 13, isSaudiCurrency: true, @@ -250,7 +249,7 @@ class _AncillaryOrderPaymentPageState extends State { children: [ "".needTranslation.toText14(isBold: true), Utils.getPaymentAmountWithSymbol( - widget.totalAmount.toString().toText24(isBold: true), + widget.totalAmount.toStringAsFixed(2).toText24(isBold: true), AppColors.blackColor, 17, isSaudiCurrency: true, diff --git a/lib/presentation/todo_section/ancillary_procedures_details_page.dart b/lib/presentation/todo_section/ancillary_procedures_details_page.dart index 449d21e..cb6cbd2 100644 --- a/lib/presentation/todo_section/ancillary_procedures_details_page.dart +++ b/lib/presentation/todo_section/ancillary_procedures_details_page.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'package:collection/collection.dart'; +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_assets.dart'; @@ -13,6 +14,7 @@ import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/features/todo_section/models/resp_models/ancillary_order_list_response_model.dart'; import 'package:hmg_patient_app_new/features/todo_section/models/resp_models/ancillary_order_procedures_detail_response_model.dart'; import 'package:hmg_patient_app_new/features/todo_section/todo_section_view_model.dart'; +import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/presentation/todo_section/ancillary_order_payment_page.dart'; import 'package:hmg_patient_app_new/presentation/todo_section/widgets/ancillary_orders_list.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; @@ -130,7 +132,6 @@ class _AncillaryOrderDetailsListState extends State { if (viewModel.patientAncillaryOrderProceduresList.isNotEmpty) { orderData = viewModel.patientAncillaryOrderProceduresList[0]; } - return Column( children: [ Expanded( @@ -618,39 +619,102 @@ class _AncillaryOrderDetailsListState extends State { Widget _buildStickyPaymentButton(orderData) { final isButtonEnabled = selectedProcedures.isNotEmpty; - return Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - SizedBox(height: 16.h), - _buildSummarySection(orderData), - SizedBox(height: 16.h), - CustomButton( - borderWidth: 0, - backgroundColor: AppColors.infoLightColor, - text: "Proceed to Payment".needTranslation, - onPressed: () { - // Navigate to payment page with selected procedures - Navigator.of(context).push( - CustomPageRoute( - page: AncillaryOrderPaymentPage( - appointmentNoVida: widget.appointmentNoVida, - orderNo: widget.orderNo, - projectID: widget.projectID, - selectedProcedures: selectedProcedures, - totalAmount: _getTotalAmount(), - appointmentDate: orderData.appointmentDate, - ), + return Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 24.r, + hasShadow: true, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height: 4.h), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded(child: LocaleKeys.upcomingPaymentNow.tr(context: context).toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor)), + ], + ), + SizedBox(height: 18.h), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SizedBox( + width: 150.h, + child: Utils.getPaymentMethods(), ), - ); - }, - isDisabled: !isButtonEnabled, - textColor: AppColors.whiteColor, - borderRadius: 12.r, - borderColor: Colors.transparent, - padding: EdgeInsets.symmetric(vertical: 16.h), - ), - SizedBox(height: 22.h), - ], - ).paddingSymmetrical(24.w, 0); + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Utils.getPaymentAmountWithSymbol(_getTotalAmount().toStringAsFixed(2).toText24(isBold: true), AppColors.blackColor, 17, isSaudiCurrency: true), + ], + ), + ], + ), + SizedBox(height: 16.h), + CustomButton( + borderWidth: 0, + backgroundColor: AppColors.infoLightColor, + text: "Proceed to Payment".needTranslation, + onPressed: () { + // Navigate to payment page with selected procedures + Navigator.of(context).push( + CustomPageRoute( + page: AncillaryOrderPaymentPage( + appointmentNoVida: widget.appointmentNoVida, + orderNo: widget.orderNo, + projectID: widget.projectID, + selectedProcedures: selectedProcedures, + totalAmount: _getTotalAmount(), + appointmentDate: orderData.appointmentDate, + ), + ), + ); + }, + isDisabled: !isButtonEnabled, + textColor: AppColors.whiteColor, + borderRadius: 12.r, + borderColor: Colors.transparent, + padding: EdgeInsets.symmetric(vertical: 16.h), + ), + SizedBox(height: 22.h), + ], + ).paddingOnly(left: 16.h, top: 24.h, right: 16.h, bottom: 0.h), + ); + + // Column( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // SizedBox(height: 16.h), + // _buildSummarySection(orderData), + // SizedBox(height: 16.h), + // CustomButton( + // borderWidth: 0, + // backgroundColor: AppColors.infoLightColor, + // text: "Proceed to Payment".needTranslation, + // onPressed: () { + // // Navigate to payment page with selected procedures + // Navigator.of(context).push( + // CustomPageRoute( + // page: AncillaryOrderPaymentPage( + // appointmentNoVida: widget.appointmentNoVida, + // orderNo: widget.orderNo, + // projectID: widget.projectID, + // selectedProcedures: selectedProcedures, + // totalAmount: _getTotalAmount(), + // appointmentDate: orderData.appointmentDate, + // ), + // ), + // ); + // }, + // isDisabled: !isButtonEnabled, + // textColor: AppColors.whiteColor, + // borderRadius: 12.r, + // borderColor: Colors.transparent, + // padding: EdgeInsets.symmetric(vertical: 16.h), + // ), + // SizedBox(height: 22.h), + // ], + // ).paddingSymmetrical(24.w, 0); } } diff --git a/lib/presentation/todo_section/todo_page.dart b/lib/presentation/todo_section/todo_page.dart index 11e258f..8907fc8 100644 --- a/lib/presentation/todo_section/todo_page.dart +++ b/lib/presentation/todo_section/todo_page.dart @@ -68,6 +68,7 @@ class _ToDoPageState extends State { children: [ SizedBox(height: 16.h), "Ancillary Orders".needTranslation.toText18(isBold: true), + SizedBox(height: 24.h), Consumer( builder: (BuildContext context, TodoSectionViewModel todoSectionViewModel, Widget? child) { return todoSectionViewModel.isAncillaryOrdersLoading @@ -82,8 +83,9 @@ class _ToDoPageState extends State { orderNo: order.orderNo ?? 0, projectID: order.projectID ?? 0, projectName: order.projectName ?? "", - ))); - log("View details for order: ${order.orderNo}"); + ), + ), + ); }, ); }, diff --git a/lib/presentation/todo_section/widgets/ancillary_orders_list.dart b/lib/presentation/todo_section/widgets/ancillary_orders_list.dart index 31a778f..8a3e3fa 100644 --- a/lib/presentation/todo_section/widgets/ancillary_orders_list.dart +++ b/lib/presentation/todo_section/widgets/ancillary_orders_list.dart @@ -35,10 +35,10 @@ class AncillaryOrdersList extends StatelessWidget { shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemCount: orders.length, + padding: EdgeInsets.zero, separatorBuilder: (BuildContext context, int index) => SizedBox(height: 12.h), itemBuilder: (context, index) { final order = orders[index]; - return AnimationConfiguration.staggeredList( position: index, duration: const Duration(milliseconds: 500),