diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index d64b9b7..cb2b71a 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -1496,10 +1496,6 @@ "someRemarksAboutPrescription": "ستجدون هنا بعض الملاحظات حول الوصفة الطبية", "notifyMeBeforeConsumptionTime": "أبلغني قبل وقت الاستهلاك", "noMedicationsToday": "لا أدوية اليوم", - "route": "Route: {route}", - "frequency": "Frequency: {frequency}", - "instruction": "Instruction: {instruction}", - "duration": "Duration: {days}", "reminders": "تذكيرات", "reminderAddedToCalendar": "تمت إضافة تذكير إلى التقويم ✅", "errorWhileSettingCalendar": "حدث خطأ أثناء ضبط التقويم:{error}", diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 03b766d..e56d861 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -1487,10 +1487,8 @@ "someRemarksAboutPrescription": "some remarks about the prescription will be here", "notifyMeBeforeConsumptionTime": "Notify me before the consumption time", "noMedicationsToday": "No medications today", - "route": "Route: {route}", - "frequency": "Frequency: {frequency}", - "instruction": "Instruction: {instruction}", - "duration": "Duration: {days}", + "route": "Route", + "frequency": "Frequency", "reminders": "Reminders", "reminderAddedToCalendar": "Reminder added to calendar ✅", "errorWhileSettingCalendar": "Error while setting calendar: {error}", diff --git a/lib/core/api/api_client.dart b/lib/core/api/api_client.dart index c063932..3eb8fa2 100644 --- a/lib/core/api/api_client.dart +++ b/lib/core/api/api_client.dart @@ -184,7 +184,6 @@ class ApiClientImp implements ApiClient { // body['TokenID'] = "@dm!n"; // body['PatientID'] = 4769038; // body['PatientTypeID'] = 1; - // // body['PatientOutSA'] = 0; // body['SessionID'] = "45786230487560q"; } diff --git a/lib/features/authentication/authentication_view_model.dart b/lib/features/authentication/authentication_view_model.dart index 8206160..c49554f 100644 --- a/lib/features/authentication/authentication_view_model.dart +++ b/lib/features/authentication/authentication_view_model.dart @@ -605,7 +605,7 @@ class AuthenticationViewModel extends ChangeNotifier { } // _appState.setUserBloodGroup = (activation.patientBlodType ?? ""); _appState.setAppAuthToken = activation.authenticationTokenId; - myAppointmentsVM.getActiveAppointmentsCount(); + // myAppointmentsVM.getActiveAppointmentsCount(); final request = RequestUtils.getAuthanticatedCommonRequest().toJson(); bool isUserAgreedBefore = await checkIfUserAgreedBefore(request: request); diff --git a/lib/features/book_appointments/book_appointments_repo.dart b/lib/features/book_appointments/book_appointments_repo.dart index cfd473e..cab79ad 100644 --- a/lib/features/book_appointments/book_appointments_repo.dart +++ b/lib/features/book_appointments/book_appointments_repo.dart @@ -30,6 +30,8 @@ abstract class BookAppointmentsRepo { Future>> getDoctorProfile(int clinicID, int projectID, int doctorId, {Function(dynamic)? onSuccess, Function(String)? onError}); + Future>> getDoctorRatingDetails(int doctorId, {Function(dynamic)? onSuccess, Function(String)? onError}); + Future>> getDoctorFreeSlots(int clinicID, int projectID, int doctorId, bool isBookingForLiveCare, {bool continueDentalPlan = false, Function(dynamic)? onSuccess, Function(String)? onError}); @@ -298,6 +300,52 @@ class BookAppointmentsRepoImp implements BookAppointmentsRepo { } } + @override + Future>> getDoctorRatingDetails(int doctorId, {Function(dynamic)? onSuccess, Function(String)? onError}) async { + Map mapDevice = { + "DoctorID": doctorId, + "PatientID": 0, + "License": true, + "IsRegistered": true, + "isDentalAllowedBackend": false, + }; + + try { + GenericApiModel? apiResponse; + Failure? failure; + await apiClient.post( + GET_DOCTOR_RATING_DETAILS, + body: mapDevice, + onFailure: (error, statusCode, {messageStatus, failureType}) { + failure = failureType; + if (onError != null) { + onError(error); + } + }, + onSuccess: (response, statusCode, {messageStatus, errorMessage}) { + try { + apiResponse = GenericApiModel( + messageStatus: messageStatus, + statusCode: statusCode, + errorMessage: null, + data: response, + ); + if (onSuccess != null) { + onSuccess(response); + } + } catch (e) { + failure = DataParsingFailure(e.toString()); + } + }, + ); + if (failure != null) return Left(failure!); + if (apiResponse == null) return Left(ServerFailure("Unknown error")); + return Right(apiResponse!); + } catch (e) { + return Left(UnknownFailure(e.toString())); + } + } + //TODO: Implement the logic for Dental & laser clinics @override Future>> getDoctorFreeSlots(int clinicID, int projectID, int doctorId, bool isBookingForLiveCare, diff --git a/lib/features/book_appointments/book_appointments_view_model.dart b/lib/features/book_appointments/book_appointments_view_model.dart index 664f244..34858b4 100644 --- a/lib/features/book_appointments/book_appointments_view_model.dart +++ b/lib/features/book_appointments/book_appointments_view_model.dart @@ -17,6 +17,7 @@ import 'package:hmg_patient_app_new/features/book_appointments/models/free_slot. import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/appointment_nearest_gate_response_model.dart'; import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/dental_chief_complaints_response_model.dart'; import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/doctor_profile_response_model.dart'; +import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/doctor_rating_details_response_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/book_appointments/models/resp_models/get_clinic_list_response_model.dart'; import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/get_patient_dental_plan_response_model.dart'; @@ -92,6 +93,9 @@ class BookAppointmentsViewModel extends ChangeNotifier { late DoctorsProfileResponseModel doctorsProfileResponseModel; + bool isDoctorRatingDetailsLoading = false; + List doctorDetailsList = []; + List slotsList = []; List docFreeSlots = []; List dayEvents = []; @@ -340,6 +344,14 @@ class BookAppointmentsViewModel extends ChangeNotifier { notifyListeners(); } + setIsLiveCareDoctorsListLoading(bool value) { + if (value) { + liveCareDoctorsList.clear(); + } + isDoctorsListLoading = value; + notifyListeners(); + } + setIsClinicsListLoading(bool value) { if (value) { clinicsList.clear(); @@ -467,10 +479,10 @@ class BookAppointmentsViewModel extends ChangeNotifier { } Future getLiveCareDoctorsList({Function(dynamic)? onSuccess, Function(String)? onError}) async { - doctorsList.clear(); + liveCareDoctorsList.clear(); + notifyListeners(); final result = await bookAppointmentsRepo.getLiveCareDoctorsList(selectedLiveCareClinic.serviceID!, _appState.getAuthenticatedUser()!.age!, _appState.getAuthenticatedUser()!.gender!, onError: onError); - result.fold( (failure) async { onError!(LocaleKeys.noDoctorFound.tr()); @@ -614,6 +626,46 @@ class BookAppointmentsViewModel extends ChangeNotifier { ); } + Future getDoctorRatingDetails({Function(dynamic)? onSuccess, Function(String)? onError}) async { + isDoctorRatingDetailsLoading = true; + doctorDetailsList.clear(); + notifyListeners(); + + final result = await bookAppointmentsRepo.getDoctorRatingDetails(selectedDoctor.doctorID ?? 0, onSuccess: onSuccess, onError: onError); + + result.fold( + (failure) async { + if (onError != null) { + onError("Failed to load doctor rating details"); + } + }, + (apiResponse) { + if (apiResponse.messageStatus == 2) { + if (onError != null) { + onError(apiResponse.errorMessage ?? "Unknown error occurred"); + } + isDoctorRatingDetailsLoading = false; + } else if (apiResponse.messageStatus == 1) { + try { + apiResponse.data['DoctorRatingDetailsList'].forEach((v) { + doctorDetailsList.add(DoctorRateDetails.fromJson(v)); + }); + isDoctorRatingDetailsLoading = false; + // doctorRatingDetails = DoctorRateDetails.fromJson(apiResponse.data); + notifyListeners(); + if (onSuccess != null) { + onSuccess(apiResponse.data); + } + } catch (e) { + if (onError != null) { + onError("Failed to parse rating details: ${e.toString()}"); + } + } + } + }, + ); + } + Future getDoctorFreeSlots({bool isBookingForLiveCare = false, Function(dynamic)? onSuccess, Function(String)? onError}) async { docFreeSlots.clear(); DateTime date; diff --git a/lib/features/book_appointments/models/resp_models/doctor_rating_details_response_model.dart b/lib/features/book_appointments/models/resp_models/doctor_rating_details_response_model.dart new file mode 100644 index 0000000..5866885 --- /dev/null +++ b/lib/features/book_appointments/models/resp_models/doctor_rating_details_response_model.dart @@ -0,0 +1,36 @@ +class DoctorRateDetails { + dynamic doctorID; + dynamic projectID; + dynamic clinicID; + dynamic rate; + dynamic patientNumber; + dynamic ratio; + + DoctorRateDetails( + {this.doctorID, + this.projectID, + this.clinicID, + this.rate, + this.patientNumber, + this.ratio}); + + DoctorRateDetails.fromJson(Map json) { + doctorID = json['DoctorID']; + projectID = json['ProjectID']; + clinicID = json['ClinicID']; + rate = json['Rate']; + patientNumber = json['PatientNumber']; + ratio = json['Ratio']; + } + + Map toJson() { + final Map data = new Map(); + data['DoctorID'] = this.doctorID; + data['ProjectID'] = this.projectID; + data['ClinicID'] = this.clinicID; + data['Rate'] = this.rate; + data['PatientNumber'] = this.patientNumber; + data['Ratio'] = this.ratio; + return data; + } +} diff --git a/lib/features/medical_file/medical_file_view_model.dart b/lib/features/medical_file/medical_file_view_model.dart index 17cbb94..b26a87a 100644 --- a/lib/features/medical_file/medical_file_view_model.dart +++ b/lib/features/medical_file/medical_file_view_model.dart @@ -41,6 +41,7 @@ class MedicalFileViewModel extends ChangeNotifier { List patientSickLeavesViewList = []; bool isSickLeavesSortByClinic = true; + bool isSickLeavesDataNeedsReloading = true; List patientAllergiesList = []; @@ -163,15 +164,15 @@ class MedicalFileViewModel extends ChangeNotifier { } setIsPatientSickLeaveListLoading(bool val) { - if (val) { + if (val && isSickLeavesDataNeedsReloading) { patientSickLeaveList.clear(); patientSickLeavesByClinic.clear(); patientSickLeavesByHospital.clear(); patientSickLeavesViewList.clear(); patientSickLeavePDFBase64 = ""; isSickLeavesSortByClinic = true; + isPatientSickLeaveListLoading = val; } - isPatientSickLeaveListLoading = val; notifyListeners(); } @@ -267,6 +268,10 @@ class MedicalFileViewModel extends ChangeNotifier { } Future getPatientSickLeaveList({Function(dynamic)? onSuccess, Function(String)? onError}) async { + if (!isSickLeavesDataNeedsReloading) { + return; + } + patientSickLeaveList.clear(); final result = await medicalFileRepo.getPatientSickLeavesList(); @@ -309,6 +314,7 @@ class MedicalFileViewModel extends ChangeNotifier { } } patientSickLeavesViewList = patientSickLeavesByClinic; + isSickLeavesDataNeedsReloading = false; notifyListeners(); if (onSuccess != null) { diff --git a/lib/features/prescriptions/prescriptions_view_model.dart b/lib/features/prescriptions/prescriptions_view_model.dart index 3f9af34..a7cd42f 100644 --- a/lib/features/prescriptions/prescriptions_view_model.dart +++ b/lib/features/prescriptions/prescriptions_view_model.dart @@ -47,20 +47,24 @@ class PrescriptionsViewModel extends ChangeNotifier { late GeocodeResponse locationGeocodeResponse; bool isPrescriptionsDeliveryOrdersLoading = false; + + bool isPrescriptionsDataNeedsReloading = true; List prescriptionsOrderList = []; PrescriptionsViewModel({required this.prescriptionsRepo, required this.errorHandlerService, required this.navServices}); initPrescriptionsViewModel() { - patientPrescriptionOrders.clear(); - patientPrescriptionOrdersByClinic.clear(); - patientPrescriptionOrdersByHospital.clear(); - patientPrescriptionOrdersViewList.clear(); - prescriptionsOrderList.clear(); - isPrescriptionsOrdersLoading = true; + if (isPrescriptionsDataNeedsReloading) { + patientPrescriptionOrders.clear(); + patientPrescriptionOrdersByClinic.clear(); + patientPrescriptionOrdersByHospital.clear(); + patientPrescriptionOrdersViewList.clear(); + prescriptionsOrderList.clear(); + isPrescriptionsOrdersLoading = true; + getPatientPrescriptionOrders(); + } isSortByClinic = true; isPrescriptionsDeliveryOrdersLoading = true; - getPatientPrescriptionOrders(); notifyListeners(); } @@ -98,6 +102,10 @@ class PrescriptionsViewModel extends ChangeNotifier { } Future getPatientPrescriptionOrders({Function(dynamic)? onSuccess, Function(String)? onError}) async { + if (!isPrescriptionsDataNeedsReloading) { + return; + } + final result = await prescriptionsRepo.getPatientPrescriptionOrders(patientId: "1231755"); result.fold( @@ -131,6 +139,7 @@ class PrescriptionsViewModel extends ChangeNotifier { } } patientPrescriptionOrdersViewList = patientPrescriptionOrdersByClinic; + isPrescriptionsDataNeedsReloading = false; notifyListeners(); if (onSuccess != null) { onSuccess(apiResponse); diff --git a/lib/features/todo_section/todo_section_view_model.dart b/lib/features/todo_section/todo_section_view_model.dart index 92d893a..0f6cc87 100644 --- a/lib/features/todo_section/todo_section_view_model.dart +++ b/lib/features/todo_section/todo_section_view_model.dart @@ -13,17 +13,20 @@ class TodoSectionViewModel extends ChangeNotifier { String? notificationsCount = "0"; initializeTodoSectionViewModel() async { - patientAncillaryOrdersList.clear(); - isAncillaryOrdersLoading = true; - isAncillaryDetailsProceduresLoading = true; - notificationsCount = "0"; - getPatientOnlineAncillaryOrderList(); + if (isAncillaryOrdersNeedReloading) { + patientAncillaryOrdersList.clear(); + isAncillaryOrdersLoading = true; + isAncillaryDetailsProceduresLoading = true; + notificationsCount = "0"; + getPatientOnlineAncillaryOrderList(); + } getPatientDashboard(); } bool isAncillaryOrdersLoading = false; bool isAncillaryDetailsProceduresLoading = false; bool isProcessingPayment = false; + bool isAncillaryOrdersNeedReloading = true; List patientAncillaryOrdersList = []; List patientAncillaryOrderProceduresList = []; @@ -32,6 +35,11 @@ class TodoSectionViewModel extends ChangeNotifier { notifyListeners(); } + void setIsAncillaryOrdersNeedReloading(bool value) { + isAncillaryOrdersNeedReloading = value; + notifyListeners(); + } + Future getPatientDashboard({Function(dynamic)? onSuccess, Function(String)? onError}) async { final result = await todoSectionRepo.getPatientDashboard(); @@ -55,6 +63,10 @@ class TodoSectionViewModel extends ChangeNotifier { } Future getPatientOnlineAncillaryOrderList({Function(dynamic)? onSuccess, Function(String)? onError}) async { + if (!isAncillaryOrdersNeedReloading) { + return; + } + patientAncillaryOrdersList.clear(); isAncillaryOrdersLoading = true; notifyListeners(); @@ -71,6 +83,7 @@ class TodoSectionViewModel extends ChangeNotifier { } else if (apiResponse.messageStatus == 1) { patientAncillaryOrdersList = apiResponse.data!; isAncillaryOrdersLoading = false; + isAncillaryOrdersNeedReloading = false; notifyListeners(); if (onSuccess != null) { onSuccess(apiResponse); diff --git a/lib/presentation/appointments/appointment_details_page.dart b/lib/presentation/appointments/appointment_details_page.dart index 46ed33e..e93d604 100644 --- a/lib/presentation/appointments/appointment_details_page.dart +++ b/lib/presentation/appointments/appointment_details_page.dart @@ -15,6 +15,7 @@ import 'package:hmg_patient_app_new/extensions/widget_extensions.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'; +import 'package:hmg_patient_app_new/features/contact_us/models/feedback_type.dart'; import 'package:hmg_patient_app_new/features/lab/lab_view_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/my_appointments_view_model.dart'; @@ -92,6 +93,7 @@ class _AppointmentDetailsPageState extends State { title: LocaleKeys.appointmentDetails.tr(context: context), report: AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel) ? () { + contactUsViewModel.setSelectedFeedbackType(FeedbackType(id: 1, nameEN: "Complaint for appointment", nameAR: 'شكوى على موعد')); contactUsViewModel.setPatientFeedbackSelectedAppointment(widget.patientAppointmentHistoryResponseModel); Navigator.of(context).push( CustomPageRoute( @@ -214,11 +216,8 @@ class _AppointmentDetailsPageState extends State { borderRadius: BorderRadius.circular(24.r), // Todo: what is this???? Api Key??? 😲 child: Image.network( - "https://maps.googleapis.com/maps/api/staticmap?center=${widget.patientAppointmentHistoryResponseModel.latitude},${widget.patientAppointmentHistoryResponseModel.longitude}&zoom=14&size=${(MediaQuery.of(context).size.width * 1.5).toInt()}x165&maptype=roadmap&markers=color:red%7C${widget.patientAppointmentHistoryResponseModel.latitude},${widget.patientAppointmentHistoryResponseModel.longitude}&key=${ApiKeyConstants.googleMapsApiKey}", + "https://maps.googleapis.com/maps/api/staticmap?center=${widget.patientAppointmentHistoryResponseModel.latitude},${widget.patientAppointmentHistoryResponseModel.longitude}&zoom=14&size=${(MediaQuery.of(context).size.width * 1.5).toInt()}x${(MediaQuery.of(context).size.height * 0.35).toInt()}&maptype=roadmap&markers=color:red%7C${widget.patientAppointmentHistoryResponseModel.latitude},${widget.patientAppointmentHistoryResponseModel.longitude}&key=${ApiKeyConstants.googleMapsApiKey}", fit: BoxFit.contain, - // errorBuilder: (cxt, child, tr) { - // return SizedBox.shrink(); - // }, ), ), Positioned( @@ -756,9 +755,10 @@ class _AppointmentDetailsPageState extends State { ], ).paddingOnly(left: 16.h, top: 24.h, right: 16.h, bottom: 0.h), AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel) - ? CustomButton( - text: LocaleKeys.rebookAppointment.tr(context: context), - onPressed: () { + ? !widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment! + ? CustomButton( + text: LocaleKeys.rebookAppointment.tr(context: context), + onPressed: () { openDoctorScheduleCalendar(); }, backgroundColor: AppColors.successColor, @@ -772,7 +772,8 @@ class _AppointmentDetailsPageState extends State { icon: AppAssets.add_icon, iconColor: AppColors.whiteColor, iconSize: 18.h, - ).paddingSymmetrical(16.h, 24.h) + ).paddingSymmetrical(16.h, 24.h) + : SizedBox.shrink() : CustomButton( text: AppointmentType.getNextActionText(widget.patientAppointmentHistoryResponseModel.nextAction), onPressed: () { diff --git a/lib/presentation/appointments/widgets/appointment_card.dart b/lib/presentation/appointments/widgets/appointment_card.dart index aa82b51..a8735d0 100644 --- a/lib/presentation/appointments/widgets/appointment_card.dart +++ b/lib/presentation/appointments/widgets/appointment_card.dart @@ -153,7 +153,7 @@ class AppointmentCard extends StatelessWidget { SizedBox(height: 2.h), (isFoldable || isTablet) ? "${patientAppointmentHistoryResponseModel.decimalDoctorRate}".toText9(isBold: true, color: AppColors.textColor) - : "${patientAppointmentHistoryResponseModel.decimalDoctorRate}".toText11(isBold: true, color: AppColors.textColor), + : "${patientAppointmentHistoryResponseModel.decimalDoctorRate ?? "0.0"}".toText11(isBold: true, color: AppColors.textColor), ], ), ).circle(100).toShimmer2(isShow: isLoading), @@ -228,18 +228,27 @@ class AppointmentCard extends StatelessWidget { Widget _buildActionArea(BuildContext context, AppState appState) { if ((patientAppointmentHistoryResponseModel.isLiveCareAppointment ?? false) && AppointmentType.isArrived(patientAppointmentHistoryResponseModel)) { return CustomButton( - text: LocaleKeys.viewDetails.tr(context: context), + text: isFromMedicalReport ? LocaleKeys.selectAppointment.tr(context: context) : LocaleKeys.viewDetails.tr(context: context), onPressed: () { - Navigator.of(context) - .push( - CustomPageRoute( - page: AppointmentDetailsPage(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel), - ), - ) - .then((_) { - myAppointmentsViewModel.initAppointmentsViewModel(); - myAppointmentsViewModel.getPatientAppointments(true, false); - }); + if (isFromMedicalReport) { + if (isForFeedback) { + contactUsViewModel!.setPatientFeedbackSelectedAppointment(patientAppointmentHistoryResponseModel); + } else { + medicalFileViewModel!.setSelectedMedicalReportAppointment(patientAppointmentHistoryResponseModel); + } + Navigator.pop(context, false); + } else { + Navigator.of(context) + .push( + CustomPageRoute( + page: AppointmentDetailsPage(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel), + ), + ) + .then((_) { + myAppointmentsViewModel.initAppointmentsViewModel(); + myAppointmentsViewModel.getPatientAppointments(true, false); + }); + } }, backgroundColor: AppColors.secondaryLightRedColor, borderColor: AppColors.secondaryLightRedColor, @@ -250,6 +259,9 @@ class AppointmentCard extends StatelessWidget { padding: EdgeInsets.symmetric(horizontal: 10.w), // height: isTablet || isFoldable ? 46.h : 40.h, height: 40.h, + icon: isFromMedicalReport ? AppAssets.checkmark_icon : null, + iconColor: AppColors.primaryRedColor, + iconSize: 16.h, ); } else { if (isFromMedicalReport) { diff --git a/lib/presentation/appointments/widgets/appointment_doctor_card.dart b/lib/presentation/appointments/widgets/appointment_doctor_card.dart index 8583d9b..6eaa379 100644 --- a/lib/presentation/appointments/widgets/appointment_doctor_card.dart +++ b/lib/presentation/appointments/widgets/appointment_doctor_card.dart @@ -159,8 +159,9 @@ class AppointmentDoctorCard extends StatelessWidget { icon: AppAssets.ask_doctor_icon, iconColor: AppColors.primaryRedColor, ) - : CustomButton( - text: LocaleKeys.rebookSameDoctor.tr(), + : !patientAppointmentHistoryResponseModel.isLiveCareAppointment! + ? CustomButton( + text: LocaleKeys.rebookSameDoctor.tr(), onPressed: () { onRescheduleTap(); }, @@ -175,7 +176,8 @@ class AppointmentDoctorCard extends StatelessWidget { icon: AppAssets.rebook_appointment_icon, iconColor: AppColors.blackColor, iconSize: 14.h, - ); + ) + : SizedBox.shrink(); } else { return patientAppointmentHistoryResponseModel.isLiveCareAppointment ?? false ? CustomButton( diff --git a/lib/presentation/book_appointment/doctor_profile_page.dart b/lib/presentation/book_appointment/doctor_profile_page.dart index 72f242d..c62404a 100644 --- a/lib/presentation/book_appointment/doctor_profile_page.dart +++ b/lib/presentation/book_appointment/doctor_profile_page.dart @@ -11,6 +11,7 @@ import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/widgets/appointment_calendar.dart'; +import 'package:hmg_patient_app_new/presentation/book_appointment/widgets/doctor_rating_details.dart'; import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; @@ -108,9 +109,21 @@ class DoctorProfilePage extends StatelessWidget { ), SizedBox(height: 16.h), "Ratings".toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor), - bookAppointmentsViewModel.doctorsProfileResponseModel.decimalDoctorRate.toString().toText16(isBold: true, color: AppColors.textColor), + bookAppointmentsViewModel.doctorsProfileResponseModel.decimalDoctorRate + .toString() + .toText16(isBold: true, color: AppColors.textColor, isUnderLine: true, decorationColor: AppColors.textColor), ], - ), + ).onPress(() { + bookAppointmentsViewModel.getDoctorRatingDetails(); + showCommonBottomSheetWithoutHeight( + title: LocaleKeys.doctorRating.tr(context: context), + context, + child: DoctorRatingDetails(), + callBackFunc: () {}, + isFullScreen: false, + isCloseButtonVisible: true, + ); + }), SizedBox(width: 36.w), Column( children: [ @@ -122,15 +135,28 @@ class DoctorProfilePage extends StatelessWidget { ), SizedBox(height: 16.h), "Reviews".toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor), - bookAppointmentsViewModel.doctorsProfileResponseModel.noOfPatientsRate.toString().toText16(isBold: true, color: AppColors.textColor), + bookAppointmentsViewModel.doctorsProfileResponseModel.noOfPatientsRate + .toString() + .toText16(isBold: true, color: AppColors.textColor, isUnderLine: true, decorationColor: AppColors.textColor), ], - ), + ).onPress(() { + bookAppointmentsViewModel.getDoctorRatingDetails(); + showCommonBottomSheetWithoutHeight( + title: LocaleKeys.doctorRating.tr(context: context), + context, + child: DoctorRatingDetails(), + callBackFunc: () {}, + isFullScreen: false, + isCloseButtonVisible: true, + ); + }), ], ), SizedBox(height: 16.h), Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.1), height: 1.h), SizedBox(height: 16.h), - "Biography".toText14(weight: FontWeight.w600, color: AppColors.textColor), + LocaleKeys.docInfo.tr(context: context).toText14(weight: FontWeight.w600, color: AppColors.textColor), + SizedBox(height: 6.h), bookAppointmentsViewModel.doctorsProfileResponseModel.doctorProfileInfo!.toText12(fontWeight: FontWeight.w600, color: AppColors.greyTextColor), ], ).paddingSymmetrical(24.h, 0.h), diff --git a/lib/presentation/book_appointment/select_clinic_page.dart b/lib/presentation/book_appointment/select_clinic_page.dart index d96c9da..ac40d69 100644 --- a/lib/presentation/book_appointment/select_clinic_page.dart +++ b/lib/presentation/book_appointment/select_clinic_page.dart @@ -941,7 +941,7 @@ class _SelectClinicPageState extends State { void onLiveCareClinicSelected(GetLiveCareClinicsResponseModel clinic) { bookAppointmentsViewModel.setLiveCareSelectedClinic(clinic); - bookAppointmentsViewModel.setIsDoctorsListLoading(true); + bookAppointmentsViewModel.setIsLiveCareDoctorsListLoading(true); Navigator.of(context).push( CustomPageRoute( page: SelectDoctorPage(), diff --git a/lib/presentation/book_appointment/select_doctor_page.dart b/lib/presentation/book_appointment/select_doctor_page.dart index 3723bee..f8a0ad9 100644 --- a/lib/presentation/book_appointment/select_doctor_page.dart +++ b/lib/presentation/book_appointment/select_doctor_page.dart @@ -95,9 +95,59 @@ class _SelectDoctorPageState extends State { child: Padding( padding: EdgeInsets.symmetric(horizontal: 24.h), child: Consumer(builder: (context, bookAppointmentsVM, child) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ + return bookAppointmentsViewModel.isLiveCareSchedule + ? Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ListView.separated( + padding: EdgeInsets.only(top: 16.h), + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + itemCount: bookAppointmentsVM.isDoctorsListLoading ? 5 : (bookAppointmentsVM.liveCareDoctorsList.isNotEmpty ? bookAppointmentsVM.liveCareDoctorsList.length : 1), + itemBuilder: (context, index) { + // final isExpanded = bookAppointmentsVM.expandedGroupIndex == index; + final isExpanded = true; + return bookAppointmentsVM.isDoctorsListLoading + ? DoctorCard( + doctorsListResponseModel: DoctorsListResponseModel(), + isLoading: true, + bookAppointmentsViewModel: bookAppointmentsViewModel, + ) + : bookAppointmentsVM.liveCareDoctorsList.isEmpty + ? Utils.getNoDataWidget(context, noDataText: LocaleKeys.noDoctorFound.tr()) + : 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, + decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true), + child: Padding( + padding: EdgeInsets.all(16.h), + child: DoctorCard( + isLoading: bookAppointmentsVM.isClinicsListLoading, + doctorsListResponseModel: bookAppointmentsVM.liveCareDoctorsList[index], + bookAppointmentsViewModel: bookAppointmentsViewModel, + ).onPress(() { + // onLiveCareClinicSelected(bookAppointmentsVM.liveCareClinicsList[index]); + }), + ), + ), + ), + ), + ); + }, + separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h), + ), + SizedBox(height: 24.h), + ], + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ SizedBox(height: 16.h), Row( spacing: 8.h, diff --git a/lib/presentation/book_appointment/widgets/doctor_card.dart b/lib/presentation/book_appointment/widgets/doctor_card.dart index 97a941d..e2009bb 100644 --- a/lib/presentation/book_appointment/widgets/doctor_card.dart +++ b/lib/presentation/book_appointment/widgets/doctor_card.dart @@ -90,7 +90,7 @@ class DoctorCard extends StatelessWidget { Row( children: [ SizedBox( - width: MediaQuery.of(context).size.width * 0.49, + width: MediaQuery.of(context).size.width * 0.55, child: (isLoading ? "Dr John Smith" : "${doctorsListResponseModel.doctorTitle} ${doctorsListResponseModel.name}") .toString() .toText16(isBold: true, maxlines: 1), @@ -99,14 +99,14 @@ class DoctorCard extends StatelessWidget { ), SizedBox(height: 2.h), Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ SizedBox( - width: MediaQuery.of(context).size.width * 0.45, child: (isLoading ? "Consultant Cardiologist" : doctorsListResponseModel.speciality!.isNotEmpty - ? doctorsListResponseModel.speciality!.first + ? (doctorsListResponseModel.speciality!.first.length > 32 + ? '${doctorsListResponseModel.speciality!.first.substring(0, 32)}...' + : doctorsListResponseModel.speciality!.first) : "") .toString() .toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor, maxLine: 2) @@ -121,6 +121,29 @@ class DoctorCard extends StatelessWidget { ).toShimmer2(isShow: isLoading), ], ), + SizedBox(height: 6.h), + Wrap( + direction: Axis.horizontal, + spacing: 3.h, + runSpacing: 4.h, + children: [ + AppCustomChipWidget( + labelText: "${isLoading ? "Cardiologist" : doctorsListResponseModel.clinicName}", + ).toShimmer2(isShow: isLoading), + AppCustomChipWidget( + labelText: "${isLoading ? "Olaya Hospital" : doctorsListResponseModel.projectName}", + ).toShimmer2(isShow: isLoading), + bookAppointmentsViewModel.isNearestAppointmentSelected + ? doctorsListResponseModel.nearestFreeSlot != null + ? AppCustomChipWidget( + labelText: (isLoading ? "Cardiologist" : DateUtil.getDateStringForNearestSlot(doctorsListResponseModel.nearestFreeSlot)), + backgroundColor: AppColors.successColor, + textColor: AppColors.whiteColor, + ).toShimmer2(isShow: isLoading) + : SizedBox.shrink() + : SizedBox.shrink(), + ], + ), ], ), ), @@ -131,28 +154,6 @@ class DoctorCard extends StatelessWidget { ), ], ), - Wrap( - direction: Axis.horizontal, - spacing: 3.h, - runSpacing: 4.h, - children: [ - AppCustomChipWidget( - labelText: "${isLoading ? "Cardiologist" : doctorsListResponseModel.clinicName}", - ).toShimmer2(isShow: isLoading), - AppCustomChipWidget( - labelText: "${isLoading ? "Olaya Hospital" : doctorsListResponseModel.projectName}", - ).toShimmer2(isShow: isLoading), - bookAppointmentsViewModel.isNearestAppointmentSelected - ? doctorsListResponseModel.nearestFreeSlot != null - ? AppCustomChipWidget( - labelText: (isLoading ? "Cardiologist" : DateUtil.getDateStringForNearestSlot(doctorsListResponseModel.nearestFreeSlot)), - backgroundColor: AppColors.successColor, - textColor: AppColors.whiteColor, - ).toShimmer2(isShow: isLoading) - : SizedBox.shrink() - : SizedBox.shrink(), - ], - ), SizedBox(height: 12.h), CustomButton( text: LocaleKeys.bookAppo.tr(context: context), diff --git a/lib/presentation/book_appointment/widgets/doctor_rating_details.dart b/lib/presentation/book_appointment/widgets/doctor_rating_details.dart new file mode 100644 index 0000000..0ed5486 --- /dev/null +++ b/lib/presentation/book_appointment/widgets/doctor_rating_details.dart @@ -0,0 +1,195 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_rating_bar/flutter_rating_bar.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/features/book_appointments/book_appointments_view_model.dart'; +import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; +import 'package:hmg_patient_app_new/theme/colors.dart'; +import 'package:provider/provider.dart'; + +class DoctorRatingDetails extends StatelessWidget { + const DoctorRatingDetails({super.key}); + + @override + Widget build(BuildContext context) { + return Consumer(builder: (context, bookAppointmentsVM, child) { + return bookAppointmentsVM.isDoctorRatingDetailsLoading + ? Utils.getLoadingWidget() + : Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + bookAppointmentsVM.doctorsProfileResponseModel.actualDoctorRate!.ceilToDouble().toString().toText44(isBold: true), + SizedBox(height: 4.h), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + "${bookAppointmentsVM.doctorsProfileResponseModel.noOfPatientsRate} ${LocaleKeys.reviews.tr(context: context)}" + .toText16(weight: FontWeight.w500, color: AppColors.greyInfoTextColor), + RatingBar( + initialRating: bookAppointmentsVM.doctorsProfileResponseModel.actualDoctorRate!.toDouble(), + direction: Axis.horizontal, + allowHalfRating: true, + itemCount: 5, + itemSize: 20.h, + ignoreGestures: true, + ratingWidget: RatingWidget( + full: Icon( + Icons.star, + color: AppColors.ratingColorYellow, + size: 24.h, + ), + half: Icon( + Icons.star_half, + color: AppColors.ratingColorYellow, + ), + empty: Icon( + Icons.star, + color: AppColors.ratingColorYellow, + ), + ), + tapOnlyMode: true, + unratedColor: Colors.grey[500], + itemPadding: EdgeInsets.symmetric(horizontal: 4.0), + onRatingUpdate: (rating) { + print(rating); + }, + ), + ], + ), + SizedBox(height: 8.h), + Container( + margin: EdgeInsets.only(top: 10.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Container( + width: 100.0, + margin: EdgeInsets.only(top: 10.0, left: 15.0, right: 15.0), + child: Text(LocaleKeys.excellent.tr(context: context), style: TextStyle(fontSize: 13.0, color: Colors.black, fontWeight: FontWeight.w600))), + getRatingLine(bookAppointmentsVM.doctorDetailsList[0].ratio, Colors.green[700]!), + ], + ), + Container( + margin: EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0), + child: Text("${getRatingWidth(bookAppointmentsVM.doctorDetailsList[0].ratio).round()}%", style: TextStyle(fontSize: 14.0, color: Colors.black, fontWeight: FontWeight.w600)), + ), + ], + ), + ), + Container( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Container( + width: 100.0, + margin: EdgeInsets.only(top: 10.0, left: 15.0, right: 15.0), + child: Text(LocaleKeys.vGood.tr(context: context), style: TextStyle(fontSize: 13.0, color: Colors.black, fontWeight: FontWeight.w600))), + getRatingLine(bookAppointmentsVM.doctorDetailsList[1].ratio, Color(0xffB7B723)), + ], + ), + Container( + margin: EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0), + child: Text("${bookAppointmentsVM.doctorDetailsList[1].ratio.round()}%", style: TextStyle(fontSize: 14.0, color: Colors.black, fontWeight: FontWeight.w600)), + ), + ], + ), + ), + Container( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Container( + width: 100.0, + margin: EdgeInsets.only(top: 10.0, left: 15.0, right: 15.0), + child: Text(LocaleKeys.good.tr(context: context), style: TextStyle(fontSize: 13.0, color: Colors.black, fontWeight: FontWeight.w600))), + getRatingLine(bookAppointmentsVM.doctorDetailsList[2].ratio, Color(0xffEBA727)), + ], + ), + Container( + margin: EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0), + child: Text("${bookAppointmentsVM.doctorDetailsList[2].ratio.round()}%", style: TextStyle(fontSize: 14.0, color: Colors.black, fontWeight: FontWeight.w600)), + ), + ], + ), + ), + Container( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Container( + width: 100.0, + margin: EdgeInsets.only(top: 10.0, left: 15.0, right: 15.0), + child: Text(LocaleKeys.average.tr(context: context), style: TextStyle(fontSize: 13.0, color: Colors.black, fontWeight: FontWeight.w600))), + getRatingLine(bookAppointmentsVM.doctorDetailsList[3].ratio, Color(0xffEB7227)), + ], + ), + Container( + margin: EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0), + child: Text("${bookAppointmentsVM.doctorDetailsList[3].ratio.round()}%", style: TextStyle(fontSize: 14.0, color: Colors.black, fontWeight: FontWeight.w600)), + ), + ], + ), + ), + Container( + margin: EdgeInsets.only(bottom: 30.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Container( + width: 100.0, + margin: EdgeInsets.only(top: 10.0, left: 15.0, right: 15.0), + child: Text(LocaleKeys.average.tr(context: context), style: TextStyle(fontSize: 13.0, color: Colors.black, fontWeight: FontWeight.w600))), + getRatingLine(bookAppointmentsVM.doctorDetailsList[4].ratio, Color(0xffE20C0C)), + ], + ), + Container( + margin: EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0), + child: Text("${bookAppointmentsVM.doctorDetailsList[4].ratio.round()}%", style: TextStyle(fontSize: 14.0, color: Colors.black, fontWeight: FontWeight.w600)), + ), + ], + ), + ), + ], + ); + }); + } + + double getRatingWidth(num patientNumber) { + var width = patientNumber; + return width.roundToDouble(); + } + + Widget getRatingLine(double patientNumber, Color color) { + return Container( + margin: EdgeInsets.only(top: 10.0), + child: Stack(children: [ + SizedBox( + width: 150.0, + height: 7.h, + child: Container( + color: Colors.grey[300], + ), + ), + SizedBox( + width: patientNumber * 1.55, + height: 7.h, + child: Container( + color: color, + ), + ), + ]), + ); + } +} diff --git a/lib/presentation/emergency_services/er_online_checkin/er_online_checkin_home.dart b/lib/presentation/emergency_services/er_online_checkin/er_online_checkin_home.dart index 3850c1f..999a43e 100644 --- a/lib/presentation/emergency_services/er_online_checkin/er_online_checkin_home.dart +++ b/lib/presentation/emergency_services/er_online_checkin/er_online_checkin_home.dart @@ -159,6 +159,15 @@ class ErOnlineCheckinHome extends StatelessWidget { await vm.getPatientERPaymentInformation(onSuccess: (response) { LoaderBottomSheet.hideLoader(); vm.navigateToEROnlineCheckInPaymentPage(); + }, onError: (err) { + LoaderBottomSheet.hideLoader(); + showCommonBottomSheetWithoutHeight( + context, + child: Utils.getErrorWidget(loadingText: err.toString()), + callBackFunc: () {}, + isFullScreen: false, + isCloseButtonVisible: true, + ); }); }, onHospitalSearch: (value) { diff --git a/lib/presentation/health_calculators_and_converts/health_calculators_page.dart b/lib/presentation/health_calculators_and_converts/health_calculators_page.dart index 95e9aec..aae25b0 100644 --- a/lib/presentation/health_calculators_and_converts/health_calculators_page.dart +++ b/lib/presentation/health_calculators_and_converts/health_calculators_page.dart @@ -204,7 +204,7 @@ class _HealthCalculatorsPageState extends State { crossAxisCount: 3, // 4 icons per row crossAxisSpacing: 16.w, mainAxisSpacing: 16.w, - childAspectRatio: 0.80), + childAspectRatio: 0.85), physics: NeverScrollableScrollPhysics(), shrinkWrap: true, itemCount: type == HealthCalculatorEnum.general ? generalHealthServices.length : womenHealthServices.length, @@ -214,6 +214,7 @@ class _HealthCalculatorsPageState extends State { icon: type == HealthCalculatorEnum.general ? generalHealthServices[index].icon : womenHealthServices[index].icon, labelText: type == HealthCalculatorEnum.general ? generalHealthServices[index].title : womenHealthServices[index].title, onTap: () { + Navigator.pop(context); Navigator.of(context).push( CustomPageRoute( page: HealthCalculatorDetailedPage( diff --git a/lib/presentation/medical_file/patient_sickleaves_list_page.dart b/lib/presentation/medical_file/patient_sickleaves_list_page.dart index fcdb12e..93cf17f 100644 --- a/lib/presentation/medical_file/patient_sickleaves_list_page.dart +++ b/lib/presentation/medical_file/patient_sickleaves_list_page.dart @@ -17,6 +17,7 @@ import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; +import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; import 'package:open_filex/open_filex.dart'; import 'package:provider/provider.dart'; @@ -197,49 +198,23 @@ class _PatientSickleavesListPageState extends State { ], ), SizedBox(height: 8.h), - Row( + Wrap( + direction: Axis.horizontal, + spacing: 6.h, + runSpacing: 6.h, children: [ - CustomButton( - text: DateUtil.formatDateToDate(DateUtil.convertStringToDate(sickLeave.appointmentDate), 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, + AppCustomChipWidget( + labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(sickLeave.appointmentDate), false), ), - SizedBox(width: 8.h), - CustomButton( - text: model.isSickLeavesSortByClinic ? sickLeave.projectName! : sickLeave.clinicName!, - 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, + AppCustomChipWidget( + labelText: model.isSickLeavesSortByClinic ? sickLeave.projectName! : sickLeave.clinicName!, ), - SizedBox(width: 8.h), - CustomButton( - text: "${sickLeave.sickLeaveDays} Days", - 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, + AppCustomChipWidget( + labelText: "${sickLeave.sickLeaveDays} Days", ), ], ), - SizedBox(height: 8.h), + SizedBox(height: 12.h), Row( children: [ Expanded( diff --git a/lib/presentation/monthly_report/monthly_report.dart b/lib/presentation/monthly_report/monthly_report.dart index 474863b..43c7fc1 100644 --- a/lib/presentation/monthly_report/monthly_report.dart +++ b/lib/presentation/monthly_report/monthly_report.dart @@ -80,7 +80,10 @@ class MonthlyReport extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ LocaleKeys.email.tr(context: context).toText12(color: AppColors.greyTextColor, fontWeight: FontWeight.w500), - "${appState.getAuthenticatedUser()!.emailAddress}".toText16(color: AppColors.textColor, weight: FontWeight.w500), + SizedBox( + width: MediaQuery.of(context).size.width * 0.7, + child: "${appState.getAuthenticatedUser()!.emailAddress}".toText16(color: AppColors.textColor, weight: FontWeight.w500, maxlines: 2), + ), ], ), ], diff --git a/lib/presentation/prescriptions/prescription_detail_page.dart b/lib/presentation/prescriptions/prescription_detail_page.dart index 9b1ae6d..796bfdd 100644 --- a/lib/presentation/prescriptions/prescription_detail_page.dart +++ b/lib/presentation/prescriptions/prescription_detail_page.dart @@ -148,7 +148,7 @@ class _PrescriptionDetailPageState extends State { text: LocaleKeys.downloadPrescription.tr(context: context), onPressed: () async { LoaderBottomSheet.showLoader(loadingText: LocaleKeys.fetchingPrescriptionPDFPleaseWait.tr(context: context)); - await prescriptionVM.getPrescriptionPDFBase64(widget.prescriptionsResponseModel).then((val) async { + await prescriptionVM.getPrescriptionPDFBase64(widget.prescriptionsResponseModel, onSuccess: (value) async { LoaderBottomSheet.hideLoader(); if (prescriptionVM.prescriptionPDFBase64Data.isNotEmpty) { String path = await Utils.createFileFromString(prescriptionVM.prescriptionPDFBase64Data, "pdf"); @@ -164,6 +164,15 @@ class _PrescriptionDetailPageState extends State { ); } } + }, onError: (err) { + LoaderBottomSheet.hideLoader(); + showCommonBottomSheetWithoutHeight( + context, + child: Utils.getErrorWidget(loadingText: err), + callBackFunc: () {}, + isFullScreen: false, + isCloseButtonVisible: true, + ); }); }, backgroundColor: AppColors.successColor.withValues(alpha: 0.15), diff --git a/lib/presentation/prescriptions/prescription_item_view.dart b/lib/presentation/prescriptions/prescription_item_view.dart index a2a3e7f..a41b53f 100644 --- a/lib/presentation/prescriptions/prescription_item_view.dart +++ b/lib/presentation/prescriptions/prescription_item_view.dart @@ -10,6 +10,7 @@ import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_view_mo import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; +import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart'; import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; @@ -56,74 +57,18 @@ class PrescriptionItemView extends StatelessWidget { spacing: 6.h, runSpacing: 6.h, children: [ - Row( - mainAxisSize: MainAxisSize.min, - children: [ - CustomButton( - text: "${LocaleKeys.route.tr(context: context)}: ${isLoading ? "" : prescriptionVM.prescriptionDetailsList[index].route}", - 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: 30.h, - ).toShimmer2(isShow: isLoading), - ], - ), - Row( - mainAxisSize: MainAxisSize.min, - children: [ - CustomButton( - text: "${LocaleKeys.frequency.tr(context: context)}: ${isLoading ? "" : prescriptionVM.prescriptionDetailsList[index].frequency}", - 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: 30.h, - ).toShimmer2(isShow: isLoading), - ], - ), - Row( - mainAxisSize: MainAxisSize.min, - children: [ - CustomButton( - text: "${LocaleKeys.dailyDoses.tr(context: context)}: ${isLoading ? "" : prescriptionVM.prescriptionDetailsList[index].doseDailyQuantity}", - 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: 30.h, - ).toShimmer2(isShow: isLoading), - ], - ), - Row( - mainAxisSize: MainAxisSize.min, - children: [ - CustomButton( - text: "${LocaleKeys.days.tr(context: context)}: ${isLoading ? "" : prescriptionVM.prescriptionDetailsList[index].days}", - 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: 30.h, - ).toShimmer2(isShow: isLoading), - ], - ), + AppCustomChipWidget( + labelText: "${LocaleKeys.route.tr(context: context)}: ${isLoading ? "" : prescriptionVM.prescriptionDetailsList[index].route}", + ).toShimmer2(isShow: isLoading), + AppCustomChipWidget( + labelText: "${LocaleKeys.frequency.tr(context: context)}: ${isLoading ? "" : prescriptionVM.prescriptionDetailsList[index].frequency}", + ).toShimmer2(isShow: isLoading), + AppCustomChipWidget( + labelText: "${LocaleKeys.dailyDoses.tr(context: context)}: ${isLoading ? "" : prescriptionVM.prescriptionDetailsList[index].doseDailyQuantity}", + ).toShimmer2(isShow: isLoading), + AppCustomChipWidget( + labelText: "${LocaleKeys.days.tr(context: context)}: ${isLoading ? "" : prescriptionVM.prescriptionDetailsList[index].days}", + ).toShimmer2(isShow: isLoading), ], ).paddingSymmetrical(16.h, 0.h), SizedBox(height: 8.h), diff --git a/lib/presentation/prescriptions/prescriptions_list_page.dart b/lib/presentation/prescriptions/prescriptions_list_page.dart index e2a862b..c2d97f8 100644 --- a/lib/presentation/prescriptions/prescriptions_list_page.dart +++ b/lib/presentation/prescriptions/prescriptions_list_page.dart @@ -19,6 +19,7 @@ import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/presentation/prescriptions/prescription_detail_page.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; +import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import 'package:provider/provider.dart'; @@ -207,32 +208,16 @@ class _PrescriptionsListPageState extends State { ], ), SizedBox(height: 8.h), - Row( + Wrap( + direction: Axis.horizontal, + spacing: 6.h, + runSpacing: 6.h, children: [ - CustomButton( - text: DateUtil.formatDateToDate(DateUtil.convertStringToDate(prescription.appointmentDate), 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, + AppCustomChipWidget( + labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(prescription.appointmentDate), false), ), - SizedBox(width: 8.h), - CustomButton( - text: model.isSortByClinic ? prescription.name! : prescription.clinicDescription!, - 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, + AppCustomChipWidget( + labelText: model.isSortByClinic ? prescription.name! : prescription.clinicDescription!, ), ], ), diff --git a/lib/presentation/todo_section/ancillary_procedures_details_page.dart b/lib/presentation/todo_section/ancillary_procedures_details_page.dart index 9e97509..eba80cd 100644 --- a/lib/presentation/todo_section/ancillary_procedures_details_page.dart +++ b/lib/presentation/todo_section/ancillary_procedures_details_page.dart @@ -658,6 +658,7 @@ class _AncillaryOrderDetailsListState extends State { text: LocaleKeys.proceedToPayment.tr(context: context), onPressed: () { // Navigate to payment page with selected procedures + todoSectionViewModel.setIsAncillaryOrdersNeedReloading(true); Navigator.of(context).push( CustomPageRoute( page: AncillaryOrderPaymentPage( diff --git a/lib/presentation/todo_section/widgets/ancillary_orders_list.dart b/lib/presentation/todo_section/widgets/ancillary_orders_list.dart index 05eb6c7..58ee6d4 100644 --- a/lib/presentation/todo_section/widgets/ancillary_orders_list.dart +++ b/lib/presentation/todo_section/widgets/ancillary_orders_list.dart @@ -71,19 +71,12 @@ class AncillaryOrdersList extends StatelessWidget { return Center( child: Padding( padding: EdgeInsets.symmetric(vertical: 40.h), - child: Container( - decoration: RoundedRectangleBorder().toSmoothCornerDecoration( - color: AppColors.whiteColor, - borderRadius: 12.r, - hasShadow: false, - ), - child: Utils.getNoDataWidget( - context, - noDataText: LocaleKeys.youDontHaveAnyAncillaryOrdersYet.tr(context: context), - isSmallWidget: true, - width: 62.w, - height: 62.h, - ), + child: Utils.getNoDataWidget( + context, + noDataText: LocaleKeys.youDontHaveAnyAncillaryOrdersYet.tr(context: context), + isSmallWidget: true, + width: 62.w, + height: 62.h, ), ), );