From 287dcf3482f95aab42e98a3fe32481bc27139f72 Mon Sep 17 00:00:00 2001 From: Sultan khan Date: Wed, 8 Apr 2026 10:05:25 +0300 Subject: [PATCH 1/8] updates --- android/app/build.gradle.kts | 2 +- .../rate_appointment/rate_appointment_doctor.dart | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index 347ab714..81543587 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -34,7 +34,7 @@ android { defaultConfig { applicationId = "com.cloudsolutions.HMGPatientApp" // minSdk = 24 - minSdk = 26 + minSdk = 29 targetSdk = 35 compileSdk = 36 // targetSdk = flutter.targetSdkVersion diff --git a/lib/presentation/rate_appointment/rate_appointment_doctor.dart b/lib/presentation/rate_appointment/rate_appointment_doctor.dart index b9a6c587..02457347 100644 --- a/lib/presentation/rate_appointment/rate_appointment_doctor.dart +++ b/lib/presentation/rate_appointment/rate_appointment_doctor.dart @@ -143,12 +143,7 @@ class _RateAppointmentDoctorState extends State { maxLines: 4, decoration: InputDecoration.collapsed( hintText: LocaleKeys.notes.tr(context: context), - hintStyle: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Color(0xff2B353E), - letterSpacing: -0.64, - height: 23 / 16)), + ), onChanged: (value) { setState(() { note = value; From 53184379415a1b456e69f394a2a64f877fafdd71 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Wed, 8 Apr 2026 10:10:27 +0300 Subject: [PATCH 2/8] updates --- lib/presentation/appointments/appointment_details_page.dart | 4 ++-- lib/presentation/my_invoices/my_invoices_details_page.dart | 4 ++-- .../symptoms_checker/widgets/selected_organs_section.dart | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/presentation/appointments/appointment_details_page.dart b/lib/presentation/appointments/appointment_details_page.dart index 10f616e8..0ba38bd9 100644 --- a/lib/presentation/appointments/appointment_details_page.dart +++ b/lib/presentation/appointments/appointment_details_page.dart @@ -393,8 +393,8 @@ class _AppointmentDetailsPageState extends State { ), const Spacer(), Switch( - // activeThumbColor: AppColors.successColor, - activeTrackColor: AppColors.successColor.withValues(alpha: .15), + activeThumbColor: AppColors.successColor, + // activeTrackColor: AppColors.successColor.withValues(alpha: .15), value: widget.patientAppointmentHistoryResponseModel.hasReminder!, onChanged: (newValue) async { CalenderUtilsNew calender = CalenderUtilsNew.instance; diff --git a/lib/presentation/my_invoices/my_invoices_details_page.dart b/lib/presentation/my_invoices/my_invoices_details_page.dart index 62e5a336..b8f534ac 100644 --- a/lib/presentation/my_invoices/my_invoices_details_page.dart +++ b/lib/presentation/my_invoices/my_invoices_details_page.dart @@ -185,7 +185,7 @@ class _MyInvoicesDetailsPageState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - (getIt().isArabic() ? widget.getInvoiceDetailsResponseModel.doctorNameN ?? LocaleKeys.doctor.tr(context: context) : widget.getInvoiceDetailsResponseModel.doctorName!).toText16(isBold: true), + (getIt().isArabic() ? widget.getInvoiceDetailsResponseModel.doctorName ?? LocaleKeys.doctor.tr(context: context) : widget.getInvoiceDetailsResponseModel.doctorName!).toText16(isBold: true), SizedBox(height: 8.h), Wrap( direction: Axis.horizontal, @@ -199,7 +199,7 @@ class _MyInvoicesDetailsPageState extends State { ), AppCustomChipWidget( labelText: ((getIt().isArabic() ? widget.getInvoiceDetailsResponseModel.clinicDescriptionN : widget.getInvoiceDetailsResponseModel.clinicDescription ?? "")!.length > 15 - ? '${widget.getInvoiceDetailsResponseModel.clinicDescription!.substring(0, 12)}...' + ? '${(getIt().isArabic() ? widget.getInvoiceDetailsResponseModel.clinicDescriptionN : widget.getInvoiceDetailsResponseModel.clinicDescription ?? "")!.substring(0, 12)}...' : getIt().isArabic() ? widget.getInvoiceDetailsResponseModel.clinicDescriptionN : widget.getInvoiceDetailsResponseModel.clinicDescription ?? ""), labelPadding: EdgeInsetsDirectional.only(start: 4.w, end: 4.w), ), diff --git a/lib/presentation/symptoms_checker/widgets/selected_organs_section.dart b/lib/presentation/symptoms_checker/widgets/selected_organs_section.dart index 13688e0d..b66ef037 100644 --- a/lib/presentation/symptoms_checker/widgets/selected_organs_section.dart +++ b/lib/presentation/symptoms_checker/widgets/selected_organs_section.dart @@ -57,7 +57,7 @@ class _SelectedOrgansSectionState extends State { LocaleKeys.selectedOrgans.tr(context: context), style: TextStyle( fontSize: 16.f, - isBold: true, + fontWeight: FontWeight.w600, color: AppColors.textColor, ), ), @@ -78,7 +78,7 @@ class _SelectedOrgansSectionState extends State { style: TextStyle( color: AppColors.whiteColor, fontSize: 12.f, - isBold: true, + fontWeight: FontWeight.w600, ), ), ), From 572c37785b4e6a3f4fdf9b3fd480b4146115c881 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Wed, 8 Apr 2026 13:46:22 +0300 Subject: [PATCH 3/8] updates --- assets/animations/lottie/HourGlass.json | 1 + assets/langs/ar-SA.json | 5 +- assets/langs/en-US.json | 3 +- lib/core/app_assets.dart | 2 + .../book_appointments_view_model.dart | 14 +- .../emergency_services_view_model.dart | 2 +- lib/generated/locale_keys.g.dart | 1 + lib/main.dart | 2 + .../widgets/appointment_card.dart | 150 ++++++++++++++---- .../immediate_livecare_payment_details.dart | 16 +- .../immediate_livecare_payment_page.dart | 10 +- ...mediate_livecare_pending_request_page.dart | 22 ++- .../book_appointment/select_clinic_page.dart | 3 +- .../habib_wallet/habib_wallet_page.dart | 16 +- lib/presentation/home/landing_page.dart | 95 +++++++---- .../home/widgets/habib_wallet_card.dart | 123 +++++++------- lib/theme/app_theme.dart | 5 +- lib/widgets/countdown_timer.dart | 2 +- lib/widgets/map/gms_map.dart | 2 +- .../lib/src/custom_layout.dart | 68 ++------ 20 files changed, 338 insertions(+), 204 deletions(-) create mode 100644 assets/animations/lottie/HourGlass.json diff --git a/assets/animations/lottie/HourGlass.json b/assets/animations/lottie/HourGlass.json new file mode 100644 index 00000000..d0c87fd3 --- /dev/null +++ b/assets/animations/lottie/HourGlass.json @@ -0,0 +1 @@ +{"nm":"Hourglass","h":500,"w":500,"meta":{"g":"LottieFiles AE 1.1.0"},"layers":[{"ty":4,"nm":"Side 2 Matte","sr":1,"st":-25,"op":76,"ip":0,"hasMask":false,"td":1,"ao":0,"ks":{"a":{"a":0,"k":[-6552.114,-5982.041,0]},"s":{"a":0,"k":[100,100,100]},"sk":{"a":0,"k":0},"p":{"a":0,"k":[-6552,-6594.232,0]},"r":{"a":0,"k":0},"sa":{"a":0,"k":0},"o":{"a":0,"k":100}},"ef":[],"shapes":[{"ty":"gr","nm":"Group 1","it":[{"ty":"sh","nm":"Path 1","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[-2.437,0],[0,0]],"o":[[0,0],[0,0],[0,0],[2.437,0],[0,0]],"v":[[-6469.931,-6116.998],[-6634.298,-6117.35],[-6555.846,-5981.885],[-6552.176,-5979.025],[-6548.382,-5982.198]]}}},{"ty":"fl","nm":"Fill 1","c":{"a":0,"k":[0.18,0.188,0.224]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"sk":{"a":0,"k":0},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"sa":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"ind":1,"parent":7},{"ty":4,"nm":"Sand 2","sr":1,"st":-25,"op":76,"ip":0,"tt":1,"hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]},"sk":{"a":0,"k":0},"p":{"a":0,"k":[-6552.114,-5982.041,0]},"r":{"a":0,"k":0},"sa":{"a":0,"k":0},"o":{"a":0,"k":100}},"ef":[],"shapes":[{"ty":"gr","nm":"Shape 1","it":[{"ty":"sh","nm":"Path 1","d":1,"ks":{"a":1,"k":[{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[{"c":true,"i":[[0.486,0.846],[0.625,-1.344],[-0.28,-0.728],[0.057,-0.656],[-0.144,-3.463],[0,0],[-0.063,3.469],[-0.062,1.125],[-0.268,0.626]],"o":[[-0.844,-1.469],[-0.34,0.73],[0.235,0.612],[-0.125,1.438],[0.144,3.463],[0,0],[0.063,-3.469],[0.026,-0.477],[0.364,-0.851]],"v":[[1.781,1.656],[-1.906,1.969],[-1.715,4.139],[-1.281,6.031],[-3.988,12.194],[-1.25,23],[5.062,8.062],[1,5.969],[1.59,4.283]]}],"t":0},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[{"c":true,"i":[[0,0],[0,0],[2.534,0.174],[-4.393,-4.956],[4.426,-20.319],[0,0],[4.269,23.889],[-9.5,9],[-0.283,0.932]],"o":[[0,0],[0,0],[-2.13,-0.147],[9.75,11],[-4.333,19.892],[0,0],[-5.875,-32.875],[3.487,-3.304],[0.384,-1.268]],"v":[[14,-138.75],[-3.5,-136.5],[-10.497,-138.771],[-9,-132.75],[-3.676,2.319],[-1.25,23],[3.375,1.375],[10,-131.75],[15.02,-137.747]]}],"t":9},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[{"c":true,"i":[[0,0],[0,0],[-20.182,-2.387],[-4.393,-4.956],[4.426,-20.319],[0,0],[4.269,23.889],[-9.5,9],[-15.597,1.657]],"o":[[0,0],[0,0],[16.964,2.006],[9.75,11],[-4.333,19.892],[0,0],[-5.875,-32.875],[3.487,-3.304],[21.209,-2.253]],"v":[[91.5,-136],[-89.75,-137.5],[-49.161,-134.405],[-11,-124.25],[-3.676,2.319],[-1.25,23],[3.375,1.375],[13.5,-125.5],[47.123,-132.85]]}],"t":25},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[{"c":true,"i":[[0,0],[0,0],[-21.104,-9.934],[-6.5,-8],[0,-21.193],[0,0],[0,24.267],[-7.401,10.793],[-19.85,6.269]],"o":[[0,0],[0,0],[21.691,10.211],[9.269,11.408],[0,20.359],[0,0],[0,-31.5],[6,-8.75],[22.388,-7.071]],"v":[[91.5,-136],[-89.75,-137.5],[-72.691,-114.461],[-9.25,-108.5],[-3.301,0.194],[-1.25,23],[2.75,-0.25],[13,-106.75],[64.35,-110.519]]}],"t":36},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[{"c":true,"i":[[0,0],[0,0],[-22.88,-4.534],[-1.313,-0.25],[-1.613,-0.182],[-1.375,-0.062],[-1.75,0.062],[-1.937,0.188],[-19.225,4.769]],"o":[[0,0],[0,0],[14.941,2.961],[1.312,0.25],[1.613,0.182],[1.375,0.062],[1.75,-0.062],[1.937,-0.188],[22.788,-5.653]],"v":[[91.5,-136],[-89.75,-137.5],[-64.441,-101.961],[-11.188,-97],[-4.863,-96.557],[-0.75,-96.5],[3.75,-96.5],[10.188,-96.625],[64.1,-102.019]]}],"t":50},{"s":[{"c":true,"i":[[14.5,-2],[25,7],[-12.809,-15.539],[-1.313,-0.25],[-1.613,-0.182],[-1.375,-0.062],[-1.75,0.062],[-1.937,0.188],[-6.715,12.881]],"o":[[-18.589,2.564],[-23.131,-6.477],[9.688,11.753],[1.312,0.25],[1.613,0.182],[1.375,0.062],[1.75,-0.062],[1.937,-0.188],[3.9,-7.481]],"v":[[38.5,-89],[-32.75,-76.5],[-45.191,-56.711],[-10.188,-2.5],[-4.613,0.193],[-0.25,0.5],[3.25,0.25],[9.938,-0.875],[57.6,-77.519]]}],"t":75}]}},{"ty":"st","nm":"Stroke 1","lc":1,"lj":1,"ml":4,"o":{"a":0,"k":100},"w":{"a":0,"k":0},"c":{"a":0,"k":[0,0.58,0.616]}},{"ty":"fl","nm":"Fill 1","c":{"a":0,"k":[0.18,0.188,0.224]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"sk":{"a":0,"k":0},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"sa":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"ind":2,"parent":1},{"ty":4,"nm":"Side 1 Matte","sr":1,"st":-25,"op":76,"ip":0,"hasMask":false,"td":1,"ao":0,"ks":{"a":{"a":0,"k":[-6552.114,-5982.041,0]},"s":{"a":0,"k":[100,100,100]},"sk":{"a":0,"k":0},"p":{"a":0,"k":[250,250,0]},"r":{"a":0,"k":0},"sa":{"a":0,"k":0},"o":{"a":0,"k":100}},"ef":[],"shapes":[{"ty":"gr","nm":"Group 1","it":[{"ty":"sh","nm":"Path 1","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[-0.99,-0.125],[0,0]],"o":[[0,0],[0,0],[0,0],[0.99,0.125],[0,0]],"v":[[-6469.931,-6116.998],[-6634.298,-6117.35],[-6555.846,-5981.885],[-6552.229,-5980.042],[-6548.382,-5982.198]]}}},{"ty":"fl","nm":"Fill 1","c":{"a":0,"k":[0.18,0.188,0.224]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"sk":{"a":0,"k":0},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"sa":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"ind":3},{"ty":4,"nm":"Sand 1","sr":1,"st":-25,"op":76,"ip":0,"tt":1,"hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]},"sk":{"a":0,"k":0},"p":{"a":1,"k":[{"o":{"x":0.167,"y":0.167},"i":{"x":0.4,"y":1},"s":[250,250,0],"t":0,"ti":[0,0,0],"to":[0,0,0]},{"s":[250,331,0],"t":50}]},"r":{"a":0,"k":0},"sa":{"a":0,"k":0},"o":{"a":0,"k":100}},"ef":[],"shapes":[{"ty":"gr","nm":"Shape 1","it":[{"ty":"sh","nm":"Path 1","d":1,"ks":{"a":1,"k":[{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[{"c":true,"i":[[14.5,-2],[9.627,-3.183],[8.064,-1.099],[7.079,1.982],[-12.809,-15.539],[-1.156,-1.094],[-0.582,-0.244],[-0.656,0],[-0.719,0.281],[-1.219,1.562],[-6.715,12.881]],"o":[[-7.462,1.029],[-7.564,2.501],[-7.239,0.986],[-23.131,-6.477],[9.688,11.753],[1.156,1.094],[0.582,0.244],[0.656,0],[0.719,-0.281],[1.219,-1.562],[3.9,-7.481]],"v":[[38.5,-89],[12.486,-81.442],[-11.141,-75.441],[-32.75,-76.5],[-45.191,-56.711],[-10.188,-2.5],[-3.019,2.287],[0.094,2.719],[2.75,2.344],[9.938,-0.875],[57.6,-77.519]]}],"t":0},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[{"c":true,"i":[[14.5,-2],[2.585,2.626],[5.445,-3.528],[6.397,1.791],[-12.809,-15.539],[-1.156,-1.094],[-0.582,-0.244],[-0.656,0],[-0.719,0.281],[-1.219,1.562],[-6.715,12.881]],"o":[[-8.027,1.107],[-5.58,-5.669],[-5.652,3.663],[-23.131,-6.477],[9.688,11.753],[1.156,1.094],[0.582,0.244],[0.656,0],[0.719,-0.281],[1.219,-1.562],[3.9,-7.481]],"v":[[38.5,-89],[8.79,-71.474],[-8.07,-72.57],[-32.75,-76.5],[-45.191,-56.711],[-10.188,-2.5],[-3.019,2.287],[0.094,2.719],[2.75,2.344],[9.938,-0.875],[57.6,-77.519]]}],"t":39},{"s":[{"c":true,"i":[[14.5,-2],[9.627,-3.183],[8.064,-1.099],[7.079,1.982],[-12.809,-15.539],[-1.156,-1.094],[-0.582,-0.244],[-0.656,0],[-0.719,0.281],[-1.219,1.562],[-6.715,12.881]],"o":[[-7.462,1.029],[-7.564,2.501],[-7.239,0.986],[-23.131,-6.477],[9.688,11.753],[1.156,1.094],[0.582,0.244],[0.656,0],[0.719,-0.281],[1.219,-1.562],[3.9,-7.481]],"v":[[38.5,-89],[12.486,-81.442],[-11.141,-75.441],[-32.75,-76.5],[-45.191,-56.711],[-10.188,-2.5],[-3.019,2.287],[0.094,2.719],[2.75,2.344],[9.938,-0.875],[57.6,-77.519]]}],"t":45}]}},{"ty":"st","nm":"Stroke 1","lc":1,"lj":1,"ml":4,"o":{"a":0,"k":100},"w":{"a":0,"k":0},"c":{"a":0,"k":[0,0.58,0.616]}},{"ty":"fl","nm":"Fill 1","c":{"a":0,"k":[0.18,0.188,0.224]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"sk":{"a":0,"k":0},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"sa":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"ind":4},{"ty":4,"nm":"Shadow Matte","sr":1,"st":-25,"op":76,"ip":0,"hasMask":false,"td":1,"ao":0,"ks":{"a":{"a":0,"k":[-6552,-6594.232,0]},"s":{"a":0,"k":[100,100,100]},"sk":{"a":0,"k":0},"p":{"a":0,"k":[-6552,-6594.232,0]},"r":{"a":0,"k":0},"sa":{"a":0,"k":0},"o":{"a":0,"k":100}},"ef":[],"shapes":[{"ty":"gr","nm":"Group 3","it":[{"ty":"sh","nm":"Path 1","d":1,"ks":{"a":0,"k":{"c":true,"i":[[8.207,0],[0,0],[-1.738,-7.444],[-0.605,-1.021],[0,0],[-0.214,-1.589],[0.143,-1.057],[0.823,-1.388],[0,0],[0.269,-1.149],[-8.207,0],[0,0],[1.738,7.444],[0.605,1.021],[0,0],[0.214,1.589],[-0.143,1.057],[-0.823,1.388],[0,0],[-0.269,1.149]],"o":[[0,0],[-8.207,0],[0.269,1.149],[0,0],[0.823,1.388],[0.143,1.057],[-0.214,1.589],[0,0],[-0.605,1.021],[-1.738,7.444],[0,0],[8.207,0],[-0.269,-1.149],[0,0],[-0.823,-1.388],[-0.143,-1.057],[0.214,-1.589],[0,0],[0.605,-1.021],[1.738,-7.444]],"v":[[-6458.712,-6744.95],[-6645.288,-6744.95],[-6657.545,-6730.055],[-6656.154,-6726.804],[-6581.067,-6600.158],[-6579.392,-6595.673],[-6579.392,-6592.49],[-6581.067,-6588.004],[-6656.154,-6461.358],[-6657.545,-6458.107],[-6645.288,-6443.213],[-6458.712,-6443.213],[-6446.455,-6458.107],[-6447.846,-6461.358],[-6522.933,-6588.004],[-6524.608,-6592.49],[-6524.608,-6595.673],[-6522.933,-6600.158],[-6447.846,-6726.804],[-6446.455,-6730.055]]}}},{"ty":"fl","nm":"Fill 1","c":{"a":0,"k":[1,1,1]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"sk":{"a":0,"k":0},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"sa":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"ind":5,"parent":7},{"ty":4,"nm":"Shadow","sr":1,"st":-25,"op":76,"ip":0,"tt":1,"hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]},"sk":{"a":0,"k":0},"p":{"a":0,"k":[250,250,0]},"r":{"a":0,"k":0},"sa":{"a":0,"k":0},"o":{"a":0,"k":10}},"ef":[],"shapes":[{"ty":"gr","nm":"Shape 1","it":[{"ty":"sh","nm":"Path 1","d":1,"ks":{"a":1,"k":[{"o":{"x":0.6,"y":0},"i":{"x":0.833,"y":0.833},"s":[{"c":true,"i":[[0,0],[49.135,-3.183],[-13.025,-0.599],[-29.109,-5.019],[13.5,-22],[-0.77,-28.49],[29.438,-20.455],[28.507,-1.289],[-25.5,-5.5],[0,0]],"o":[[0,0],[-12.896,0.835],[43.5,2],[29,5],[-13.5,22],[1,37],[-21.22,14.745],[-24.059,1.087],[25.5,5.5],[0,0]],"v":[[229.5,-239],[-92.882,-163.672],[-71.5,-153],[41,-141.5],[66.5,-106],[13,1],[57,123],[-37.5,133.501],[-42.5,152],[238,239.5]]}],"t":50},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[{"c":true,"i":[[0,0],[48.989,-4.946],[-18.192,-25.462],[-22.077,-19.192],[7.048,-23.757],[2.816,-27.802],[1.115,-25.846],[53.077,0.154],[-25.5,-5.5],[0,0]],"o":[[0,0],[-46.272,4.672],[18.192,25.462],[22.077,19.192],[-7.039,24.308],[-3.749,36.459],[-1.115,25.846],[-53.077,-0.154],[25.5,5.5],[0,0]],"v":[[237.269,-237.077],[115.272,-238.672],[25.808,-162.462],[78.923,-108.192],[124.885,-41.538],[37.692,15.808],[61.615,97.154],[1.577,168.654],[-49.038,228.923],[241.615,239.193]]}],"t":57},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[{"c":true,"i":[[0,0],[49.135,-3.183],[-39.5,-8],[-27.395,11.046],[-3.726,-32.793],[13,-36],[36,18],[28.507,-1.289],[-25.5,-5.5],[0,0]],"o":[[0,0],[-12.896,0.835],[39.5,8],[31,-12.5],[2.5,22],[-11.892,32.933],[-23.112,-11.556],[-24.059,1.088],[25.5,5.5],[0,0]],"v":[[220.5,-166.5],[-18.882,-189.672],[10.5,-128.5],[117,-126],[138.5,-50],[130,54],[81,152],[-12.5,143],[-12,233],[217,157]]}],"t":63},{"o":{"x":0.167,"y":0.167},"i":{"x":0.4,"y":1},"s":[{"c":true,"i":[[0,0],[49.135,-3.183],[-16.242,-32.949],[-16.167,-13.833],[-28.167,-13.5],[-3.833,-25.667],[28.167,-23.833],[28.337,-16.478],[-25.5,-5.5],[0,0]],"o":[[0,0],[-12.896,0.835],[23.333,47.333],[16.167,13.833],[28.167,13.5],[4.387,24.133],[-28.167,23.833],[-20.032,9.541],[25.5,5.5],[0,0]],"v":[[222.833,-223.333],[-65.548,-175.506],[-15.333,-124.333],[29.833,-53.833],[75.833,-31.5],[138.167,21.833],[78.167,128.167],[2.667,206.334],[-43.833,233.5],[235.333,241.5]]}],"t":68},{"s":[{"c":true,"i":[[0,0],[49.135,-3.183],[-13.025,-0.599],[-29.109,-5.019],[13.5,-22],[-0.77,-28.49],[29.438,-20.455],[28.507,-1.289],[-25.5,-5.5],[0,0]],"o":[[0,0],[-12.896,0.835],[43.5,2],[29,5],[-13.5,22],[1,37],[-21.22,14.745],[-24.059,1.087],[25.5,5.5],[0,0]],"v":[[229.5,-239],[-92.882,-163.672],[-71.5,-153],[41,-141.5],[66.5,-106],[13,1],[57,123],[-37.5,133.501],[-42.5,152],[238,239.5]]}],"t":75}]}},{"ty":"st","nm":"Stroke 1","lc":1,"lj":1,"ml":4,"o":{"a":0,"k":100},"w":{"a":0,"k":0},"c":{"a":0,"k":[0,0.58,0.616]}},{"ty":"fl","nm":"Fill 1","c":{"a":0,"k":[0.18,0.188,0.224]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"sk":{"a":0,"k":0},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"sa":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"ind":6},{"ty":4,"nm":"Main Hourglass","sr":1,"st":-25,"op":76,"ip":0,"hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[-6552,-6594.232,0]},"s":{"a":0,"k":[100,100,100]},"sk":{"a":0,"k":0},"p":{"a":0,"k":[250,250,0]},"r":{"a":1,"k":[{"o":{"x":0.6,"y":0},"i":{"x":0.4,"y":1},"s":[0],"t":-25},{"o":{"x":0.6,"y":0},"i":{"x":0.4,"y":1},"s":[180],"t":0},{"o":{"x":0.6,"y":0},"i":{"x":0.4,"y":1},"s":[180],"t":50},{"s":[360],"t":75}]},"sa":{"a":0,"k":0},"o":{"a":0,"k":100}},"ef":[],"shapes":[{"ty":"gr","nm":"Group 1","it":[{"ty":"sh","nm":"Path 1","d":1,"ks":{"a":0,"k":{"c":true,"i":[[3.931,0],[0,0],[0,3.931],[0,0],[-3.931,0],[0,0],[0,-3.931],[0,0]],"o":[[0,0],[-3.931,0],[0,0],[0,-3.931],[0,0],[3.931,0],[0,0],[0,3.931]],"v":[[-6436.617,-6754.998],[-6667.383,-6754.998],[-6674.5,-6762.115],[-6674.5,-6762.115],[-6667.383,-6769.232],[-6436.617,-6769.232],[-6429.5,-6762.115],[-6429.5,-6762.115]]}}},{"ty":"fl","nm":"Fill 1","c":{"a":0,"k":[0.18,0.188,0.224]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"sk":{"a":0,"k":0},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"sa":{"a":0,"k":0},"o":{"a":0,"k":100}}]},{"ty":"gr","nm":"Group 2","it":[{"ty":"sh","nm":"Path 1","d":1,"ks":{"a":0,"k":{"c":true,"i":[[3.931,0],[0,0],[0,3.931],[0,0],[-3.931,0],[0,0],[0,-3.931],[0,0]],"o":[[0,0],[-3.931,0],[0,0],[0,-3.931],[0,0],[3.931,0],[0,0],[0,3.931]],"v":[[-6436.617,-6419.232],[-6667.383,-6419.232],[-6674.5,-6426.35],[-6674.5,-6426.35],[-6667.383,-6433.467],[-6436.617,-6433.467],[-6429.5,-6426.35],[-6429.5,-6426.35]]}}},{"ty":"fl","nm":"Fill 1","c":{"a":0,"k":[0.18,0.188,0.224]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"sk":{"a":0,"k":0},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"sa":{"a":0,"k":0},"o":{"a":0,"k":100}}]},{"ty":"gr","nm":"Group 3","it":[{"ty":"sh","nm":"Path 1","d":1,"ks":{"a":0,"k":{"c":true,"i":[[8.207,0],[0,0],[-1.738,-7.444],[-0.605,-1.021],[0,0],[-0.214,-1.589],[0.143,-1.057],[0.823,-1.388],[0,0],[0.269,-1.149],[-8.207,0],[0,0],[1.738,7.444],[0.605,1.021],[0,0],[0.214,1.589],[-0.143,1.057],[-0.823,1.388],[0,0],[-0.269,1.149]],"o":[[0,0],[-8.207,0],[0.269,1.149],[0,0],[0.823,1.388],[0.143,1.057],[-0.214,1.589],[0,0],[-0.605,1.021],[-1.738,7.444],[0,0],[8.207,0],[-0.269,-1.149],[0,0],[-0.823,-1.388],[-0.143,-1.057],[0.214,-1.589],[0,0],[0.605,-1.021],[1.738,-7.444]],"v":[[-6458.712,-6744.95],[-6645.288,-6744.95],[-6657.545,-6730.055],[-6656.154,-6726.804],[-6581.067,-6600.158],[-6579.392,-6595.673],[-6579.392,-6592.49],[-6581.067,-6588.004],[-6656.154,-6461.358],[-6657.545,-6458.107],[-6645.288,-6443.213],[-6458.712,-6443.213],[-6446.455,-6458.107],[-6447.846,-6461.358],[-6522.933,-6588.004],[-6524.608,-6592.49],[-6524.608,-6595.673],[-6522.933,-6600.158],[-6447.846,-6726.804],[-6446.455,-6730.055]]}}},{"ty":"fl","nm":"Fill 1","c":{"a":0,"k":[1,1,1]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"sk":{"a":0,"k":0},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"sa":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"ind":7}],"v":"4.8.0","fr":25,"op":76,"ip":0,"assets":[]} \ No newline at end of file diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index 92f202f0..137faf3f 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -1249,7 +1249,7 @@ "quickLinks": "روابط سريعة", "viewMedicalFileLandingPage": "عرض الملف الطبي", "immediateLiveCareRequest": "طلب لايف كير فوري", - "yourTurnIsAfterPatients": "دورك بعد {count} مريض.", + "yourTurnIsAfterPatients": "دورك بعد {count} مريض. يرجى الانتظار حتى يحين دورك، وسيناديك الطبيب قريباً.", "dontHaveHHCOrders": "ليس لديك أي أوامر رعاية صحية منزلية حتى الآن.", "hhcOrders": "أوامر الرعاية الصحية المنزلية", "requestedServices": "الخدمات المطلوبة", @@ -1689,5 +1689,6 @@ "openGallery": "افتح المعرض", "openFiles": "فتح الملفات", "generateAiAnalysisRadResult": "بإنشاء تحليل الذكاء الاصطناعي لهذا التقرير", - "grantLocationPermission": "يرجى منح إذن الوصول إلى الموقع من إعدادات التطبيق للحصول على نتائج أفضل." + "grantLocationPermission": "يرجى منح إذن الوصول إلى الموقع من إعدادات التطبيق للحصول على نتائج أفضل.", + "NoBookedAppointments": "لا توجد مواعيد محجوزة" } diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 384b16d5..dbd77443 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -1681,5 +1681,6 @@ "openGallery": "Open Gallery", "openFiles": "Open Files", "generateAiAnalysisRadResult": "Generate AI analysis for this result", - "grantLocationPermission": "Please grant location permission from app settings to see better results." + "grantLocationPermission": "Please grant location permission from app settings to see better results.", + "NoBookedAppointments": "No Booked Appointments" } diff --git a/lib/core/app_assets.dart b/lib/core/app_assets.dart index e4308bd5..21280f45 100644 --- a/lib/core/app_assets.dart +++ b/lib/core/app_assets.dart @@ -415,4 +415,6 @@ class AppAnimations { static const String ambulance = '$lottieBasePath/ambulance.json'; static const String ambulanceAlert = '$lottieBasePath/ambulance_alert.json'; static const String rrtAmbulance = '$lottieBasePath/rrt_ambulance.json'; + + static const String hourGlass = '$lottieBasePath/HourGlass.json'; } diff --git a/lib/features/book_appointments/book_appointments_view_model.dart b/lib/features/book_appointments/book_appointments_view_model.dart index 6f2092f9..59a593af 100644 --- a/lib/features/book_appointments/book_appointments_view_model.dart +++ b/lib/features/book_appointments/book_appointments_view_model.dart @@ -402,7 +402,11 @@ class BookAppointmentsViewModel extends ChangeNotifier { refreshDoctorsList() { setIsDoctorsListLoading(true); - getDoctorsList(isNearest: isNearestAppointmentSelected); + if(selectedClinic.clinicID == 17) { + getDentalChiefComplaintDoctorsList(projectID: currentlySelectedHospitalFromRegionFlow != null ? int.parse(currentlySelectedHospitalFromRegionFlow!) : 0); + } else { + getDoctorsList(isNearest: isNearestAppointmentSelected); + } } setIsNearestAppointmentSelected(bool isNearestAppointmentSelected) { @@ -861,8 +865,8 @@ class BookAppointmentsViewModel extends ChangeNotifier { } initialSlotDuration = apiResponse.data["InitialSlotDuration"]; freeSlotsResponse = apiResponse.data['FreeTimeSlots']; - // isWaitingAppointmentAvailable = apiResponse.data["IsAllowToBookWaitingAppointment"]; - isWaitingAppointmentAvailable = true; + isWaitingAppointmentAvailable = apiResponse.data["IsAllowToBookWaitingAppointment"]; + // isWaitingAppointmentAvailable = true; freeSlotsResponse.forEach((element) { // date = (isLiveCareSchedule != null && isLiveCareSchedule) @@ -1466,7 +1470,10 @@ class BookAppointmentsViewModel extends ChangeNotifier { } Future getDentalChiefComplaintDoctorsList({int projectID = 0, Function(dynamic)? onSuccess, Function(String)? onError}) async { + setIsNearestAppointmentSelected(false); doctorsList.clear(); + notifyListeners(); + projectID = currentlySelectedHospitalFromRegionFlow != null ? int.parse(currentlySelectedHospitalFromRegionFlow!) : projectID; final result = await bookAppointmentsRepo.getDentalChiefComplaintDoctorsList(projectID, selectedChiefComplaintID); @@ -1485,6 +1492,7 @@ class BookAppointmentsViewModel extends ChangeNotifier { // clearSearchFilters(); // getFiltersFromDoctorList(); _groupDoctorsList(); + setIsNearestAppointmentSelected(isNearestAppointmentSelected); notifyListeners(); if (onSuccess != null) { onSuccess(apiResponse); diff --git a/lib/features/emergency_services/emergency_services_view_model.dart b/lib/features/emergency_services/emergency_services_view_model.dart index bfe226f8..c8a16455 100644 --- a/lib/features/emergency_services/emergency_services_view_model.dart +++ b/lib/features/emergency_services/emergency_services_view_model.dart @@ -713,7 +713,7 @@ class EmergencyServicesViewModel extends ChangeNotifier { appointments = response.data; if (appointments?.isEmpty == true) { haveAnAppointment = false; - dialogService.showErrorBottomSheet(message: "Unable to Fetch Appointment"); + dialogService.showErrorBottomSheet(message: LocaleKeys.NoBookedAppointments.tr()); } notifyListeners(); }); diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index 2a999ae7..c6c4182f 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -1681,5 +1681,6 @@ abstract class LocaleKeys { static const openFiles = 'openFiles'; static const generateAiAnalysisRadResult = 'generateAiAnalysisRadResult'; static const grantLocationPermission = 'grantLocationPermission'; + static const NoBookedAppointments = 'NoBookedAppointments'; } diff --git a/lib/main.dart b/lib/main.dart index c44a3a45..e9b599c9 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -10,6 +10,7 @@ import 'package:flutter/services.dart'; import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart'; +import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/features/ask_doctor/ask_doctor_view_model.dart'; import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart'; import 'package:hmg_patient_app_new/features/blood_donation/blood_donation_view_model.dart'; @@ -50,6 +51,7 @@ import 'package:hmg_patient_app_new/routes/app_routes.dart'; import 'package:hmg_patient_app_new/services/logger_service.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart'; import 'package:hmg_patient_app_new/theme/app_theme.dart'; +import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/date_range_selector/viewmodel/date_range_view_model.dart' show DateRangeSelectorRangeViewModel; import 'package:provider/provider.dart'; import 'package:provider/single_child_widget.dart'; diff --git a/lib/presentation/appointments/widgets/appointment_card.dart b/lib/presentation/appointments/widgets/appointment_card.dart index c69a2bc4..d5ea4c97 100644 --- a/lib/presentation/appointments/widgets/appointment_card.dart +++ b/lib/presentation/appointments/widgets/appointment_card.dart @@ -243,42 +243,123 @@ class AppointmentCard extends StatelessWidget { (patientAppointmentHistoryResponseModel.isExecludeDoctor ?? false) || !Utils.isClinicAllowedForRebook(patientAppointmentHistoryResponseModel.clinicID ?? 0))) && AppointmentType.isArrived(patientAppointmentHistoryResponseModel)) { - return CustomButton( - text: isFromMedicalReport ? LocaleKeys.selectAppointment.tr(context: context) : LocaleKeys.viewDetails.tr(context: context), - onPressed: () { - if (isFromMedicalReport) { - if (isForFeedback) { - contactUsViewModel!.setPatientFeedbackSelectedAppointment(patientAppointmentHistoryResponseModel); + if (((patientAppointmentHistoryResponseModel.isLiveCareAppointment ?? false) && + DateTime.now().difference(DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate)).inDays <= 15)) { + return Row( + children: [ + Expanded( + flex: 6, + child: CustomButton( + text: LocaleKeys.askDoctor.tr(context: context), + onPressed: () async { + LoaderBottomSheet.showLoader(loadingText: LocaleKeys.checkingDoctorAvailability.tr(context: context)); + await myAppointmentsViewModel.isDoctorAvailable( + projectID: patientAppointmentHistoryResponseModel.projectID, + doctorId: patientAppointmentHistoryResponseModel.doctorID, + clinicId: patientAppointmentHistoryResponseModel.clinicID, + onSuccess: (value) async { + if (value) { + await myAppointmentsViewModel.getAskDoctorRequestTypes(onSuccess: (val) { + LoaderBottomSheet.hideLoader(); + showCommonBottomSheetWithoutHeight( + context, + title: LocaleKeys.askDoctor.tr(context: context), + child: AskDoctorRequestTypeSelect( + askDoctorRequestTypeList: myAppointmentsViewModel.askDoctorRequestTypeList, + myAppointmentsViewModel: myAppointmentsViewModel, + patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel, + ), + callBackFunc: () {}, + isFullScreen: false, + isCloseButtonVisible: true, + ); + }); + } else { + print("Doctor is not available"); + } + }); + }, + backgroundColor: AppColors.secondaryLightRedColor, + borderColor: AppColors.secondaryLightRedColor, + textColor: AppColors.primaryRedColor, + fontSize: (isFoldable || isTablet) ? 12.f : 14.f, + fontWeight: FontWeight.w600, + borderRadius: 12.r, + padding: EdgeInsets.symmetric(horizontal: 10.w), + // height: isTablet || isFoldable ? 46.h : 40.h, + height: 40.h, + icon: AppAssets.ask_doctor_icon, + iconColor: AppColors.primaryRedColor, + iconSize: 16.h, + ), + ), + SizedBox(width: 8.h), + Expanded( + flex: 1, + child: Container( + height: (isFoldable || isTablet) ? 50.h : 40.h, + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.textColor, + borderRadius: 10.h, + side: BorderSide( + color: AppColors.textColor, + width: 1.2, + ), + ), + child: Transform.flip( + flipX: appState.isArabic(), + child: Utils.buildSvgWithAssets( + icon: AppAssets.forward_arrow_icon, + iconColor: AppColors.whiteColor, + width: 24.w, + height: 24.h, + fit: BoxFit.contain, + ), + ), + ).toShimmer2(isShow: isLoading).onPress(() { + _goToDetails(context); + }), + ), + ], + ); + } else { + return CustomButton( + text: isFromMedicalReport ? LocaleKeys.selectAppointment.tr(context: context) : LocaleKeys.viewDetails.tr(context: context), + onPressed: () { + if (isFromMedicalReport) { + if (isForFeedback) { + contactUsViewModel!.setPatientFeedbackSelectedAppointment(patientAppointmentHistoryResponseModel); + } else { + medicalFileViewModel!.setSelectedMedicalReportAppointment(patientAppointmentHistoryResponseModel); + } + Navigator.pop(context, false); } else { - medicalFileViewModel!.setSelectedMedicalReportAppointment(patientAppointmentHistoryResponseModel); + Navigator.of(context) + .push( + CustomPageRoute( + page: AppointmentDetailsPage(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel), + ), + ) + .then((_) { + myAppointmentsViewModel.initAppointmentsViewModel(); + myAppointmentsViewModel.getPatientAppointments(true, false); + }); } - 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, - textColor: AppColors.primaryRedColor, - fontSize: (isFoldable || isTablet) ? 12.f : 14.f, - fontWeight: FontWeight.w600, - borderRadius: 12.r, - 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, - ); + }, + backgroundColor: AppColors.secondaryLightRedColor, + borderColor: AppColors.secondaryLightRedColor, + textColor: AppColors.primaryRedColor, + fontSize: (isFoldable || isTablet) ? 12.f : 14.f, + fontWeight: FontWeight.w600, + borderRadius: 12.r, + 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) { if (isForEyeMeasurements) { @@ -309,7 +390,6 @@ class AppointmentCard extends StatelessWidget { ); } } - return Row( children: [ Expanded( diff --git a/lib/presentation/book_appointment/livecare/immediate_livecare_payment_details.dart b/lib/presentation/book_appointment/livecare/immediate_livecare_payment_details.dart index 5f44448a..1228e1e4 100644 --- a/lib/presentation/book_appointment/livecare/immediate_livecare_payment_details.dart +++ b/lib/presentation/book_appointment/livecare/immediate_livecare_payment_details.dart @@ -215,8 +215,8 @@ class ImmediateLiveCarePaymentDetails extends StatelessWidget { children: [ LocaleKeys.amountBeforeTax.tr(context: context).toText14(isBold: true), Utils.getPaymentAmountWithSymbol((immediateLiveCareVM.liveCareImmediateAppointmentFeesList.amount ?? "").toText16(isBold: true, isEnglishOnly: true), AppColors.blackColor, 13, - isSaudiCurrency: immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency!.toLowerCase() == "sar" || - immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency!.toLowerCase() == "ريال"), + isSaudiCurrency: (immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency ?? "sar").toLowerCase() == "sar" || + (immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency ?? "ريال").toLowerCase() == "ريال"), ], ).paddingSymmetrical(24.h, 0.h), Row( @@ -224,9 +224,9 @@ class ImmediateLiveCarePaymentDetails extends StatelessWidget { children: [ LocaleKeys.vat15.tr(context: context).toText14(isBold: true, color: AppColors.greyTextColor), Utils.getPaymentAmountWithSymbol( - immediateLiveCareVM.liveCareImmediateAppointmentFeesList.tax!.toText14(isBold: true, color: AppColors.greyTextColor, isEnglishOnly: true), AppColors.greyTextColor, 13, - isSaudiCurrency: (immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency!.toLowerCase() == "sar" || - immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency!.toLowerCase() == "ريال")), + (immediateLiveCareVM.liveCareImmediateAppointmentFeesList.tax ?? "0.0").toText14(isBold: true, color: AppColors.greyTextColor, isEnglishOnly: true), AppColors.greyTextColor, 13, + isSaudiCurrency: ((immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency ?? "sar").toLowerCase() == "sar" || + (immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency ?? "ريال").toLowerCase() == "ريال")), ], ).paddingSymmetrical(24.h, 0.h), SizedBox(height: 17.h), @@ -234,9 +234,9 @@ class ImmediateLiveCarePaymentDetails extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ SizedBox(width: 200.h, child: Utils.getPaymentMethods()), - Utils.getPaymentAmountWithSymbol(immediateLiveCareVM.liveCareImmediateAppointmentFeesList.total!.toText24(isBold: true, isEnglishOnly: true), AppColors.blackColor, 17, - isSaudiCurrency: (immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency!.toLowerCase() == "sar" || - immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency!.toLowerCase() == "ريال")), + Utils.getPaymentAmountWithSymbol((immediateLiveCareVM.liveCareImmediateAppointmentFeesList.total ?? "0.0").toText24(isBold: true, isEnglishOnly: true), AppColors.blackColor, 17, + isSaudiCurrency: ((immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency ?? "sar").toLowerCase() == "sar" || + (immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency ?? "ريال").toLowerCase() == "ريال")), ], ).paddingSymmetrical(24.h, 0.h), (immediateLiveCareVM.liveCareImmediateAppointmentFeesList.total == "0" || immediateLiveCareVM.liveCareImmediateAppointmentFeesList.total == "0.0") diff --git a/lib/presentation/book_appointment/livecare/immediate_livecare_payment_page.dart b/lib/presentation/book_appointment/livecare/immediate_livecare_payment_page.dart index 0341796f..031bb0b8 100644 --- a/lib/presentation/book_appointment/livecare/immediate_livecare_payment_page.dart +++ b/lib/presentation/book_appointment/livecare/immediate_livecare_payment_page.dart @@ -264,7 +264,7 @@ class _ImmediateLiveCarePaymentPageState extends State( valueListenable: immediateLiveCareVM.durationNotifier, diff --git a/lib/presentation/book_appointment/select_clinic_page.dart b/lib/presentation/book_appointment/select_clinic_page.dart index b08564ca..e617194e 100644 --- a/lib/presentation/book_appointment/select_clinic_page.dart +++ b/lib/presentation/book_appointment/select_clinic_page.dart @@ -1079,7 +1079,8 @@ class _SelectClinicPageState extends State { // } var bottomSheetType = RegionBottomSheetType.FOR_CLINIIC; if (clinic.clinicID == 17) { - regionalViewModel.setBottomSheetState(AppointmentViaRegionState.HOSPITAL_SELECTION); + // regionalViewModel.setBottomSheetState(AppointmentViaRegionState.HOSPITAL_SELECTION); + // bottomSheetType = RegionBottomSheetType.REGION_FOR_DENTAL_AND_LASER; bottomSheetType = RegionBottomSheetType.REGION_FOR_DENTAL_AND_LASER; } // if (clinic.clinicID == 253) { diff --git a/lib/presentation/habib_wallet/habib_wallet_page.dart b/lib/presentation/habib_wallet/habib_wallet_page.dart index 8e6230e8..fd5d17a1 100644 --- a/lib/presentation/habib_wallet/habib_wallet_page.dart +++ b/lib/presentation/habib_wallet/habib_wallet_page.dart @@ -74,7 +74,8 @@ class _HabibWalletState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ "${_appState.getAuthenticatedUser()!.firstName!} ${_appState.getAuthenticatedUser()!.lastName!}".toText19(isBold: true, color: Colors.white), - "MRN: ${_appState.getAuthenticatedUser()!.patientId!}".toText14(isBold: true, color: AppColors.greyTextColor, isEnglishOnly: true), + "${LocaleKeys.fileno.tr(context: context)}: ${_appState.getAuthenticatedUser()!.patientId!}" + .toText14(isBold: true, color: AppColors.greyTextColor, isEnglishOnly: true), ], ).expanded, Utils.buildSvgWithAssets(icon: AppAssets.habiblogo, width: 24.h, height: 24.h, applyThemeColor: false), @@ -84,8 +85,15 @@ class _HabibWalletState extends State { LocaleKeys.balanceAmount.tr(context: context).toText14(isBold: true, color: Colors.white), SizedBox(height: 4.h), Consumer(builder: (context, habibWalletVM, child) { - return Utils.getPaymentAmountWithSymbol2(num.parse(NumberFormat.decimalPattern().format(habibWalletVM.habibWalletAmount)), - textColor: Colors.white, iconColor: Colors.white, iconSize: 16, isExpanded: false) + return Utils.getPaymentAmountWithSymbol2( + num.parse( + NumberFormat.decimalPattern().format(habibWalletVM.habibWalletAmount), + ), + textColor: Colors.white, + iconColor: Colors.white, + iconSize: 16, + isExpanded: false, + letterSpacing: -1) .toShimmer2(isShow: habibWalletVM.isWalletAmountLoading, radius: 12.h, width: 80.h, height: 24.h); }), ], @@ -140,7 +148,7 @@ class _HabibWalletState extends State { children: [ Expanded(child: habibWalletVM.habibWalletBalanceList[index].projectDescription!.toText16(isBold: true, color: AppColors.textColor)), Utils.getPaymentAmountWithSymbol2(num.parse(NumberFormat.decimalPattern().format(habibWalletVM.habibWalletBalanceList[index].patientAdvanceBalanceAmount!)), - textColor: AppColors.textColor, iconColor: AppColors.textColor, iconSize: 18.h, isExpanded: false, fontSize: 28.f, fontWeight: FontWeight.w600,), + textColor: AppColors.textColor, iconColor: AppColors.textColor, iconSize: 18.h, isExpanded: false, fontSize: 28.f, fontWeight: FontWeight.w600, letterSpacing: -1), ], ).paddingSymmetrical(0, 12.h); }, diff --git a/lib/presentation/home/landing_page.dart b/lib/presentation/home/landing_page.dart index 93d616da..357af662 100644 --- a/lib/presentation/home/landing_page.dart +++ b/lib/presentation/home/landing_page.dart @@ -69,6 +69,7 @@ import 'package:hmg_patient_app_new/widgets/countdown_timer.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:hmg_patient_app_new/widgets/routes/spring_page_route_builder.dart'; +import 'package:lottie/lottie.dart'; import 'package:provider/provider.dart'; import 'package:smooth_corner/smooth_corner.dart'; @@ -483,29 +484,37 @@ class _LandingPageState extends State { ) : SizedBox( height: 255.h + 20 + 30, // itemHeight + shadow padding (10 top + 10 bottom) + pagination dots space - child: Swiper( - itemCount: myAppointmentsVM.isMyAppointmentsLoading - ? 3 - : myAppointmentsVM.patientAppointmentsHistoryList.length < 3 - ? myAppointmentsVM.patientAppointmentsHistoryList.length - : 3, - layout: SwiperLayout.STACK, - loop: false, - itemWidth: MediaQuery.of(context).size.width - 48.h, - indicatorLayout: PageIndicatorLayout.COLOR, - axisDirection: appState.isArabic() ? AxisDirection.right : AxisDirection.left, - controller: _controller, - itemHeight: 255.h + 20, - // extra space for shadow - pagination: SwiperPagination( - alignment: Alignment.bottomCenter, - margin: EdgeInsets.only(top: 220.h + 20 + 8 + 24), - builder: DotSwiperPaginationBuilder(color: Color(0xffD9D9D9), activeColor: AppColors.blackBgColor), - ), - itemBuilder: (BuildContext context, int index) { - return Padding( - padding: const EdgeInsets.symmetric(vertical: 10), - child: getIndexSwiperCard(index), + child: Builder( + builder: (context) { + final int swiperItemCount = myAppointmentsVM.isMyAppointmentsLoading + ? 3 + : myAppointmentsVM.patientAppointmentsHistoryList.length < 3 + ? myAppointmentsVM.patientAppointmentsHistoryList.length + : 3; + final bool isArabic = appState.isArabic(); + return Swiper( + itemCount: swiperItemCount, + layout: SwiperLayout.STACK, + loop: false, + itemWidth: MediaQuery.of(context).size.width - 48.h, + indicatorLayout: PageIndicatorLayout.COLOR, + axisDirection: isArabic ? AxisDirection.right : AxisDirection.left, + controller: _controller, + index: isArabic ? swiperItemCount - 1 : 0, + itemHeight: 255.h + 20, + // extra space for shadow + pagination: SwiperPagination( + alignment: Alignment.bottomCenter, + margin: EdgeInsets.only(top: 220.h + 20 + 8 + 24), + builder: DotSwiperPaginationBuilder(color: Color(0xffD9D9D9), activeColor: AppColors.blackBgColor), + ), + itemBuilder: (BuildContext context, int index) { + final int actualIndex = isArabic ? (swiperItemCount - 1 - index) : index; + return Padding( + padding: const EdgeInsets.symmetric(vertical: 10), + child: getIndexSwiperCard(actualIndex), + ); + }, ); }, ), @@ -1148,6 +1157,7 @@ class _LandingPageState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( + crossAxisAlignment: CrossAxisAlignment.start, children: [ AppCustomChipWidget( labelText: liveCareData.stringCallStatus, @@ -1162,13 +1172,42 @@ class _LandingPageState extends State { false, ), ), + SizedBox(width: 8.w), + AppCustomChipWidget( + richText: ValueListenableBuilder( + valueListenable: immediateLiveCareViewModel.durationNotifier, + builder: (context, duration, child) { + final hours = duration.inHours.toString().padLeft(2, '0'); + final minutes = duration.inMinutes.remainder(60).toString().padLeft(2, '0'); + final seconds = duration.inSeconds.remainder(60).toString().padLeft(2, '0'); + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + '$hours:$minutes:$seconds'.toText10(isBold: true), + ], + ); + }, + ), + // labelText: DateUtil.formatDateToDate( + // DateUtil.convertStringToDate(liveCareData.arrivalTime), + // false, + // ), + ), ], ), - Utils.buildSvgWithAssets( - icon: AppAssets.waiting_icon, - width: 24.h, - height: 24.h, - ), + Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.greyColor, + borderRadius: 10.h, + hasShadow: false, + ), + padding: EdgeInsets.all(6.h), + child: Lottie.asset(AppAnimations.hourGlass, repeat: true, reverse: false, frameRate: FrameRate(60), width: 40.h, height: 40.h, fit: BoxFit.fill)), + // Utils.buildSvgWithAssets( + // icon: AppAssets.waiting_icon, + // width: 24.h, + // height: 24.h, + // ), ], ); } diff --git a/lib/presentation/home/widgets/habib_wallet_card.dart b/lib/presentation/home/widgets/habib_wallet_card.dart index 2e1292b2..2a45e2f5 100644 --- a/lib/presentation/home/widgets/habib_wallet_card.dart +++ b/lib/presentation/home/widgets/habib_wallet_card.dart @@ -1,6 +1,8 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart'; +import 'package:hmg_patient_app_new/core/app_state.dart'; +import 'package:hmg_patient_app_new/core/dependencies.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'; @@ -76,13 +78,14 @@ class HabibWalletCard extends StatelessWidget { // ], // ), SizedBox(height: 4.h), - Row( + Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Consumer(builder: (context, habibWalletVM, child) { - return Row( + Consumer(builder: (context, habibWalletVM, child) { + return Row( + mainAxisSize: MainAxisSize.max, + children: [ + Row( children: [ Utils.buildSvgWithAssets( icon: AppAssets.saudi_riyal_icon, @@ -98,58 +101,70 @@ class HabibWalletCard extends StatelessWidget { .toText32(isBold: true, isEnglishOnly: true) .toShimmer2(isShow: habibWalletVM.isWalletAmountLoading, radius: 12.h, width: 80.h, height: 40.h), ], - ); - }), - Padding( - padding: EdgeInsets.symmetric(horizontal: 35.h), - child: Row( - children: [ - LocaleKeys.viewDetails.tr(context: context).toText12(color: AppColors.primaryRedColor, isBold: true), - Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h), - ], - ).onPress(() { - Navigator.of(context).push( - CustomPageRoute( - page: HabibWalletPage(), - ), - ); - }), - ), - ], - ), - SizedBox( - // width: 50.h, - child: Utils.getPaymentMethods(), - ), + ), + Spacer(), + Utils.getPaymentMethods(), + ], + ); + }), ], ), SizedBox(height: 16.h), - CustomButton( - height: 40.h, - icon: AppAssets.recharge_icon, - iconColor: AppColors.infoColor, - iconSize: 24.h, - backgroundColor: AppColors.infoColor.withAlpha(15), - textColor: AppColors.infoColor, - text: LocaleKeys.recharge.tr(context: context), - borderWidth: 0.w, - fontWeight: FontWeight.w600, - borderColor: AppColors.infoColor.withAlpha(15), - padding: EdgeInsets.fromLTRB(4, 0, 12, 0), - fontSize: 14.f, - onPressed: () { - Navigator.of(context).push(CustomPageRoute(page: RechargeWalletPage())); - }, + Row( + children: [ + Expanded( + flex: 6, + child: CustomButton( + height: 40.h, + icon: AppAssets.recharge_icon, + iconColor: AppColors.infoColor, + iconSize: 24.h, + backgroundColor: AppColors.infoColor.withAlpha(15), + textColor: AppColors.infoColor, + text: LocaleKeys.recharge.tr(context: context), + borderWidth: 0.w, + fontWeight: FontWeight.w600, + borderColor: AppColors.infoColor.withAlpha(15), + padding: EdgeInsets.fromLTRB(4, 0, 12, 0), + fontSize: 14.f, + onPressed: () { + Navigator.of(context).push(CustomPageRoute(page: RechargeWalletPage())); + }, + ), + ), + SizedBox(width: 8.h), + Expanded( + flex: 1, + child: Container( + height: (isFoldable || isTablet) ? 50.h : 40.h, + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.textColor, + borderRadius: 10.h, + side: BorderSide( + color: AppColors.textColor, + width: 1.2, + ), + ), + child: Transform.flip( + flipX: getIt.get().isArabic(), + child: Utils.buildSvgWithAssets( + icon: AppAssets.forward_arrow_icon, + iconColor: AppColors.whiteColor, + width: 24.w, + height: 24.h, + fit: BoxFit.contain, + ), + ), + ).onPress(() { + Navigator.of(context).push( + CustomPageRoute( + page: HabibWalletPage(), + ), + ); + }), + ), + ], ), - // Row( - // mainAxisAlignment: MainAxisAlignment.spaceBetween, - // children: [ - // SizedBox( - // width: 200.h, - // child: Utils.getPaymentMethods(), - // ), - // ], - // ), ], ), ), diff --git a/lib/theme/app_theme.dart b/lib/theme/app_theme.dart index 0f057efe..c676819f 100644 --- a/lib/theme/app_theme.dart +++ b/lib/theme/app_theme.dart @@ -26,8 +26,7 @@ class AppTheme { canvasColor: Colors.white, highlightColor: Colors.grey[100]!.withOpacity(0.4), splashColor: Colors.transparent, - bottomSheetTheme: BottomSheetThemeData( - backgroundColor: Colors.black.withOpacity(0)), + bottomSheetTheme: BottomSheetThemeData(backgroundColor: Colors.black.withOpacity(0)), floatingActionButtonTheme: const FloatingActionButtonThemeData(highlightElevation: 2, disabledElevation: 0, elevation: 2), appBarTheme: AppBarTheme( color: const Color(0xff515A5D), @@ -35,7 +34,7 @@ class AppTheme { actionsIconTheme: IconThemeData( color: Colors.grey[800], ), - systemOverlayStyle: SystemUiOverlayStyle.light, + systemOverlayStyle: SystemUiOverlayStyle.dark, surfaceTintColor: Colors.transparent, ), ); diff --git a/lib/widgets/countdown_timer.dart b/lib/widgets/countdown_timer.dart index 86249fc8..8cd3fa73 100644 --- a/lib/widgets/countdown_timer.dart +++ b/lib/widgets/countdown_timer.dart @@ -88,7 +88,7 @@ Widget buildDigit(String digit) { style: TextStyle( fontWeight: FontWeight.bold, color: Colors.black, - fontSize: 14.f, + fontSize: 10.f, ), ), ), diff --git a/lib/widgets/map/gms_map.dart b/lib/widgets/map/gms_map.dart index 1d06fb10..33e0befb 100644 --- a/lib/widgets/map/gms_map.dart +++ b/lib/widgets/map/gms_map.dart @@ -210,7 +210,7 @@ class _GMSMapState extends State { Icons.location_pin, size: 36.h, color: AppColors.primaryRedColor, - ).paddingOnly(bottom: Platform.isAndroid ? 30.h : double.parse((widget.bottomPaddingHeight + 25.h).toString())), + ).paddingOnly(bottom: Platform.isAndroid ? 30.h : 60.h), ), // ── My Location button ──────────────────────────────────────────── diff --git a/package/flutter_swiper_view/lib/src/custom_layout.dart b/package/flutter_swiper_view/lib/src/custom_layout.dart index 68eab940..8270a490 100644 --- a/package/flutter_swiper_view/lib/src/custom_layout.dart +++ b/package/flutter_swiper_view/lib/src/custom_layout.dart @@ -204,44 +204,22 @@ abstract class _CustomLayoutStateBase extends State void _onPanEnd(DragEndDetails details) { if (_lockScroll) return; - final bool _isReversedGesture = widget.axisDirection == AxisDirection.right; - double velocity = widget.scrollDirection == Axis.horizontal ? details.velocity.pixelsPerSecond.dx : details.velocity.pixelsPerSecond.dy; - if (_isReversedGesture) { - // Reversed: swipe right (value >= 0.75) = next, swipe left (value < 0.25) = previous - if (_animationController.value >= 0.75 || velocity > 500.0) { - if (_currentIndex >= widget.itemCount - 1 && !widget.loop) { - _move(0.5); - return; - } - _move(1.0, nextIndex: _currentIndex + 1); - } else if (_animationController.value < 0.25 || velocity < -500.0) { - if (_currentIndex <= 0 && !widget.loop) { - _move(0.5); - return; - } - _move(0.0, nextIndex: _currentIndex - 1); - } else { - _move(0.5); + if (_animationController.value >= 0.75 || velocity > 500.0) { + if (_currentIndex <= 0 && !widget.loop) { + return; } - } else { - // Default: swipe right (value >= 0.75) = previous, swipe left (value < 0.25) = next - if (_animationController.value >= 0.75 || velocity > 500.0) { - if (_currentIndex <= 0 && !widget.loop) { - return; - } - _move(1.0, nextIndex: _currentIndex - 1); - } else if (_animationController.value < 0.25 || velocity < -500.0) { - if (_currentIndex >= widget.itemCount - 1 && !widget.loop) { - return; - } - _move(0.0, nextIndex: _currentIndex + 1); - } else { - _move(0.5); + _move(1.0, nextIndex: _currentIndex - 1); + } else if (_animationController.value < 0.25 || velocity < -500.0) { + if (_currentIndex >= widget.itemCount - 1 && !widget.loop) { + return; } + _move(0.0, nextIndex: _currentIndex + 1); + } else { + _move(0.5); } } @@ -255,7 +233,6 @@ abstract class _CustomLayoutStateBase extends State void _onPanUpdate(DragUpdateDetails details) { if (_lockScroll) return; - double value = _currentValue + ((widget.scrollDirection == Axis.horizontal ? details.globalPosition.dx @@ -265,26 +242,13 @@ abstract class _CustomLayoutStateBase extends State 2; // no loop ? if (!widget.loop) { - if (widget.axisDirection == AxisDirection.right) { - // Reversed bounds: block dragging left past first, right past last - if (_currentIndex <= 0) { - if (value < 0.5) { - value = 0.5; - } - } else if (_currentIndex >= widget.itemCount - 1) { - if (value > 0.5) { - value = 0.5; - } + if (_currentIndex >= widget.itemCount - 1) { + if (value < 0.5) { + value = 0.5; } - } else { - if (_currentIndex >= widget.itemCount - 1) { - if (value < 0.5) { - value = 0.5; - } - } else if (_currentIndex <= 0) { - if (value > 0.5) { - value = 0.5; - } + } else if (_currentIndex <= 0) { + if (value > 0.5) { + value = 0.5; } } } From fe1e0fdb405beb5eb9b9a5c587ba357796acbe69 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Wed, 8 Apr 2026 14:52:09 +0300 Subject: [PATCH 4/8] Updates --- .../book_appointments_view_model.dart | 3 ++- .../appointments/appointment_queue_page.dart | 16 +++++++++++++--- .../appointment_checkin_bottom_sheet.dart | 2 +- .../review_appointment_page.dart | 3 ++- .../emergency_services/nearest_er_page.dart | 2 +- .../widgets/nearestERItem.dart | 11 +++++------ lib/presentation/home/landing_page.dart | 18 +++++++++++------- 7 files changed, 35 insertions(+), 20 deletions(-) diff --git a/lib/features/book_appointments/book_appointments_view_model.dart b/lib/features/book_appointments/book_appointments_view_model.dart index 59a593af..647b8632 100644 --- a/lib/features/book_appointments/book_appointments_view_model.dart +++ b/lib/features/book_appointments/book_appointments_view_model.dart @@ -1048,7 +1048,8 @@ class BookAppointmentsViewModel extends ChangeNotifier { ); LoaderBottomSheet.showLoader( - loadingText: LocaleKeys.reschedulingAppo.tr(context: navigationService.navigatorKey.currentContext!), + // loadingText: LocaleKeys.reschedulingAppo.tr(context: navigationService.navigatorKey.currentContext!), + loadingText: LocaleKeys.loadingText.tr(context: navigationService.navigatorKey.currentContext!), ); await cancelAppointment(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel).then((val) async { LoaderBottomSheet.hideLoader(); diff --git a/lib/presentation/appointments/appointment_queue_page.dart b/lib/presentation/appointments/appointment_queue_page.dart index cc1c7fd1..35403dc6 100644 --- a/lib/presentation/appointments/appointment_queue_page.dart +++ b/lib/presentation/appointments/appointment_queue_page.dart @@ -15,6 +15,7 @@ import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; +import 'package:lottie/lottie.dart'; import 'package:provider/provider.dart'; class AppointmentQueuePage extends StatelessWidget { @@ -32,13 +33,14 @@ class AppointmentQueuePage extends StatelessWidget { children: [ Expanded( child: CollapsingListView( - title: LocaleKeys.queueing.tr(context: context), + title: LocaleKeys.queueing.tr(context: context), child: RefreshIndicator( color: AppColors.primaryRedColor, onRefresh: () async { await myAppointmentsVM.getPatientAppointmentQueueDetails(); }, child: SingleChildScrollView( + physics: const AlwaysScrollableScrollPhysics(), child: Padding( padding: EdgeInsets.all(24.0), child: Column( @@ -59,13 +61,21 @@ class AppointmentQueuePage extends StatelessWidget { children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, children: [ AppCustomChipWidget( labelText: myAppointmentsVM.currentQueueStatus == 0 ? LocaleKeys.inQueue.tr(context: context) : LocaleKeys.yourTurn.tr(context: context), backgroundColor: Utils.getCardBorderColor(myAppointmentsVM.currentQueueStatus).withValues(alpha: 0.20), textColor: Utils.getCardBorderColor(myAppointmentsVM.currentQueueStatus), ), - Utils.buildSvgWithAssets(icon: AppAssets.waiting_icon, width: 24.h, height: 24.h), + Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.greyColor, + borderRadius: 10.h, + hasShadow: false, + ), + padding: EdgeInsets.all(6.h), + child: Lottie.asset(AppAnimations.hourGlass, repeat: true, reverse: false, frameRate: FrameRate(60), width: 40.h, height: 40.h, fit: BoxFit.fill)), ], ).toShimmer2(isShow: myAppointmentsVM.isAppointmentQueueDetailsLoading), SizedBox(height: 10.h), @@ -189,9 +199,9 @@ class AppointmentQueuePage extends StatelessWidget { ], ), ), + ), ), ), - ), ), Container( decoration: RoundedRectangleBorder().toSmoothCornerDecoration( diff --git a/lib/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart b/lib/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart index da50b3c7..817ebfa0 100644 --- a/lib/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart +++ b/lib/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart @@ -168,7 +168,7 @@ class AppointmentCheckinBottomSheet extends StatelessWidget { // page: AppointmentQueuePage(), // ), // ); - }, isFullScreen: false); + }, isFullScreen: false, isAutoDismiss: true, isCloseButtonVisible: false); }, onError: (error) { LoaderBottomSheet.hideLoader(); diff --git a/lib/presentation/book_appointment/review_appointment_page.dart b/lib/presentation/book_appointment/review_appointment_page.dart index a3138dff..689e6cf3 100644 --- a/lib/presentation/book_appointment/review_appointment_page.dart +++ b/lib/presentation/book_appointment/review_appointment_page.dart @@ -317,7 +317,8 @@ class _ReviewAppointmentPageState extends State { void initiateBookAppointment() async { // LoadingUtils.showFullScreenLoader(barrierDismissible: true, isSuccessDialog: false, loadingText: bookAppointmentsViewModel.isPatientRescheduleAppointment ? LocaleKeys.reschedulingAppo.tr(context: context) : LocaleKeys.bookingYourAppointment.tr(context: context)); - LoaderBottomSheet.showLoader(loadingText: bookAppointmentsViewModel.isPatientRescheduleAppointment ? LocaleKeys.reschedulingAppo.tr(context: context) : LocaleKeys.bookingYourAppointment.tr(context: context)); + // LoaderBottomSheet.showLoader(loadingText: bookAppointmentsViewModel.isPatientRescheduleAppointment ? LocaleKeys.reschedulingAppo.tr(context: context) : LocaleKeys.bookingYourAppointment.tr(context: context)); + LoaderBottomSheet.showLoader(loadingText: LocaleKeys.loadingText.tr(context: context)); myAppointmentsViewModel.setIsAppointmentDataToBeLoaded(true); if (bookAppointmentsViewModel.isLiveCareSchedule) { diff --git a/lib/presentation/emergency_services/nearest_er_page.dart b/lib/presentation/emergency_services/nearest_er_page.dart index 0ea3ab8f..ea9a1517 100644 --- a/lib/presentation/emergency_services/nearest_er_page.dart +++ b/lib/presentation/emergency_services/nearest_er_page.dart @@ -44,7 +44,7 @@ class _NearestErPageState extends State { children: [ TextInputWidget( labelText: LocaleKeys.search.tr(), - hintText: 'Type any facility name', + hintText: '', controller: searchText, onChange: (value) { debouncer.run(() { diff --git a/lib/presentation/emergency_services/widgets/nearestERItem.dart b/lib/presentation/emergency_services/widgets/nearestERItem.dart index 5579fd75..58e89421 100644 --- a/lib/presentation/emergency_services/widgets/nearestERItem.dart +++ b/lib/presentation/emergency_services/widgets/nearestERItem.dart @@ -59,7 +59,7 @@ class NearestERItem extends StatelessWidget { Expanded( child: (nearestERItem.projectName?.toText16( color: AppColors.textColor, - weight: FontWeight.w600, + isBold: true ) ?? SizedBox.shrink()).toShimmer2(isShow: isLoading), ), @@ -84,7 +84,7 @@ class NearestERItem extends StatelessWidget { Directionality( textDirection: ui.TextDirection.ltr, child: AppCustomChipWidget( - labelText: "Expected waiting time: ${nearestERItem.getTime()} mins", + labelText: "${LocaleKeys.waitingTime.tr(context: context)} ${nearestERItem.getTime()} ${LocaleKeys.mins.tr(context: context)}", icon: AppAssets.waiting_time_clock, iconHasColor: false, labelPadding: EdgeInsetsDirectional.only(start: 4.h, end: 0.h), @@ -109,14 +109,14 @@ class NearestERItem extends StatelessWidget { borderColor: AppColors.secondaryLightRedColor, textColor: AppColors.primaryRedColor, iconColor: AppColors.primaryRedColor, - height: 40.h, + height: 46.h, fontSize: 14.f, isBold: true, ).toShimmer2(isShow: isLoading), ), SizedBox(width: 8.h), SizedBox( - height: 40.h, + height: 46.h, width: 40.h, child: CustomButton( text: '', @@ -124,12 +124,11 @@ class NearestERItem extends StatelessWidget { icon: AppAssets.call_fill, onPressed: () { context.read().openDialer( nearestERItem.phonenumber??""); - }, backgroundColor: AppColors.greyColor, iconColor: AppColors.textColor, borderColor: AppColors.greyColor, - height: 40.h, + height: 46.h, ).toShimmer2(isShow: isLoading), ), ], diff --git a/lib/presentation/home/landing_page.dart b/lib/presentation/home/landing_page.dart index 357af662..622f3991 100644 --- a/lib/presentation/home/landing_page.dart +++ b/lib/presentation/home/landing_page.dart @@ -265,8 +265,8 @@ class _LandingPageState extends State { borderColor: AppColors.secondaryLightRedColor, textColor: AppColors.primaryRedColor, fontSize: 14.f, - fontWeight: FontWeight.w600, - borderRadius: 12.r, + fontWeight: FontWeight.w700, + borderRadius: 12.r, padding: EdgeInsets.fromLTRB(12.h, 0, 12.h, 0), height: 40.h, ), @@ -1013,17 +1013,21 @@ class _LandingPageState extends State { Widget _buildQueueHeader(int currentStatus) { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, children: [ AppCustomChipWidget( labelText: currentStatus == 0 ? LocaleKeys.inQueue.tr() : LocaleKeys.yourTurn.tr(), backgroundColor: Utils.getCardBorderColor(currentStatus).withValues(alpha: 0.20), textColor: Utils.getCardBorderColor(currentStatus), ), - Utils.buildSvgWithAssets( - icon: AppAssets.waiting_icon, - width: 24.h, - height: 24.h, - ), + Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.greyColor, + borderRadius: 10.h, + hasShadow: false, + ), + padding: EdgeInsets.all(6.h), + child: Lottie.asset(AppAnimations.hourGlass, repeat: true, reverse: false, frameRate: FrameRate(60), width: 40.h, height: 40.h, fit: BoxFit.fill)), ], ); } From 712e835176fa5a78b6d26a64a26a960587aeb89d Mon Sep 17 00:00:00 2001 From: Sultan khan Date: Wed, 8 Apr 2026 14:53:37 +0300 Subject: [PATCH 5/8] ui fixes --- lib/extensions/widget_extensions.dart | 3 +- .../my_appointments_view_model.dart | 6 +- .../widgets/appointment_card.dart | 6 +- .../authentication/saved_login_screen.dart | 11 ++-- lib/presentation/home/landing_page.dart | 7 ++- lib/presentation/lab/lab_orders_page.dart | 2 +- .../lab_ai_analysis_detailed_page.dart | 7 ++- .../lab_order_result_item.dart | 62 ++++++++----------- .../rate_appointment_doctor.dart | 18 +++++- .../widgets/selected_organs_section.dart | 4 +- lib/widgets/datepicker_widget.dart | 4 +- 11 files changed, 69 insertions(+), 61 deletions(-) diff --git a/lib/extensions/widget_extensions.dart b/lib/extensions/widget_extensions.dart index 866c26a4..3c0079f2 100644 --- a/lib/extensions/widget_extensions.dart +++ b/lib/extensions/widget_extensions.dart @@ -155,6 +155,7 @@ extension SmoothContainerExtension on ShapeBorder { BorderRadius? customBorder, bool hasShadow = false, bool hasDenseShadow = false, + List? isCustomShadow, }) { final bgColor = backgroundColor ?? color; return ShapeDecoration( @@ -174,7 +175,7 @@ extension SmoothContainerExtension on ShapeBorder { offset: const Offset(1, 0), ) ] - : [], + : isCustomShadow ?? [], ); } } diff --git a/lib/features/my_appointments/my_appointments_view_model.dart b/lib/features/my_appointments/my_appointments_view_model.dart index ede63ca9..bc0bfc74 100644 --- a/lib/features/my_appointments/my_appointments_view_model.dart +++ b/lib/features/my_appointments/my_appointments_view_model.dart @@ -676,9 +676,9 @@ class MyAppointmentsViewModel extends ChangeNotifier { Future getPatientFavouriteDoctors({bool forceRefresh = false, Function(dynamic)? onSuccess, Function(String)? onError}) async { // If data is already fetched and not forcing refresh, skip API call - // if (isFavouriteDoctorsDataFetched && !forceRefresh) { - // return; - // } + if (isFavouriteDoctorsDataFetched && !forceRefresh) { + return; + } isPatientFavouriteDoctorsLoading = true; patientFavouriteDoctorsList.clear(); diff --git a/lib/presentation/appointments/widgets/appointment_card.dart b/lib/presentation/appointments/widgets/appointment_card.dart index c69a2bc4..b7ffc826 100644 --- a/lib/presentation/appointments/widgets/appointment_card.dart +++ b/lib/presentation/appointments/widgets/appointment_card.dart @@ -205,7 +205,7 @@ class AppointmentCard extends StatelessWidget { richText: isLoading ? 'Cardiology'.toText10().toShimmer2(isShow: isLoading) : "${DateUtil.formatDateToDate(DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate), false)} ${DateUtil.formatDateToTimeLang(DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate), false)}" - .toText10(isEnglishOnly: true), + .toText10(isEnglishOnly: true, isBold: true), ).toShimmer2(isShow: isLoading), ), @@ -415,6 +415,10 @@ class AppointmentCard extends StatelessWidget { } return CustomButton( + borderSide: BorderSide( + color: AppColors.textColor, + width: 1.2, + ), text: LocaleKeys.rebookSameDoctor.tr(context: context), onPressed: () => openDoctorScheduleCalendar(context), backgroundColor: AppColors.transparent, diff --git a/lib/presentation/authentication/saved_login_screen.dart b/lib/presentation/authentication/saved_login_screen.dart index bd29e3d2..4659972e 100644 --- a/lib/presentation/authentication/saved_login_screen.dart +++ b/lib/presentation/authentication/saved_login_screen.dart @@ -8,6 +8,7 @@ import 'package:hmg_patient_app_new/core/utils/date_util.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; +import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/presentation/authentication/login.dart'; @@ -89,15 +90,11 @@ class _SavedLogin extends State { : SizedBox(), SizedBox(height: 24.h), Container( + padding: EdgeInsets.all(16.h), - decoration: BoxDecoration( - color: AppColors.whiteColor, - border: Border.all(color: AppColors.whiteColor), - borderRadius: BorderRadius.circular(24.h), - boxShadow: [ + decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.h, hasShadow: false, isCustomShadow: [ BoxShadow(color: Color(0x0D000000), blurRadius: 16.h, offset: Offset(0, 0), spreadRadius: 5.h), - ], - ), + ]), child: Column( children: [ // Last login info - show WhatsApp only if isOther AND loginType is SMS diff --git a/lib/presentation/home/landing_page.dart b/lib/presentation/home/landing_page.dart index 93d616da..414a2def 100644 --- a/lib/presentation/home/landing_page.dart +++ b/lib/presentation/home/landing_page.dart @@ -272,7 +272,7 @@ class _LandingPageState extends State { Consumer(builder: (context, todoSectionVM, child) { return Row( mainAxisSize: MainAxisSize.min, - spacing: 18.h, + // spacing: 18.h, children: [ Stack(clipBehavior: Clip.none, children: [ if (appState.isAuthenticated) @@ -292,7 +292,7 @@ class _LandingPageState extends State { }), (appState.isAuthenticated && (int.parse(todoSectionVM.notificationsCount ?? "0") > 0)) ? Positioned( - right: appState.isArabic() ? 8.w : -8.w, + // right: appState.isArabic() ? 8.w : -8.w, top: -8.h, // left: 4.h, // bottom: 4.h, @@ -318,6 +318,7 @@ class _LandingPageState extends State { ) : SizedBox.shrink(), ]), + SizedBox(width: 24.w,), Utils.buildSvgWithAssets(icon: AppAssets.location, height: 24.h, width: 24.w).onPress(() { // openIndoorNavigationBottomSheet(context); showCommonBottomSheetWithoutHeight( @@ -612,7 +613,7 @@ class _LandingPageState extends State { LocaleKeys.quickLinks.tr(context: context).toText16(isBold: true), Row( children: [ - LocaleKeys.viewMedicalFile.tr(context: context).toText12(color: AppColors.primaryRedColor, isBold: true), + LocaleKeys.viewMedicalFile.tr(context: context).toText14(color: AppColors.primaryRedColor, isBold: true), SizedBox(width: 2.h), Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 14.h), ], diff --git a/lib/presentation/lab/lab_orders_page.dart b/lib/presentation/lab/lab_orders_page.dart index c635246e..b1495fed 100644 --- a/lib/presentation/lab/lab_orders_page.dart +++ b/lib/presentation/lab/lab_orders_page.dart @@ -1 +1 @@ -import 'dart:async'; import 'dart:convert'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/enums.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/features/lab/lab_view_model.dart'; import 'package:hmg_patient_app_new/features/lab/models/resp_models/patient_lab_orders_response_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/presentation/lab/lab_result_item_view.dart'; import 'package:hmg_patient_app_new/presentation/lab/lab_result_via_clinic/LabResultByClinic.dart'; import 'package:hmg_patient_app_new/presentation/lab/search_lab_report.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/utils/date_util.dart'; import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/appbar/collapsing_toolbar.dart'; import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/chip/custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart'; import 'package:hmg_patient_app_new/widgets/date_range_selector/viewmodel/date_range_view_model.dart'; import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import 'package:provider/provider.dart'; import 'alphabeticScroll.dart'; import 'dart:ui' as ui; class LabOrdersPage extends StatefulWidget { const LabOrdersPage({super.key}); @override State createState() => _LabOrdersPageState(); } class _LabOrdersPageState extends State { late LabViewModel labProvider; late DateRangeSelectorRangeViewModel rangeViewModel; late AppState _appState; List?> labSuggestions = []; int? expandedIndex; String? selectedFilterText = ''; int activeIndex = 0; @override void initState() { scheduleMicrotask(() { labProvider.initLabProvider(); }); super.initState(); } @override Widget build(BuildContext context) { labProvider = Provider.of(context, listen: false); rangeViewModel = Provider.of(context); _appState = getIt(); return CollapsingListView( title: LocaleKeys.labResults.tr(context: context), search: () async { if (labProvider.isLabOrdersLoading) { return; } else { String? value = await Navigator.of(context).push( CustomPageRoute( page: SearchLabResultsContent(labSuggestionsList: labProvider.labSuggestions), fullScreenDialog: true, direction: AxisDirection.down, ), ); if (value != null) { selectedFilterText = value; labProvider.filterLabReports(value); } } }, child: Consumer( builder: (context, labViewModel, child) { return SingleChildScrollView( physics: NeverScrollableScrollPhysics(), padding: EdgeInsets.all(24.h), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: CustomTabBar( activeTextColor: Color(0xffED1C2B), activeBackgroundColor: Color(0xffED1C2B).withValues(alpha: .1), tabs: [ CustomTabBarModel(null, LocaleKeys.byVisit.tr()), CustomTabBarModel(null, LocaleKeys.byTest.tr()), // CustomTabBarModel(null, "Completed".needTranslation), ], onTabChange: (index) { activeIndex = index; setState(() {}); }, ), ), ], ), if (activeIndex == 0) Padding( padding: EdgeInsets.symmetric(vertical: 10.h), child: Row( children: [ // CustomButton( // text: LocaleKeys.byClinic.tr(context: context), // onPressed: () { // labViewModel.setIsSortByClinic(true); // }, // backgroundColor: labViewModel.isSortByClinic ? AppColors.bgRedLightColor : AppColors.whiteColor, // borderColor: labViewModel.isSortByClinic ? AppColors.primaryRedColor : AppColors.textColor.withValues(alpha: 0.2), // textColor: labViewModel.isSortByClinic ? AppColors.primaryRedColor : AppColors.blackColor, // fontSize: 12.f, // isBold: true, // borderRadius: 10, // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // height: 40.h, // ), // SizedBox(width: 8.h), // CustomButton( // text: LocaleKeys.byHospital.tr(context: context), // onPressed: () { // labViewModel.setIsSortByClinic(false); // }, // backgroundColor: labViewModel.isSortByClinic ? AppColors.whiteColor : AppColors.bgRedLightColor, // borderColor: labViewModel.isSortByClinic ? AppColors.textColor.withValues(alpha: 0.2) : AppColors.primaryRedColor, // textColor: labViewModel.isSortByClinic ? AppColors.blackColor : AppColors.primaryRedColor, // fontSize: 12, // isBold: true, // borderRadius: 10, // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // height: 40.h, // ), ], ), ), SizedBox(height: 8.h), selectedFilterText!.isNotEmpty ? Column( children: [ AppCustomChipWidget( labelText: selectedFilterText!, backgroundColor: AppColors.alertColor, textColor: AppColors.whiteColor, deleteIcon: AppAssets.close_bottom_sheet_icon, deleteIconColor: AppColors.whiteColor, deleteIconHasColor: true, isEnglishOnly: true, onDeleteTap: () { selectedFilterText = ""; labProvider.filterLabReports(""); }, ), SizedBox(height: 8.h), ], ) : SizedBox(), activeIndex == 0 ? // By Visit - show grouped view when available labViewModel.isLabOrdersLoading ? ListView.builder( shrinkWrap: true, physics: AlwaysScrollableScrollPhysics(), padding: EdgeInsets.zero, itemCount: 5, itemBuilder: (context, index) => LabResultItemView( onTap: () {}, labOrder: null, index: index, isLoading: true, ), ) : (labViewModel.patientLabOrders.isNotEmpty ? ListView.builder( shrinkWrap: true, physics: NeverScrollableScrollPhysics(), padding: EdgeInsets.zero, itemCount: labViewModel.filteredLabOrders.length, itemBuilder: (context, index) { final group = labViewModel.filteredLabOrders[index]; final isExpanded = expandedIndex == index; return AnimationConfiguration.staggeredList( position: index, duration: const Duration(milliseconds: 500), child: SlideAnimation( verticalOffset: 100.0, child: FadeInAnimation( child: AnimatedContainer( duration: Duration(milliseconds: 300), curve: Curves.easeInOut, margin: EdgeInsets.symmetric(vertical: 8.h), decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.h, hasShadow: true), child: InkWell( onTap: () { setState(() { expandedIndex = isExpanded ? null : index; }); }, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: EdgeInsets.all(16.h), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Wrap( direction: Axis.horizontal, spacing: 4.h, runSpacing: 4.h, children: [ AppCustomChipWidget( richText: Row( children: [ "${group.testDetails!.length} ".toText10(color: AppColors.successColor, isEnglishOnly: true), LocaleKeys.tests.tr(context: context).toText10(color: AppColors.successColor), ], ), labelText: "${group.testDetails!.length} ${LocaleKeys.tests.tr(context: context)}", backgroundColor: AppColors.successColor.withOpacity(0.1), textColor: AppColors.successColor, ), AppCustomChipWidget( labelText: "${_appState.isArabic() ? group.isInOutPatientDescriptionN : group.isInOutPatientDescription}", backgroundColor: AppColors.warningColorYellow.withOpacity(0.1), textColor: AppColors.warningColorYellow, ) ], ), Icon(isExpanded ? Icons.expand_less : Icons.expand_more), ], ), SizedBox(height: 8.h), Row( mainAxisSize: MainAxisSize.min, children: [ Image.network( group.doctorImageURL ?? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png", width: 24.w, height: 24.h, fit: BoxFit.cover, ).circle(100), SizedBox(width: 8.h), Expanded(child: (group.doctorName ?? group.doctorNameEnglish ?? "").toString().toText14(isBold: true)), ], ), SizedBox(height: 8.h), Wrap( direction: Axis.horizontal, spacing: 4.h, runSpacing: 4.h, children: [ Directionality( textDirection: ui.TextDirection.ltr, child: AppCustomChipWidget( labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(group.orderDate ?? ""), false), isEnglishOnly: true, )), AppCustomChipWidget( labelText: (group.projectName ?? ""), ), AppCustomChipWidget( labelText: (group.clinicDescription ?? ""), ), ], ), ], ), ), AnimatedSwitcher( duration: Duration(milliseconds: 500), switchInCurve: Curves.easeIn, switchOutCurve: Curves.easeOut, transitionBuilder: (Widget child, Animation animation) { return FadeTransition( opacity: animation, child: SizeTransition( sizeFactor: animation, axisAlignment: 0.0, child: child, ), ); }, child: isExpanded ? Container( key: ValueKey(index), padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 0.h), child: Column( children: [ ListView.separated( shrinkWrap: true, physics: NeverScrollableScrollPhysics(), padding: EdgeInsets.zero, itemBuilder: (cxt, index) { PatientLabOrdersResponseModel order = group; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ "• ${order.testDetails![index].description!}".toText14(isBold: true, isEnglishOnly: true), SizedBox(height: 4.h), order.testDetails![index].testDescriptionEn!.toText12(isBold: true, color: AppColors.textColorLight, isEnglishOnly: true), // Row( // mainAxisSize: MainAxisSize.min, // children: [ // Image.network( // order.doctorImageURL ?? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png", // width: 24.w, // height: 24.h, // fit: BoxFit.cover, // ).circle(100), // SizedBox(width: 8.h), // Expanded(child: (order.doctorName ?? order.doctorNameEnglish ?? "").toString().toText14(isBold: true)), // ], // ), // SizedBox(height: 8.h), // Wrap( // direction: Axis.horizontal, // spacing: 4.h, // runSpacing: 4.h, // children: [ // AppCustomChipWidget( // labelText: ("${LocaleKeys.orderNo.tr(context: context)}: ${order.orderNo!}"), isEnglishOnly: true, // ), // Directionality( // textDirection: ui.TextDirection.ltr, // child: AppCustomChipWidget( // labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(order.orderDate ?? ""), false), // isEnglishOnly: true, // )), // AppCustomChipWidget( // labelText: labViewModel.isSortByClinic ? (order.projectName ?? "") : (order.clinicDescription ?? ""), // ), // ], // ), // // Row( // // children: [ // // CustomButton( // // text: ("Order No: ".needTranslation + order.orderNo!), // // onPressed: () {}, // // backgroundColor: AppColors.greyColor, // // borderColor: AppColors.greyColor, // // textColor: AppColors.blackColor, // // fontSize: 10, // // isBold: true, // // borderRadius: 8, // // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // // height: 24.h, // // ), // // SizedBox(width: 8.h), // // CustomButton( // // text: DateUtil.formatDateToDate(DateUtil.convertStringToDate(order.orderDate ?? ""), false), // // onPressed: () {}, // // backgroundColor: AppColors.greyColor, // // borderColor: AppColors.greyColor, // // textColor: AppColors.blackColor, // // fontSize: 10, // // isBold: true, // // borderRadius: 8, // // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // // height: 24.h, // // ), // // ], // // ), // // SizedBox(height: 8.h), // // Row( // // children: [ // // CustomButton( // // text: model.isSortByClinic ? (order.clinicDescription ?? "") : (order.projectName ?? ""), // // onPressed: () {}, // // backgroundColor: AppColors.greyColor, // // borderColor: AppColors.greyColor, // // textColor: AppColors.blackColor, // // fontSize: 10, // // isBold: true, // // borderRadius: 8, // // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // // height: 24.h, // // ), // // ], // // ), // SizedBox(height: 12.h), // Row( // children: [ // Expanded(flex: 2, child: SizedBox()), // // Expanded( // // flex: 1, // // child: Container( // // height: 40.h, // // width: 40.w, // // decoration: RoundedRectangleBorder().toSmoothCornerDecoration( // // color: AppColors.textColor, // // borderRadius: 12, // // ), // // child: Padding( // // padding: EdgeInsets.all(12.h), // // child: Transform.flip( // // flipX: _appState.isArabic(), // // child: Utils.buildSvgWithAssets( // // icon: AppAssets.forward_arrow_icon_small, // // iconColor: AppColors.whiteColor, // // fit: BoxFit.contain, // // ), // // ), // // ), // // ).onPress(() { // // model.currentlySelectedPatientOrder = order; // // labProvider.getPatientLabResultByHospital(order); // // labProvider.getPatientSpecialResult(order); // // Navigator.of(context).push( // // CustomPageRoute(page: LabResultByClinic(labOrder: order)), // // ); // // }), // // ) // // Expanded( // flex: 2, // child: CustomButton( // icon: AppAssets.view_report_icon, // iconColor: AppColors.primaryRedColor, // iconSize: 16.h, // text: LocaleKeys.viewResults.tr(context: context), // onPressed: () { // labViewModel.currentlySelectedPatientOrder = order; // labProvider.getPatientLabResultByHospital(order); // labProvider.getPatientSpecialResult(order); // Navigator.of(context).push( // CustomPageRoute(page: LabResultByClinic(labOrder: order)), // ); // }, // backgroundColor: AppColors.secondaryLightRedColor, // borderColor: AppColors.secondaryLightRedColor, // textColor: AppColors.primaryRedColor, // fontSize: 14, // isBold: true, // borderRadius: 12, // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // height: 40.h, // ), // ) // ], // ), // SizedBox(height: 12.h), // Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h), // SizedBox(height: 12.h), ], ).paddingOnly(top: 16, bottom: 16); }, separatorBuilder: (cxt, index) => Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h), itemCount: group.testDetails!.length > 3 ? 3 : group.testDetails!.length), SizedBox(height: 16.h), CustomButton( text: "${LocaleKeys.viewResults.tr()} (${group.testDetails!.length})", onPressed: () { labProvider.currentlySelectedPatientOrder = group; labProvider.getPatientLabResultByHospital(group); labProvider.getPatientSpecialResult(group); Navigator.of(context).push( CustomPageRoute( page: LabResultByClinic(labOrder: group), ), ); }, backgroundColor: AppColors.infoColor.withAlpha(20), borderColor: AppColors.infoColor.withAlpha(0), textColor: AppColors.infoColor, fontSize: (isFoldable || isTablet) ? 12.f : 14.f, isBold: true, borderRadius: 12.r, padding: EdgeInsets.fromLTRB(10.w, 0, 10.w, 0), height: 40.h, iconSize: 14.h, icon: AppAssets.view_report_icon, iconColor: AppColors.infoColor, ), SizedBox(height: 16.h), ], ), ) : SizedBox.shrink(), ), ], ), ), ), ), )); }, ) : Utils.getNoDataWidget(context, noDataText: LocaleKeys.noLabResults.tr(context: context))) : // By Test or other tabs keep existing behavior (labViewModel.isLabOrdersLoading) ? Column( children: List.generate( 5, (index) => LabResultItemView( onTap: () {}, labOrder: null, index: index, isLoading: true, )), ) : AlphabeticScroll( alpahbetsAvailable: labViewModel.filteredIndexedCharacterForUniqueTest, details: labViewModel.filteredUniqueTestsList, labViewModel: labViewModel, rangeViewModel: rangeViewModel, appState: _appState, ) ], )); }, ), ); } Color getLabOrderStatusColor(num status) { switch (status) { case 44: return AppColors.warningColorYellow; case 45: return AppColors.warningColorYellow; case 16: return AppColors.successColor; case 17: return AppColors.successColor; default: return AppColors.greyColor; } } String getLabOrderStatusText(num status) { switch (status) { case 44: return LocaleKeys.resultsPending.tr(context: context); case 45: return LocaleKeys.resultsPending.tr(context: context); case 16: return LocaleKeys.resultsAvailable.tr(context: context); case 17: return LocaleKeys.resultsAvailable.tr(context: context); default: return ""; } } getLabSuggestions(LabViewModel model) { if (model.patientLabOrders.isEmpty) { return []; } return model.patientLabOrders.map((m) => m.testDetails).toList(); } } \ No newline at end of file +import 'dart:async'; import 'dart:convert'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/enums.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/features/lab/lab_view_model.dart'; import 'package:hmg_patient_app_new/features/lab/models/resp_models/patient_lab_orders_response_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/presentation/lab/lab_result_item_view.dart'; import 'package:hmg_patient_app_new/presentation/lab/lab_result_via_clinic/LabResultByClinic.dart'; import 'package:hmg_patient_app_new/presentation/lab/search_lab_report.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/utils/date_util.dart'; import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/appbar/collapsing_toolbar.dart'; import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/chip/custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart'; import 'package:hmg_patient_app_new/widgets/date_range_selector/viewmodel/date_range_view_model.dart'; import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import 'package:provider/provider.dart'; import 'alphabeticScroll.dart'; import 'dart:ui' as ui; class LabOrdersPage extends StatefulWidget { const LabOrdersPage({super.key}); @override State createState() => _LabOrdersPageState(); } class _LabOrdersPageState extends State { late LabViewModel labProvider; late DateRangeSelectorRangeViewModel rangeViewModel; late AppState _appState; List?> labSuggestions = []; int? expandedIndex; String? selectedFilterText = ''; int activeIndex = 0; @override void initState() { scheduleMicrotask(() { labProvider.initLabProvider(); }); super.initState(); } @override Widget build(BuildContext context) { labProvider = Provider.of(context, listen: false); rangeViewModel = Provider.of(context); _appState = getIt(); return CollapsingListView( title: LocaleKeys.labResults.tr(context: context), search: () async { if (labProvider.isLabOrdersLoading) { return; } else { String? value = await Navigator.of(context).push( CustomPageRoute( page: SearchLabResultsContent(labSuggestionsList: labProvider.labSuggestions), fullScreenDialog: true, direction: AxisDirection.down, ), ); if (value != null) { selectedFilterText = value; labProvider.filterLabReports(value); } } }, child: Consumer( builder: (context, labViewModel, child) { return SingleChildScrollView( physics: NeverScrollableScrollPhysics(), padding: EdgeInsets.all(24.h), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: CustomTabBar( activeTextColor: Color(0xffED1C2B), activeBackgroundColor: Color(0xffED1C2B).withValues(alpha: .1), tabs: [ CustomTabBarModel(null, LocaleKeys.byVisit.tr()), CustomTabBarModel(null, LocaleKeys.byTest.tr()), // CustomTabBarModel(null, "Completed".needTranslation), ], onTabChange: (index) { activeIndex = index; setState(() {}); }, ), ), ], ), if (activeIndex == 0) Padding( padding: EdgeInsets.symmetric(vertical: 10.h), child: Row( children: [ // CustomButton( // text: LocaleKeys.byClinic.tr(context: context), // onPressed: () { // labViewModel.setIsSortByClinic(true); // }, // backgroundColor: labViewModel.isSortByClinic ? AppColors.bgRedLightColor : AppColors.whiteColor, // borderColor: labViewModel.isSortByClinic ? AppColors.primaryRedColor : AppColors.textColor.withValues(alpha: 0.2), // textColor: labViewModel.isSortByClinic ? AppColors.primaryRedColor : AppColors.blackColor, // fontSize: 12.f, // isBold: true, // borderRadius: 10, // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // height: 40.h, // ), // SizedBox(width: 8.h), // CustomButton( // text: LocaleKeys.byHospital.tr(context: context), // onPressed: () { // labViewModel.setIsSortByClinic(false); // }, // backgroundColor: labViewModel.isSortByClinic ? AppColors.whiteColor : AppColors.bgRedLightColor, // borderColor: labViewModel.isSortByClinic ? AppColors.textColor.withValues(alpha: 0.2) : AppColors.primaryRedColor, // textColor: labViewModel.isSortByClinic ? AppColors.blackColor : AppColors.primaryRedColor, // fontSize: 12, // isBold: true, // borderRadius: 10, // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // height: 40.h, // ), ], ), ), SizedBox(height: 8.h), selectedFilterText!.isNotEmpty ? Column( children: [ AppCustomChipWidget( labelText: selectedFilterText!, backgroundColor: AppColors.alertColor, textColor: AppColors.whiteColor, deleteIcon: AppAssets.close_bottom_sheet_icon, deleteIconColor: AppColors.whiteColor, deleteIconHasColor: true, isEnglishOnly: true, onDeleteTap: () { selectedFilterText = ""; labProvider.filterLabReports(""); }, ), SizedBox(height: 8.h), ], ) : SizedBox(), activeIndex == 0 ? // By Visit - show grouped view when available labViewModel.isLabOrdersLoading ? ListView.builder( shrinkWrap: true, physics: AlwaysScrollableScrollPhysics(), padding: EdgeInsets.zero, itemCount: 5, itemBuilder: (context, index) => LabResultItemView( onTap: () {}, labOrder: null, index: index, isLoading: true, ), ) : (labViewModel.patientLabOrders.isNotEmpty ? ListView.builder( shrinkWrap: true, physics: NeverScrollableScrollPhysics(), padding: EdgeInsets.zero, itemCount: labViewModel.filteredLabOrders.length, itemBuilder: (context, index) { final group = labViewModel.filteredLabOrders[index]; final isExpanded = expandedIndex == index; return AnimationConfiguration.staggeredList( position: index, duration: const Duration(milliseconds: 500), child: SlideAnimation( verticalOffset: 100.0, child: FadeInAnimation( child: AnimatedContainer( duration: Duration(milliseconds: 300), curve: Curves.easeInOut, margin: EdgeInsets.symmetric(vertical: 8.h), decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.h, hasShadow: true), child: InkWell( onTap: () { setState(() { expandedIndex = isExpanded ? null : index; }); }, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: EdgeInsets.all(16.h), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Wrap( direction: Axis.horizontal, spacing: 4.h, runSpacing: 4.h, children: [ AppCustomChipWidget( richText: Row( children: [ "${group.testDetails!.length} ".toText10(color: AppColors.successColor, isEnglishOnly: true, weight: FontWeight.w600), LocaleKeys.tests.tr(context: context).toText10(color: AppColors.successColor, weight: FontWeight.w600), ], ), labelText: "${group.testDetails!.length} ${LocaleKeys.tests.tr(context: context)}", backgroundColor: AppColors.successColor.withOpacity(0.1), textColor: AppColors.successColor, ), AppCustomChipWidget( labelText: "${_appState.isArabic() ? group.isInOutPatientDescriptionN : group.isInOutPatientDescription}", backgroundColor: AppColors.warningColorYellow.withOpacity(0.1), textColor: AppColors.warningColorYellow, ) ], ), Icon(isExpanded ? Icons.expand_less : Icons.expand_more), ], ), SizedBox(height: 8.h), Row( mainAxisSize: MainAxisSize.min, children: [ Image.network( group.doctorImageURL ?? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png", width: 24.w, height: 24.h, fit: BoxFit.cover, ).circle(100), SizedBox(width: 8.h), Expanded(child: (group.doctorName ?? group.doctorNameEnglish ?? "").toString().toText14(isBold: true)), ], ), SizedBox(height: 8.h), Wrap( direction: Axis.horizontal, spacing: 4.h, runSpacing: 4.h, children: [ Directionality( textDirection: ui.TextDirection.ltr, child: AppCustomChipWidget( labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(group.orderDate ?? ""), false), isEnglishOnly: true, )), AppCustomChipWidget( labelText: (group.projectName ?? ""), ), AppCustomChipWidget( labelText: (group.clinicDescription ?? ""), ), ], ), ], ), ), AnimatedSwitcher( duration: Duration(milliseconds: 500), switchInCurve: Curves.easeIn, switchOutCurve: Curves.easeOut, transitionBuilder: (Widget child, Animation animation) { return FadeTransition( opacity: animation, child: SizeTransition( sizeFactor: animation, axisAlignment: 0.0, child: child, ), ); }, child: isExpanded ? Container( key: ValueKey(index), padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 0.h), child: Column( children: [ ListView.separated( shrinkWrap: true, physics: NeverScrollableScrollPhysics(), padding: EdgeInsets.zero, itemBuilder: (cxt, index) { PatientLabOrdersResponseModel order = group; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ "• ${order.testDetails![index].description!}".toText14(isBold: true, isEnglishOnly: true), SizedBox(height: 4.h), order.testDetails![index].testDescriptionEn!.toText12(isBold: true, color: AppColors.textColorLight, isEnglishOnly: true), // Row( // mainAxisSize: MainAxisSize.min, // children: [ // Image.network( // order.doctorImageURL ?? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png", // width: 24.w, // height: 24.h, // fit: BoxFit.cover, // ).circle(100), // SizedBox(width: 8.h), // Expanded(child: (order.doctorName ?? order.doctorNameEnglish ?? "").toString().toText14(isBold: true)), // ], // ), // SizedBox(height: 8.h), // Wrap( // direction: Axis.horizontal, // spacing: 4.h, // runSpacing: 4.h, // children: [ // AppCustomChipWidget( // labelText: ("${LocaleKeys.orderNo.tr(context: context)}: ${order.orderNo!}"), isEnglishOnly: true, // ), // Directionality( // textDirection: ui.TextDirection.ltr, // child: AppCustomChipWidget( // labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(order.orderDate ?? ""), false), // isEnglishOnly: true, // )), // AppCustomChipWidget( // labelText: labViewModel.isSortByClinic ? (order.projectName ?? "") : (order.clinicDescription ?? ""), // ), // ], // ), // // Row( // // children: [ // // CustomButton( // // text: ("Order No: ".needTranslation + order.orderNo!), // // onPressed: () {}, // // backgroundColor: AppColors.greyColor, // // borderColor: AppColors.greyColor, // // textColor: AppColors.blackColor, // // fontSize: 10, // // isBold: true, // // borderRadius: 8, // // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // // height: 24.h, // // ), // // SizedBox(width: 8.h), // // CustomButton( // // text: DateUtil.formatDateToDate(DateUtil.convertStringToDate(order.orderDate ?? ""), false), // // onPressed: () {}, // // backgroundColor: AppColors.greyColor, // // borderColor: AppColors.greyColor, // // textColor: AppColors.blackColor, // // fontSize: 10, // // isBold: true, // // borderRadius: 8, // // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // // height: 24.h, // // ), // // ], // // ), // // SizedBox(height: 8.h), // // Row( // // children: [ // // CustomButton( // // text: model.isSortByClinic ? (order.clinicDescription ?? "") : (order.projectName ?? ""), // // onPressed: () {}, // // backgroundColor: AppColors.greyColor, // // borderColor: AppColors.greyColor, // // textColor: AppColors.blackColor, // // fontSize: 10, // // isBold: true, // // borderRadius: 8, // // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // // height: 24.h, // // ), // // ], // // ), // SizedBox(height: 12.h), // Row( // children: [ // Expanded(flex: 2, child: SizedBox()), // // Expanded( // // flex: 1, // // child: Container( // // height: 40.h, // // width: 40.w, // // decoration: RoundedRectangleBorder().toSmoothCornerDecoration( // // color: AppColors.textColor, // // borderRadius: 12, // // ), // // child: Padding( // // padding: EdgeInsets.all(12.h), // // child: Transform.flip( // // flipX: _appState.isArabic(), // // child: Utils.buildSvgWithAssets( // // icon: AppAssets.forward_arrow_icon_small, // // iconColor: AppColors.whiteColor, // // fit: BoxFit.contain, // // ), // // ), // // ), // // ).onPress(() { // // model.currentlySelectedPatientOrder = order; // // labProvider.getPatientLabResultByHospital(order); // // labProvider.getPatientSpecialResult(order); // // Navigator.of(context).push( // // CustomPageRoute(page: LabResultByClinic(labOrder: order)), // // ); // // }), // // ) // // Expanded( // flex: 2, // child: CustomButton( // icon: AppAssets.view_report_icon, // iconColor: AppColors.primaryRedColor, // iconSize: 16.h, // text: LocaleKeys.viewResults.tr(context: context), // onPressed: () { // labViewModel.currentlySelectedPatientOrder = order; // labProvider.getPatientLabResultByHospital(order); // labProvider.getPatientSpecialResult(order); // Navigator.of(context).push( // CustomPageRoute(page: LabResultByClinic(labOrder: order)), // ); // }, // backgroundColor: AppColors.secondaryLightRedColor, // borderColor: AppColors.secondaryLightRedColor, // textColor: AppColors.primaryRedColor, // fontSize: 14, // isBold: true, // borderRadius: 12, // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // height: 40.h, // ), // ) // ], // ), // SizedBox(height: 12.h), // Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h), // SizedBox(height: 12.h), ], ).paddingOnly(top: 16, bottom: 16); }, separatorBuilder: (cxt, index) => Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h), itemCount: group.testDetails!.length > 3 ? 3 : group.testDetails!.length), SizedBox(height: 16.h), CustomButton( text: "${LocaleKeys.viewResults.tr()} (${group.testDetails!.length})", onPressed: () { labProvider.currentlySelectedPatientOrder = group; labProvider.getPatientLabResultByHospital(group); labProvider.getPatientSpecialResult(group); Navigator.of(context).push( CustomPageRoute( page: LabResultByClinic(labOrder: group), ), ); }, backgroundColor: AppColors.infoColor.withAlpha(20), borderColor: AppColors.infoColor.withAlpha(0), textColor: AppColors.infoColor, fontSize: (isFoldable || isTablet) ? 12.f : 14.f, isBold: true, borderRadius: 12.r, padding: EdgeInsets.fromLTRB(10.w, 0, 10.w, 0), height: 40.h, iconSize: 14.h, icon: AppAssets.view_report_icon, iconColor: AppColors.infoColor, ), SizedBox(height: 16.h), ], ), ) : SizedBox.shrink(), ), ], ), ), ), ), )); }, ) : Utils.getNoDataWidget(context, noDataText: LocaleKeys.noLabResults.tr(context: context))) : // By Test or other tabs keep existing behavior (labViewModel.isLabOrdersLoading) ? Column( children: List.generate( 5, (index) => LabResultItemView( onTap: () {}, labOrder: null, index: index, isLoading: true, )), ) : AlphabeticScroll( alpahbetsAvailable: labViewModel.filteredIndexedCharacterForUniqueTest, details: labViewModel.filteredUniqueTestsList, labViewModel: labViewModel, rangeViewModel: rangeViewModel, appState: _appState, ) ], )); }, ), ); } Color getLabOrderStatusColor(num status) { switch (status) { case 44: return AppColors.warningColorYellow; case 45: return AppColors.warningColorYellow; case 16: return AppColors.successColor; case 17: return AppColors.successColor; default: return AppColors.greyColor; } } String getLabOrderStatusText(num status) { switch (status) { case 44: return LocaleKeys.resultsPending.tr(context: context); case 45: return LocaleKeys.resultsPending.tr(context: context); case 16: return LocaleKeys.resultsAvailable.tr(context: context); case 17: return LocaleKeys.resultsAvailable.tr(context: context); default: return ""; } } getLabSuggestions(LabViewModel model) { if (model.patientLabOrders.isEmpty) { return []; } return model.patientLabOrders.map((m) => m.testDetails).toList(); } } \ No newline at end of file diff --git a/lib/presentation/lab/lab_result_via_clinic/lab_ai_analysis_detailed_page.dart b/lib/presentation/lab/lab_result_via_clinic/lab_ai_analysis_detailed_page.dart index 8d25ef37..8c3739ba 100644 --- a/lib/presentation/lab/lab_result_via_clinic/lab_ai_analysis_detailed_page.dart +++ b/lib/presentation/lab/lab_result_via_clinic/lab_ai_analysis_detailed_page.dart @@ -50,7 +50,7 @@ class _LabAiAnalysisDetailedPageState extends State { children: [ SizedBox(height: 10.h), Container( - decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 12.r, side: BorderSide(width: 1, color: Color(0xFF0B85F7))), + decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.transparent, borderRadius: 12.r, side: BorderSide(width: 1, color: Color(0xFF0B85F7))), padding: EdgeInsets.all(16.r), child: (analysis.summary ?? "").toText14(color: AppColors.textColorLight, height: 1.5, weight: FontWeight.w400), ), @@ -88,7 +88,7 @@ class _LabAiAnalysisDetailedPageState extends State { children: [ SizedBox(height: 10.h), Container( - decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 12.r, side: BorderSide(width: 1, color: Color(0xFFFFAF15))), + decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.transparent, borderRadius: 12.r, side: BorderSide(width: 1, color: Color(0xFFFFAF15))), padding: EdgeInsets.all(16.r), child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -109,7 +109,8 @@ class _LabAiAnalysisDetailedPageState extends State { children: [ SizedBox(height: 10.h), Container( - decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 12.r), + decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.transparent + , borderRadius: 12.r), padding: EdgeInsets.all(16.r), child: Column( crossAxisAlignment: CrossAxisAlignment.start, diff --git a/lib/presentation/lab/lab_result_via_clinic/lab_order_result_item.dart b/lib/presentation/lab/lab_result_via_clinic/lab_order_result_item.dart index 84e69e53..7ae38db1 100644 --- a/lib/presentation/lab/lab_result_via_clinic/lab_order_result_item.dart +++ b/lib/presentation/lab/lab_result_via_clinic/lab_order_result_item.dart @@ -49,48 +49,38 @@ class LabOrderResultItem extends StatelessWidget { SizedBox(height: 12.h), Directionality( textDirection: ui.TextDirection.ltr, - child: Row( - mainAxisSize: MainAxisSize.max, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Flexible( + Text( + "${tests?.resultValue} ${tests?.uOM}", + style: TextStyle( + fontSize: 24.f, + fontWeight: FontWeight.w600, + fontFamily: 'Poppins', + color: tests!.checkIfGraphShouldBeDisplayed() + ? context.read().getColor( + tests?.calculatedResultFlag ?? "", + ) + : Colors.grey.shade700, + letterSpacing: -1, + ), + ), + // SizedBox( + // height: 2.h, + // ), + Visibility( + visible: tests?.referanceRange != null, child: Text( - "${tests?.resultValue} ${tests?.uOM}", + "(${LocaleKeys.referenceRange.tr(context: context)}: ${tests?.referanceRange})", style: TextStyle( - fontSize: 24.f, + fontSize: 12.f, fontWeight: FontWeight.w600, fontFamily: 'Poppins', - color: tests!.checkIfGraphShouldBeDisplayed() - ? context.read().getColor( - tests?.calculatedResultFlag ?? "", - ) - : Colors.grey.shade700, - letterSpacing: -2, - ), - ), - ), - SizedBox( - width: 4.h, - ), - Visibility( - // visible: tests?.checkIfGraphShouldBeDisplayed() == true, - visible: true, - child: Expanded( - flex: 2, - child: Visibility( - visible: tests?.referanceRange != null, - child: Text( - "(${LocaleKeys.referenceRange.tr(context: context)}: ${tests?.referanceRange})", - style: TextStyle( - fontSize: 12.f, - fontWeight: FontWeight.w600, - fontFamily: 'Poppins', - color: AppColors.greyTextColor, - ), - // overflow: TextOverflow.ellipsis, - // maxLines: 2, - softWrap: true, - ), + color: AppColors.greyTextColor, ), + softWrap: true, ), ) ], diff --git a/lib/presentation/rate_appointment/rate_appointment_doctor.dart b/lib/presentation/rate_appointment/rate_appointment_doctor.dart index c3e7b526..0020624c 100644 --- a/lib/presentation/rate_appointment/rate_appointment_doctor.dart +++ b/lib/presentation/rate_appointment/rate_appointment_doctor.dart @@ -1,5 +1,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:hmg_patient_app_new/core/app_state.dart'; +import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; @@ -90,7 +92,7 @@ class _RateAppointmentDoctorState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - "Please rate the doctor".toText16(isBold: true), + LocaleKeys.rateTheDoctor.tr(context: context).toText16(isBold: true), SizedBox(height: 12), Row( mainAxisAlignment: MainAxisAlignment.center, @@ -139,10 +141,22 @@ class _RateAppointmentDoctorState extends State { child: Padding( padding: EdgeInsets.all(16.0), child: TextField( - maxLines: 4, + // style: TextStyle( + // fontSize: 14.f, + // fontWeight: FontWeight.w400, + // color: Color(0xff2B353E), + // letterSpacing: 0, + // fontFamily: getIt.get().getLanguageCode() == "ar" ? 'CairoArabic' : 'Poppins', + // ), decoration: InputDecoration.collapsed( hintText: LocaleKeys.notes.tr(context: context), + hintStyle: TextStyle( + fontSize: 16.f, + fontWeight: FontWeight.w600, + letterSpacing: -0.4, + fontFamily: getIt.get().getLanguageCode() == "ar" ? 'CairoArabic' : 'Poppins', + ), ), onChanged: (value) { setState(() { diff --git a/lib/presentation/symptoms_checker/widgets/selected_organs_section.dart b/lib/presentation/symptoms_checker/widgets/selected_organs_section.dart index 13688e0d..52eef749 100644 --- a/lib/presentation/symptoms_checker/widgets/selected_organs_section.dart +++ b/lib/presentation/symptoms_checker/widgets/selected_organs_section.dart @@ -57,7 +57,7 @@ class _SelectedOrgansSectionState extends State { LocaleKeys.selectedOrgans.tr(context: context), style: TextStyle( fontSize: 16.f, - isBold: true, + // isBold: true, color: AppColors.textColor, ), ), @@ -78,7 +78,7 @@ class _SelectedOrgansSectionState extends State { style: TextStyle( color: AppColors.whiteColor, fontSize: 12.f, - isBold: true, + // isBold: true, ), ), ), diff --git a/lib/widgets/datepicker_widget.dart b/lib/widgets/datepicker_widget.dart index bbbd2a0a..364897df 100644 --- a/lib/widgets/datepicker_widget.dart +++ b/lib/widgets/datepicker_widget.dart @@ -55,7 +55,7 @@ class DatePickerWidget extends StatelessWidget { labelText, style: TextStyle( fontSize: 12.f, - isBold: true, + // isBold: true, color: Color(0xff898A8D), letterSpacing: -0.2, height: 18 / 12, @@ -102,7 +102,7 @@ class DatePickerWidget extends StatelessWidget { style: TextStyle( fontSize: 14.f, height: 21 / 14, - isBold: true, + // isBold: true, color: (selectedValue != null && selectedValue!.isNotEmpty) ? const Color(0xff2E3039) : const Color(0xffB0B0B0), letterSpacing: -0.2, ), From 708cbb138dede8cb88b97a21af502600ca925327 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Wed, 8 Apr 2026 15:55:56 +0300 Subject: [PATCH 6/8] Updates # Conflicts: # lib/presentation/radiology/radiology_result_page.dart --- assets/langs/ar-SA.json | 5 +++-- assets/langs/en-US.json | 5 +++-- lib/generated/locale_keys.g.dart | 1 + lib/presentation/appointments/appointment_details_page.dart | 6 +++--- lib/presentation/radiology/radiology_result_page.dart | 2 +- 5 files changed, 11 insertions(+), 8 deletions(-) diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index 137faf3f..822b73dd 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -1578,7 +1578,7 @@ "noFreeSlot": "لا توجد مواعيد متاحة في التاريخ المحدد. يرجى اختيار تاريخ آخر أو إعادة المحاولة لاحقاً.", "noThanksIKnowTheClinic": "لا، شكراً. أنا أعرف العيادة.", "unableToSendOTP": "تعذر إرسال رمز التحقق لمرة واحدة", - "loadingAIAnalysis": "جارٍ تحليل نتائج المختبر، يرجى التحلي بالصبر والسماح للذكاء الاصطناعي بالقيام بالمهمة، قد يستغرق هذا بعض الوقت.", + "loadingAIAnalysis": "نقوم بتحليل نتائجك، يرجى التحلي بالصبر والسماح للذكاء الاصطناعي بالقيام بالمهمة، قد يستغرق هذا بعض الوقت.", "symptoms": "أعراض", "insuranceInActive": "التأمين غير نشط", "insuranceInActiveContactSupport": "لديك تأمين ساري المفعول، ولكنه غير مُفعّل حاليًا في مجموعة حبيب الطبية. يُرجى التواصل مع خدمة عملاء مجموعة حبيب الطبية.", @@ -1690,5 +1690,6 @@ "openFiles": "فتح الملفات", "generateAiAnalysisRadResult": "بإنشاء تحليل الذكاء الاصطناعي لهذا التقرير", "grantLocationPermission": "يرجى منح إذن الوصول إلى الموقع من إعدادات التطبيق للحصول على نتائج أفضل.", - "NoBookedAppointments": "لا توجد مواعيد محجوزة" + "NoBookedAppointments": "لا توجد مواعيد محجوزة", + "aiDisclaimerRad": "سيتم مشاركة بيانات نتائج الأشعة الخاصة بك بشكل آمن مع محلل الذكاء الاصطناعي لدينا لتحليلها. يساعد هذا في توفير رؤى صحية مخصصة. هل ترغب في المتابعة؟" } diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index dbd77443..27a67857 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -1572,7 +1572,7 @@ "contextDependent": "Context Dependent", "calculatedValue": "Calculated Value", "calculationFormula": "Calculation Formula", - "loadingAIAnalysis": "Analysing your lab results, Please be patient and let the AI do the magic, This might take some time.", + "loadingAIAnalysis": "Analysing your results, Please be patient and let the AI do the magic, This might take some time.", "symptoms": "Symptoms", "insuranceInActive": "Insurance Inactive", "insuranceInActiveContactSupport": "You have a valid insurance but it is currently inactive in HMG. Please contact HMG customer support to activate it.", @@ -1682,5 +1682,6 @@ "openFiles": "Open Files", "generateAiAnalysisRadResult": "Generate AI analysis for this result", "grantLocationPermission": "Please grant location permission from app settings to see better results.", - "NoBookedAppointments": "No Booked Appointments" + "NoBookedAppointments": "No Booked Appointments", + "aiDisclaimerRad": "Your radiology result data will be securely shared with our AI Analyzer for analysis. This helps provide personalized health insights. Do you want to proceed?" } diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index c6c4182f..29656b23 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -1682,5 +1682,6 @@ abstract class LocaleKeys { static const generateAiAnalysisRadResult = 'generateAiAnalysisRadResult'; static const grantLocationPermission = 'grantLocationPermission'; static const NoBookedAppointments = 'NoBookedAppointments'; + static const aiDisclaimerRad = 'aiDisclaimerRad'; } diff --git a/lib/presentation/appointments/appointment_details_page.dart b/lib/presentation/appointments/appointment_details_page.dart index 0ba38bd9..31cd5403 100644 --- a/lib/presentation/appointments/appointment_details_page.dart +++ b/lib/presentation/appointments/appointment_details_page.dart @@ -612,7 +612,7 @@ class _AppointmentDetailsPageState extends State { isLocked: false, ).toShimmer2() : MedicalFileCard( - label: !((myAppointmentsVM.appointmentRatedResponseModel!).isAppointmentRated ?? true) + label: !((myAppointmentsVM.appointmentRatedResponseModel!).isAllowedToRate ?? false) ? LocaleKeys.ratingSubmitted.tr(context: context) : LocaleKeys.doctorRatingAppointment.tr(context: context), textColor: AppColors.blackColor, @@ -620,9 +620,9 @@ class _AppointmentDetailsPageState extends State { svgIcon: AppAssets.appointmentRatingIcon, isLargeText: true, iconSize: 36.w, - isLocked: !(myAppointmentsVM.appointmentRatedResponseModel!.isAppointmentRated ?? true), + isLocked: !(myAppointmentsVM.appointmentRatedResponseModel!.isAllowedToRate ?? false), ).onPress(() { - if(!(myAppointmentsVM.appointmentRatedResponseModel!.isAppointmentRated ?? true)) { + if ((myAppointmentsVM.appointmentRatedResponseModel!.isAllowedToRate ?? true)) { showCommonBottomSheetWithoutHeight( context, title: LocaleKeys.doctorRating.tr(context: context), diff --git a/lib/presentation/radiology/radiology_result_page.dart b/lib/presentation/radiology/radiology_result_page.dart index 96b35009..39a268ad 100644 --- a/lib/presentation/radiology/radiology_result_page.dart +++ b/lib/presentation/radiology/radiology_result_page.dart @@ -258,7 +258,7 @@ class _RadiologyResultPageState extends State { ).paddingSymmetrical(24.h, 12.h).onPress(() async { final _dialogService = getIt.get(); await _dialogService.showCommonBottomSheetWithoutH( - message: LocaleKeys.aiDisclaimer.tr(), + message: LocaleKeys.aiDisclaimerRad.tr(), label: LocaleKeys.consent.tr(), okLabel: LocaleKeys.acceptLbl.tr(), cancelLabel: LocaleKeys.rejectView.tr(), From a5f7bd80b2512acdb565c05130329955137b1d61 Mon Sep 17 00:00:00 2001 From: Sultan khan Date: Wed, 8 Apr 2026 16:17:22 +0300 Subject: [PATCH 7/8] updates --- .../lab_ai_analysis_detailed_page.dart | 24 +++- lib/widgets/input_widget.dart | 114 ++++++++++-------- 2 files changed, 81 insertions(+), 57 deletions(-) diff --git a/lib/presentation/lab/lab_result_via_clinic/lab_ai_analysis_detailed_page.dart b/lib/presentation/lab/lab_result_via_clinic/lab_ai_analysis_detailed_page.dart index 8c3739ba..6fb0f393 100644 --- a/lib/presentation/lab/lab_result_via_clinic/lab_ai_analysis_detailed_page.dart +++ b/lib/presentation/lab/lab_result_via_clinic/lab_ai_analysis_detailed_page.dart @@ -45,12 +45,15 @@ class _LabAiAnalysisDetailedPageState extends State { if (analysis.summary != null && analysis.summary!.isNotEmpty) { expandableItems.add( ExpandableListItem( + backgroundColor: Colors.transparent, + expandedBackgroundColor:Colors.transparent , title: LocaleKeys.summary.tr(context: context).toText18(weight: FontWeight.w700, color: AppColors.blackColor), initiallyExpanded: true, children: [ SizedBox(height: 10.h), Container( - decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.transparent, borderRadius: 12.r, side: BorderSide(width: 1, color: Color(0xFF0B85F7))), + + decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 12.r, side: BorderSide(width: 1, color: Color(0xFF0B85F7))), padding: EdgeInsets.all(16.r), child: (analysis.summary ?? "").toText14(color: AppColors.textColorLight, height: 1.5, weight: FontWeight.w400), ), @@ -64,6 +67,9 @@ class _LabAiAnalysisDetailedPageState extends State { if (analysis.aiGeneratedAttributes != null && analysis.aiGeneratedAttributes!.isNotEmpty) { expandableItems.add( ExpandableListItem( + + backgroundColor: Colors.transparent, + expandedBackgroundColor:Colors.transparent , title: LocaleKeys.labResults.tr(context: context).toText18(weight: FontWeight.w700, color: AppColors.blackColor), children: [ SizedBox(height: 10.h), @@ -84,11 +90,13 @@ class _LabAiAnalysisDetailedPageState extends State { if (analysis.aiPredictions != null && analysis.aiPredictions!.isNotEmpty) { expandableItems.add( ExpandableListItem( + backgroundColor: Colors.transparent, + expandedBackgroundColor:Colors.transparent , title: LocaleKeys.prediction.tr(context: context).toText18(weight: FontWeight.w700, color: AppColors.blackColor), children: [ SizedBox(height: 10.h), Container( - decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.transparent, borderRadius: 12.r, side: BorderSide(width: 1, color: Color(0xFFFFAF15))), + decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 12.r, side: BorderSide(width: 1, color: Color(0xFFFFAF15))), padding: EdgeInsets.all(16.r), child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -105,12 +113,13 @@ class _LabAiAnalysisDetailedPageState extends State { if (analysis.aiRecommendations != null && analysis.aiRecommendations!.isNotEmpty) { expandableItems.add( ExpandableListItem( + backgroundColor: Colors.transparent, + expandedBackgroundColor:Colors.transparent , title: LocaleKeys.suggestions.tr(context: context).toText18(weight: FontWeight.w700, color: AppColors.blackColor), children: [ SizedBox(height: 10.h), Container( - decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.transparent - , borderRadius: 12.r), + decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 12.r), padding: EdgeInsets.all(16.r), child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -153,6 +162,8 @@ class _LabAiAnalysisDetailedPageState extends State { if (analysis.riskFactors != null && analysis.riskFactors!.isNotEmpty) { expandableItems.add( ExpandableListItem( + backgroundColor: Colors.transparent, + expandedBackgroundColor:Colors.transparent , title: LocaleKeys.riskFactors.tr(context: context).toText18(weight: FontWeight.w700, color: AppColors.blackColor), children: [ SizedBox(height: 10.h), @@ -222,6 +233,8 @@ class _LabAiAnalysisDetailedPageState extends State { if (analysis.prevention != null && analysis.prevention!.isNotEmpty) { expandableItems.add( ExpandableListItem( + backgroundColor: Colors.transparent, + expandedBackgroundColor:Colors.transparent , title: LocaleKeys.prevention.tr(context: context).toText18(weight: FontWeight.w700, color: AppColors.blackColor), children: [ SizedBox(height: 10.h), @@ -309,10 +322,11 @@ class _LabAiAnalysisDetailedPageState extends State { else CustomExpandableList( expansionMode: ExpansionMode.exactlyOne, - dividerColor: Color(0xff2b353e1a), + dividerColor: AppColors.dividerColor, itemPadding: EdgeInsets.symmetric(vertical: 16.h, horizontal: 14.h), items: expandableItems, theme: ExpandableListTheme.custom( + defaultTrailingIcon: Utils.buildSvgWithAssets(icon: AppAssets.arrow_down, height: 22.h, width: 22.w, iconColor: AppColors.textColor), ), ).paddingSymmetrical(16.w, 0.0), diff --git a/lib/widgets/input_widget.dart b/lib/widgets/input_widget.dart index 5b598c40..a134ac79 100644 --- a/lib/widgets/input_widget.dart +++ b/lib/widgets/input_widget.dart @@ -12,7 +12,6 @@ import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/dropdown/country_dropdown_widget.dart'; import 'package:hmg_patient_app_new/widgets/time_picker_widget.dart'; -import 'dart:ui' as ui; class TextInputWidget extends StatelessWidget { final String labelText; @@ -295,59 +294,70 @@ class TextInputWidget extends StatelessWidget { Widget _buildTextField(BuildContext context) { double fontS = fontSize ?? 14.f; + final isArabic = getIt.get().isArabic(); + return Builder( builder: (context) { - return Localizations.override( - context: context, - locale: const Locale('en', 'US'), // Force English locale for TextField - child: TextField( - hintLocales: const [Locale('en', 'US')], - enabled: isEnable, - scrollPadding: EdgeInsets.zero, - keyboardType: isMultiline ? TextInputType.multiline : (isWalletAmountInput! ? const TextInputType.numberWithOptions(decimal: true) : keyboardType), - controller: controller, - readOnly: isReadOnly, - textAlignVertical: TextAlignVertical.top, - textAlign: TextAlign.left, - textDirection: TextDirection.ltr, - onChanged: onChange, - focusNode: focusNode ?? _focusNode, - autofocus: autoFocus, - textInputAction: TextInputAction.done, - cursorHeight: isWalletAmountInput! ? 40.h : 20.h, - maxLength: isWalletAmountInput! ? 7 : 100, - inputFormatters: isWalletAmountInput! - ? [ - _ThousandSeparatorInputFormatter(), - ] - : null, - onTapOutside: (event) { - FocusManager.instance.primaryFocus?.unfocus(); - }, - onSubmitted: onSubmitted, - minLines: isMultiline ? minLines : 1, - maxLines: isMultiline ? maxLines : 1, - style: TextStyle( - fontSize: fontS, - height: isMultiline ? 1.2 : (isWalletAmountInput! ? 1 / 4 : 0), - fontWeight: FontWeight.w600, - color: AppColors.textColor, - letterSpacing: -1, - // fontFamily: keyboardType == TextInputType.number ? getIt.get().isArabic() ? 'GESSTwo' : 'Poppins' : 'Poppins', - fontFamily: fontFamily, - locale: const Locale('en', 'US'), // Force English locale for text style - ), - decoration: InputDecoration( - counterText: "", - isDense: true, - hintText: hintText, - hintStyle: TextStyle(fontSize: 14.f, height: 21 / 16, fontWeight: FontWeight.w600, color: hintColor != null ? AppColors.textColor : Color(0xff898A8D), letterSpacing: -0.75), - prefixIconConstraints: BoxConstraints(minWidth: 30.h), - prefixIcon: prefix == null ? null : "+${prefix!}".toText14(letterSpacing: -1, color: AppColors.textColor, isBold: true), - contentPadding: EdgeInsets.zero, - border: InputBorder.none, - focusedBorder: InputBorder.none, - enabledBorder: InputBorder.none, + return Directionality( + textDirection: isArabic ? TextDirection.rtl : TextDirection.ltr, + child: Localizations.override( + context: context, + locale: const Locale('en', 'US'), // Force English locale for TextField + child: TextField( + hintLocales: const [Locale('en', 'US')], + enabled: isEnable, + scrollPadding: EdgeInsets.zero, + keyboardType: isMultiline ? TextInputType.multiline : (isWalletAmountInput! ? const TextInputType.numberWithOptions(decimal: true) : keyboardType), + controller: controller, + readOnly: isReadOnly, + textAlignVertical: TextAlignVertical.top, + textAlign: isArabic ? TextAlign.right : TextAlign.left, + textDirection: TextDirection.ltr, + onChanged: onChange, + focusNode: focusNode ?? _focusNode, + autofocus: autoFocus, + textInputAction: TextInputAction.done, + cursorHeight: isWalletAmountInput! ? 40.h : 20.h, + maxLength: isWalletAmountInput! ? 7 : 100, + inputFormatters: isWalletAmountInput! + ? [ + _ThousandSeparatorInputFormatter(), + ] + : null, + onTapOutside: (event) { + FocusManager.instance.primaryFocus?.unfocus(); + }, + onSubmitted: onSubmitted, + minLines: isMultiline ? minLines : 1, + maxLines: isMultiline ? maxLines : 1, + style: TextStyle( + fontSize: fontS, + height: isMultiline ? 1.2 : (isWalletAmountInput! ? 1 / 4 : 0), + fontWeight: FontWeight.w600, + color: AppColors.textColor, + letterSpacing: -1, + fontFamily: fontFamily, + locale: const Locale('en', 'US'), // Force English locale for text style + ), + decoration: InputDecoration( + counterText: "", + isDense: true, + hintText: hintText, + hintStyle: TextStyle( + fontFamily: isArabic ? 'CairoArabic' : 'Poppins', + fontSize: 14.f, + height: 21 / 16, + fontWeight: FontWeight.w600, + color: hintColor != null ? AppColors.textColor : Color(0xff898A8D), + letterSpacing: -0.75, + ), + prefixIconConstraints: BoxConstraints(minWidth: 30.h), + prefixIcon: prefix == null ? null : "+${prefix!}".toText14(letterSpacing: -1, color: AppColors.textColor, isBold: true), + contentPadding: EdgeInsets.zero, + border: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + ), ), ), ); From 3d1c415e2c21c35acd997c8f3c1eeabf67f586ad Mon Sep 17 00:00:00 2001 From: Sultan khan Date: Wed, 8 Apr 2026 17:42:25 +0300 Subject: [PATCH 8/8] my invoice updated --- lib/core/api_consts.dart | 4 +- .../get_invoices_list_response_model.dart | 151 +++++++++--------- .../my_invoices/my_invoices_repo.dart | 2 +- lib/presentation/home/landing_page.dart | 7 +- .../my_invoices/my_invoices_details_page.dart | 103 ++++++------ .../my_invoices/my_invoices_list.dart | 8 +- .../widgets/invoice_list_card.dart | 41 ++--- 7 files changed, 167 insertions(+), 149 deletions(-) diff --git a/lib/core/api_consts.dart b/lib/core/api_consts.dart index 020f37e7..9a16cdbc 100644 --- a/lib/core/api_consts.dart +++ b/lib/core/api_consts.dart @@ -826,8 +826,8 @@ var FILTERED_PRODUCTS = 'products?categoryids='; var GET_DOCTOR_LIST_CALCULATION = "Services/Doctors.svc/REST/GetCallculationDoctors"; -var GET_ALL_APPOINTMENTS_FOR_DENTAL_CLINIC = "Services/Patients.svc/REST/GetDentalAppointments"; - +// var GET_ALL_APPOINTMENTS_FOR_DENTAL_CLINIC = "Services/Patients.svc/REST/GetDentalAppointments"; +var GET_ALL_APPOINTMENTS_FOR_DENTAL_CLINIC ='Services/Patients.svc/REST/GetAllInvoices'; var GET_DENTAL_APPOINTMENT_INVOICE = "Services/Patients.svc/REST/HIS_eInvoiceForDentalByAppointmentNo"; var SEND_DENTAL_APPOINTMENT_INVOICE_EMAIL = "Services/Notifications.svc/REST/SendInvoiceForDental"; diff --git a/lib/features/my_invoices/models/get_invoices_list_response_model.dart b/lib/features/my_invoices/models/get_invoices_list_response_model.dart index fe59c045..6e515feb 100644 --- a/lib/features/my_invoices/models/get_invoices_list_response_model.dart +++ b/lib/features/my_invoices/models/get_invoices_list_response_model.dart @@ -1,88 +1,93 @@ +import 'dart:convert'; + class GetInvoicesListResponseModel { String? setupId; - int? projectID; - int? patientID; + int? projectId; + int? patientId; int? appointmentNo; String? appointmentDate; - String? appointmentDateN; - int? clinicID; - int? doctorID; + dynamic appointmentDateN; + int? clinicId; + int? doctorId; int? invoiceNo; int? status; String? arrivedOn; String? doctorName; String? doctorNameN; String? clinicName; - num? decimalDoctorRate; - String? doctorImageURL; - num? doctorRate; - num? patientNumber; + double? decimalDoctorRate; + String? doctorImageUrl; + int? doctorRate; + int? patientNumber; String? projectName; - GetInvoicesListResponseModel( - {this.setupId, - this.projectID, - this.patientID, - this.appointmentNo, - this.appointmentDate, - this.appointmentDateN, - this.clinicID, - this.doctorID, - this.invoiceNo, - this.status, - this.arrivedOn, - this.doctorName, - this.doctorNameN, - this.clinicName, - this.decimalDoctorRate, - this.doctorImageURL, - this.doctorRate, - this.patientNumber, - this.projectName}); + GetInvoicesListResponseModel({ + this.setupId, + this.projectId, + this.patientId, + this.appointmentNo, + this.appointmentDate, + this.appointmentDateN, + this.clinicId, + this.doctorId, + this.invoiceNo, + this.status, + this.arrivedOn, + this.doctorName, + this.doctorNameN, + this.clinicName, + this.decimalDoctorRate, + this.doctorImageUrl, + this.doctorRate, + this.patientNumber, + this.projectName, + }); + + factory GetInvoicesListResponseModel.fromRawJson(String str) => GetInvoicesListResponseModel.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); - GetInvoicesListResponseModel.fromJson(Map json) { - setupId = json['SetupId']; - projectID = json['ProjectID']; - patientID = json['PatientID']; - appointmentNo = json['AppointmentNo']; - appointmentDate = json['AppointmentDate']; - appointmentDateN = json['AppointmentDateN']; - clinicID = json['ClinicID']; - doctorID = json['DoctorID']; - invoiceNo = json['InvoiceNo']; - status = json['Status']; - arrivedOn = json['ArrivedOn']; - doctorName = json['DoctorName']; - doctorNameN = json['DoctorNameN']; - clinicName = json['ClinicName']; - decimalDoctorRate = json['DecimalDoctorRate']; - doctorImageURL = json['DoctorImageURL']; - doctorRate = json['DoctorRate']; - patientNumber = json['PatientNumber']; - projectName = json['ProjectName']; - } + factory GetInvoicesListResponseModel.fromJson(Map json) => GetInvoicesListResponseModel( + setupId: json["SetupId"], + projectId: json["ProjectID"], + patientId: json["PatientID"], + appointmentNo: json["AppointmentNo"], + appointmentDate: json["AppointmentDate"], + appointmentDateN: json["AppointmentDateN"], + clinicId: json["ClinicID"], + doctorId: json["DoctorID"], + invoiceNo: json["InvoiceNo"], + status: json["Status"], + arrivedOn: json["ArrivedOn"], + doctorName: json["DoctorName"], + doctorNameN: json["DoctorNameN"], + clinicName: json["ClinicName"], + decimalDoctorRate: json["DecimalDoctorRate"]?.toDouble(), + doctorImageUrl: json["DoctorImageURL"], + doctorRate: json["DoctorRate"], + patientNumber: json["PatientNumber"], + projectName: json["ProjectName"], + ); - Map toJson() { - final Map data = {}; - data['SetupId'] = this.setupId; - data['ProjectID'] = this.projectID; - data['PatientID'] = this.patientID; - data['AppointmentNo'] = this.appointmentNo; - data['AppointmentDate'] = this.appointmentDate; - data['AppointmentDateN'] = this.appointmentDateN; - data['ClinicID'] = this.clinicID; - data['DoctorID'] = this.doctorID; - data['InvoiceNo'] = this.invoiceNo; - data['Status'] = this.status; - data['ArrivedOn'] = this.arrivedOn; - data['DoctorName'] = this.doctorName; - data['DoctorNameN'] = this.doctorNameN; - data['ClinicName'] = this.clinicName; - data['DecimalDoctorRate'] = this.decimalDoctorRate; - data['DoctorImageURL'] = this.doctorImageURL; - data['DoctorRate'] = this.doctorRate; - data['PatientNumber'] = this.patientNumber; - data['ProjectName'] = this.projectName; - return data; - } + Map toJson() => { + "SetupId": setupId, + "ProjectID": projectId, + "PatientID": patientId, + "AppointmentNo": appointmentNo, + "AppointmentDate": appointmentDate, + "AppointmentDateN": appointmentDateN, + "ClinicID": clinicId, + "DoctorID": doctorId, + "InvoiceNo": invoiceNo, + "Status": status, + "ArrivedOn": arrivedOn, + "DoctorName": doctorName, + "DoctorNameN": doctorNameN, + "ClinicName": clinicName, + "DecimalDoctorRate": decimalDoctorRate, + "DoctorImageURL": doctorImageUrl, + "DoctorRate": doctorRate, + "PatientNumber": patientNumber, + "ProjectName": projectName, + }; } diff --git a/lib/features/my_invoices/my_invoices_repo.dart b/lib/features/my_invoices/my_invoices_repo.dart index 79136ba0..486fdc2a 100644 --- a/lib/features/my_invoices/my_invoices_repo.dart +++ b/lib/features/my_invoices/my_invoices_repo.dart @@ -38,7 +38,7 @@ class MyInvoicesRepoImp implements MyInvoicesRepo { }, onSuccess: (response, statusCode, {messageStatus, errorMessage}) { try { - final list = response['List_DentalAppointments']; + final list = response['List_AllInvoices']; final invoicesList = list.map((item) => GetInvoicesListResponseModel.fromJson(item as Map)).toList().cast(); diff --git a/lib/presentation/home/landing_page.dart b/lib/presentation/home/landing_page.dart index b6311c58..371fe892 100644 --- a/lib/presentation/home/landing_page.dart +++ b/lib/presentation/home/landing_page.dart @@ -330,6 +330,7 @@ class _LandingPageState extends State { isFullScreen: false, ); }), + // Utils.buildSvgWithAssets(icon: AppAssets.contact_icon, height: 24.h, width: 24.h).onPress(() { // showCommonBottomSheetWithoutHeight( // context, @@ -340,10 +341,10 @@ class _LandingPageState extends State { // ); // }), !appState.isAuthenticated - ? Utils.buildSvgWithAssets(icon: appState.isArabic() ? AppAssets.enLangIcon : AppAssets.arLangIcon, height: 24.h, width: 24.h).onPress(() { + ?Row(children: [ SizedBox(width: 24.w,), Utils.buildSvgWithAssets(icon: appState.isArabic() ? AppAssets.enLangIcon : AppAssets.arLangIcon, height: 24.h, width: 24.h).onPress(() { context.setLocale(appState.isArabic() ? Locale('en', 'US') : Locale('ar', 'SA')); - }) - : SizedBox.shrink() + })]) + : SizedBox() ], ); }), diff --git a/lib/presentation/my_invoices/my_invoices_details_page.dart b/lib/presentation/my_invoices/my_invoices_details_page.dart index b8f534ac..9f0370a0 100644 --- a/lib/presentation/my_invoices/my_invoices_details_page.dart +++ b/lib/presentation/my_invoices/my_invoices_details_page.dart @@ -51,7 +51,7 @@ class _MyInvoicesDetailsPageState extends State { myInvoicesViewModel.downloadInvoicePDF( setupId: widget.getInvoicesListResponseModel.setupId!, invoiceNo: widget.getInvoicesListResponseModel.invoiceNo!, - projectID: widget.getInvoicesListResponseModel.projectID!, + projectID: widget.getInvoicesListResponseModel.projectId!, onError: (err) { LoaderBottomSheet.hideLoader(); showCommonBottomSheetWithoutHeight( @@ -150,7 +150,7 @@ class _MyInvoicesDetailsPageState extends State { Column( children: [ Image.network( - widget.getInvoiceDetailsResponseModel.doctorImageURL!, + widget.getInvoiceDetailsResponseModel.doctorImageURL ?? 'https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png', width: 63.h, height: 63.h, fit: BoxFit.cover, @@ -162,10 +162,10 @@ class _MyInvoicesDetailsPageState extends State { height: 40.h, decoration: BoxDecoration( color: AppColors.whiteColor, - shape: BoxShape.circle, // Makes the container circular + shape: BoxShape.circle, border: Border.all( - color: AppColors.scaffoldBgColor, // Color of the border - width: 1.5.w, // Width of the border + color: AppColors.scaffoldBgColor, + width: 1.5.w, ), ), child: Column( @@ -173,7 +173,7 @@ class _MyInvoicesDetailsPageState extends State { children: [ Utils.buildSvgWithAssets(icon: AppAssets.rating_icon, width: 15.w, height: 15.h, applyThemeColor: false), SizedBox(height: 2.h), - "${widget.getInvoicesListResponseModel.decimalDoctorRate}".toText11(isBold: true, color: AppColors.textColor), + "${widget.getInvoicesListResponseModel.decimalDoctorRate ?? '0.0'}".toText11(isBold: true, color: AppColors.textColor), ], ), ).circle(100), @@ -185,7 +185,7 @@ class _MyInvoicesDetailsPageState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - (getIt().isArabic() ? widget.getInvoiceDetailsResponseModel.doctorName ?? LocaleKeys.doctor.tr(context: context) : widget.getInvoiceDetailsResponseModel.doctorName!).toText16(isBold: true), + (widget.getInvoiceDetailsResponseModel.doctorName ?? LocaleKeys.doctor.tr(context: context)).toText16(isBold: true), SizedBox(height: 8.h), Wrap( direction: Axis.horizontal, @@ -193,29 +193,33 @@ class _MyInvoicesDetailsPageState extends State { runSpacing: 6.h, children: [ AppCustomChipWidget( - labelText: "${LocaleKeys.invoiceNo.tr(context: context)}: ${widget.getInvoiceDetailsResponseModel.invoiceNo!}", + labelText: "${LocaleKeys.invoiceNo.tr(context: context)}: ${widget.getInvoiceDetailsResponseModel.invoiceNo ?? '-'}", labelPadding: EdgeInsetsDirectional.only(start: 6.w, end: 6.w), isEnglishOnly: true, ), AppCustomChipWidget( - labelText: ((getIt().isArabic() ? widget.getInvoiceDetailsResponseModel.clinicDescriptionN : widget.getInvoiceDetailsResponseModel.clinicDescription ?? "")!.length > 15 - ? '${(getIt().isArabic() ? widget.getInvoiceDetailsResponseModel.clinicDescriptionN : widget.getInvoiceDetailsResponseModel.clinicDescription ?? "")!.substring(0, 12)}...' - : getIt().isArabic() ? widget.getInvoiceDetailsResponseModel.clinicDescriptionN : widget.getInvoiceDetailsResponseModel.clinicDescription ?? ""), + labelText: () { + final clinicName = getIt().isArabic() + ? (widget.getInvoiceDetailsResponseModel.clinicDescriptionN ?? widget.getInvoiceDetailsResponseModel.clinicDescription ?? LocaleKeys.clinic.tr(context: context)) + : (widget.getInvoiceDetailsResponseModel.clinicDescription ?? widget.getInvoiceDetailsResponseModel.clinicDescriptionN ?? LocaleKeys.clinic.tr(context: context)); + return clinicName.length > 15 ? '${clinicName.substring(0, 12)}...' : clinicName; + }(), labelPadding: EdgeInsetsDirectional.only(start: 4.w, end: 4.w), ), AppCustomChipWidget( - labelText: widget.getInvoiceDetailsResponseModel.projectName!, + labelText: widget.getInvoiceDetailsResponseModel.projectName ?? LocaleKeys.hospital.tr(context: context), labelPadding: EdgeInsetsDirectional.only(start: 6.w, end: 6.w), ), - Directionality( - textDirection: ui.TextDirection.ltr, - child: AppCustomChipWidget( - labelPadding: EdgeInsetsDirectional.only(start: -4.w, end: 6.w), - icon: AppAssets.doctor_calendar_icon, - labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(widget.getInvoiceDetailsResponseModel.appointmentDate), false), - isEnglishOnly: true, + if (widget.getInvoiceDetailsResponseModel.appointmentDate != null) + Directionality( + textDirection: ui.TextDirection.ltr, + child: AppCustomChipWidget( + labelPadding: EdgeInsetsDirectional.only(start: -4.w, end: 6.w), + icon: AppAssets.doctor_calendar_icon, + labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(widget.getInvoiceDetailsResponseModel.appointmentDate), false), + isEnglishOnly: true, + ), ), - ), ], ), ], @@ -241,22 +245,25 @@ class _MyInvoicesDetailsPageState extends State { children: [ LocaleKeys.insurance.tr(context: context).toText16(isBold: true), SizedBox(height: 16.h), - (getIt().isArabic() ? widget.getInvoiceDetailsResponseModel.groupNameN : widget.getInvoiceDetailsResponseModel.groupName)!.toText14(isBold: true), + (getIt().isArabic() + ? (widget.getInvoiceDetailsResponseModel.groupNameN ?? widget.getInvoiceDetailsResponseModel.groupName ?? LocaleKeys.insurance.tr(context: context)) + : (widget.getInvoiceDetailsResponseModel.groupName ?? widget.getInvoiceDetailsResponseModel.groupNameN ?? LocaleKeys.insurance.tr(context: context)) + ).toText14(isBold: true), Row( children: [ Expanded(child: (widget.getInvoiceDetailsResponseModel.companyName ?? "").toText14(isBold: true)), ], ), SizedBox(height: 12.h), - Row( - children: [ - AppCustomChipWidget( - labelText: "Insurance ID: ${widget.getInvoiceDetailsResponseModel.insuranceID ?? "-"}", - labelPadding: EdgeInsetsDirectional.only(start: 6.w, end: 6.w), - isEnglishOnly: true, - ), - ], - ), + // Row( + // children: [ + // AppCustomChipWidget( + // labelText: "Insurance ID: ${widget.getInvoiceDetailsResponseModel.insuranceID ?? "-"}", + // labelPadding: EdgeInsetsDirectional.only(start: 6.w, end: 6.w), + // isEnglishOnly: true, + // ), + // ], + // ), ], ), ), @@ -299,8 +306,8 @@ class _MyInvoicesDetailsPageState extends State { children: [ Expanded(flex: 3, child: (consultation.procedureName ?? '-').toText12(isBold: true)), Expanded(flex: 1, child: '${consultation.quantity ?? '-'}'.toText12(isBold: true, isCenter: true, isEnglishOnly: true)), - Expanded(flex: 2, child: (NumberFormat.decimalPattern().format(consultation.price) ?? '-').toText12(isBold: true, isCenter: true, isEnglishOnly: true)), - Expanded(flex: 2, child: (NumberFormat.decimalPattern().format(consultation.total) ?? '-').toText12(isBold: true, isCenter: true, isEnglishOnly: true)), + Expanded(flex: 2, child: (NumberFormat.decimalPattern().format(consultation.totalPatientShare) ?? '-').toText12(isBold: true, isCenter: true, isEnglishOnly: true)), + Expanded(flex: 2, child: (NumberFormat.decimalPattern().format(consultation.totalPatientShare) ?? '-').toText12(isBold: true, isCenter: true, isEnglishOnly: true)), ], ), ), @@ -335,7 +342,7 @@ class _MyInvoicesDetailsPageState extends State { children: [ LocaleKeys.amountBeforeTax.tr(context: context).toText14(isBold: true), Utils.getPaymentAmountWithSymbol( - NumberFormat.decimalPattern().format(widget.getInvoiceDetailsResponseModel.listConsultation!.first.totalShare).toString().toText16(isBold: true, isEnglishOnly: true), AppColors.blackColor, 13, + NumberFormat.decimalPattern().format(widget.getInvoiceDetailsResponseModel.listConsultation!.first.patientShare).toString().toText16(isBold: true, isEnglishOnly: true), AppColors.blackColor, 13, isSaudiCurrency: true), ], ).paddingSymmetrical(24.h, 0.h), @@ -345,7 +352,7 @@ class _MyInvoicesDetailsPageState extends State { LocaleKeys.vat15.tr(context: context).toText14(isBold: true, color: AppColors.greyTextColor), Utils.getPaymentAmountWithSymbol( NumberFormat.decimalPattern() - .format(widget.getInvoiceDetailsResponseModel.listConsultation!.first.totalVATAmount!) + .format(widget.getInvoiceDetailsResponseModel.listConsultation!.first.patientVATAmount!) .toString() .toText14(isBold: true, color: AppColors.greyTextColor, isEnglishOnly: true), AppColors.greyTextColor, @@ -354,25 +361,25 @@ class _MyInvoicesDetailsPageState extends State { ], ).paddingSymmetrical(24.h, 0.h), SizedBox(height: 16.h), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - LocaleKeys.discount.tr(context: context).toText14(isBold: true), - Utils.getPaymentAmountWithSymbol( - NumberFormat.decimalPattern() - .format(widget.getInvoiceDetailsResponseModel.listConsultation!.first.discountAmount!) - .toString() - .toText14(isBold: true, color: AppColors.primaryRedColor, isEnglishOnly: true), - AppColors.primaryRedColor, 13, - isSaudiCurrency: true), - ], - ).paddingSymmetrical(24.h, 0.h), + // Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // LocaleKeys.discount.tr(context: context).toText14(isBold: true), + // Utils.getPaymentAmountWithSymbol( + // NumberFormat.decimalPattern() + // .format(widget.getInvoiceDetailsResponseModel.listConsultation!.first.discountAmount!) + // .toString() + // .toText14(isBold: true, color: AppColors.primaryRedColor, isEnglishOnly: true), + // AppColors.primaryRedColor, 13, + // isSaudiCurrency: true), + // ], + // ).paddingSymmetrical(24.h, 0.h), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ LocaleKeys.paid.tr(context: context).toText14(isBold: true), Utils.getPaymentAmountWithSymbol( - NumberFormat.decimalPattern().format(widget.getInvoiceDetailsResponseModel.listConsultation!.first.grandTotal!).toString().toText14(isBold: true, color: AppColors.textColor, isEnglishOnly: true), + NumberFormat.decimalPattern().format(widget.getInvoiceDetailsResponseModel.listConsultation!.first.totalPatientShare!).toString().toText14(isBold: true, color: AppColors.textColor, isEnglishOnly: true), AppColors.textColor, 13, isSaudiCurrency: true), diff --git a/lib/presentation/my_invoices/my_invoices_list.dart b/lib/presentation/my_invoices/my_invoices_list.dart index bb2c4f8e..a935f0d1 100644 --- a/lib/presentation/my_invoices/my_invoices_list.dart +++ b/lib/presentation/my_invoices/my_invoices_list.dart @@ -143,7 +143,7 @@ class _MyInvoicesListState extends State { CustomButton( text: LocaleKeys.hospitals.tr(context: context), onPressed: () { - if (myInvoicesVM.allInvoicesList.isEmpty) return; + if (myInvoicesVM.getOriginalInvoicesList().isEmpty) return; _showHospitalFilterBottomSheet(context); }, backgroundColor: myInvoicesVM.currentFilter == InvoiceFilterType.hospital ? AppColors.bgRedLightColor : AppColors.whiteColor, @@ -159,7 +159,7 @@ class _MyInvoicesListState extends State { CustomButton( text: LocaleKeys.clinics.tr(context: context), onPressed: () { - if (myInvoicesVM.allInvoicesList.isEmpty) return; + if (myInvoicesVM.getOriginalInvoicesList().isEmpty) return; _showClinicFilterBottomSheet(context); }, backgroundColor: myInvoicesVM.currentFilter == InvoiceFilterType.clinic ? AppColors.bgRedLightColor : AppColors.whiteColor, @@ -175,7 +175,7 @@ class _MyInvoicesListState extends State { CustomButton( text: LocaleKeys.doctors.tr(context: context), onPressed: () { - if (myInvoicesVM.allInvoicesList.isEmpty) return; + if (myInvoicesVM.getOriginalInvoicesList().isEmpty) return; _showDoctorFilterBottomSheet(context); }, backgroundColor: myInvoicesVM.currentFilter == InvoiceFilterType.doctor ? AppColors.bgRedLightColor : AppColors.whiteColor, @@ -220,7 +220,7 @@ class _MyInvoicesListState extends State { await myInvoicesVM.getInvoiceDetails( appointmentNo: myInvoicesVM.allInvoicesList[index].appointmentNo!, invoiceNo: myInvoicesVM.allInvoicesList[index].invoiceNo!, - projectID: myInvoicesVM.allInvoicesList[index].projectID!, + projectID: myInvoicesVM.allInvoicesList[index].projectId!, onSuccess: (val) { LoaderBottomSheet.hideLoader(); Navigator.of(context).push( diff --git a/lib/presentation/my_invoices/widgets/invoice_list_card.dart b/lib/presentation/my_invoices/widgets/invoice_list_card.dart index 8aa4e174..3aacb85c 100644 --- a/lib/presentation/my_invoices/widgets/invoice_list_card.dart +++ b/lib/presentation/my_invoices/widgets/invoice_list_card.dart @@ -61,7 +61,7 @@ class InvoiceListCard extends StatelessWidget { Column( children: [ Image.network( - getInvoicesListResponseModel.doctorImageURL!, + getInvoicesListResponseModel.doctorImageUrl ?? 'https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png', width: 63.h, height: 63.h, fit: BoxFit.cover, @@ -73,10 +73,10 @@ class InvoiceListCard extends StatelessWidget { height: 40.h, decoration: BoxDecoration( color: AppColors.whiteColor, - shape: BoxShape.circle, // Makes the container circular + shape: BoxShape.circle, border: Border.all( - color: AppColors.scaffoldBgColor, // Color of the border - width: 1.5.w, // Width of the border + color: AppColors.scaffoldBgColor, + width: 1.5.w, ), ), child: Column( @@ -84,7 +84,7 @@ class InvoiceListCard extends StatelessWidget { children: [ Utils.buildSvgWithAssets(icon: AppAssets.rating_icon, width: 15.w, height: 15.h, applyThemeColor: false), SizedBox(height: 2.h), - "${getInvoicesListResponseModel.decimalDoctorRate}".toText11(isBold: true, color: AppColors.textColor), + "${getInvoicesListResponseModel.decimalDoctorRate ?? '0.0'}".toText11(isBold: true, color: AppColors.textColor), ], ), ).circle(100), @@ -96,7 +96,10 @@ class InvoiceListCard extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - (getIt().isArabic() ? getInvoicesListResponseModel.doctorNameN! : getInvoicesListResponseModel.doctorName ?? "HMG Doctor").toText16(isBold: true), + (getIt().isArabic() + ? (getInvoicesListResponseModel.doctorNameN ?? getInvoicesListResponseModel.doctorName ?? LocaleKeys.doctor.tr(context: context)) + : (getInvoicesListResponseModel.doctorName ?? getInvoicesListResponseModel.doctorNameN ?? LocaleKeys.doctor.tr(context: context)) + ).toText16(isBold: true), SizedBox(height: 8.h), Wrap( direction: Axis.horizontal, @@ -104,28 +107,30 @@ class InvoiceListCard extends StatelessWidget { runSpacing: 6.h, children: [ AppCustomChipWidget( - labelText: "${LocaleKeys.invoiceNo.tr(context: context)}: ${getInvoicesListResponseModel.invoiceNo!}", + labelText: "${LocaleKeys.invoiceNo.tr(context: context)}: ${getInvoicesListResponseModel.invoiceNo ?? '-'}", labelPadding: EdgeInsetsDirectional.only(start: 6.w, end: 6.w), isEnglishOnly: true, ), AppCustomChipWidget( - labelText: - (getInvoicesListResponseModel.clinicName!.length > 15 ? '${getInvoicesListResponseModel.clinicName!.substring(0, 12)}...' : getInvoicesListResponseModel.clinicName!), + labelText: ((getInvoicesListResponseModel.clinicName ?? LocaleKeys.clinic.tr(context: context)).length > 15 + ? '${(getInvoicesListResponseModel.clinicName ?? LocaleKeys.clinic.tr(context: context)).substring(0, 12)}...' + : (getInvoicesListResponseModel.clinicName ?? LocaleKeys.clinic.tr(context: context))), labelPadding: EdgeInsetsDirectional.only(start: 4.w, end: 4.w), ), AppCustomChipWidget( - labelText: getInvoicesListResponseModel.projectName!, + labelText: getInvoicesListResponseModel.projectName ?? LocaleKeys.hospital.tr(context: context), labelPadding: EdgeInsetsDirectional.only(start: 6.w, end: 6.w), ), - Directionality( - textDirection: ui.TextDirection.ltr, - child: AppCustomChipWidget( - labelPadding: EdgeInsetsDirectional.only(start: -4.w, end: 6.w), - icon: AppAssets.doctor_calendar_icon, - labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(getInvoicesListResponseModel.appointmentDate), false), - isEnglishOnly: true, + if (getInvoicesListResponseModel.appointmentDate != null) + Directionality( + textDirection: ui.TextDirection.ltr, + child: AppCustomChipWidget( + labelPadding: EdgeInsetsDirectional.only(start: -4.w, end: 6.w), + icon: AppAssets.doctor_calendar_icon, + labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(getInvoicesListResponseModel.appointmentDate), false), + isEnglishOnly: true, + ), ), - ), ], ), ],