From 6f07bc7c2ccfe84e1ab217274958d0df3523ac36 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Wed, 3 Sep 2025 12:08:58 +0300 Subject: [PATCH] Radiology Orders implemented --- assets/langs/ar-SA.json | 3 +- assets/langs/en-US.json | 3 +- lib/core/dependencies.dart | 10 + .../patient_radiology_response_model.dart | 232 ++++++++++++++++ lib/features/radiology/radiology_repo.dart | 82 ++++++ .../radiology/radiology_view_model.dart | 45 ++++ lib/generated/locale_keys.g.dart | 1 + lib/main.dart | 7 + .../home/widgets/small_service_card.dart | 6 + lib/presentation/lab/lab_orders_page.dart | 12 +- .../radiology/radiology_orders_page.dart | 251 ++++++++++++++++++ 11 files changed, 640 insertions(+), 12 deletions(-) create mode 100644 lib/features/radiology/models/resp_models/patient_radiology_response_model.dart create mode 100644 lib/features/radiology/radiology_repo.dart create mode 100644 lib/features/radiology/radiology_view_model.dart create mode 100644 lib/presentation/radiology/radiology_orders_page.dart diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index 304dba1..6355b66 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -780,5 +780,6 @@ "loginOrRegister": "تسجيل الدخول أو التسجيل", "myFiles" : "ملفاتي", "resultsPending": "النتائج معلقة", - "resultsAvailable": "النتائج متاحة" + "resultsAvailable": "النتائج متاحة", + "viewReport": "عرض التقرير" } \ No newline at end of file diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index e369613..c18eb97 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -776,5 +776,6 @@ "loginOrRegister": "Login or Register", "myFiles": "My Files", "resultsPending": "Results Pending", - "resultsAvailable": "Results Available" + "resultsAvailable": "Results Available", + "viewReport": "View Report" } \ No newline at end of file diff --git a/lib/core/dependencies.dart b/lib/core/dependencies.dart index dca08fc..a9fc9d6 100644 --- a/lib/core/dependencies.dart +++ b/lib/core/dependencies.dart @@ -9,6 +9,8 @@ import 'package:hmg_patient_app_new/features/common/common_repo.dart'; 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/my_appointments/my_appointments_repo.dart'; +import 'package:hmg_patient_app_new/features/radiology/radiology_repo.dart'; +import 'package:hmg_patient_app_new/features/radiology/radiology_view_model.dart'; import 'package:hmg_patient_app_new/services/analytics/analytics_service.dart'; import 'package:hmg_patient_app_new/services/cache_service.dart'; import 'package:hmg_patient_app_new/services/dialog_service.dart'; @@ -59,6 +61,7 @@ class AppDependencies { getIt.registerLazySingleton(() => BookAppointmentsRepoImp(loggerService: getIt(), apiClient: getIt())); getIt.registerLazySingleton(() => MyAppointmentsRepoImp(loggerService: getIt(), apiClient: getIt())); getIt.registerLazySingleton(() => LabRepoImp(loggerService: getIt(), apiClient: getIt())); + getIt.registerLazySingleton(() => RadiologyRepoImp(loggerService: getIt(), apiClient: getIt())); // ViewModels // Global/shared VMs → LazySingleton @@ -70,6 +73,13 @@ class AppDependencies { ), ); + getIt.registerLazySingleton( + () => RadiologyViewModel( + radiologyRepo: getIt(), + errorHandlerService: getIt(), + ), + ); + getIt.registerLazySingleton( () => AuthenticationViewModel( authenticationRepo: getIt(), diff --git a/lib/features/radiology/models/resp_models/patient_radiology_response_model.dart b/lib/features/radiology/models/resp_models/patient_radiology_response_model.dart new file mode 100644 index 0000000..b5568bf --- /dev/null +++ b/lib/features/radiology/models/resp_models/patient_radiology_response_model.dart @@ -0,0 +1,232 @@ +class PatientRadiologyResponseModel { + String? setupID; + int? projectID; + dynamic patientID; + int? invoiceLineItemNo; + int? invoiceNo; + int? doctorID; + int? clinicID; + String? orderDate; + String? reportData; + String? imageURL; + String? procedureID; + int? appointmentNo; + dynamic dIAPacsURL; + bool? isRead; + String? readOn; + dynamic admissionNo; + bool? isInOutPatient; + int? actualDoctorRate; + dynamic admissionDate; + dynamic admissionNumber; + dynamic appointmentDate; + dynamic appointmentNumber; + dynamic appointmentTime; + String? clinicDescription; + String? dIAPACSURL; + dynamic decimalDoctorRate; + String? description; + String? doctorImageURL; + String? doctorName; + num? doctorRate; + num? doctorStarsRate; + String? doctorTitle; + String? examId; + int? gender; + dynamic genderDescription; + int? invoiceNoVP; + String? invoiceType; + bool? isActiveDoctorProfile; + bool? isExecludeDoctor; + String? isInOutPatientDescription; + String? isInOutPatientDescriptionN; + bool? isLiveCareAppointment; + dynamic nationalityFlagURL; + int? noOfPatientsRate; + int? orderNo; + dynamic procedureName; + String? projectName; + String? qR; + String? reportDataHTML; + String? reportDataTextString; + dynamic strAppointmentDate; + dynamic strOrderDate; + bool? isCVI; + bool? isRadMedicalReport; + dynamic vida3Id; + + PatientRadiologyResponseModel( + {this.setupID, + this.projectID, + this.patientID, + this.invoiceLineItemNo, + this.invoiceNo, + this.doctorID, + this.clinicID, + this.orderDate, + this.reportData, + this.imageURL, + this.procedureID, + this.appointmentNo, + this.dIAPacsURL, + this.isRead, + this.readOn, + this.admissionNo, + this.isInOutPatient, + this.actualDoctorRate, + this.admissionDate, + this.admissionNumber, + this.appointmentDate, + this.appointmentNumber, + this.appointmentTime, + this.clinicDescription, + this.dIAPACSURL, + this.decimalDoctorRate, + this.description, + this.doctorImageURL, + this.doctorName, + this.doctorRate, + this.doctorStarsRate, + this.doctorTitle, + this.examId, + this.gender, + this.genderDescription, + this.invoiceNoVP, + this.invoiceType, + this.isActiveDoctorProfile, + this.isExecludeDoctor, + this.isInOutPatientDescription, + this.isInOutPatientDescriptionN, + this.isLiveCareAppointment, + this.nationalityFlagURL, + this.noOfPatientsRate, + this.orderNo, + this.procedureName, + this.projectName, + this.qR, + this.reportDataHTML, + this.reportDataTextString, + this.strAppointmentDate, + this.strOrderDate, + this.isCVI, + this.isRadMedicalReport, + this.vida3Id}); + + PatientRadiologyResponseModel.fromJson(Map json) { + setupID = json['SetupID']; + projectID = json['ProjectID']; + patientID = json['PatientID']; + invoiceLineItemNo = json['InvoiceLineItemNo']; + invoiceNo = json['InvoiceNo']; + doctorID = json['DoctorID']; + clinicID = json['ClinicID']; + orderDate = json['OrderDate']; + reportData = json['ReportData']; + imageURL = json['ImageURL']; + procedureID = json['ProcedureID']; + appointmentNo = json['AppointmentNo']; + dIAPacsURL = json['DIAPacsURL']; + isRead = json['IsRead']; + readOn = json['ReadOn']; + admissionNo = json['AdmissionNo']; + isInOutPatient = json['IsInOutPatient']; + actualDoctorRate = json['ActualDoctorRate']; + admissionDate = json['AdmissionDate']; + admissionNumber = json['AdmissionNumber']; + appointmentDate = json['AppointmentDate']; + appointmentNumber = json['AppointmentNumber']; + appointmentTime = json['AppointmentTime']; + clinicDescription = json['ClinicDescription']; + dIAPACSURL = json['DIA_PACS_URL']; + decimalDoctorRate = json['DecimalDoctorRate']; + description = json['Description']; + doctorImageURL = json['DoctorImageURL']; + doctorName = json['DoctorName']; + doctorRate = json['DoctorRate']; + doctorStarsRate = json['DoctorStarsRate']; + doctorTitle = json['DoctorTitle']; + examId = json['Exam_id']; + gender = json['Gender']; + genderDescription = json['GenderDescription']; + invoiceNoVP = json['InvoiceNo_VP']; + invoiceType = json['InvoiceType']; + isActiveDoctorProfile = json['IsActiveDoctorProfile']; + isExecludeDoctor = json['IsExecludeDoctor']; + isInOutPatientDescription = json['IsInOutPatientDescription']; + isInOutPatientDescriptionN = json['IsInOutPatientDescriptionN']; + isLiveCareAppointment = json['IsLiveCareAppointment']; + nationalityFlagURL = json['NationalityFlagURL']; + noOfPatientsRate = json['NoOfPatientsRate']; + orderNo = json['OrderNo']; + procedureName = json['ProcedureName']; + projectName = json['ProjectName']; + qR = json['QR']; + reportDataHTML = json['ReportDataHTML']; + reportDataTextString = json['ReportDataTextString']; + strAppointmentDate = json['StrAppointmentDate']; + strOrderDate = json['StrOrderDate']; + isCVI = json['isCVI']; + isRadMedicalReport = json['isRadMedicalReport']; + vida3Id = json['vida3Id']; + } + + Map toJson() { + final Map data = new Map(); + data['SetupID'] = this.setupID; + data['ProjectID'] = this.projectID; + data['PatientID'] = this.patientID; + data['InvoiceLineItemNo'] = this.invoiceLineItemNo; + data['InvoiceNo'] = this.invoiceNo; + data['DoctorID'] = this.doctorID; + data['ClinicID'] = this.clinicID; + data['OrderDate'] = this.orderDate; + data['ReportData'] = this.reportData; + data['ImageURL'] = this.imageURL; + data['ProcedureID'] = this.procedureID; + data['AppointmentNo'] = this.appointmentNo; + data['DIAPacsURL'] = this.dIAPacsURL; + data['IsRead'] = this.isRead; + data['ReadOn'] = this.readOn; + data['AdmissionNo'] = this.admissionNo; + data['IsInOutPatient'] = this.isInOutPatient; + data['ActualDoctorRate'] = this.actualDoctorRate; + data['AdmissionDate'] = this.admissionDate; + data['AdmissionNumber'] = this.admissionNumber; + data['AppointmentDate'] = this.appointmentDate; + data['AppointmentNumber'] = this.appointmentNumber; + data['AppointmentTime'] = this.appointmentTime; + data['ClinicDescription'] = this.clinicDescription; + data['DIA_PACS_URL'] = this.dIAPACSURL; + data['DecimalDoctorRate'] = this.decimalDoctorRate; + data['Description'] = this.description; + data['DoctorImageURL'] = this.doctorImageURL; + data['DoctorName'] = this.doctorName; + data['DoctorRate'] = this.doctorRate; + data['DoctorStarsRate'] = this.doctorStarsRate; + data['DoctorTitle'] = this.doctorTitle; + data['Exam_id'] = this.examId; + data['Gender'] = this.gender; + data['GenderDescription'] = this.genderDescription; + data['InvoiceNo_VP'] = this.invoiceNoVP; + data['InvoiceType'] = this.invoiceType; + data['IsActiveDoctorProfile'] = this.isActiveDoctorProfile; + data['IsExecludeDoctor'] = this.isExecludeDoctor; + data['IsInOutPatientDescription'] = this.isInOutPatientDescription; + data['IsInOutPatientDescriptionN'] = this.isInOutPatientDescriptionN; + data['IsLiveCareAppointment'] = this.isLiveCareAppointment; + data['NationalityFlagURL'] = this.nationalityFlagURL; + data['NoOfPatientsRate'] = this.noOfPatientsRate; + data['OrderNo'] = this.orderNo; + data['ProcedureName'] = this.procedureName; + data['ProjectName'] = this.projectName; + data['QR'] = this.qR; + data['ReportDataHTML'] = this.reportDataHTML; + data['ReportDataTextString'] = this.reportDataTextString; + data['StrAppointmentDate'] = this.strAppointmentDate; + data['StrOrderDate'] = this.strOrderDate; + data['isCVI'] = this.isCVI; + data['isRadMedicalReport'] = this.isRadMedicalReport; + data['vida3Id'] = this.vida3Id; + return data; + } +} diff --git a/lib/features/radiology/radiology_repo.dart b/lib/features/radiology/radiology_repo.dart new file mode 100644 index 0000000..ea916e6 --- /dev/null +++ b/lib/features/radiology/radiology_repo.dart @@ -0,0 +1,82 @@ +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/exceptions/api_failure.dart'; +import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart'; +import 'package:dartz/dartz.dart'; +import 'package:hmg_patient_app_new/features/lab/models/resp_models/patient_lab_orders_response_model.dart'; +import 'package:hmg_patient_app_new/features/radiology/models/resp_models/patient_radiology_response_model.dart'; +import 'package:hmg_patient_app_new/services/logger_service.dart'; + +abstract class RadiologyRepo { + Future>>> getPatientRadiologyOrders({required String patientId}); +} + +class RadiologyRepoImp implements RadiologyRepo { + final ApiClient apiClient; + final LoggerService loggerService; + + RadiologyRepoImp({required this.loggerService, required this.apiClient}); + + @override + Future>>> getPatientRadiologyOrders({required String patientId}) async { + final mapDevice = { + "isDentalAllowedBackend": false, + "VersionID": 50.0, + "Channel": 3, + "LanguageID": 2, + "IPAdress": "10.20.10.20", + "generalid": "Cs2020@2016\$2958", + "Latitude": 0.0, + "Longitude": 0.0, + "DeviceTypeID": 1, + "PatientType": 1, + "PatientTypeID": 1, + "TokenID": "@dm!n", + "PatientID": "1018977", + "PatientOutSA": "0", + "SessionID": "03478TYC02N80874CTYN04883475!?" + }; + + try { + GenericApiModel>? apiResponse; + Failure? failure; + await apiClient.post( + GET_PATIENT_ORDERS, + body: mapDevice, + onFailure: (error, statusCode, {messageStatus, failureType}) { + failure = failureType; + }, + onSuccess: (response, statusCode, {messageStatus}) { + final radOrders; + try { + if (response['FinalRadiologyList'] != null && response['FinalRadiologyList'].length != 0) { + final list = response['FinalRadiologyList']; + radOrders = list.map((item) => PatientRadiologyResponseModel.fromJson(item as Map)).toList().cast(); + } else { + final list = response['FinalRadiologyListAPI']; + radOrders = list.map((item) => PatientRadiologyResponseModel.fromJson(item as Map)).toList().cast(); + } + // final list = response['ListPLO']; + // if (list == null || list.isEmpty) { + // throw Exception("lab list is empty"); + // } + + apiResponse = GenericApiModel>( + messageStatus: messageStatus, + statusCode: statusCode, + errorMessage: null, + data: radOrders, + ); + } 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/radiology/radiology_view_model.dart b/lib/features/radiology/radiology_view_model.dart new file mode 100644 index 0000000..22857d0 --- /dev/null +++ b/lib/features/radiology/radiology_view_model.dart @@ -0,0 +1,45 @@ +import 'package:flutter/material.dart'; +import 'package:hmg_patient_app_new/features/lab/lab_repo.dart'; +import 'package:hmg_patient_app_new/features/lab/models/resp_models/patient_lab_orders_response_model.dart'; +import 'package:hmg_patient_app_new/features/radiology/radiology_repo.dart'; +import 'package:hmg_patient_app_new/services/error_handler_service.dart'; + +import 'models/resp_models/patient_radiology_response_model.dart'; + +class RadiologyViewModel extends ChangeNotifier { + bool isRadiologyOrdersLoading = false; + + RadiologyRepo radiologyRepo; + ErrorHandlerService errorHandlerService; + + List patientRadiologyOrders = []; + + RadiologyViewModel({required this.radiologyRepo, required this.errorHandlerService}); + + initRadiologyProvider() { + patientRadiologyOrders.clear(); + isRadiologyOrdersLoading = true; + getPatientRadiologyOrders(); + notifyListeners(); + } + + Future getPatientRadiologyOrders({Function(dynamic)? onSuccess, Function(String)? onError}) async { + final result = await radiologyRepo.getPatientRadiologyOrders(patientId: "1231755"); + + 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) { + patientRadiologyOrders = apiResponse.data!; + isRadiologyOrdersLoading = false; + notifyListeners(); + if (onSuccess != null) { + onSuccess(apiResponse); + } + } + }, + ); + } +} diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index a1082b3..3defa60 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -779,5 +779,6 @@ abstract class LocaleKeys { static const myFiles = 'myFiles'; static const resultsPending = 'resultsPending'; static const resultsAvailable = 'resultsAvailable'; + static const viewReport = 'viewReport'; } diff --git a/lib/main.dart b/lib/main.dart index 3f09649..f9ff19e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -8,6 +8,7 @@ import 'package:flutter/services.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart'; import 'package:hmg_patient_app_new/features/lab/lab_view_model.dart'; +import 'package:hmg_patient_app_new/features/radiology/radiology_view_model.dart'; import 'package:hmg_patient_app_new/routes/app_routes.dart'; import 'package:hmg_patient_app_new/services/logger_service.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart'; @@ -57,6 +58,12 @@ void main() async { errorHandlerService: getIt(), ), ), + ChangeNotifierProvider( + create: (_) => RadiologyViewModel( + radiologyRepo: getIt(), + errorHandlerService: getIt(), + ), + ), ChangeNotifierProvider( create: (_) => AuthenticationViewModel( authenticationRepo: getIt(), diff --git a/lib/presentation/home/widgets/small_service_card.dart b/lib/presentation/home/widgets/small_service_card.dart index 0983a06..4cf90f5 100644 --- a/lib/presentation/home/widgets/small_service_card.dart +++ b/lib/presentation/home/widgets/small_service_card.dart @@ -7,6 +7,7 @@ import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart'; import '../../../core/utils/utils.dart'; import '../../../theme/colors.dart'; +import '../../radiology/radiology_orders_page.dart' show RadiologyOrdersPage; class SmallServiceCard extends StatelessWidget { final String serviceName; @@ -62,6 +63,11 @@ class SmallServiceCard extends StatelessWidget { ); break; case "radiology_results": + Navigator.of(context).push( + FadePage( + page: RadiologyOrdersPage(), + ), + ); break; case "prescriptions": break; diff --git a/lib/presentation/lab/lab_orders_page.dart b/lib/presentation/lab/lab_orders_page.dart index a60f3cf..03c9eb0 100644 --- a/lib/presentation/lab/lab_orders_page.dart +++ b/lib/presentation/lab/lab_orders_page.dart @@ -28,14 +28,6 @@ class _LabOrdersPageState extends State { int? expandedIndex; - // Sample data for demonstration - final List labOrders = [ - 'Mohammad Al Harbi', - 'Mohammad Al Harbi', - 'Mohammad Al Harbi', - 'Mohammad Al Harbi', - ]; - @override void initState() { scheduleMicrotask(() { @@ -50,7 +42,7 @@ class _LabOrdersPageState extends State { return Scaffold( backgroundColor: AppColors.bgScaffoldColor, appBar: AppBar( - title: const Text('Lab Results'), + title: LocaleKeys.labResults.tr(context: context).toText18(), backgroundColor: AppColors.bgScaffoldColor, ), body: Padding( @@ -191,7 +183,7 @@ class _LabOrdersPageState extends State { icon: AppAssets.view_report_icon, iconColor: AppColors.primaryRedColor, iconSize: 16.h, - text: "View Report", + text: LocaleKeys.viewReport.tr(context: context), onPressed: () {}, backgroundColor: AppColors.secondaryLightRedColor, borderColor: AppColors.secondaryLightRedColor, diff --git a/lib/presentation/radiology/radiology_orders_page.dart b/lib/presentation/radiology/radiology_orders_page.dart new file mode 100644 index 0000000..d1b3830 --- /dev/null +++ b/lib/presentation/radiology/radiology_orders_page.dart @@ -0,0 +1,251 @@ +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_assets.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/generated/locale_keys.g.dart'; +import 'package:hmg_patient_app_new/features/lab/lab_view_model.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/shimmer/movies_shimmer_widget.dart'; +import 'package:provider/provider.dart'; + +import '../../features/radiology/radiology_view_model.dart'; + +class RadiologyOrdersPage extends StatefulWidget { + const RadiologyOrdersPage({super.key}); + + @override + State createState() => _RadiologyOrdersPageState(); +} + +class _RadiologyOrdersPageState extends State { + late RadiologyViewModel radiologyViewModel; + + int? expandedIndex; + + @override + void initState() { + scheduleMicrotask(() { + radiologyViewModel.initRadiologyProvider(); + }); + super.initState(); + } + + @override + Widget build(BuildContext context) { + radiologyViewModel = Provider.of(context); + return Scaffold( + backgroundColor: AppColors.bgScaffoldColor, + appBar: AppBar( + title: LocaleKeys.radiology.tr(context: context).toText18(), + backgroundColor: AppColors.bgScaffoldColor, + ), + body: Padding( + padding: EdgeInsets.all(24.h), + child: SingleChildScrollView( + child: Consumer( + builder: (context, model, child) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + LocaleKeys.radiology.tr(context: context).toText24(isBold: true), + Utils.buildSvgWithAssets(icon: AppAssets.search_icon), + ], + ), + SizedBox(height: 16.h), + // Build Tab Bar + SizedBox(height: 16.h), + // Expandable list + ListView.builder( + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + itemCount: model.isRadiologyOrdersLoading ? 5 : model.patientRadiologyOrders.length, + itemBuilder: (context, index) { + final isExpanded = expandedIndex == index; + return model.isRadiologyOrdersLoading + ? const MoviesShimmerWidget() + : AnimationConfiguration.staggeredList( + position: index, + duration: const Duration(milliseconds: 500), + child: SlideAnimation( + verticalOffset: 100.0, + child: FadeInAnimation( + child: AnimatedContainer( + duration: Duration(milliseconds: 300), + curve: Curves.easeInOut, + margin: EdgeInsets.symmetric(vertical: 8.h), + decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.h, hasShadow: true), + child: InkWell( + onTap: () { + setState(() { + expandedIndex = isExpanded ? null : index; + }); + }, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.all(16.h), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + CustomButton( + text: LocaleKeys.resultsAvailable.tr(context: context), + onPressed: () {}, + backgroundColor: AppColors.successColor.withOpacity(0.15), + borderColor: AppColors.successColor.withOpacity(0.01), + textColor: AppColors.successColor, + fontSize: 10, + fontWeight: FontWeight.w500, + borderRadius: 8, + padding: EdgeInsets.fromLTRB(10, 0, 10, 0), + height: 30.h, + ), + Icon(isExpanded ? Icons.expand_less : Icons.expand_more), + ], + ), + SizedBox(height: 8.h), + Row( + children: [ + Image.network( + model.patientRadiologyOrders[index].doctorImageURL!, + width: 24.h, + height: 24.h, + fit: BoxFit.fill, + ).circle(100), + SizedBox(width: 4.h), + model.patientRadiologyOrders[index].doctorName!.toText16(isBold: true) + ], + ), + SizedBox(height: 8.h), + Row( + children: [ + CustomButton( + text: DateUtil.formatDateToDate(DateUtil.convertStringToDate(model.patientRadiologyOrders[index].orderDate), false), + onPressed: () {}, + backgroundColor: AppColors.greyColor, + borderColor: AppColors.greyColor, + textColor: AppColors.blackColor, + fontSize: 12, + fontWeight: FontWeight.w500, + borderRadius: 8, + padding: EdgeInsets.fromLTRB(10, 0, 10, 0), + height: 24.h, + ), + SizedBox(width: 8.h), + CustomButton( + text: model.patientRadiologyOrders[index].clinicDescription!, + onPressed: () {}, + backgroundColor: AppColors.greyColor, + borderColor: AppColors.greyColor, + textColor: AppColors.blackColor, + fontSize: 12, + fontWeight: FontWeight.w500, + borderRadius: 8, + padding: EdgeInsets.fromLTRB(10, 0, 10, 0), + height: 24.h, + ), + ], + ), + ], + ), + ), + AnimatedCrossFade( + firstChild: SizedBox.shrink(), + secondChild: Padding( + padding: EdgeInsets.symmetric(horizontal: 16.h, vertical: 8.h), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.only(bottom: 8.h), + child: '● ${model.patientRadiologyOrders[index].description}'.toText14(weight: FontWeight.w500), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SizedBox(), + CustomButton( + icon: AppAssets.view_report_icon, + iconColor: AppColors.primaryRedColor, + iconSize: 16.h, + text: LocaleKeys.viewReport.tr(context: context), + onPressed: () {}, + backgroundColor: AppColors.secondaryLightRedColor, + borderColor: AppColors.secondaryLightRedColor, + textColor: AppColors.primaryRedColor, + fontSize: 14, + fontWeight: FontWeight.bold, + borderRadius: 12, + padding: EdgeInsets.fromLTRB(10, 0, 10, 0), + height: 40.h, + ), + ], + ), + ], + ), + ), + crossFadeState: isExpanded ? CrossFadeState.showSecond : CrossFadeState.showFirst, + duration: Duration(milliseconds: 300), + ), + ], + ), + ), + ), + ), + ), + ); + }, + ), + ], + ); + }, + ), + ), + ), + ); + } + + Color getLabOrderStatusColor(num status) { + switch (status) { + case 44: + return AppColors.warningColorYellow; + case 45: + return AppColors.warningColorYellow; + case 16: + return AppColors.successColor; + case 17: + return AppColors.successColor; + default: + return AppColors.greyColor; + } + } + + String getLabOrderStatusText(num status) { + switch (status) { + case 44: + return LocaleKeys.resultsPending.tr(context: context); + case 45: + return LocaleKeys.resultsPending.tr(context: context); + case 16: + return LocaleKeys.resultsAvailable.tr(context: context); + case 17: + return LocaleKeys.resultsAvailable.tr(context: context); + default: + return ""; + } + } +}