From 25fa1acc9e64b1ae79bf5206c0c3cbb126f10b9f Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Tue, 7 Oct 2025 15:49:23 +0300 Subject: [PATCH] Medical file widgets, Insurance approval implementation contd. --- lib/core/api/api_client.dart | 4 +- lib/core/dependencies.dart | 5 + lib/features/insurance/insurance_repo.dart | 41 +- .../insurance/insurance_view_model.dart | 33 ++ ...ent_insurance_approval_response_model.dart | 465 ++++++++++++++++++ lib/features/lab/lab_view_model.dart | 30 +- .../appointment_details_page.dart | 2 +- .../appointment_payment_page.dart | 6 +- .../appointments/my_appointments_page.dart | 6 +- .../appointments/my_doctors_page.dart | 6 +- .../widgets/AppointmentFilter.dart | 4 +- .../widgets/appointment_card.dart | 55 ++- .../appointment_checkin_bottom_sheet.dart | 2 +- .../widgets/appointment_doctor_card.dart | 2 +- .../facility_selection_item.dart | 2 +- .../hospital_list_items.dart | 2 +- .../region_bottomsheet/region_list_item.dart | 2 +- .../book_appointment_page.dart | 12 +- .../book_appointment/doctor_profile_page.dart | 4 +- .../immediate_livecare_payment_page.dart | 6 +- .../widgets/livecare_clinic_card.dart | 2 +- .../review_appointment_page.dart | 4 +- .../wallet_payment_confirm_page.dart | 4 +- .../widgets/hospital_list_item.dart | 2 +- lib/presentation/home/landing_page.dart | 6 + .../insurance/insurance_approvals_page.dart | 109 ++++ .../insurance/insurance_home_page.dart | 1 - .../widgets/insurance_approval_card.dart | 129 +++++ .../insurance_approval_details_page.dart | 135 +++++ .../medical_file/medical_file_page.dart | 89 ++-- .../medical_file/vaccine_list_page.dart | 2 +- .../medical_file/widgets/lab_rad_card.dart | 27 +- .../widgets/patient_sick_leave_card.dart | 2 +- .../medical_report_request_page.dart | 2 + .../prescriptions_list_page.dart | 5 +- lib/widgets/appbar/collapsing_list_view.dart | 2 +- lib/widgets/chip/app_custom_chip_widget.dart | 2 +- 37 files changed, 1121 insertions(+), 91 deletions(-) create mode 100644 lib/features/insurance/models/resp_models/patient_insurance_approval_response_model.dart create mode 100644 lib/presentation/insurance/insurance_approvals_page.dart create mode 100644 lib/presentation/insurance/widgets/insurance_approval_card.dart create mode 100644 lib/presentation/insurance/widgets/insurance_approval_details_page.dart diff --git a/lib/core/api/api_client.dart b/lib/core/api/api_client.dart index 9140a13..a36f554 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'] = 4767884; + body['TokenID'] = "@dm!n"; + body['PatientID'] = 4772172; // body['PatientTypeID'] = 1; // // body['PatientOutSA'] = 0; diff --git a/lib/core/dependencies.dart b/lib/core/dependencies.dart index 638d80f..3ce8a19 100644 --- a/lib/core/dependencies.dart +++ b/lib/core/dependencies.dart @@ -19,6 +19,7 @@ import 'package:hmg_patient_app_new/features/lab/lab_repo.dart'; import 'package:hmg_patient_app_new/features/lab/lab_view_model.dart'; import 'package:hmg_patient_app_new/features/medical_file/medical_file_repo.dart'; import 'package:hmg_patient_app_new/features/medical_file/medical_file_view_model.dart'; +import 'package:hmg_patient_app_new/features/my_appointments/appointment_via_region_viewmodel.dart'; import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_repo.dart'; import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart'; import 'package:hmg_patient_app_new/features/payfort/payfort_repo.dart'; @@ -181,6 +182,10 @@ class AppDependencies { () => DoctorFilterViewModel(), ); + getIt.registerLazySingleton( + () => AppointmentViaRegionViewmodel(navigationService: getIt(), appState: getIt()), + ); + // Screen-specific VMs → Factory // getIt.registerFactory( // () => BookAppointmentsViewModel( diff --git a/lib/features/insurance/insurance_repo.dart b/lib/features/insurance/insurance_repo.dart index d367509..1aeb769 100644 --- a/lib/features/insurance/insurance_repo.dart +++ b/lib/features/insurance/insurance_repo.dart @@ -3,6 +3,7 @@ import 'package:hmg_patient_app_new/core/api/api_client.dart'; import 'package:hmg_patient_app_new/core/api_consts.dart'; import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart'; import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart'; +import 'package:hmg_patient_app_new/features/insurance/models/resp_models/patient_insurance_approval_response_model.dart'; import 'package:hmg_patient_app_new/features/insurance/models/resp_models/patient_insurance_card_history.dart'; import 'package:hmg_patient_app_new/features/insurance/models/resp_models/patient_insurance_details_response_model.dart'; import 'package:hmg_patient_app_new/features/insurance/models/resp_models/patient_insurance_update_response_model.dart'; @@ -14,6 +15,8 @@ abstract class InsuranceRepo { Future>>> getPatientInsuranceCardHistory(); Future>> getPatientInsuranceDetailsForUpdate({required String patientId, required String identificationNo}); + + Future>>> getPatientInsuranceApprovalsList(); } class InsuranceRepoImp implements InsuranceRepo { @@ -66,7 +69,6 @@ class InsuranceRepoImp implements InsuranceRepo { @override Future>>> getPatientInsuranceCardHistory() async { Map mapDevice = {}; - try { GenericApiModel>? apiResponse; Failure? failure; @@ -144,4 +146,41 @@ class InsuranceRepoImp implements InsuranceRepo { return Left(UnknownFailure(e.toString())); } } + + @override + Future>>> getPatientInsuranceApprovalsList() async { + Map mapDevice = {}; + try { + GenericApiModel>? apiResponse; + Failure? failure; + await apiClient.post( + GET_PAtIENTS_INSURANCE_APPROVALS, + body: mapDevice, + onFailure: (error, statusCode, {messageStatus, failureType}) { + failure = failureType; + }, + onSuccess: (response, statusCode, {messageStatus, errorMessage}) { + try { + final list = response['HIS_Approval_List']; + + final insuranceCardsList = list.map((item) => InsuranceApprovalResponseModel.fromJson(item as Map)).toList().cast(); + + apiResponse = GenericApiModel>( + messageStatus: messageStatus, + statusCode: statusCode, + errorMessage: null, + data: insuranceCardsList, + ); + } catch (e) { + failure = DataParsingFailure(e.toString()); + } + }, + ); + if (failure != null) return Left(failure!); + if (apiResponse == null) return Left(ServerFailure("Unknown error")); + return Right(apiResponse!); + } catch (e) { + return Left(UnknownFailure(e.toString())); + } + } } diff --git a/lib/features/insurance/insurance_view_model.dart b/lib/features/insurance/insurance_view_model.dart index 0bcf30f..363ad28 100644 --- a/lib/features/insurance/insurance_view_model.dart +++ b/lib/features/insurance/insurance_view_model.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:hmg_patient_app_new/features/insurance/insurance_repo.dart'; +import 'package:hmg_patient_app_new/features/insurance/models/resp_models/patient_insurance_approval_response_model.dart'; import 'package:hmg_patient_app_new/features/insurance/models/resp_models/patient_insurance_card_history.dart'; import 'package:hmg_patient_app_new/features/insurance/models/resp_models/patient_insurance_details_response_model.dart'; import 'package:hmg_patient_app_new/features/insurance/models/resp_models/patient_insurance_update_response_model.dart'; @@ -14,11 +15,14 @@ class InsuranceViewModel extends ChangeNotifier { bool isInsuranceDataToBeLoaded = true; + bool isInsuranceApprovalsLoading = false; + InsuranceRepo insuranceRepo; ErrorHandlerService errorHandlerService; List patientInsuranceList = []; List patientInsuranceCardHistoryList = []; + List patientInsuranceApprovalsList = []; PatientInsuranceUpdateResponseModel? patientInsuranceUpdateResponseModel; @@ -34,6 +38,7 @@ class InsuranceViewModel extends ChangeNotifier { isInsuranceHistoryLoading = true; isInsuranceDetailsLoading = true; isInsuranceUpdateDetailsLoading = true; + isInsuranceApprovalsLoading = true; notifyListeners(); } @@ -57,6 +62,11 @@ class InsuranceViewModel extends ChangeNotifier { notifyListeners(); } + setIsInsuranceApprovalsLoading(bool val) { + isInsuranceApprovalsLoading = val; + notifyListeners(); + } + Future getPatientInsuranceDetails({Function(dynamic)? onSuccess, Function(String)? onError}) async { if (!isInsuranceDataToBeLoaded) return; @@ -130,4 +140,27 @@ class InsuranceViewModel extends ChangeNotifier { }, ); } + + Future getPatientInsuranceApprovalsList({Function(dynamic)? onSuccess, Function(String)? onError}) async { + final result = await insuranceRepo.getPatientInsuranceApprovalsList(); + + result.fold( + (failure) async { + isInsuranceApprovalsLoading = false; + notifyListeners(); + }, + (apiResponse) { + if (apiResponse.messageStatus == 2) { + // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {}); + } else if (apiResponse.messageStatus == 1) { + patientInsuranceApprovalsList = apiResponse.data!; + isInsuranceApprovalsLoading = false; + notifyListeners(); + if (onSuccess != null) { + onSuccess(apiResponse); + } + } + }, + ); + } } diff --git a/lib/features/insurance/models/resp_models/patient_insurance_approval_response_model.dart b/lib/features/insurance/models/resp_models/patient_insurance_approval_response_model.dart new file mode 100644 index 0000000..f272f2d --- /dev/null +++ b/lib/features/insurance/models/resp_models/patient_insurance_approval_response_model.dart @@ -0,0 +1,465 @@ +class InsuranceApprovalResponseModel { + String? setupID; + int? projectID; + int? approvalNo; + String? approvalDate; + int? patientType; + int? patientID; + int? companyID; + int? subCategoryID; + int? doctorID; + int? clinicID; + int? approvalType; + String? inpatientApprovalSubType; + String? validFrom; + String? vaildDays; + String? validTo; + bool? isApprovalOnGross; + bool? isPackage; + int? requestedAmount; + int? actualApprovedAmount; + int? aviliableAmount; + String? companyApprovalNo; + int? progNoteOrderNo; + String? submitOn; + String? receiptOn; + String? remarks1; + String? remarks2; + int? status; + String? feedbackStatusBy; + String? feedbackStatus; + String? feedbackStatusOn; + int? authorizerID; + String? expiryDate; + int? appointmentNo; + int? admissionNo; + int? admissionRequestNo; + int? createdBy; + String? createdOn; + int? editedBy; + String? editedOn; + String? rowVer; + bool? isAddlDiscApplied; + int? inProgressReasonID; + String? extendedBy; + String? extendedOn; + int? subPolicyNo; + int? noOrderAuthorizerID; + bool? isVerbalApproval; + String? subStatus; + bool? isNotificationSend; + String? eApprovalStatus; + String? eApprovalRemarks; + bool? isEmailSentOnDelayApproval; + int? eAuthorizationID; + InsuranceApprovalDetails? apporvalDetails; + String? approvalStatusDescption; + String? clinicName; + String? clinicNameN; + String? companyName; + String? doctorImageURL; + String? doctorName; + String? doctorNameN; + int? doctorRate; + String? doctorTitle; + int? gender; + String? genderDescription; + bool? isActiveDoctorProfile; + bool? isExecludeDoctor; + bool? isInOutPatient; + String? isInOutPatientDescription; + String? isInOutPatientDescriptionN; + bool? isLiveCareAppointment; + String? projectName; + String? projectNameN; + String? qR; + List? speciality; + String? strApprovalDate; + String? strExpiryDate; + String? strSubmitDate; + int? totaUnUsedCount; + int? unUsedCount; + + InsuranceApprovalResponseModel( + {this.setupID, + this.projectID, + this.approvalNo, + this.approvalDate, + this.patientType, + this.patientID, + this.companyID, + this.subCategoryID, + this.doctorID, + this.clinicID, + this.approvalType, + this.inpatientApprovalSubType, + this.validFrom, + this.vaildDays, + this.validTo, + this.isApprovalOnGross, + this.isPackage, + this.requestedAmount, + this.actualApprovedAmount, + this.aviliableAmount, + this.companyApprovalNo, + this.progNoteOrderNo, + this.submitOn, + this.receiptOn, + this.remarks1, + this.remarks2, + this.status, + this.feedbackStatusBy, + this.feedbackStatus, + this.feedbackStatusOn, + this.authorizerID, + this.expiryDate, + this.appointmentNo, + this.admissionNo, + this.admissionRequestNo, + this.createdBy, + this.createdOn, + this.editedBy, + this.editedOn, + this.rowVer, + this.isAddlDiscApplied, + this.inProgressReasonID, + this.extendedBy, + this.extendedOn, + this.subPolicyNo, + this.noOrderAuthorizerID, + this.isVerbalApproval, + this.subStatus, + this.isNotificationSend, + this.eApprovalStatus, + this.eApprovalRemarks, + this.isEmailSentOnDelayApproval, + this.eAuthorizationID, + this.apporvalDetails, + this.approvalStatusDescption, + this.clinicName, + this.clinicNameN, + this.companyName, + this.doctorImageURL, + this.doctorName, + this.doctorNameN, + this.doctorRate, + this.doctorTitle, + this.gender, + this.genderDescription, + this.isActiveDoctorProfile, + this.isExecludeDoctor, + this.isInOutPatient, + this.isInOutPatientDescription, + this.isInOutPatientDescriptionN, + this.isLiveCareAppointment, + this.projectName, + this.projectNameN, + this.qR, + this.speciality, + this.strApprovalDate, + this.strExpiryDate, + this.strSubmitDate, + this.totaUnUsedCount, + this.unUsedCount}); + + InsuranceApprovalResponseModel.fromJson(Map json) { + setupID = json['SetupID']; + projectID = json['ProjectID']; + approvalNo = json['ApprovalNo']; + approvalDate = json['ApprovalDate']; + patientType = json['PatientType']; + patientID = json['PatientID']; + companyID = json['CompanyID']; + subCategoryID = json['SubCategoryID']; + doctorID = json['DoctorID']; + clinicID = json['ClinicID']; + approvalType = json['ApprovalType']; + inpatientApprovalSubType = json['InpatientApprovalSubType']; + validFrom = json['ValidFrom']; + vaildDays = json['VaildDays']; + validTo = json['ValidTo']; + isApprovalOnGross = json['IsApprovalOnGross']; + isPackage = json['IsPackage']; + requestedAmount = json['RequestedAmount']; + actualApprovedAmount = json['ActualApprovedAmount']; + aviliableAmount = json['AviliableAmount']; + companyApprovalNo = json['CompanyApprovalNo']; + progNoteOrderNo = json['ProgNoteOrderNo']; + submitOn = json['SubmitOn']; + receiptOn = json['ReceiptOn']; + remarks1 = json['Remarks1']; + remarks2 = json['Remarks2']; + status = json['Status']; + feedbackStatusBy = json['FeedbackStatusBy']; + feedbackStatus = json['FeedbackStatus']; + feedbackStatusOn = json['FeedbackStatusOn']; + authorizerID = json['AuthorizerID']; + expiryDate = json['ExpiryDate']; + appointmentNo = json['AppointmentNo']; + admissionNo = json['AdmissionNo']; + admissionRequestNo = json['AdmissionRequestNo']; + createdBy = json['CreatedBy']; + createdOn = json['CreatedOn']; + editedBy = json['EditedBy']; + editedOn = json['EditedOn']; + rowVer = json['RowVer']; + isAddlDiscApplied = json['IsAddlDiscApplied']; + inProgressReasonID = json['InProgressReasonID']; + extendedBy = json['ExtendedBy']; + extendedOn = json['ExtendedOn']; + subPolicyNo = json['SubPolicyNo']; + noOrderAuthorizerID = json['NoOrderAuthorizerID']; + isVerbalApproval = json['isVerbalApproval']; + subStatus = json['SubStatus']; + isNotificationSend = json['IsNotificationSend']; + eApprovalStatus = json['EApprovalStatus']; + eApprovalRemarks = json['EApprovalRemarks']; + isEmailSentOnDelayApproval = json['IsEmailSentOnDelayApproval']; + eAuthorizationID = json['EAuthorizationID']; + if (json['ApporvalDetails'] != null && json['ApporvalDetails'].length != 0) { + apporvalDetails = InsuranceApprovalDetails.fromJson(json['ApporvalDetails'][0]); + } + approvalStatusDescption = json['ApprovalStatusDescption']; + clinicName = json['ClinicName']; + clinicNameN = json['ClinicNameN']; + companyName = json['CompanyName']; + doctorImageURL = json['DoctorImageURL']; + doctorName = json['DoctorName']; + doctorNameN = json['DoctorNameN']; + doctorRate = json['DoctorRate']; + doctorTitle = json['DoctorTitle']; + gender = json['Gender']; + genderDescription = json['GenderDescription']; + isActiveDoctorProfile = json['IsActiveDoctorProfile']; + isExecludeDoctor = json['IsExecludeDoctor']; + isInOutPatient = json['IsInOutPatient']; + isInOutPatientDescription = json['IsInOutPatientDescription']; + isInOutPatientDescriptionN = json['IsInOutPatientDescriptionN']; + isLiveCareAppointment = json['IsLiveCareAppointment']; + projectName = json['ProjectName']; + projectNameN = json['ProjectNameN']; + qR = json['QR']; + if (json['Speciality'] != null) speciality = json['Speciality'].cast(); + strApprovalDate = json['StrApprovalDate']; + strExpiryDate = json['StrExpiryDate']; + strSubmitDate = json['StrSubmitDate']; + totaUnUsedCount = json['TotaUnUsedCount']; + unUsedCount = json['UnUsedCount']; + } + + Map toJson() { + final Map data = new Map(); + data['SetupID'] = this.setupID; + data['ProjectID'] = this.projectID; + data['ApprovalNo'] = this.approvalNo; + data['ApprovalDate'] = this.approvalDate; + data['PatientType'] = this.patientType; + data['PatientID'] = this.patientID; + data['CompanyID'] = this.companyID; + data['SubCategoryID'] = this.subCategoryID; + data['DoctorID'] = this.doctorID; + data['ClinicID'] = this.clinicID; + data['ApprovalType'] = this.approvalType; + data['InpatientApprovalSubType'] = this.inpatientApprovalSubType; + data['ValidFrom'] = this.validFrom; + data['VaildDays'] = this.vaildDays; + data['ValidTo'] = this.validTo; + data['IsApprovalOnGross'] = this.isApprovalOnGross; + data['IsPackage'] = this.isPackage; + data['RequestedAmount'] = this.requestedAmount; + data['ActualApprovedAmount'] = this.actualApprovedAmount; + data['AviliableAmount'] = this.aviliableAmount; + data['CompanyApprovalNo'] = this.companyApprovalNo; + data['ProgNoteOrderNo'] = this.progNoteOrderNo; + data['SubmitOn'] = this.submitOn; + data['ReceiptOn'] = this.receiptOn; + data['Remarks1'] = this.remarks1; + data['Remarks2'] = this.remarks2; + data['Status'] = this.status; + data['FeedbackStatusBy'] = this.feedbackStatusBy; + data['FeedbackStatus'] = this.feedbackStatus; + data['FeedbackStatusOn'] = this.feedbackStatusOn; + data['AuthorizerID'] = this.authorizerID; + data['ExpiryDate'] = this.expiryDate; + data['AppointmentNo'] = this.appointmentNo; + data['AdmissionNo'] = this.admissionNo; + data['AdmissionRequestNo'] = this.admissionRequestNo; + data['CreatedBy'] = this.createdBy; + data['CreatedOn'] = this.createdOn; + data['EditedBy'] = this.editedBy; + data['EditedOn'] = this.editedOn; + data['RowVer'] = this.rowVer; + data['IsAddlDiscApplied'] = this.isAddlDiscApplied; + data['InProgressReasonID'] = this.inProgressReasonID; + data['ExtendedBy'] = this.extendedBy; + data['ExtendedOn'] = this.extendedOn; + data['SubPolicyNo'] = this.subPolicyNo; + data['NoOrderAuthorizerID'] = this.noOrderAuthorizerID; + data['isVerbalApproval'] = this.isVerbalApproval; + data['SubStatus'] = this.subStatus; + data['IsNotificationSend'] = this.isNotificationSend; + data['EApprovalStatus'] = this.eApprovalStatus; + data['EApprovalRemarks'] = this.eApprovalRemarks; + data['IsEmailSentOnDelayApproval'] = this.isEmailSentOnDelayApproval; + data['EAuthorizationID'] = this.eAuthorizationID; + if (this.apporvalDetails != null) { + data['ApporvalDetails'] = this.apporvalDetails!.toJson; + } + data['ApprovalStatusDescption'] = this.approvalStatusDescption; + data['ClinicName'] = this.clinicName; + data['ClinicNameN'] = this.clinicNameN; + data['CompanyName'] = this.companyName; + data['DoctorImageURL'] = this.doctorImageURL; + data['DoctorName'] = this.doctorName; + data['DoctorNameN'] = this.doctorNameN; + data['DoctorRate'] = this.doctorRate; + data['DoctorTitle'] = this.doctorTitle; + data['Gender'] = this.gender; + data['GenderDescription'] = this.genderDescription; + data['IsActiveDoctorProfile'] = this.isActiveDoctorProfile; + data['IsExecludeDoctor'] = this.isExecludeDoctor; + data['IsInOutPatient'] = this.isInOutPatient; + data['IsInOutPatientDescription'] = this.isInOutPatientDescription; + data['IsInOutPatientDescriptionN'] = this.isInOutPatientDescriptionN; + data['IsLiveCareAppointment'] = this.isLiveCareAppointment; + data['ProjectName'] = this.projectName; + data['ProjectNameN'] = this.projectNameN; + data['QR'] = this.qR; + data['Speciality'] = this.speciality; + data['StrApprovalDate'] = this.strApprovalDate; + data['StrExpiryDate'] = this.strExpiryDate; + data['StrSubmitDate'] = this.strSubmitDate; + data['TotaUnUsedCount'] = this.totaUnUsedCount; + data['UnUsedCount'] = this.unUsedCount; + return data; + } +} + +class InsuranceApprovalDetails { + int? setupID; + int? projectID; + int? approvalNo; + int? lineItemNo; + int? orderType; + int? procedureID; + int? toothNo; + int? price; + int? approvedAmount; + String? unapprovedPatientShare; + int? waivedAmount; + String? discountType; + int? discountValue; + String? shareType; + String? patientShareTypeValue; + String? companyShareTypeValue; + String? patientShare; + String? companyShare; + int? deductableAmount; + String? disapprovedRemarks; + int? progNoteOrderNo; + int? progNoteLineItemNo; + String? invoiceTransactionType; + int? invoiceNo; + String? procedureName; + String? procedureNameN; + String? status; + bool? isInvoiced; + String? isInvoicedDesc; + + InsuranceApprovalDetails( + {this.setupID, + this.projectID, + this.approvalNo, + this.lineItemNo, + this.orderType, + this.procedureID, + this.toothNo, + this.price, + this.approvedAmount, + this.unapprovedPatientShare, + this.waivedAmount, + this.discountType, + this.discountValue, + this.shareType, + this.patientShareTypeValue, + this.companyShareTypeValue, + this.patientShare, + this.companyShare, + this.deductableAmount, + this.disapprovedRemarks, + this.progNoteOrderNo, + this.progNoteLineItemNo, + this.invoiceTransactionType, + this.invoiceNo, + this.procedureName, + this.procedureNameN, + this.status, + this.isInvoiced, + this.isInvoicedDesc}); + + InsuranceApprovalDetails.fromJson(Map json) { + setupID = json['SetupID']; + projectID = json['ProjectID']; + approvalNo = json['ApprovalNo']; + lineItemNo = json['LineItemNo']; + orderType = json['OrderType']; + procedureID = json['ProcedureID']; + toothNo = json['ToothNo']; + price = json['Price']; + approvedAmount = json['ApprovedAmount']; + unapprovedPatientShare = json['UnapprovedPatientShare']; + waivedAmount = json['WaivedAmount']; + discountType = json['DiscountType']; + discountValue = json['DiscountValue']; + shareType = json['ShareType']; + patientShareTypeValue = json['PatientShareTypeValue']; + companyShareTypeValue = json['CompanyShareTypeValue']; + patientShare = json['PatientShare']; + companyShare = json['CompanyShare']; + deductableAmount = json['DeductableAmount']; + disapprovedRemarks = json['DisapprovedRemarks']; + progNoteOrderNo = json['ProgNoteOrderNo']; + progNoteLineItemNo = json['ProgNoteLineItemNo']; + invoiceTransactionType = json['InvoiceTransactionType']; + invoiceNo = json['InvoiceNo']; + procedureName = json['ProcedureName']; + procedureNameN = json['ProcedureNameN']; + status = json['Status']; + isInvoiced = json['IsInvoiced']; + isInvoicedDesc = json['IsInvoicedDesc']; + } + + Map toJson() { + final Map data = new Map(); + data['SetupID'] = this.setupID; + data['ProjectID'] = this.projectID; + data['ApprovalNo'] = this.approvalNo; + data['LineItemNo'] = this.lineItemNo; + data['OrderType'] = this.orderType; + data['ProcedureID'] = this.procedureID; + data['ToothNo'] = this.toothNo; + data['Price'] = this.price; + data['ApprovedAmount'] = this.approvedAmount; + data['UnapprovedPatientShare'] = this.unapprovedPatientShare; + data['WaivedAmount'] = this.waivedAmount; + data['DiscountType'] = this.discountType; + data['DiscountValue'] = this.discountValue; + data['ShareType'] = this.shareType; + data['PatientShareTypeValue'] = this.patientShareTypeValue; + data['CompanyShareTypeValue'] = this.companyShareTypeValue; + data['PatientShare'] = this.patientShare; + data['CompanyShare'] = this.companyShare; + data['DeductableAmount'] = this.deductableAmount; + data['DisapprovedRemarks'] = this.disapprovedRemarks; + data['ProgNoteOrderNo'] = this.progNoteOrderNo; + data['ProgNoteLineItemNo'] = this.progNoteLineItemNo; + data['InvoiceTransactionType'] = this.invoiceTransactionType; + data['InvoiceNo'] = this.invoiceNo; + data['ProcedureName'] = this.procedureName; + data['ProcedureNameN'] = this.procedureNameN; + data['Status'] = this.status; + data['IsInvoiced'] = this.isInvoiced; + data['IsInvoicedDesc'] = this.isInvoicedDesc; + return data; + } +} diff --git a/lib/features/lab/lab_view_model.dart b/lib/features/lab/lab_view_model.dart index 8a397e3..9f713ac 100644 --- a/lib/features/lab/lab_view_model.dart +++ b/lib/features/lab/lab_view_model.dart @@ -25,6 +25,8 @@ class LabViewModel extends ChangeNotifier { bool isGraphVisible = true; bool shouldShowGraph = true; + bool isLabNeedToLoad = true; + LabRepo labRepo; ErrorHandlerService errorHandlerService; NavigationService navigationService; @@ -33,6 +35,7 @@ class LabViewModel extends ChangeNotifier { List filteredLabOrders = []; List tempLabOrdersList = []; String labSpecialResult = ""; + List labOrderTests = []; PatientLabOrdersResponseModel? currentlySelectedPatientOrder; @@ -71,17 +74,29 @@ class LabViewModel extends ChangeNotifier { required this.navigationService}); initLabProvider() { - patientLabOrders.clear(); - filteredLabOrders.clear(); - isLabOrdersLoading = true; - isLabResultsLoading = true; - getPatientLabOrders(); + if (isLabNeedToLoad) { + patientLabOrders.clear(); + filteredLabOrders.clear(); + labOrderTests.clear(); + isLabOrdersLoading = true; + isLabResultsLoading = true; + getPatientLabOrders(); + } + notifyListeners(); + } + + setIsLabNeedToLoad(bool value) { + isLabNeedToLoad = value; notifyListeners(); } Future getPatientLabOrders({Function(dynamic)? onSuccess, Function(String)? onError}) async { + if (!isLabNeedToLoad) return; + + isLabOrdersLoading = true; patientLabOrders.clear(); uniqueTests.clear(); + labOrderTests.clear(); uniqueTests = {}; notifyListeners(); @@ -105,6 +120,7 @@ class LabViewModel extends ChangeNotifier { isLabResultsLoading = false; filterSuggestions(); getUniqueTestDescription(); + isLabNeedToLoad = false; notifyListeners(); if (onSuccess != null) { onSuccess(apiResponse); @@ -151,6 +167,9 @@ class LabViewModel extends ChangeNotifier { createdOn: item.createdOn, model: item)) }; + for (var element in uniqueTests) { + labOrderTests.add(element.description ?? ""); + } } Future getPatientLabResultByHospital( @@ -165,6 +184,7 @@ class LabViewModel extends ChangeNotifier { result.fold( (failure) async { isLabResultByHospitalLoading = false; + notifyListeners(); // await errorHandlerService.handleError(failure: failure); }, (apiResponse) { diff --git a/lib/presentation/appointments/appointment_details_page.dart b/lib/presentation/appointments/appointment_details_page.dart index 54353a4..c87039c 100644 --- a/lib/presentation/appointments/appointment_details_page.dart +++ b/lib/presentation/appointments/appointment_details_page.dart @@ -313,7 +313,7 @@ class _AppointmentDetailsPageState extends State { ), SizedBox(width: 68.h), Transform.flip( - flipX: appState.isArabic() ? true : false, + flipX: appState.isArabic(), child: Utils.buildSvgWithAssets( icon: AppAssets.forward_arrow_icon, iconColor: AppColors.blackColor, diff --git a/lib/presentation/appointments/appointment_payment_page.dart b/lib/presentation/appointments/appointment_payment_page.dart index 3c475c1..467a480 100644 --- a/lib/presentation/appointments/appointment_payment_page.dart +++ b/lib/presentation/appointments/appointment_payment_page.dart @@ -117,7 +117,7 @@ class _AppointmentPaymentPageState extends State { SizedBox(width: 8.h), const Spacer(), Transform.flip( - flipX: appState.isArabic() ? true : false, + flipX: appState.isArabic(), child: Utils.buildSvgWithAssets( icon: AppAssets.forward_arrow_icon_small, iconColor: AppColors.blackColor, @@ -159,7 +159,7 @@ class _AppointmentPaymentPageState extends State { SizedBox(width: 8.h), const Spacer(), Transform.flip( - flipX: appState.isArabic() ? true : false, + flipX: appState.isArabic(), child: Utils.buildSvgWithAssets( icon: AppAssets.forward_arrow_icon_small, iconColor: AppColors.blackColor, @@ -196,7 +196,7 @@ class _AppointmentPaymentPageState extends State { SizedBox(width: 8.h), const Spacer(), Transform.flip( - flipX: appState.isArabic() ? true : false, + flipX: appState.isArabic(), child: Utils.buildSvgWithAssets( icon: AppAssets.forward_arrow_icon_small, iconColor: AppColors.blackColor, diff --git a/lib/presentation/appointments/my_appointments_page.dart b/lib/presentation/appointments/my_appointments_page.dart index 150f0bf..1305ea0 100644 --- a/lib/presentation/appointments/my_appointments_page.dart +++ b/lib/presentation/appointments/my_appointments_page.dart @@ -8,6 +8,7 @@ import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; +import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/appointemnet_filters.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'; @@ -37,6 +38,7 @@ class MyAppointmentsPage extends StatefulWidget { class _MyAppointmentsPageState extends State { late MyAppointmentsViewModel myAppointmentsViewModel; + late BookAppointmentsViewModel bookAppointmentsViewModel; @override void initState() { @@ -50,6 +52,7 @@ class _MyAppointmentsPageState extends State { @override Widget build(BuildContext context) { myAppointmentsViewModel = Provider.of(context, listen: false); + bookAppointmentsViewModel = Provider.of(context, listen: false); return Scaffold( backgroundColor: AppColors.bgScaffoldColor, body: CollapsingListView( @@ -92,7 +95,6 @@ class _MyAppointmentsPageState extends State { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Visibility( visible: myAppointmentsVM.availableFilters.isNotEmpty, child: getAppointmentFilters(myAppointmentsVM)), @@ -117,6 +119,7 @@ class _MyAppointmentsPageState extends State { patientAppointmentHistoryResponseModel: PatientAppointmentHistoryResponseModel(), myAppointmentsViewModel: myAppointmentsViewModel, + bookAppointmentsViewModel: bookAppointmentsViewModel, isLoading: true, isFromHomePage: false, ), @@ -141,6 +144,7 @@ class _MyAppointmentsPageState extends State { filteredAppointmentList[index], myAppointmentsViewModel: myAppointmentsViewModel, + bookAppointmentsViewModel: bookAppointmentsViewModel, isLoading: false, isFromHomePage: false, ), diff --git a/lib/presentation/appointments/my_doctors_page.dart b/lib/presentation/appointments/my_doctors_page.dart index 2fedfd8..06257c7 100644 --- a/lib/presentation/appointments/my_doctors_page.dart +++ b/lib/presentation/appointments/my_doctors_page.dart @@ -61,7 +61,7 @@ class MyDoctorsPage extends StatelessWidget { "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png", width: 63.h, height: 63.h, - fit: BoxFit.fill, + fit: BoxFit.cover, ).circle(100).toShimmer2(isShow: true), SizedBox(width: 16.h), Expanded( @@ -112,7 +112,7 @@ class MyDoctorsPage extends StatelessWidget { myAppointmentsVM.patientMyDoctorsList[index].doctorImageURL!, width: 63.h, height: 63.h, - fit: BoxFit.fill, + fit: BoxFit.cover, ).circle(100).toShimmer2(isShow: false), SizedBox(width: 16.h), Expanded( @@ -140,7 +140,7 @@ class MyDoctorsPage extends StatelessWidget { children: [ "".toText16(), Transform.flip( - flipX: appState.isArabic() ? true : false, + flipX: appState.isArabic(), child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, width: 15.h, height: 15.h, fit: BoxFit.contain, iconColor: AppColors.textColor)), ], ), diff --git a/lib/presentation/appointments/widgets/AppointmentFilter.dart b/lib/presentation/appointments/widgets/AppointmentFilter.dart index fd2a9fe..98da22d 100644 --- a/lib/presentation/appointments/widgets/AppointmentFilter.dart +++ b/lib/presentation/appointments/widgets/AppointmentFilter.dart @@ -36,8 +36,8 @@ class AppointmentFilters extends StatelessWidget { padding: EdgeInsets.symmetric(vertical: 12.h, horizontal: 8.h), deleteIconSize: Size(18.h, 18.h), shape: SmoothRectangleBorder( - borderRadius: BorderRadius.circular(10 ), - smoothness: 10, + borderRadius: BorderRadius.circular(10.h), + smoothness: 10.h, side: BorderSide( color: selectedFilter?.contains(item) == true ? AppColors.chipPrimaryRedBorderColor diff --git a/lib/presentation/appointments/widgets/appointment_card.dart b/lib/presentation/appointments/widgets/appointment_card.dart index 3a65124..aa67a76 100644 --- a/lib/presentation/appointments/widgets/appointment_card.dart +++ b/lib/presentation/appointments/widgets/appointment_card.dart @@ -8,15 +8,20 @@ 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/book_appointments/models/resp_models/doctors_list_response_model.dart'; import 'package:hmg_patient_app_new/features/medical_file/medical_file_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/features/my_appointments/utils/appointment_type.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/presentation/appointments/appointment_details_page.dart'; +import 'package:hmg_patient_app_new/presentation/book_appointment/widgets/appointment_calendar.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; +import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart'; +import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart'; import 'package:smooth_corner/smooth_corner.dart'; @@ -26,6 +31,7 @@ class AppointmentCard extends StatefulWidget { {super.key, required this.patientAppointmentHistoryResponseModel, required this.myAppointmentsViewModel, + required this.bookAppointmentsViewModel, this.isLoading = false, this.isFromHomePage = false, this.isFromMedicalReport = false, @@ -37,6 +43,7 @@ class AppointmentCard extends StatefulWidget { bool isFromHomePage; bool isFromMedicalReport; MedicalFileViewModel? medicalFileViewModel; + BookAppointmentsViewModel bookAppointmentsViewModel; @override State createState() => _AppointmentCardState(); @@ -140,7 +147,7 @@ class _AppointmentCardState extends State { widget.isLoading ? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png" : widget.patientAppointmentHistoryResponseModel.doctorImageURL!, width: 63.h, height: 63.h, - fit: BoxFit.fill, + fit: BoxFit.cover, ).circle(100).toShimmer2(isShow: widget.isLoading), SizedBox(width: 16.h), Expanded( @@ -244,7 +251,7 @@ class _AppointmentCardState extends State { borderRadius: 10.h, ), child: Transform.flip( - flipX: appState.isArabic() ? true : false, + flipX: appState.isArabic(), child: Utils.buildSvgWithAssets( icon: AppAssets.forward_arrow_icon, iconColor: AppColors.whiteColor, @@ -293,7 +300,9 @@ class _AppointmentCardState extends State { ) : CustomButton( text: "Rebook with same doctor".needTranslation, - onPressed: () {}, + onPressed: () { + openDoctorScheduleCalendar(); + }, backgroundColor: AppColors.greyColor, borderColor: AppColors.greyColor, textColor: AppColors.blackColor, @@ -308,5 +317,45 @@ class _AppointmentCardState extends State { ); } + openDoctorScheduleCalendar() async { + DoctorsListResponseModel doctor = DoctorsListResponseModel( + clinicID: widget.patientAppointmentHistoryResponseModel.clinicID, + projectID: widget.patientAppointmentHistoryResponseModel.projectID, + doctorID: widget.patientAppointmentHistoryResponseModel.doctorID, + doctorImageURL: widget.patientAppointmentHistoryResponseModel.doctorImageURL, + doctorTitle: widget.patientAppointmentHistoryResponseModel.doctorTitle, + name: widget.patientAppointmentHistoryResponseModel.doctorNameObj, + nationalityFlagURL: "https://hmgwebservices.com/Images/flag/SYR.png", + speciality: [], + clinicName: widget.patientAppointmentHistoryResponseModel.clinicName, + projectName: widget.patientAppointmentHistoryResponseModel.projectName, + ); + widget.bookAppointmentsViewModel.setSelectedDoctor(doctor); + LoaderBottomSheet.showLoader(); + await widget.bookAppointmentsViewModel.getDoctorFreeSlots( + isBookingForLiveCare: false, + onSuccess: (dynamic respData) async { + LoaderBottomSheet.hideLoader(); + showCommonBottomSheetWithoutHeight( + title: "Pick a Date".needTranslation, + context, + child: AppointmentCalendar(), + isFullScreen: false, + isCloseButtonVisible: true, + callBackFunc: () {}, + ); + }, + onError: (err) { + LoaderBottomSheet.hideLoader(); + showCommonBottomSheetWithoutHeight( + context, + child: Utils.getErrorWidget(loadingText: err), + callBackFunc: () {}, + isFullScreen: false, + isCloseButtonVisible: true, + ); + }); + } + void performAppointmentNextAction(nextAction) {} } diff --git a/lib/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart b/lib/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart index 93f2bda..1863875 100644 --- a/lib/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart +++ b/lib/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart @@ -122,7 +122,7 @@ class AppointmentCheckinBottomSheet extends StatelessWidget { ), ), Transform.flip( - flipX: appState.isArabic() ? true : false, + flipX: appState.isArabic(), child: Utils.buildSvgWithAssets( icon: AppAssets.forward_arrow_icon_small, iconColor: AppColors.blackColor, diff --git a/lib/presentation/appointments/widgets/appointment_doctor_card.dart b/lib/presentation/appointments/widgets/appointment_doctor_card.dart index b35305f..efc5a6b 100644 --- a/lib/presentation/appointments/widgets/appointment_doctor_card.dart +++ b/lib/presentation/appointments/widgets/appointment_doctor_card.dart @@ -40,7 +40,7 @@ class AppointmentDoctorCard extends StatelessWidget { patientAppointmentHistoryResponseModel.doctorImageURL!, width: 63.h, height: 63.h, - fit: BoxFit.fill, + fit: BoxFit.cover, ).circle(100), SizedBox(width: 16.h), Expanded( diff --git a/lib/presentation/appointments/widgets/faculity_selection/facility_selection_item.dart b/lib/presentation/appointments/widgets/faculity_selection/facility_selection_item.dart index 16dfb1e..c7ef3a9 100644 --- a/lib/presentation/appointments/widgets/faculity_selection/facility_selection_item.dart +++ b/lib/presentation/appointments/widgets/faculity_selection/facility_selection_item.dart @@ -46,7 +46,7 @@ class FacilitySelectionItem extends StatelessWidget { children: [ info, Transform.flip( - flipX: appState.isArabic() ? true : false, + flipX: appState.isArabic(), child: Utils.buildSvgWithAssets( icon: AppAssets.forward_arrow_icon_small, iconColor: AppColors.blackColor, diff --git a/lib/presentation/appointments/widgets/hospital_bottom_sheet/hospital_list_items.dart b/lib/presentation/appointments/widgets/hospital_bottom_sheet/hospital_list_items.dart index cad0309..31dc74e 100644 --- a/lib/presentation/appointments/widgets/hospital_bottom_sheet/hospital_list_items.dart +++ b/lib/presentation/appointments/widgets/hospital_bottom_sheet/hospital_list_items.dart @@ -39,7 +39,7 @@ class HospitalListItem extends StatelessWidget { ), ), Transform.flip( - flipX: appState.isArabic() ? true : false, + flipX: appState.isArabic(), child: Utils.buildSvgWithAssets( icon: AppAssets.forward_arrow_icon_small, iconColor: AppColors.blackColor, diff --git a/lib/presentation/appointments/widgets/region_bottomsheet/region_list_item.dart b/lib/presentation/appointments/widgets/region_bottomsheet/region_list_item.dart index 688580c..8b35921 100644 --- a/lib/presentation/appointments/widgets/region_bottomsheet/region_list_item.dart +++ b/lib/presentation/appointments/widgets/region_bottomsheet/region_list_item.dart @@ -43,7 +43,7 @@ class RegionListItem extends StatelessWidget { ], ), Transform.flip( - flipX: appState.isArabic() ? true : false, + flipX: appState.isArabic(), child: Utils.buildSvgWithAssets( icon: AppAssets.forward_arrow_icon_small, iconColor: AppColors.blackColor, diff --git a/lib/presentation/book_appointment/book_appointment_page.dart b/lib/presentation/book_appointment/book_appointment_page.dart index b124438..b39c51e 100644 --- a/lib/presentation/book_appointment/book_appointment_page.dart +++ b/lib/presentation/book_appointment/book_appointment_page.dart @@ -130,7 +130,7 @@ class _BookAppointmentPageState extends State { ], ), Transform.flip( - flipX: appState.isArabic() ? true : false, child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, iconColor: AppColors.textColor, width: 40.h, height: 40.h)), + flipX: appState.isArabic(), child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, iconColor: AppColors.textColor, width: 40.h, height: 40.h)), ], ).onPress(() { bookAppointmentsViewModel.setIsClinicsListLoading(true); @@ -163,7 +163,7 @@ class _BookAppointmentPageState extends State { ], ), Transform.flip( - flipX: appState.isArabic() ? true : false, child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, iconColor: AppColors.textColor, width: 40.h, height: 40.h)), + flipX: appState.isArabic(), child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, iconColor: AppColors.textColor, width: 40.h, height: 40.h)), ], ).onPress(() { bookAppointmentsViewModel.setIsDoctorSearchByNameStarted(false); @@ -194,7 +194,7 @@ class _BookAppointmentPageState extends State { ], ), Transform.flip( - flipX: appState.isArabic() ? true : false, child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, iconColor: AppColors.textColor, width: 40.h, height: 40.h)), + flipX: appState.isArabic(), child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, iconColor: AppColors.textColor, width: 40.h, height: 40.h)), ], ).onPress(() { bookAppointmentsViewModel.setProjectID(null); @@ -239,7 +239,7 @@ class _BookAppointmentPageState extends State { ], ), Transform.flip( - flipX: appState.isArabic() ? true : false, child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, iconColor: AppColors.textColor, width: 40.h, height: 40.h)), + flipX: appState.isArabic(), child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, iconColor: AppColors.textColor, width: 40.h, height: 40.h)), ], ).onPress(() async { //TODO Implement API to check for existing LiveCare Requests @@ -282,7 +282,7 @@ class _BookAppointmentPageState extends State { ], ), Transform.flip( - flipX: appState.isArabic() ? true : false, child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, iconColor: AppColors.textColor, width: 40.h, height: 40.h)), + flipX: appState.isArabic(), child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, iconColor: AppColors.textColor, width: 40.h, height: 40.h)), ], ).onPress(() { bookAppointmentsViewModel.setIsClinicsListLoading(true); @@ -313,7 +313,7 @@ class _BookAppointmentPageState extends State { ], ), Transform.flip( - flipX: appState.isArabic() ? true : false, child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, iconColor: AppColors.textColor, width: 40.h, height: 40.h)), + flipX: appState.isArabic(), child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, iconColor: AppColors.textColor, width: 40.h, height: 40.h)), ], ).onPress(() { openRegionListBottomSheet(context, RegionBottomSheetType.FOR_REGION); diff --git a/lib/presentation/book_appointment/doctor_profile_page.dart b/lib/presentation/book_appointment/doctor_profile_page.dart index 6084c3d..1223842 100644 --- a/lib/presentation/book_appointment/doctor_profile_page.dart +++ b/lib/presentation/book_appointment/doctor_profile_page.dart @@ -53,7 +53,7 @@ class DoctorProfilePage extends StatelessWidget { bookAppointmentsViewModel.doctorsProfileResponseModel.doctorImageURL!, width: 63.h, height: 63.h, - fit: BoxFit.fill, + fit: BoxFit.cover, ).circle(100), SizedBox(width: 8.h), Column( @@ -73,7 +73,7 @@ class DoctorProfilePage extends StatelessWidget { bookAppointmentsViewModel.doctorsProfileResponseModel.nationalityFlagURL!, width: 32.h, height: 32.h, - fit: BoxFit.fill, + fit: BoxFit.cover, ), ], ), 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 95d6302..914ac4a 100644 --- a/lib/presentation/book_appointment/livecare/immediate_livecare_payment_page.dart +++ b/lib/presentation/book_appointment/livecare/immediate_livecare_payment_page.dart @@ -115,7 +115,7 @@ class _ImmediateLiveCarePaymentPageState extends State { bookAppointmentsViewModel.selectedDoctor.doctorImageURL!, width: 50.h, height: 50.h, - fit: BoxFit.fill, + fit: BoxFit.cover, ).circle(100), SizedBox(width: 8.h), Column( @@ -88,7 +88,7 @@ class _ReviewAppointmentPageState extends State { bookAppointmentsViewModel.selectedDoctor.nationalityFlagURL!, width: 20.h, height: 15.h, - fit: BoxFit.fill, + fit: BoxFit.cover, ), ], ), diff --git a/lib/presentation/habib_wallet/wallet_payment_confirm_page.dart b/lib/presentation/habib_wallet/wallet_payment_confirm_page.dart index 63aa313..b414799 100644 --- a/lib/presentation/habib_wallet/wallet_payment_confirm_page.dart +++ b/lib/presentation/habib_wallet/wallet_payment_confirm_page.dart @@ -88,7 +88,7 @@ class _WalletPaymentConfirmPageState extends State { SizedBox(width: 8.h), const Spacer(), Transform.flip( - flipX: appState.isArabic() ? true : false, + flipX: appState.isArabic(), child: Utils.buildSvgWithAssets( icon: AppAssets.forward_arrow_icon, iconColor: AppColors.blackColor, @@ -130,7 +130,7 @@ class _WalletPaymentConfirmPageState extends State { SizedBox(width: 8.h), const Spacer(), Transform.flip( - flipX: appState.isArabic() ? true : false, + flipX: appState.isArabic(), child: Utils.buildSvgWithAssets( icon: AppAssets.forward_arrow_icon, iconColor: AppColors.blackColor, diff --git a/lib/presentation/habib_wallet/widgets/hospital_list_item.dart b/lib/presentation/habib_wallet/widgets/hospital_list_item.dart index c5583e2..8e10e28 100644 --- a/lib/presentation/habib_wallet/widgets/hospital_list_item.dart +++ b/lib/presentation/habib_wallet/widgets/hospital_list_item.dart @@ -36,7 +36,7 @@ class HospitalListItemAdvancePayment extends StatelessWidget { ), ), Transform.flip( - flipX: appState.isArabic() ? true : false, + flipX: appState.isArabic(), child: Utils.buildSvgWithAssets( icon: AppAssets.forward_arrow_icon, iconColor: AppColors.blackColor, diff --git a/lib/presentation/home/landing_page.dart b/lib/presentation/home/landing_page.dart index 258e8e0..d235f4d 100644 --- a/lib/presentation/home/landing_page.dart +++ b/lib/presentation/home/landing_page.dart @@ -15,6 +15,7 @@ import 'package:hmg_patient_app_new/extensions/int_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart'; +import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart'; import 'package:hmg_patient_app_new/features/habib_wallet/habib_wallet_view_model.dart'; import 'package:hmg_patient_app_new/features/immediate_livecare/immediate_livecare_view_model.dart'; import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart'; @@ -67,6 +68,7 @@ class _LandingPageState extends State { late InsuranceViewModel insuranceViewModel; late ImmediateLiveCareViewModel immediateLiveCareViewModel; + late BookAppointmentsViewModel bookAppointmentsViewModel; final SwiperController _controller = SwiperController(); @@ -100,6 +102,7 @@ class _LandingPageState extends State { Widget build(BuildContext context) { appState = getIt.get(); NavigationService navigationService = getIt.get(); + bookAppointmentsViewModel = Provider.of(context, listen: false); myAppointmentsViewModel = Provider.of(context, listen: false); prescriptionsViewModel = Provider.of(context, listen: false); insuranceViewModel = Provider.of(context, listen: false); @@ -200,6 +203,7 @@ class _LandingPageState extends State { child: AppointmentCard( patientAppointmentHistoryResponseModel: PatientAppointmentHistoryResponseModel(), myAppointmentsViewModel: myAppointmentsViewModel, + bookAppointmentsViewModel: bookAppointmentsViewModel, isLoading: true, isFromHomePage: true, ), @@ -211,6 +215,7 @@ class _LandingPageState extends State { child: AppointmentCard( patientAppointmentHistoryResponseModel: myAppointmentsVM.patientAppointmentsHistoryList.first, myAppointmentsViewModel: myAppointmentsViewModel, + bookAppointmentsViewModel: bookAppointmentsViewModel, isLoading: false, isFromHomePage: true, ), @@ -239,6 +244,7 @@ class _LandingPageState extends State { child: AppointmentCard( patientAppointmentHistoryResponseModel: myAppointmentsVM.patientAppointmentsHistoryList[index], myAppointmentsViewModel: myAppointmentsViewModel, + bookAppointmentsViewModel: bookAppointmentsViewModel, isLoading: false, isFromHomePage: true, ), diff --git a/lib/presentation/insurance/insurance_approvals_page.dart b/lib/presentation/insurance/insurance_approvals_page.dart new file mode 100644 index 0000000..50e659c --- /dev/null +++ b/lib/presentation/insurance/insurance_approvals_page.dart @@ -0,0 +1,109 @@ +import 'dart:async'; + +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/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/insurance/insurance_view_model.dart'; +import 'package:hmg_patient_app_new/features/insurance/models/resp_models/patient_insurance_approval_response_model.dart'; +import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; +import 'package:hmg_patient_app_new/presentation/insurance/widgets/insurance_approval_card.dart'; +import 'package:hmg_patient_app_new/presentation/insurance/widgets/insurance_approval_details_page.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/routes/custom_page_route.dart'; +import 'package:provider/provider.dart'; + +class InsuranceApprovalsPage extends StatefulWidget { + const InsuranceApprovalsPage({super.key}); + + @override + State createState() => _InsuranceApprovalsPageState(); +} + +class _InsuranceApprovalsPageState extends State { + late InsuranceViewModel insuranceViewModel; + late AppState appState; + + @override + void initState() { + scheduleMicrotask(() { + insuranceViewModel.setIsInsuranceApprovalsLoading(true); + insuranceViewModel.getPatientInsuranceApprovalsList(); + }); + super.initState(); + } + + @override + Widget build(BuildContext context) { + appState = getIt.get(); + insuranceViewModel = Provider.of(context, listen: false); + return CollapsingListView( + title: "${LocaleKeys.insurance.tr(context: context)} ${LocaleKeys.approvals.tr(context: context)}", + child: SingleChildScrollView( + child: Consumer(builder: (context, insuranceVM, child) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ListView.separated( + padding: EdgeInsets.only(top: 24.h), + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + itemCount: insuranceVM.isInsuranceApprovalsLoading + ? 5 + : insuranceVM.patientInsuranceApprovalsList.isNotEmpty + ? insuranceVM.patientInsuranceApprovalsList.length + : 1, + itemBuilder: (context, index) { + return insuranceVM.isInsuranceApprovalsLoading + ? Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true), + child: InsuranceApprovalCard( + insuranceApprovalResponseModel: InsuranceApprovalResponseModel(), + appState: appState, + isLoading: true, + ), + ).paddingSymmetrical(24.h, 0.h) + : insuranceVM.patientInsuranceApprovalsList.isNotEmpty + ? AnimationConfiguration.staggeredList( + position: index, + duration: const Duration(milliseconds: 500), + child: SlideAnimation( + verticalOffset: 100.0, + child: FadeInAnimation( + child: AnimatedContainer( + duration: Duration(milliseconds: 300), + curve: Curves.easeInOut, + decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true), + child: InsuranceApprovalCard( + insuranceApprovalResponseModel: insuranceVM.patientInsuranceApprovalsList[index], + appState: appState, + isLoading: false, + ).onPress(() { + Navigator.of(context).push( + CustomPageRoute( + page: InsuranceApprovalDetailsPage(insuranceApprovalResponseModel: insuranceVM.patientInsuranceApprovalsList[index]), + ), + ); + }), + ).paddingSymmetrical(24.h, 0.h), + ), + ), + ) + : Utils.getNoDataWidget(context, noDataText: "You don't have any insurance approvals yet.".needTranslation); + }, + separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h), + ), + SizedBox(height: 24.h), + ], + ); + }), + ), + ); + } +} diff --git a/lib/presentation/insurance/insurance_home_page.dart b/lib/presentation/insurance/insurance_home_page.dart index bc56473..bd195c3 100644 --- a/lib/presentation/insurance/insurance_home_page.dart +++ b/lib/presentation/insurance/insurance_home_page.dart @@ -34,7 +34,6 @@ class InsuranceHomePage extends StatefulWidget { class _InsuranceHomePageState extends State { late InsuranceViewModel insuranceViewModel; - late AppState appState; @override diff --git a/lib/presentation/insurance/widgets/insurance_approval_card.dart b/lib/presentation/insurance/widgets/insurance_approval_card.dart new file mode 100644 index 0000000..71fce58 --- /dev/null +++ b/lib/presentation/insurance/widgets/insurance_approval_card.dart @@ -0,0 +1,129 @@ +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/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/insurance/models/resp_models/patient_insurance_approval_response_model.dart'; +import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart'; +import 'package:hmg_patient_app_new/features/my_appointments/utils/appointment_type.dart'; +import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; +import 'package:hmg_patient_app_new/theme/colors.dart'; +import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; +import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; + +class InsuranceApprovalCard extends StatelessWidget { + InsuranceApprovalCard({super.key, required this.insuranceApprovalResponseModel, required this.isLoading, required this.appState}); + + InsuranceApprovalResponseModel insuranceApprovalResponseModel; + AppState appState; + bool isLoading; + + @override + Widget build(BuildContext context) { + return Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 20.h, + hasShadow: true, + ), + child: Padding( + padding: EdgeInsets.all(14.h), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Wrap( + alignment: WrapAlignment.start, + direction: Axis.horizontal, + spacing: 6.h, + runSpacing: 6.h, + children: [ + AppCustomChipWidget( + labelText: isLoading ? "Approved" : insuranceApprovalResponseModel.approvalStatusDescption, + backgroundColor: insuranceApprovalResponseModel.status == 9 ? AppColors.successColor.withOpacity(0.1) : AppColors.primaryRedColor.withOpacity(0.1), + textColor: insuranceApprovalResponseModel.status == 9 ? AppColors.successColor : AppColors.primaryRedColor, + ).toShimmer2(isShow: isLoading), + AppCustomChipWidget( + icon: isLoading ? AppAssets.walkin_appointment_icon : (!insuranceApprovalResponseModel.isLiveCareAppointment! ? AppAssets.walkin_appointment_icon : AppAssets.small_livecare_icon), + iconColor: isLoading + ? AppColors.textColor + : !insuranceApprovalResponseModel.isLiveCareAppointment! + ? AppColors.textColor + : AppColors.whiteColor, + labelText: isLoading + ? "Walk In" + : insuranceApprovalResponseModel.isLiveCareAppointment! + ? LocaleKeys.livecare.tr(context: context) + : "Walk In".needTranslation, + backgroundColor: isLoading ? AppColors.greyColor : (!insuranceApprovalResponseModel.isLiveCareAppointment! ? AppColors.greyColor : AppColors.successColor), + textColor: isLoading ? AppColors.textColor : (!insuranceApprovalResponseModel.isLiveCareAppointment! ? AppColors.textColor : AppColors.whiteColor), + ).toShimmer2(isShow: isLoading), + AppCustomChipWidget( + labelText: isLoading + ? "OutPatient" + : appState.isArabic() + ? insuranceApprovalResponseModel.isInOutPatientDescriptionN! + : insuranceApprovalResponseModel.isInOutPatientDescription!, + backgroundColor: AppColors.primaryRedColor.withOpacity(0.1), + textColor: AppColors.primaryRedColor, + ).toShimmer2(isShow: isLoading), + ], + ).toShimmer2(isShow: isLoading), + SizedBox(height: 16.h), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Image.network( + isLoading ? "https://hmgwebservices.com/Images/MobileImages/OALAY/1439.png" : insuranceApprovalResponseModel.doctorImageURL!, + width: 63.h, + height: 63.h, + fit: BoxFit.cover, + ).circle(100).toShimmer2(isShow: isLoading), + SizedBox(width: 16.h), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + (isLoading ? "John Smith" : insuranceApprovalResponseModel.doctorName!).toText16(isBold: true).toShimmer2(isShow: isLoading), + Wrap( + direction: Axis.horizontal, + spacing: 3.h, + runSpacing: 4.h, + children: [ + // AppCustomChipWidget(labelText: isLoading ? "Approved" : insuranceApprovalResponseModel.approvalStatusDescption!, + // backgroundColor: insuranceApprovalResponseModel.status == 9 ? AppColors.successColor.withValues(alpha: 0.1) : AppColors.primaryRedColor.withValues(alpha: 0.1), + // textColor: insuranceApprovalResponseModel.status == 9 ? AppColors.successColor : AppColors.primaryRedColor, + // ).toShimmer2(isShow: isLoading), + AppCustomChipWidget(labelText: isLoading ? "Cardiology" : insuranceApprovalResponseModel.clinicName!).toShimmer2(isShow: isLoading), + AppCustomChipWidget( + icon: AppAssets.doctor_calendar_icon, + labelText: isLoading ? "Cardiology" : DateUtil.formatDateToDate(DateUtil.convertStringToDate(insuranceApprovalResponseModel.submitOn), false)) + .toShimmer2(isShow: isLoading), + isLoading + ? SizedBox.shrink() + : AppCustomChipWidget( + labelText: isLoading ? LocaleKeys.approvalNo.tr(context: context) : "${LocaleKeys.approvalNo.tr(context: context)} ${insuranceApprovalResponseModel.approvalNo}") + .toShimmer2(isShow: isLoading), + ], + ), + ], + ), + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Transform.flip( + flipX: appState.isArabic(), child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon_small, width: 15.h, height: 15.h, fit: BoxFit.contain, iconColor: AppColors.textColor)), + ], + ), + ], + ), + ), + ); + } +} diff --git a/lib/presentation/insurance/widgets/insurance_approval_details_page.dart b/lib/presentation/insurance/widgets/insurance_approval_details_page.dart new file mode 100644 index 0000000..c9b1517 --- /dev/null +++ b/lib/presentation/insurance/widgets/insurance_approval_details_page.dart @@ -0,0 +1,135 @@ +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_export.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/date_util.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/insurance/insurance_view_model.dart'; +import 'package:hmg_patient_app_new/features/insurance/models/resp_models/patient_insurance_approval_response_model.dart'; +import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; +import 'package:hmg_patient_app_new/theme/colors.dart'; +import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; +import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; +import 'package:provider/provider.dart'; + +class InsuranceApprovalDetailsPage extends StatelessWidget { + InsuranceApprovalDetailsPage({super.key, required this.insuranceApprovalResponseModel}); + + InsuranceApprovalResponseModel insuranceApprovalResponseModel; + late InsuranceViewModel insuranceViewModel; + late AppState appState; + + @override + Widget build(BuildContext context) { + appState = getIt.get(); + insuranceViewModel = Provider.of(context, listen: false); + return CollapsingListView( + title: "${LocaleKeys.insurance.tr(context: context)} ${LocaleKeys.approvals.tr(context: context)}", + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 24.h, + hasShadow: true, + ), + child: Padding( + padding: EdgeInsets.all(14.h), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Wrap( + alignment: WrapAlignment.start, + direction: Axis.horizontal, + spacing: 6.h, + runSpacing: 6.h, + children: [ + AppCustomChipWidget( + labelText: insuranceApprovalResponseModel.approvalStatusDescption, + backgroundColor: insuranceApprovalResponseModel.status == 9 ? AppColors.successColor.withOpacity(0.1) : AppColors.primaryRedColor.withOpacity(0.1), + textColor: insuranceApprovalResponseModel.status == 9 ? AppColors.successColor : AppColors.primaryRedColor, + ), + AppCustomChipWidget( + icon: (!insuranceApprovalResponseModel.isLiveCareAppointment! ? AppAssets.walkin_appointment_icon : AppAssets.small_livecare_icon), + iconColor: !insuranceApprovalResponseModel.isLiveCareAppointment! ? AppColors.textColor : AppColors.whiteColor, + labelText: insuranceApprovalResponseModel.isLiveCareAppointment! ? LocaleKeys.livecare.tr(context: context) : "Walk In".needTranslation, + backgroundColor: (!insuranceApprovalResponseModel.isLiveCareAppointment! ? AppColors.greyColor : AppColors.successColor), + textColor: (!insuranceApprovalResponseModel.isLiveCareAppointment! ? AppColors.textColor : AppColors.whiteColor), + ), + AppCustomChipWidget( + labelText: appState.isArabic() ? insuranceApprovalResponseModel.isInOutPatientDescriptionN! : insuranceApprovalResponseModel.isInOutPatientDescription!, + backgroundColor: AppColors.primaryRedColor.withOpacity(0.1), + textColor: AppColors.primaryRedColor, + ), + ], + ), + SizedBox(height: 16.h), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Image.network( + insuranceApprovalResponseModel.doctorImageURL!, + width: 63.h, + height: 63.h, + fit: BoxFit.cover, + ).circle(100), + SizedBox(width: 16.h), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + (insuranceApprovalResponseModel.doctorName!).toText16(isBold: true), + Wrap( + direction: Axis.horizontal, + spacing: 3.h, + runSpacing: 4.h, + children: [ + AppCustomChipWidget(labelText: insuranceApprovalResponseModel.clinicName!), + AppCustomChipWidget(labelText: "${LocaleKeys.approvalNo.tr(context: context)} ${insuranceApprovalResponseModel.approvalNo}"), + AppCustomChipWidget(labelText: "${LocaleKeys.unusedCount.tr(context: context)} ${insuranceApprovalResponseModel.unUsedCount}"), + AppCustomChipWidget(labelText: "${LocaleKeys.companyName.tr(context: context)} ${insuranceApprovalResponseModel.companyName}"), + AppCustomChipWidget( + labelText: + "${LocaleKeys.receiptOn.tr(context: context)} ${DateUtil.formatDateToDate(DateUtil.convertStringToDate(insuranceApprovalResponseModel.receiptOn), false)}"), + AppCustomChipWidget( + labelText: + "${LocaleKeys.expiryOn.tr(context: context)} ${DateUtil.formatDateToDate(DateUtil.convertStringToDate(insuranceApprovalResponseModel.expiryDate), false)}"), + ], + ), + ], + ), + ), + ], + ), + ], + ), + ), + ), + SizedBox(height: 16.h), + Container( + width: double.infinity, + height: 200.h, + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 24.h, + hasShadow: true, + ), + child: Padding( + padding: EdgeInsets.all(16.h), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + "Approval Details".toText16(isBold: true), + ], + ), + ), + ) + ], + ).paddingSymmetrical(24.h, 24.h), + ); + } +} diff --git a/lib/presentation/medical_file/medical_file_page.dart b/lib/presentation/medical_file/medical_file_page.dart index dd80513..8ff081f 100644 --- a/lib/presentation/medical_file/medical_file_page.dart +++ b/lib/presentation/medical_file/medical_file_page.dart @@ -8,7 +8,6 @@ import 'package:hmg_patient_app_new/core/app_export.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/date_util.dart'; -import 'package:hmg_patient_app_new/core/utils/request_utils.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'; @@ -16,8 +15,8 @@ import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart'; import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/doctors_list_response_model.dart'; import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart'; +import 'package:hmg_patient_app_new/features/lab/lab_view_model.dart'; import 'package:hmg_patient_app_new/features/medical_file/medical_file_view_model.dart'; -import 'package:hmg_patient_app_new/features/medical_file/models/family_file_response_model.dart'; import 'package:hmg_patient_app_new/features/medical_file/models/patient_sickleave_response_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart'; @@ -27,10 +26,13 @@ import 'package:hmg_patient_app_new/presentation/appointments/my_appointments_pa import 'package:hmg_patient_app_new/presentation/appointments/my_doctors_page.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/book_appointment_page.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/widgets/appointment_calendar.dart'; +import 'package:hmg_patient_app_new/presentation/insurance/insurance_approvals_page.dart'; import 'package:hmg_patient_app_new/presentation/insurance/insurance_home_page.dart'; import 'package:hmg_patient_app_new/presentation/insurance/widgets/insurance_update_details_card.dart'; import 'package:hmg_patient_app_new/presentation/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/radiology/radiology_orders_page.dart'; import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/presentation/medical_report/medical_reports_page.dart'; import 'package:hmg_patient_app_new/presentation/medical_file/patient_sickleaves_list_page.dart'; @@ -38,8 +40,6 @@ import 'package:hmg_patient_app_new/presentation/medical_file/vaccine_list_page. import 'package:hmg_patient_app_new/presentation/medical_file/widgets/lab_rad_card.dart'; import 'package:hmg_patient_app_new/presentation/medical_file/widgets/medical_file_card.dart'; import 'package:hmg_patient_app_new/presentation/medical_file/widgets/patient_sick_leave_card.dart'; -import 'package:hmg_patient_app_new/presentation/my_family/my_family.dart'; -import 'package:hmg_patient_app_new/presentation/my_family/widget/my_family_sheet.dart'; import 'package:hmg_patient_app_new/presentation/prescriptions/prescriptions_list_page.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; @@ -69,6 +69,7 @@ class _MedicalFilePageState extends State { late MyAppointmentsViewModel myAppointmentsViewModel; late MedicalFileViewModel medicalFileViewModel; late BookAppointmentsViewModel bookAppointmentsViewModel; + late LabViewModel labViewModel; int currentIndex = 0; @@ -76,10 +77,10 @@ class _MedicalFilePageState extends State { void initState() { scheduleMicrotask(() { if (appState.isAuthenticated) { + labViewModel.initLabProvider(); insuranceViewModel.initInsuranceProvider(); medicalFileViewModel.setIsPatientSickLeaveListLoading(true); medicalFileViewModel.getPatientSickLeaveList(); - // medicalFileViewModel.getFamilyFiles(); medicalFileViewModel.onTabChanged(0); } }); @@ -88,6 +89,7 @@ class _MedicalFilePageState extends State { @override Widget build(BuildContext context) { + labViewModel = Provider.of(context, listen: false); insuranceViewModel = Provider.of(context, listen: false); myAppointmentsViewModel = Provider.of(context, listen: false); medicalFileViewModel = Provider.of(context, listen: false); @@ -106,7 +108,7 @@ class _MedicalFilePageState extends State { SizedBox(height: 16.h), TextInputWidget( labelText: LocaleKeys.search.tr(context: context), - hintText: "Type any record", + hintText: "Type any record".needTranslation, controller: TextEditingController(), keyboardType: TextInputType.number, isEnable: true, @@ -183,8 +185,8 @@ class _MedicalFilePageState extends State { return Column( children: [ CustomTabBar( - activeTextColor: Color(0xffED1C2B), - activeBackgroundColor: Color(0xffED1C2B).withValues(alpha: .1), + activeTextColor: AppColors.primaryRedColor, + activeBackgroundColor: AppColors.primaryRedColor.withValues(alpha: .1), tabs: [ CustomTabBarModel(AppAssets.myFilesBottom, LocaleKeys.general.tr(context: context).needTranslation), CustomTabBarModel(AppAssets.insurance, LocaleKeys.insurance.tr(context: context)), @@ -192,7 +194,6 @@ class _MedicalFilePageState extends State { CustomTabBarModel(AppAssets.more, "More".needTranslation), ], onTabChange: (index) { - print(index); medicalFileVM.onTabChanged(index); }, ).paddingSymmetrical(24.h, 0.0), @@ -361,16 +362,32 @@ class _MedicalFilePageState extends State { child: LabRadCard( icon: AppAssets.lab_result_icon, labelText: LocaleKeys.labResults.tr(context: context), - labOrderTests: ["Complete blood count", "Creatinine", "Blood Sugar"], - ), + // labOrderTests: ["Complete blood count", "Creatinine", "Blood Sugar"], + labOrderTests: labViewModel.isLabOrdersLoading ? [] : labViewModel.labOrderTests, + isLoading: labViewModel.isLabOrdersLoading, + ).onPress(() { + Navigator.of(context).push( + CustomPageRoute( + page: LabOrdersPage(), + ), + ); + }), ), SizedBox(width: 16.h), Expanded( child: LabRadCard( icon: AppAssets.radiology_icon, labelText: LocaleKeys.radiology.tr(context: context), - labOrderTests: ["Chest X-ray", "Abdominal Ultrasound", "Dental X-ray"], - ), + // labOrderTests: ["Chest X-ray", "Abdominal Ultrasound", "Dental X-ray"], + labOrderTests: [], + isLoading: false, + ).onPress(() { + Navigator.of(context).push( + CustomPageRoute( + page: RadiologyOrdersPage(), + ), + ); + }), ), ], ).paddingSymmetrical(24.h, 0.h), @@ -408,7 +425,7 @@ class _MedicalFilePageState extends State { prescriptionVM.patientPrescriptionOrders[index].doctorImageURL!, width: 40.h, height: 40.h, - fit: BoxFit.fill, + fit: BoxFit.cover, ).circle(100), SizedBox(width: 16.h), Expanded( @@ -434,8 +451,9 @@ class _MedicalFilePageState extends State { ), // SizedBox(width: 40.h), Transform.flip( - flipX: appState.isArabic() ? true : false, - child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, width: 15.h, height: 15.h, fit: BoxFit.contain, iconColor: AppColors.textColor)), + flipX: appState.isArabic(), + child: Utils.buildSvgWithAssets( + icon: AppAssets.forward_arrow_icon_small, width: 15.h, height: 15.h, fit: BoxFit.contain, iconColor: AppColors.textColor)), ], ).onPress(() { prescriptionVM.setPrescriptionsDetailsLoading(); @@ -469,7 +487,7 @@ class _MedicalFilePageState extends State { backgroundColor: AppColors.secondaryLightRedColor, borderColor: AppColors.secondaryLightRedColor, textColor: AppColors.primaryRedColor, - fontSize: 13, + fontSize: 12.3, fontWeight: FontWeight.w500, borderRadius: 12.h, height: 40.h, @@ -505,7 +523,7 @@ class _MedicalFilePageState extends State { decoration: RoundedRectangleBorder().toSmoothCornerDecoration( color: AppColors.whiteColor, borderRadius: 20.h, - hasShadow: true, + hasShadow: false, ), child: Utils.getNoDataWidget(context, noDataText: "You don't have any prescriptions yet.".needTranslation, isSmallWidget: true, width: 62, height: 62)) .paddingSymmetrical(24.h, 0.h); @@ -601,7 +619,7 @@ class _MedicalFilePageState extends State { decoration: RoundedRectangleBorder().toSmoothCornerDecoration( color: AppColors.whiteColor, borderRadius: 20.h, - hasShadow: true, + hasShadow: false, ), child: Utils.getNoDataWidget(context, noDataText: "You don't have any completed visits yet.".needTranslation, isSmallWidget: true, width: 62, height: 62), ).paddingSymmetrical(24.h, 0.h); @@ -682,7 +700,7 @@ class _MedicalFilePageState extends State { decoration: RoundedRectangleBorder().toSmoothCornerDecoration( color: AppColors.whiteColor, borderRadius: 20.h, - hasShadow: true, + hasShadow: false, ), child: Utils.getNoDataWidget( context, @@ -740,12 +758,18 @@ class _MedicalFilePageState extends State { ); }), MedicalFileCard( - label: "Insurance Approvals".needTranslation, + label: "${LocaleKeys.insurance.tr(context: context)} ${LocaleKeys.approvals.tr(context: context)}", textColor: AppColors.blackColor, backgroundColor: AppColors.whiteColor, svgIcon: AppAssets.eye_result_icon, isLargeText: true, - iconSize: 36.h), + iconSize: 36.h).onPress(() { + Navigator.of(context).push( + CustomPageRoute( + page: InsuranceApprovalsPage(), + ), + ); + }), MedicalFileCard( label: "My Invoices List".needTranslation, textColor: AppColors.blackColor, @@ -780,13 +804,20 @@ class _MedicalFilePageState extends State { patientSickLeavesResponseModel: medicalFileVM.patientSickLeaveList.first, isLoading: false, ).paddingSymmetrical(24.h, 0.0) - : Utils.getNoDataWidget( - context, - noDataText: "You don't have any sick leaves yet.".needTranslation, - isSmallWidget: true, - width: 62, - height: 62, - ); + : Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 20.h, + hasShadow: false, + ), + child: Utils.getNoDataWidget( + context, + noDataText: "You don't have any sick leaves yet.".needTranslation, + isSmallWidget: true, + width: 62, + height: 62, + ), + ).paddingSymmetrical(24.h, 0.h); }), SizedBox(height: 16.h), GridView( diff --git a/lib/presentation/medical_file/vaccine_list_page.dart b/lib/presentation/medical_file/vaccine_list_page.dart index 82c9441..777426f 100644 --- a/lib/presentation/medical_file/vaccine_list_page.dart +++ b/lib/presentation/medical_file/vaccine_list_page.dart @@ -77,7 +77,7 @@ class _VaccineListPageState extends State { "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png", width: 63.h, height: 63.h, - fit: BoxFit.fill, + fit: BoxFit.cover, ).circle(100).toShimmer2(isShow: true), SizedBox(width: 16.h), Expanded( diff --git a/lib/presentation/medical_file/widgets/lab_rad_card.dart b/lib/presentation/medical_file/widgets/lab_rad_card.dart index e396d62..c7fd7dd 100644 --- a/lib/presentation/medical_file/widgets/lab_rad_card.dart +++ b/lib/presentation/medical_file/widgets/lab_rad_card.dart @@ -9,11 +9,12 @@ import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; class LabRadCard extends StatelessWidget { - LabRadCard({super.key, required this.icon, required this.labelText, required this.labOrderTests}); + LabRadCard({super.key, required this.icon, required this.labelText, required this.labOrderTests, required this.isLoading}); String icon; String labelText; List labOrderTests = []; + bool isLoading; @override Widget build(BuildContext context) { @@ -36,24 +37,26 @@ class LabRadCard extends StatelessWidget { ], ), SizedBox(height: 16.h), - ListView.separated( - scrollDirection: Axis.vertical, - padding: EdgeInsets.zero, - physics: NeverScrollableScrollPhysics(), - shrinkWrap: true, + labOrderTests.isNotEmpty + ? ListView.separated( + scrollDirection: Axis.vertical, + padding: EdgeInsets.zero, + physics: NeverScrollableScrollPhysics(), + shrinkWrap: true, itemBuilder: (cxt, index) { - return labOrderTests[index].toText12(isBold: true, maxLine: 1).toShimmer2(isShow: false, radius: 6.h, height: 24.h, width: 120.h); - }, - separatorBuilder: (cxt, index) => SizedBox(height: 8.h), - itemCount: labOrderTests.length, - ), + return labOrderTests[index].toText12(isBold: true, maxLine: 1).toShimmer2(isShow: false, radius: 6.h, height: 24.h, width: 120.h).toShimmer2(isShow: isLoading); + }, + separatorBuilder: (cxt, index) => SizedBox(height: 8.h), + itemCount: 3, + ) + : "You don't have any records yet".needTranslation.toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor, isCenter: true), SizedBox(height: 16.h), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ SizedBox.shrink(), Transform.flip( - flipX: appState.isArabic() ? true : false, + flipX: appState.isArabic(), child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon_small, width: 15.h, height: 15.h, fit: BoxFit.contain, iconColor: AppColors.textColor) .toShimmer2(isShow: false, radius: 12.h), ), diff --git a/lib/presentation/medical_file/widgets/patient_sick_leave_card.dart b/lib/presentation/medical_file/widgets/patient_sick_leave_card.dart index 8fc3805..87794ef 100644 --- a/lib/presentation/medical_file/widgets/patient_sick_leave_card.dart +++ b/lib/presentation/medical_file/widgets/patient_sick_leave_card.dart @@ -141,7 +141,7 @@ class PatientSickLeaveCard extends StatelessWidget { child: Padding( padding: EdgeInsets.all(10.h), child: Transform.flip( - flipX: _appState.isArabic() ? true : false, + flipX: _appState.isArabic(), child: Utils.buildSvgWithAssets( icon: AppAssets.forward_arrow_icon_small, iconColor: AppColors.whiteColor, diff --git a/lib/presentation/medical_report/medical_report_request_page.dart b/lib/presentation/medical_report/medical_report_request_page.dart index 9d1bcb1..8eabcdd 100644 --- a/lib/presentation/medical_report/medical_report_request_page.dart +++ b/lib/presentation/medical_report/medical_report_request_page.dart @@ -3,6 +3,7 @@ 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/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/medical_file/medical_file_view_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'; @@ -42,6 +43,7 @@ class MedicalReportRequestPage extends StatelessWidget { child: AppointmentCard( patientAppointmentHistoryResponseModel: medicalFileViewModel.patientMedicalReportAppointmentHistoryList[index], myAppointmentsViewModel: Provider.of(context, listen: false), + bookAppointmentsViewModel: Provider.of(context, listen: false), medicalFileViewModel: medicalFileViewModel, isLoading: false, isFromHomePage: false, diff --git a/lib/presentation/prescriptions/prescriptions_list_page.dart b/lib/presentation/prescriptions/prescriptions_list_page.dart index 87f880d..1293c9c 100644 --- a/lib/presentation/prescriptions/prescriptions_list_page.dart +++ b/lib/presentation/prescriptions/prescriptions_list_page.dart @@ -264,9 +264,10 @@ class _PrescriptionsListPageState extends State { child: Padding( padding: EdgeInsets.all(8.h), child: Transform.flip( - flipX: appState.isArabic() ? true : false, + flipX: appState.isArabic(), child: Utils.buildSvgWithAssets( - icon: AppAssets.forward_arrow_icon, + icon: AppAssets.forward_arrow_icon_small, + iconColor: AppColors.whiteColor, width: 10.h, height: 10.h, fit: BoxFit.contain, diff --git a/lib/widgets/appbar/collapsing_list_view.dart b/lib/widgets/appbar/collapsing_list_view.dart index b18c6ee..951732b 100644 --- a/lib/widgets/appbar/collapsing_list_view.dart +++ b/lib/widgets/appbar/collapsing_list_view.dart @@ -46,7 +46,7 @@ class CollapsingListView extends StatelessWidget { backgroundColor: AppColors.bgScaffoldColor, leading: isLeading ? Transform.flip( - flipX: appState.isArabic() ? true : false, + flipX: appState.isArabic(), child: IconButton( icon: Utils.buildSvgWithAssets(icon: isClose ? AppAssets.closeBottomNav : AppAssets.arrow_back, width: 32.h, height: 32.h), padding: EdgeInsets.only(left: 12), diff --git a/lib/widgets/chip/app_custom_chip_widget.dart b/lib/widgets/chip/app_custom_chip_widget.dart index 751b01c..783a83f 100644 --- a/lib/widgets/chip/app_custom_chip_widget.dart +++ b/lib/widgets/chip/app_custom_chip_widget.dart @@ -59,7 +59,7 @@ class AppCustomChipWidget extends StatelessWidget { ), child: icon.isNotEmpty ? Chip( - avatar: icon.isNotEmpty ? Utils.buildSvgWithAssets(icon: icon, width: iconSize.h, height: iconSize.h, iconColor: iconHasColor ? iconColor : null) : SizedBox.shrink(), + avatar: icon.isNotEmpty ? Utils.buildSvgWithAssets(icon: icon, width: iconSize.h, height: iconSize.h, iconColor: iconHasColor ? iconColor : null, fit: BoxFit.contain) : SizedBox.shrink(), label: richText ?? labelText!.toText10(weight: FontWeight.w500, letterSpacing: 0, color: textColor), // padding: EdgeInsets.all(0.0), padding: padding,