From 14f57027f4a95fbb6d3d425fb6ad82f2176e6bfd Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Wed, 12 Nov 2025 15:29:31 +0300 Subject: [PATCH] Eye measurements done --- lib/core/api/api_client.dart | 4 +- ...nt_appointment_history_response_model.dart | 216 +++++++++++++++++- .../my_appointments/my_appointments_repo.dart | 5 +- .../my_appointments_view_model.dart | 41 ++++ .../widgets/appointment_card.dart | 71 +++--- .../eye_measurement_details_page.dart | 198 ++++++++++++++++ .../eye_measurements_appointments_page.dart | 90 ++++++++ .../medical_file/medical_file_page.dart | 12 +- 8 files changed, 596 insertions(+), 41 deletions(-) create mode 100644 lib/presentation/medical_file/eye_measurement_details_page.dart create mode 100644 lib/presentation/medical_file/eye_measurements_appointments_page.dart diff --git a/lib/core/api/api_client.dart b/lib/core/api/api_client.dart index 029dbcb..b2cc819 100644 --- a/lib/core/api/api_client.dart +++ b/lib/core/api/api_client.dart @@ -173,8 +173,8 @@ class ApiClientImp implements ApiClient { body[_appState.isAuthenticated ? 'TokenID' : 'LogInTokenID'] = _appState.appAuthToken; } - // body['TokenID'] = "@dm!n"; - // body['PatientID'] = 3111528; + body['TokenID'] = "@dm!n"; + body['PatientID'] = 1231755; // body['PatientTypeID'] = 1; // // body['PatientOutSA'] = 0; diff --git a/lib/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart b/lib/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart index 4d8eb9c..e1ae67d 100644 --- a/lib/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart +++ b/lib/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart @@ -55,8 +55,8 @@ class PatientAppointmentHistoryResponseModel { bool? isMedicalReportRequested; bool? isOnlineCheckedIN; String? latitude; - dynamic listHISGetContactLensPerscription; - dynamic listHISGetGlassPerscription; + List? listHISGetContactLensPrescription; + List? listHISGetGlassPrescription; String? longitude; dynamic nextAction; dynamic noOfPatientsRate; @@ -130,8 +130,8 @@ class PatientAppointmentHistoryResponseModel { this.isMedicalReportRequested, this.isOnlineCheckedIN, this.latitude, - this.listHISGetContactLensPerscription, - this.listHISGetGlassPerscription, + this.listHISGetContactLensPrescription, + this.listHISGetGlassPrescription, this.longitude, this.nextAction, this.noOfPatientsRate, @@ -207,8 +207,18 @@ class PatientAppointmentHistoryResponseModel { isMedicalReportRequested = json['IsMedicalReportRequested']; isOnlineCheckedIN = json['IsOnlineCheckedIN']; latitude = json['Latitude']; - listHISGetContactLensPerscription = json['List_HIS_GetContactLensPerscription']; - listHISGetGlassPerscription = json['List_HIS_GetGlassPerscription']; + if (json['List_HIS_GetContactLensPerscription'] != null) { + listHISGetContactLensPrescription = []; + json['List_HIS_GetContactLensPerscription'].forEach((v) { + listHISGetContactLensPrescription!.add(ListHISGetContactLensPrescription.fromJson(v)); + }); + } + if (json['List_HIS_GetGlassPerscription'] != null) { + listHISGetGlassPrescription = []; + json['List_HIS_GetGlassPerscription'].forEach((v) { + listHISGetGlassPrescription!.add(ListHISGetGlassPrescription.fromJson(v)); + }); + } longitude = json['Longitude']; nextAction = json['NextAction']; noOfPatientsRate = json['NoOfPatientsRate']; @@ -285,8 +295,8 @@ class PatientAppointmentHistoryResponseModel { data['IsMedicalReportRequested'] = this.isMedicalReportRequested; data['IsOnlineCheckedIN'] = this.isOnlineCheckedIN; data['Latitude'] = this.latitude; - data['List_HIS_GetContactLensPerscription'] = this.listHISGetContactLensPerscription; - data['List_HIS_GetGlassPerscription'] = this.listHISGetGlassPerscription; + // data['List_HIS_GetContactLensPerscription'] = this.listHISGetContactLensPerscription; + // data['List_HIS_GetGlassPerscription'] = this.listHISGetGlassPerscription; data['Longitude'] = this.longitude; data['NextAction'] = this.nextAction; data['NoOfPatientsRate'] = this.noOfPatientsRate; @@ -301,6 +311,196 @@ class PatientAppointmentHistoryResponseModel { } } +class ListHISGetContactLensPrescription { + String? setupId; + int? projectId; + int? patientType; + int? patientId; + int? encounterType; + int? encounterNo; + int? oDOS; + dynamic brand; + dynamic baseCurve; + dynamic power; + dynamic diameter; + dynamic oZ; + dynamic cT; + dynamic blend; + String? remarks; + int? status; + bool? isActive; + String? createdOn; + + ListHISGetContactLensPrescription( + {this.setupId, + this.projectId, + this.patientType, + this.patientId, + this.encounterType, + this.encounterNo, + this.oDOS, + this.brand, + this.baseCurve, + this.power, + this.diameter, + this.oZ, + this.cT, + this.blend, + this.remarks, + this.status, + this.isActive, + this.createdOn}); + + ListHISGetContactLensPrescription.fromJson(Map json) { + setupId = json['SetupId']; + projectId = json['ProjectId']; + patientType = json['PatientType']; + patientId = json['PatientId']; + encounterType = json['EncounterType']; + encounterNo = json['EncounterNo']; + oDOS = json['OD_OS']; + brand = json['Brand']; + baseCurve = json['BaseCurve']; + power = json['Power']; + diameter = json['Diameter']; + oZ = json['OZ']; + cT = json['CT']; + blend = json['Blend']; + remarks = json['Remarks']; + status = json['Status']; + isActive = json['IsActive']; + createdOn = json['CreatedOn']; + } + + Map toJson() { + final Map data = new Map(); + data['SetupId'] = this.setupId; + data['ProjectId'] = this.projectId; + data['PatientType'] = this.patientType; + data['PatientId'] = this.patientId; + data['EncounterType'] = this.encounterType; + data['EncounterNo'] = this.encounterNo; + data['OD_OS'] = this.oDOS; + data['Brand'] = this.brand; + data['BaseCurve'] = this.baseCurve; + data['Power'] = this.power; + data['Diameter'] = this.diameter; + data['OZ'] = this.oZ; + data['CT'] = this.cT; + data['Blend'] = this.blend; + data['Remarks'] = this.remarks; + data['Status'] = this.status; + data['IsActive'] = this.isActive; + data['CreatedOn'] = this.createdOn; + return data; + } +} + +class ListHISGetGlassPrescription { + dynamic projectID; + String? setupID; + dynamic patientId; + dynamic encounterType; + dynamic encounterNo; + String? visionType; + double? rightEyeSpherical; + dynamic rightEyeCylinder; + dynamic rightEyeAxis; + dynamic rightEyePrism; + dynamic rightEyeVA; + String? rightEyeRemarks; + dynamic leftEyeSpherical; + dynamic leftEyeCylinder; + dynamic leftEyeAxis; + dynamic leftEyePrism; + dynamic leftEyeVA; + String? leftEyeRemarks; + dynamic pD; + dynamic bVD; + dynamic status; + bool? isActive; + String? createdOn; + + ListHISGetGlassPrescription( + {this.projectID, + this.setupID, + this.patientId, + this.encounterType, + this.encounterNo, + this.visionType, + this.rightEyeSpherical, + this.rightEyeCylinder, + this.rightEyeAxis, + this.rightEyePrism, + this.rightEyeVA, + this.rightEyeRemarks, + this.leftEyeSpherical, + this.leftEyeCylinder, + this.leftEyeAxis, + this.leftEyePrism, + this.leftEyeVA, + this.leftEyeRemarks, + this.pD, + this.bVD, + this.status, + this.isActive, + this.createdOn}); + + ListHISGetGlassPrescription.fromJson(Map json) { + projectID = json['ProjectID']; + setupID = json['SetupID']; + patientId = json['PatientId']; + encounterType = json['EncounterType']; + encounterNo = json['EncounterNo']; + visionType = json['VisionType']; + rightEyeSpherical = json['RightEyeSpherical']; + rightEyeCylinder = json['RightEyeCylinder']; + rightEyeAxis = json['RightEyeAxis']; + rightEyePrism = json['RightEyePrism']; + rightEyeVA = json['RightEyeVA']; + rightEyeRemarks = json['RightEyeRemarks']; + leftEyeSpherical = json['LeftEyeSpherical']; + leftEyeCylinder = json['LeftEyeCylinder']; + leftEyeAxis = json['LeftEyeAxis']; + leftEyePrism = json['LeftEyePrism']; + leftEyeVA = json['LeftEyeVA']; + leftEyeRemarks = json['LeftEyeRemarks']; + pD = json['PD']; + bVD = json['BVD']; + status = json['Status']; + isActive = json['IsActive']; + createdOn = json['CreatedOn']; + } + + Map toJson() { + final Map data = new Map(); + data['ProjectID'] = this.projectID; + data['SetupID'] = this.setupID; + data['PatientId'] = this.patientId; + data['EncounterType'] = this.encounterType; + data['EncounterNo'] = this.encounterNo; + data['VisionType'] = this.visionType; + data['RightEyeSpherical'] = this.rightEyeSpherical; + data['RightEyeCylinder'] = this.rightEyeCylinder; + data['RightEyeAxis'] = this.rightEyeAxis; + data['RightEyePrism'] = this.rightEyePrism; + data['RightEyeVA'] = this.rightEyeVA; + data['RightEyeRemarks'] = this.rightEyeRemarks; + data['LeftEyeSpherical'] = this.leftEyeSpherical; + data['LeftEyeCylinder'] = this.leftEyeCylinder; + data['LeftEyeAxis'] = this.leftEyeAxis; + data['LeftEyePrism'] = this.leftEyePrism; + data['LeftEyeVA'] = this.leftEyeVA; + data['LeftEyeRemarks'] = this.leftEyeRemarks; + data['PD'] = this.pD; + data['BVD'] = this.bVD; + data['Status'] = this.status; + data['IsActive'] = this.isActive; + data['CreatedOn'] = this.createdOn; + return data; + } +} + class PatientAppointmentList { String? filterName = ""; List? patientDoctorAppointmentList = []; diff --git a/lib/features/my_appointments/my_appointments_repo.dart b/lib/features/my_appointments/my_appointments_repo.dart index 5fd7c12..87ec10d 100644 --- a/lib/features/my_appointments/my_appointments_repo.dart +++ b/lib/features/my_appointments/my_appointments_repo.dart @@ -16,7 +16,7 @@ import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/ import 'package:hmg_patient_app_new/services/logger_service.dart'; abstract class MyAppointmentsRepo { - Future>>> getPatientAppointments({required bool isActiveAppointment, required bool isArrivedAppointments}); + Future>>> getPatientAppointments({required bool isActiveAppointment, required bool isArrivedAppointments, bool isForEyeMeasurement = false}); Future>> getPatientShareAppointment( {required int projectID, required int clinicID, required String appointmentNo, required bool isLiveCareAppointment}); @@ -67,13 +67,14 @@ class MyAppointmentsRepoImp implements MyAppointmentsRepo { MyAppointmentsRepoImp({required this.loggerService, required this.apiClient}); @override - Future>>> getPatientAppointments({required bool isActiveAppointment, required bool isArrivedAppointments}) async { + Future>>> getPatientAppointments({required bool isActiveAppointment, required bool isArrivedAppointments, bool isForEyeMeasurement = false}) async { Map mapDevice = { "IsActiveAppointment": isActiveAppointment, "IsComingFromCOC": false, "isForUpcomming": false, "IsForMedicalReport": false, "IsForArrived": isArrivedAppointments, + "IsIrisPrescription": isForEyeMeasurement }; try { diff --git a/lib/features/my_appointments/my_appointments_view_model.dart b/lib/features/my_appointments/my_appointments_view_model.dart index 371f838..fa1ad22 100644 --- a/lib/features/my_appointments/my_appointments_view_model.dart +++ b/lib/features/my_appointments/my_appointments_view_model.dart @@ -14,6 +14,8 @@ class MyAppointmentsViewModel extends ChangeNotifier { int selectedTabIndex = 0; int previouslySelectedTab = -1; + int eyeMeasurementsTabSelectedIndex = 0; + MyAppointmentsRepo myAppointmentsRepo; ErrorHandlerService errorHandlerService; AppState appState; @@ -27,6 +29,8 @@ class MyAppointmentsViewModel extends ChangeNotifier { bool isAppointmentDataToBeLoaded = true; + bool isEyeMeasurementsAppointmentsLoading = false; + List availableFilters = []; List? selectedFilter = []; bool isDateFilterSelected = false; @@ -43,6 +47,8 @@ class MyAppointmentsViewModel extends ChangeNotifier { List patientMyDoctorsList = []; + List patientEyeMeasurementsAppointmentsHistoryList = []; + List askDoctorRequestTypeList = []; PatientAppointmentShareResponseModel? patientAppointmentShareResponseModel; @@ -60,18 +66,25 @@ class MyAppointmentsViewModel extends ChangeNotifier { notifyListeners(); } + void onEyeMeasurementsTabChanged(int index) { + eyeMeasurementsTabSelectedIndex = index; + notifyListeners(); + } + initAppointmentsViewModel() { if (isAppointmentDataToBeLoaded) { patientAppointmentsHistoryList.clear(); patientUpcomingAppointmentsHistoryList.clear(); patientArrivedAppointmentsHistoryList.clear(); patientTimelineAppointmentsList.clear(); + patientEyeMeasurementsAppointmentsHistoryList.clear(); isMyAppointmentsLoading = true; isTimeLineAppointmentsLoading = true; patientMyDoctorsList.clear(); } isTamaraDetailsLoading = true; isAppointmentPatientShareLoading = true; + isEyeMeasurementsAppointmentsLoading = true; notifyListeners(); } @@ -108,6 +121,11 @@ class MyAppointmentsViewModel extends ChangeNotifier { notifyListeners(); } + setIsEyeMeasurementsAppointmentsLoading(bool val) { + isEyeMeasurementsAppointmentsLoading = val; + notifyListeners(); + } + setAppointmentReminder(bool value, PatientAppointmentHistoryResponseModel item) { int index = patientAppointmentsHistoryList.indexOf(item); if (index != -1) { @@ -116,6 +134,29 @@ class MyAppointmentsViewModel extends ChangeNotifier { } } + Future getPatientEyeMeasurementAppointments({Function(dynamic)? onSuccess, Function(String)? onError}) async { + patientEyeMeasurementsAppointmentsHistoryList.clear(); + notifyListeners(); + + final result = await myAppointmentsRepo.getPatientAppointments(isActiveAppointment: false, isArrivedAppointments: true, isForEyeMeasurement: true); + + result.fold( + (failure) async => await errorHandlerService.handleError(failure: failure), + (apiResponse) { + if (apiResponse.messageStatus == 2) { + // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {}); + } else if (apiResponse.messageStatus == 1) { + patientEyeMeasurementsAppointmentsHistoryList = apiResponse.data!; + isEyeMeasurementsAppointmentsLoading = false; + notifyListeners(); + if (onSuccess != null) { + onSuccess(apiResponse); + } + } + }, + ); + } + Future getPatientAppointments(bool isActiveAppointment, bool isArrivedAppointments, {Function(dynamic)? onSuccess, Function(String)? onError}) async { if (!isAppointmentDataToBeLoaded) return; diff --git a/lib/presentation/appointments/widgets/appointment_card.dart b/lib/presentation/appointments/widgets/appointment_card.dart index f20d0b6..e451088 100644 --- a/lib/presentation/appointments/widgets/appointment_card.dart +++ b/lib/presentation/appointments/widgets/appointment_card.dart @@ -18,6 +18,7 @@ import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/presentation/appointments/appointment_details_page.dart'; import 'package:hmg_patient_app_new/presentation/appointments/widgets/ask_doctor_request_type_select.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/widgets/appointment_calendar.dart'; +import 'package:hmg_patient_app_new/presentation/medical_file/eye_measurement_details_page.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; @@ -31,6 +32,7 @@ class AppointmentCard extends StatelessWidget { final bool isLoading; final bool isFromHomePage; final bool isFromMedicalReport; + final bool isForEyeMeasurements; final MedicalFileViewModel? medicalFileViewModel; final BookAppointmentsViewModel bookAppointmentsViewModel; @@ -42,6 +44,7 @@ class AppointmentCard extends StatelessWidget { this.isLoading = false, this.isFromHomePage = false, this.isFromMedicalReport = false, + this.isForEyeMeasurements = false, this.medicalFileViewModel, }); @@ -170,24 +173,28 @@ class AppointmentCard extends StatelessWidget { Widget _buildActionArea(BuildContext context, AppState appState) { if (isFromMedicalReport) { - return CustomButton( - text: 'Select appointment'.needTranslation, - onPressed: () { - medicalFileViewModel!.setSelectedMedicalReportAppointment(patientAppointmentHistoryResponseModel); - Navigator.pop(context, false); - }, - backgroundColor: AppColors.secondaryLightRedColor, - borderColor: AppColors.secondaryLightRedColor, - textColor: AppColors.primaryRedColor, - fontSize: 14.f, - fontWeight: FontWeight.w500, - borderRadius: 12.r, - padding: EdgeInsets.symmetric(horizontal: 10.w), - height: isTablet || isFoldable ? 46.h : 40.h, - icon: AppAssets.checkmark_icon, - iconColor: AppColors.primaryRedColor, - iconSize: 16.h, - ); + if (isForEyeMeasurements) { + return SizedBox.shrink(); + } else { + return CustomButton( + text: 'Select appointment'.needTranslation, + onPressed: () { + medicalFileViewModel!.setSelectedMedicalReportAppointment(patientAppointmentHistoryResponseModel); + Navigator.pop(context, false); + }, + backgroundColor: AppColors.secondaryLightRedColor, + borderColor: AppColors.secondaryLightRedColor, + textColor: AppColors.primaryRedColor, + fontSize: 14.f, + fontWeight: FontWeight.w500, + borderRadius: 12.r, + padding: EdgeInsets.symmetric(horizontal: 10.w), + height: isTablet || isFoldable ? 46.h : 40.h, + icon: AppAssets.checkmark_icon, + iconColor: AppColors.primaryRedColor, + iconSize: 16.h, + ); + } } return Row( @@ -306,16 +313,24 @@ class AppointmentCard extends StatelessWidget { } void _goToDetails(BuildContext context) { - Navigator.of(context) - .push( - CustomPageRoute( - page: AppointmentDetailsPage(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel), - ), - ) - .then((_) { - myAppointmentsViewModel.initAppointmentsViewModel(); - myAppointmentsViewModel.getPatientAppointments(true, false); - }); + if (isForEyeMeasurements) { + Navigator.of(context).push( + CustomPageRoute( + page: EyeMeasurementDetailsPage(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel), + ), + ); + } else { + Navigator.of(context) + .push( + CustomPageRoute( + page: AppointmentDetailsPage(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel), + ), + ) + .then((_) { + myAppointmentsViewModel.initAppointmentsViewModel(); + myAppointmentsViewModel.getPatientAppointments(true, false); + }); + } } void openDoctorScheduleCalendar(BuildContext context) async { diff --git a/lib/presentation/medical_file/eye_measurement_details_page.dart b/lib/presentation/medical_file/eye_measurement_details_page.dart new file mode 100644 index 0000000..e69766a --- /dev/null +++ b/lib/presentation/medical_file/eye_measurement_details_page.dart @@ -0,0 +1,198 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.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'; +import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart'; +import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart'; +import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart'; +import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; +import 'package:hmg_patient_app_new/main.dart'; +import 'package:hmg_patient_app_new/presentation/appointments/widgets/appointment_card.dart'; +import 'package:hmg_patient_app_new/theme/colors.dart'; +import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; +import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart'; +import 'package:provider/provider.dart'; + +class EyeMeasurementDetailsPage extends StatelessWidget { + EyeMeasurementDetailsPage({super.key, required this.patientAppointmentHistoryResponseModel}); + + final PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel; + late BookAppointmentsViewModel bookAppointmentsViewModel; + + @override + Widget build(BuildContext context) { + bookAppointmentsViewModel = Provider.of(context, listen: false); + return Scaffold( + backgroundColor: AppColors.bgScaffoldColor, + body: CollapsingListView( + title: LocaleKeys.eyeMeasurements.tr(), + child: SingleChildScrollView( + child: Consumer(builder: (context, myAppointmentsVM, child) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height: 16.h), + Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true), + child: AppointmentCard( + patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel, + myAppointmentsViewModel: myAppointmentsVM, + bookAppointmentsViewModel: bookAppointmentsViewModel, + isLoading: false, + isFromHomePage: false, + isFromMedicalReport: true, + isForEyeMeasurements: true, + ), + ), + SizedBox(height: 16.h), + CustomTabBar( + activeTextColor: AppColors.primaryRedColor, + activeBackgroundColor: AppColors.primaryRedColor.withValues(alpha: .1), + tabs: [ + CustomTabBarModel(null, LocaleKeys.classes.tr()), + CustomTabBarModel(null, LocaleKeys.contactLens.tr()), + ], + onTabChange: (index) { + myAppointmentsVM.onEyeMeasurementsTabChanged(index); + }, + ), + SizedBox(height: 12.h), + getSelectedTabContent(myAppointmentsVM), + ], + ).paddingSymmetrical(24.w, 0); + }), + ), + ), + ); + } + + Widget getSelectedTabContent(MyAppointmentsViewModel myAppointmentsVM) { + switch (myAppointmentsVM.eyeMeasurementsTabSelectedIndex) { + case 0: + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + padding: EdgeInsets.all(16.h), + decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.r, hasShadow: true), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocaleKeys.rightEye.tr().toText14(isBold: true), + SizedBox(height: 16.h), + getRow(LocaleKeys.sphere.tr(), '${patientAppointmentHistoryResponseModel.listHISGetGlassPrescription![0].rightEyeSpherical}', '-'), + getRow(LocaleKeys.cylinder.tr(), '${patientAppointmentHistoryResponseModel.listHISGetGlassPrescription![0].rightEyeCylinder}', '-'), + getRow(LocaleKeys.axis.tr(), '${patientAppointmentHistoryResponseModel.listHISGetGlassPrescription![0].rightEyeAxis}', '-'), + getRow(LocaleKeys.prism.tr(), '${patientAppointmentHistoryResponseModel.listHISGetGlassPrescription![0].rightEyePrism}', '-'), + getRow(LocaleKeys.va.tr(), '${patientAppointmentHistoryResponseModel.listHISGetGlassPrescription![0].rightEyeVA}', '-'), + getRow(LocaleKeys.remarks.tr(), '${patientAppointmentHistoryResponseModel.listHISGetGlassPrescription![0].rightEyeRemarks}', '-', isLast: true), + ], + ), + ), + SizedBox(height: 16.h), + Container( + padding: EdgeInsets.all(16.h), + decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.r, hasShadow: true), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocaleKeys.leftEye.tr().needTranslation.toText14(isBold: true), + SizedBox(height: 16.h), + getRow(LocaleKeys.sphere.tr(), '${patientAppointmentHistoryResponseModel.listHISGetGlassPrescription![0].leftEyeSpherical}', '-'), + getRow(LocaleKeys.cylinder.tr(), '${patientAppointmentHistoryResponseModel.listHISGetGlassPrescription![0].leftEyeCylinder}', '-'), + getRow(LocaleKeys.axis.tr(), '${patientAppointmentHistoryResponseModel.listHISGetGlassPrescription![0].leftEyeAxis}', '-'), + getRow(LocaleKeys.prism.tr(), '${patientAppointmentHistoryResponseModel.listHISGetGlassPrescription![0].leftEyePrism}', '-'), + getRow(LocaleKeys.va.tr(), '${patientAppointmentHistoryResponseModel.listHISGetGlassPrescription![0].leftEyeVA}', '-'), + getRow(LocaleKeys.remarks.tr(), '${patientAppointmentHistoryResponseModel.listHISGetGlassPrescription![0].leftEyeRemarks}', '-', isLast: true), + ], + ), + ), + SizedBox(height: 24.h), + ], + ); + case 1: + return Column( + children: [ + Container( + padding: EdgeInsets.all(16.h), + decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.r, hasShadow: true), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocaleKeys.rightEye.tr().toText14(isBold: true), + SizedBox(height: 16.h), + getRow(LocaleKeys.brand.tr(), '${patientAppointmentHistoryResponseModel.listHISGetContactLensPrescription![0].brand}', ''), + getRow('B.C', '${patientAppointmentHistoryResponseModel.listHISGetContactLensPrescription![0].baseCurve}', ''), + getRow(LocaleKeys.power.tr(), '${patientAppointmentHistoryResponseModel.listHISGetContactLensPrescription![0].power}', ''), + getRow(LocaleKeys.diameter.tr(), '${patientAppointmentHistoryResponseModel.listHISGetContactLensPrescription![0].diameter}', ''), + getRow('OZ', '${patientAppointmentHistoryResponseModel.listHISGetContactLensPrescription![0].oZ}', ''), + getRow('CT', '${patientAppointmentHistoryResponseModel.listHISGetContactLensPrescription![0].cT}', ''), + getRow('Blend', '${patientAppointmentHistoryResponseModel.listHISGetContactLensPrescription![0].blend}', ''), + getRow(LocaleKeys.remarks.tr(), '${patientAppointmentHistoryResponseModel.listHISGetContactLensPrescription![0].remarks}', '', isLast: true), + ], + ), + ), + SizedBox(height: 16.h), + Container( + padding: EdgeInsets.all(16.h), + decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.r, hasShadow: true), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocaleKeys.leftEye.tr().needTranslation.toText14(isBold: true), + SizedBox(height: 16.h), + getRow(LocaleKeys.brand.tr(), '${patientAppointmentHistoryResponseModel.listHISGetContactLensPrescription![1].brand}', ''), + getRow('B.C', '${patientAppointmentHistoryResponseModel.listHISGetContactLensPrescription![1].baseCurve}', ''), + getRow(LocaleKeys.power.tr(), '${patientAppointmentHistoryResponseModel.listHISGetContactLensPrescription![1].power}', ''), + getRow(LocaleKeys.diameter.tr(), '${patientAppointmentHistoryResponseModel.listHISGetContactLensPrescription![1].diameter}', ''), + getRow('OZ', '${patientAppointmentHistoryResponseModel.listHISGetContactLensPrescription![1].oZ}', ''), + getRow('CT', '${patientAppointmentHistoryResponseModel.listHISGetContactLensPrescription![1].cT}', ''), + getRow('Blend', '${patientAppointmentHistoryResponseModel.listHISGetContactLensPrescription![1].blend}', ''), + getRow(LocaleKeys.remarks.tr(), '${patientAppointmentHistoryResponseModel.listHISGetContactLensPrescription![1].remarks}', '', isLast: true), + ], + ), + ), + SizedBox(height: 24.h), + ], + ); + default: + return Container(); + } + } + + Widget getRow(String title, String val1, String val2, {bool isLast = false}) => Padding( + padding: EdgeInsets.only(left: 8.w, right: 8.w), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.all(8.h), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded(flex: 2, child: title.toText11(weight: FontWeight.w500)), + Expanded( + flex: 2, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + SizedBox(width: 120.w, child: (val1 == 'null' ? '-' : val1).toText10(isBold: true, textOverflow: TextOverflow.clip)), + (val2 == 'null' ? '-' : val2).toText10(isBold: true, textOverflow: TextOverflow.ellipsis), + ], + ), + ) + ], + ), + ), + isLast + ? Container( + height: 4, + ) + : Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.1), height: 2.h) + ], + ), + ); +} diff --git a/lib/presentation/medical_file/eye_measurements_appointments_page.dart b/lib/presentation/medical_file/eye_measurements_appointments_page.dart new file mode 100644 index 0000000..3b82ad4 --- /dev/null +++ b/lib/presentation/medical_file/eye_measurements_appointments_page.dart @@ -0,0 +1,90 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_staggered_animations/flutter_staggered_animations.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/book_appointments/book_appointments_view_model.dart'; +import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart'; +import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart'; +import 'package:hmg_patient_app_new/presentation/appointments/widgets/appointment_card.dart'; +import 'package:hmg_patient_app_new/theme/colors.dart'; +import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; +import 'package:provider/provider.dart'; + +class EyeMeasurementsAppointmentsPage extends StatelessWidget { + EyeMeasurementsAppointmentsPage({super.key}); + + late BookAppointmentsViewModel bookAppointmentsViewModel; + + @override + Widget build(BuildContext context) { + bookAppointmentsViewModel = Provider.of(context, listen: false); + return Scaffold( + backgroundColor: AppColors.bgScaffoldColor, + body: CollapsingListView( + title: "Eye Measurements", + child: SingleChildScrollView( + child: Consumer(builder: (context, myAppointmentsVM, child) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height: 16.h), + ListView.separated( + scrollDirection: Axis.vertical, + itemCount: myAppointmentsVM.isEyeMeasurementsAppointmentsLoading + ? 5 + : myAppointmentsVM.patientEyeMeasurementsAppointmentsHistoryList.isNotEmpty + ? myAppointmentsVM.patientEyeMeasurementsAppointmentsHistoryList.length + : 1, + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + padding: EdgeInsets.only(left: 24.h, right: 24.h), + itemBuilder: (context, index) { + return myAppointmentsVM.isEyeMeasurementsAppointmentsLoading + ? Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true), + child: AppointmentCard( + patientAppointmentHistoryResponseModel: PatientAppointmentHistoryResponseModel(), + myAppointmentsViewModel: myAppointmentsVM, + bookAppointmentsViewModel: bookAppointmentsViewModel, + isLoading: true, + isFromHomePage: false, + ), + ) + : myAppointmentsVM.patientEyeMeasurementsAppointmentsHistoryList.isNotEmpty + ? AnimationConfiguration.staggeredList( + position: index, + duration: const Duration(milliseconds: 1000), + child: SlideAnimation( + verticalOffset: 100.0, + child: FadeInAnimation( + child: AnimatedContainer( + duration: Duration(milliseconds: 300), + curve: Curves.easeInOut, + decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true), + child: AppointmentCard( + patientAppointmentHistoryResponseModel: myAppointmentsVM.patientEyeMeasurementsAppointmentsHistoryList[index], + myAppointmentsViewModel: myAppointmentsVM, + bookAppointmentsViewModel: bookAppointmentsViewModel, + isLoading: false, + isFromHomePage: false, + isForEyeMeasurements: true, + ), + ), + ), + ), + ) + : Utils.getNoDataWidget(context, noDataText: "No Ophthalmology appointments found...".needTranslation); + }, + separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h), + ), + SizedBox(height: 60.h), + ], + ); + }), + ), + ), + ); + } +} diff --git a/lib/presentation/medical_file/medical_file_page.dart b/lib/presentation/medical_file/medical_file_page.dart index 1be683b..828cbb4 100644 --- a/lib/presentation/medical_file/medical_file_page.dart +++ b/lib/presentation/medical_file/medical_file_page.dart @@ -35,6 +35,7 @@ import 'package:hmg_patient_app_new/presentation/insurance/widgets/insurance_upd import 'package:hmg_patient_app_new/presentation/insurance/widgets/patient_insurance_card.dart'; import 'package:hmg_patient_app_new/presentation/lab/lab_orders_page.dart'; import 'package:hmg_patient_app_new/presentation/lab/lab_result_item_view.dart'; +import 'package:hmg_patient_app_new/presentation/medical_file/eye_measurements_appointments_page.dart'; import 'package:hmg_patient_app_new/presentation/medical_file/patient_sickleaves_list_page.dart'; import 'package:hmg_patient_app_new/presentation/medical_file/vaccine_list_page.dart'; import 'package:hmg_patient_app_new/presentation/medical_file/widgets/lab_rad_card.dart'; @@ -751,7 +752,16 @@ class _MedicalFilePageState extends State { svgIcon: AppAssets.eye_result_icon, isLargeText: true, iconSize: 36.w, - ), + ).onPress(() { + myAppointmentsViewModel.setIsEyeMeasurementsAppointmentsLoading(true); + myAppointmentsViewModel.onEyeMeasurementsTabChanged(0); + myAppointmentsViewModel.getPatientEyeMeasurementAppointments(); + Navigator.of(context).push( + CustomPageRoute( + page: EyeMeasurementsAppointmentsPage(), + ), + ); + }), MedicalFileCard( label: "Allergy Info".needTranslation, textColor: AppColors.blackColor,