diff --git a/assets/images/svg/forward_arrow_icon.svg b/assets/images/svg/forward_arrow_icon.svg
new file mode 100644
index 0000000..d8a3d51
--- /dev/null
+++ b/assets/images/svg/forward_arrow_icon.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/images/svg/prescription_refill_icon.svg b/assets/images/svg/prescription_refill_icon.svg
new file mode 100644
index 0000000..7a9706b
--- /dev/null
+++ b/assets/images/svg/prescription_refill_icon.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json
index 6355b66..718bf83 100644
--- a/assets/langs/ar-SA.json
+++ b/assets/langs/ar-SA.json
@@ -781,5 +781,6 @@
"myFiles" : "ملفاتي",
"resultsPending": "النتائج معلقة",
"resultsAvailable": "النتائج متاحة",
- "viewReport": "عرض التقرير"
+ "viewReport": "عرض التقرير",
+ "prescriptionDeliveryError": "هذه العيادة لا تدعم إعادة التعبئة والتسليم."
}
\ No newline at end of file
diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json
index c18eb97..6743993 100644
--- a/assets/langs/en-US.json
+++ b/assets/langs/en-US.json
@@ -665,7 +665,7 @@
"healthWeatherIndicators": "Health Weather Indicators",
"healthTipsBasedOnCurrentWeather": "Health Tips Based On Current Weather",
"moreDetails": "More details",
- "resendOrder": "Refill & Delivery",
+ "resendOrder": "Refill and Delivery",
"ports": "Ports",
"way": "Way",
"dailyDoses": "Daily Doses",
@@ -777,5 +777,6 @@
"myFiles": "My Files",
"resultsPending": "Results Pending",
"resultsAvailable": "Results Available",
- "viewReport": "View Report"
+ "viewReport": "View Report",
+ "prescriptionDeliveryError": "This clinic doesn't support refill"
}
\ No newline at end of file
diff --git a/lib/core/app_assets.dart b/lib/core/app_assets.dart
index 53adac7..a43406e 100644
--- a/lib/core/app_assets.dart
+++ b/lib/core/app_assets.dart
@@ -62,6 +62,8 @@ class AppAssets {
static const String eye_result_icon = '$svgBasePath/eye_results_icon.svg';
static const String search_icon = '$svgBasePath/search_icon.svg';
static const String view_report_icon = '$svgBasePath/view_report_icon.svg';
+ static const String forward_arrow_icon = '$svgBasePath/forward_arrow_icon.svg';
+ static const String prescription_refill_icon = '$svgBasePath/prescription_refill_icon.svg';
//bottom navigation//
@@ -71,7 +73,6 @@ class AppAssets {
static const String toDoBottom = '$svgBasePath/todo_bottom.svg';
static const String servicesBottom = '$svgBasePath/services_bottom.svg';
-
// PNGS //
static const String hmg_logo = '$pngBasePath/hmg_logo.png';
static const String livecare_service = '$pngBasePath/livecare_service.png';
diff --git a/lib/core/dependencies.dart b/lib/core/dependencies.dart
index a9fc9d6..65fd2c6 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/prescriptions/prescriptions_repo.dart';
+import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_view_model.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';
@@ -62,6 +64,7 @@ class AppDependencies {
getIt.registerLazySingleton(() => MyAppointmentsRepoImp(loggerService: getIt(), apiClient: getIt()));
getIt.registerLazySingleton(() => LabRepoImp(loggerService: getIt(), apiClient: getIt()));
getIt.registerLazySingleton(() => RadiologyRepoImp(loggerService: getIt(), apiClient: getIt()));
+ getIt.registerLazySingleton(() => PrescriptionsRepoImp(loggerService: getIt(), apiClient: getIt()));
// ViewModels
// Global/shared VMs → LazySingleton
@@ -80,6 +83,13 @@ class AppDependencies {
),
);
+ getIt.registerLazySingleton(
+ () => PrescriptionsViewModel(
+ prescriptionsRepo: getIt(),
+ errorHandlerService: getIt(),
+ ),
+ );
+
getIt.registerLazySingleton(
() => AuthenticationViewModel(
authenticationRepo: getIt(),
diff --git a/lib/features/prescriptions/models/resp_models/patient_prescriptions_response_model.dart b/lib/features/prescriptions/models/resp_models/patient_prescriptions_response_model.dart
new file mode 100644
index 0000000..7b1d879
--- /dev/null
+++ b/lib/features/prescriptions/models/resp_models/patient_prescriptions_response_model.dart
@@ -0,0 +1,174 @@
+class PatientPrescriptionsResponseModel {
+ String? setupID;
+ int? projectID;
+ int? patientID;
+ int? appointmentNo;
+ String? appointmentDate;
+ String? doctorName;
+ String? clinicDescription;
+ String? name;
+ int? episodeID;
+ num? actualDoctorRate;
+ int? admission;
+ int? clinicID;
+ String? companyName;
+ num? decimalDoctorRate;
+ String? despensedStatus;
+ String? dischargeDate;
+ int? dischargeNo;
+ int? doctorID;
+ String? doctorImageURL;
+ num? doctorRate;
+ num? doctorStarsRate;
+ String? doctorTitle;
+ int? gender;
+ String? genderDescription;
+ bool? isActiveDoctorProfile;
+ bool? isDoctorAllowVedioCall;
+ bool? isExecludeDoctor;
+ bool? isHomeMedicineDeliverySupported;
+ bool? isInOutPatient;
+ String? isInOutPatientDescription;
+ String? isInOutPatientDescriptionN;
+ bool? isInsurancePatient;
+ bool? isLiveCareAppointment;
+ String? nationalityFlagURL;
+ int? noOfPatientsRate;
+ String? qR;
+
+ // List? speciality;
+ String? strAppointmentDate;
+
+ PatientPrescriptionsResponseModel(
+ {this.setupID,
+ this.projectID,
+ this.patientID,
+ this.appointmentNo,
+ this.appointmentDate,
+ this.doctorName,
+ this.clinicDescription,
+ this.name,
+ this.episodeID,
+ this.actualDoctorRate,
+ this.admission,
+ this.clinicID,
+ this.companyName,
+ this.decimalDoctorRate,
+ this.despensedStatus,
+ this.dischargeDate,
+ this.dischargeNo,
+ this.doctorID,
+ this.doctorImageURL,
+ this.doctorRate,
+ this.doctorStarsRate,
+ this.doctorTitle,
+ this.gender,
+ this.genderDescription,
+ this.isActiveDoctorProfile,
+ this.isDoctorAllowVedioCall,
+ this.isExecludeDoctor,
+ this.isHomeMedicineDeliverySupported,
+ this.isInOutPatient,
+ this.isInOutPatientDescription,
+ this.isInOutPatientDescriptionN,
+ this.isInsurancePatient,
+ this.isLiveCareAppointment,
+ this.nationalityFlagURL,
+ this.noOfPatientsRate,
+ this.qR,
+ // this.speciality,
+ this.strAppointmentDate});
+
+ PatientPrescriptionsResponseModel.fromJson(Map json) {
+ setupID = json['SetupID'];
+ projectID = json['ProjectID'];
+ patientID = json['PatientID'];
+ appointmentNo = json['AppointmentNo'];
+ appointmentDate = json['AppointmentDate'];
+ doctorName = json['DoctorName'];
+ clinicDescription = json['ClinicDescription'];
+ name = json['Name'];
+ episodeID = json['EpisodeID'];
+ actualDoctorRate = json['ActualDoctorRate'];
+ admission = json['Admission'];
+ clinicID = json['ClinicID'];
+ companyName = json['CompanyName'];
+ decimalDoctorRate = json['DecimalDoctorRate'];
+ despensedStatus = json['Despensed_Status'];
+ dischargeDate = json['DischargeDate'];
+ dischargeNo = json['DischargeNo'];
+ doctorID = json['DoctorID'];
+ doctorImageURL = json['DoctorImageURL'];
+ doctorRate = json['DoctorRate'];
+ doctorStarsRate = json['DoctorStarsRate'];
+ doctorTitle = json['DoctorTitle'];
+ gender = json['Gender'];
+ genderDescription = json['GenderDescription'];
+ isActiveDoctorProfile = json['IsActiveDoctorProfile'];
+ isDoctorAllowVedioCall = json['IsDoctorAllowVedioCall'];
+ isExecludeDoctor = json['IsExecludeDoctor'];
+ isHomeMedicineDeliverySupported = json['IsHomeMedicineDeliverySupported'];
+ isInOutPatient = json['IsInOutPatient'];
+ isInOutPatientDescription = json['IsInOutPatientDescription'];
+ isInOutPatientDescriptionN = json['IsInOutPatientDescriptionN'];
+ isInsurancePatient = json['IsInsurancePatient'];
+ isLiveCareAppointment = json['IsLiveCareAppointment'];
+ nationalityFlagURL = json['NationalityFlagURL'];
+ noOfPatientsRate = json['NoOfPatientsRate'];
+ qR = json['QR'];
+ // speciality = json['Speciality'].cast();
+ strAppointmentDate = json['StrAppointmentDate'];
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['SetupID'] = this.setupID;
+ data['ProjectID'] = this.projectID;
+ data['PatientID'] = this.patientID;
+ data['AppointmentNo'] = this.appointmentNo;
+ data['AppointmentDate'] = this.appointmentDate;
+ data['DoctorName'] = this.doctorName;
+ data['ClinicDescription'] = this.clinicDescription;
+ data['Name'] = this.name;
+ data['EpisodeID'] = this.episodeID;
+ data['ActualDoctorRate'] = this.actualDoctorRate;
+ data['Admission'] = this.admission;
+ data['ClinicID'] = this.clinicID;
+ data['CompanyName'] = this.companyName;
+ data['DecimalDoctorRate'] = this.decimalDoctorRate;
+ data['Despensed_Status'] = this.despensedStatus;
+ data['DischargeDate'] = this.dischargeDate;
+ data['DischargeNo'] = this.dischargeNo;
+ data['DoctorID'] = this.doctorID;
+ data['DoctorImageURL'] = this.doctorImageURL;
+ data['DoctorRate'] = this.doctorRate;
+ data['DoctorStarsRate'] = this.doctorStarsRate;
+ data['DoctorTitle'] = this.doctorTitle;
+ data['Gender'] = this.gender;
+ data['GenderDescription'] = this.genderDescription;
+ data['IsActiveDoctorProfile'] = this.isActiveDoctorProfile;
+ data['IsDoctorAllowVedioCall'] = this.isDoctorAllowVedioCall;
+ data['IsExecludeDoctor'] = this.isExecludeDoctor;
+ data['IsHomeMedicineDeliverySupported'] = this.isHomeMedicineDeliverySupported;
+ data['IsInOutPatient'] = this.isInOutPatient;
+ data['IsInOutPatientDescription'] = this.isInOutPatientDescription;
+ data['IsInOutPatientDescriptionN'] = this.isInOutPatientDescriptionN;
+ data['IsInsurancePatient'] = this.isInsurancePatient;
+ data['IsLiveCareAppointment'] = this.isLiveCareAppointment;
+ data['NationalityFlagURL'] = this.nationalityFlagURL;
+ data['NoOfPatientsRate'] = this.noOfPatientsRate;
+ data['QR'] = this.qR;
+ // data['Speciality'] = this.speciality;
+ data['StrAppointmentDate'] = this.strAppointmentDate;
+ return data;
+ }
+}
+
+class PrescriptionsList {
+ String? filterName = "";
+ List? prescriptionsList = [];
+
+ PrescriptionsList({this.filterName, PatientPrescriptionsResponseModel? prescriptions}) {
+ prescriptionsList!.add(prescriptions!);
+ }
+}
diff --git a/lib/features/prescriptions/prescriptions_repo.dart b/lib/features/prescriptions/prescriptions_repo.dart
new file mode 100644
index 0000000..53cf827
--- /dev/null
+++ b/lib/features/prescriptions/prescriptions_repo.dart
@@ -0,0 +1,75 @@
+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/prescriptions/models/resp_models/patient_prescriptions_response_model.dart';
+import 'package:hmg_patient_app_new/services/logger_service.dart';
+
+abstract class PrescriptionsRepo {
+ Future>>> getPatientPrescriptionOrders({required String patientId});
+}
+
+class PrescriptionsRepoImp implements PrescriptionsRepo {
+ final ApiClient apiClient;
+ final LoggerService loggerService;
+
+ PrescriptionsRepoImp({required this.loggerService, required this.apiClient});
+
+ @override
+ Future>>> getPatientPrescriptionOrders({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(
+ PRESCRIPTIONS,
+ body: mapDevice,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus}) {
+ try {
+ final list = response['PatientPrescriptionList'];
+ if (list == null || list.isEmpty) {
+ throw Exception("lab list is empty");
+ }
+
+ final prescriptionOrders = list.map((item) => PatientPrescriptionsResponseModel.fromJson(item as Map)).toList().cast();
+
+ apiResponse = GenericApiModel>(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: prescriptionOrders,
+ );
+ } 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/prescriptions/prescriptions_view_model.dart b/lib/features/prescriptions/prescriptions_view_model.dart
new file mode 100644
index 0000000..031b26e
--- /dev/null
+++ b/lib/features/prescriptions/prescriptions_view_model.dart
@@ -0,0 +1,82 @@
+import 'package:flutter/material.dart';
+import 'package:hmg_patient_app_new/features/prescriptions/models/resp_models/patient_prescriptions_response_model.dart';
+import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_repo.dart';
+import 'package:hmg_patient_app_new/services/error_handler_service.dart';
+
+class PrescriptionsViewModel extends ChangeNotifier {
+ bool isPrescriptionsOrdersLoading = false;
+
+ PrescriptionsRepo prescriptionsRepo;
+ ErrorHandlerService errorHandlerService;
+
+ List patientPrescriptionOrders = [];
+
+ List patientPrescriptionOrdersByClinic = [];
+ List patientPrescriptionOrdersByHospital = [];
+
+ List patientPrescriptionOrdersViewList = [];
+
+ bool isSortByClinic = true;
+
+ PrescriptionsViewModel({required this.prescriptionsRepo, required this.errorHandlerService});
+
+ initPrescriptionsViewModel() {
+ patientPrescriptionOrders.clear();
+ patientPrescriptionOrdersByClinic.clear();
+ patientPrescriptionOrdersByHospital.clear();
+ patientPrescriptionOrdersViewList.clear();
+ isPrescriptionsOrdersLoading = true;
+ isSortByClinic = true;
+ getPatientPrescriptionOrders();
+ notifyListeners();
+ }
+
+ setIsSortByClinic(bool value) {
+ isSortByClinic = value;
+ if (isSortByClinic) {
+ patientPrescriptionOrdersViewList = patientPrescriptionOrdersByClinic;
+ } else {
+ patientPrescriptionOrdersViewList = patientPrescriptionOrdersByHospital;
+ }
+ notifyListeners();
+ }
+
+ Future getPatientPrescriptionOrders({Function(dynamic)? onSuccess, Function(String)? onError}) async {
+ final result = await prescriptionsRepo.getPatientPrescriptionOrders(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) {
+ patientPrescriptionOrders = apiResponse.data!;
+ isPrescriptionsOrdersLoading = false;
+
+ for (var element in patientPrescriptionOrders) {
+ List prescriptionsByClinic = patientPrescriptionOrdersByClinic.where((elementClinic) => elementClinic.filterName == element.clinicDescription).toList();
+
+ if (prescriptionsByClinic.isNotEmpty) {
+ patientPrescriptionOrdersByClinic[patientPrescriptionOrdersByClinic.indexOf(prescriptionsByClinic[0])].prescriptionsList!.add(element);
+ } else {
+ patientPrescriptionOrdersByClinic.add(PrescriptionsList(filterName: element.clinicDescription, prescriptions: element));
+ }
+
+ List prescriptionsByHospital = patientPrescriptionOrdersByHospital.where((elementClinic) => elementClinic.filterName == element.name).toList();
+
+ if (prescriptionsByHospital.isNotEmpty) {
+ patientPrescriptionOrdersByHospital[patientPrescriptionOrdersByHospital.indexOf(prescriptionsByHospital[0])].prescriptionsList!.add(element);
+ } else {
+ patientPrescriptionOrdersByHospital.add(PrescriptionsList(filterName: element.name, prescriptions: element));
+ }
+ }
+ patientPrescriptionOrdersViewList = patientPrescriptionOrdersByClinic;
+ notifyListeners();
+ if (onSuccess != null) {
+ onSuccess(apiResponse);
+ }
+ }
+ },
+ );
+ }
+}
diff --git a/lib/features/radiology/radiology_repo.dart b/lib/features/radiology/radiology_repo.dart
index ea916e6..d3e4f3d 100644
--- a/lib/features/radiology/radiology_repo.dart
+++ b/lib/features/radiology/radiology_repo.dart
@@ -3,7 +3,6 @@ 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';
@@ -56,10 +55,6 @@ class RadiologyRepoImp implements RadiologyRepo {
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,
diff --git a/lib/features/radiology/radiology_view_model.dart b/lib/features/radiology/radiology_view_model.dart
index 22857d0..1bdba04 100644
--- a/lib/features/radiology/radiology_view_model.dart
+++ b/lib/features/radiology/radiology_view_model.dart
@@ -1,6 +1,4 @@
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';
diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart
index 3defa60..54a1136 100644
--- a/lib/generated/locale_keys.g.dart
+++ b/lib/generated/locale_keys.g.dart
@@ -780,5 +780,6 @@ abstract class LocaleKeys {
static const resultsPending = 'resultsPending';
static const resultsAvailable = 'resultsAvailable';
static const viewReport = 'viewReport';
+ static const prescriptionDeliveryError = 'prescriptionDeliveryError';
}
diff --git a/lib/main.dart b/lib/main.dart
index f9ff19e..035c6bf 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/prescriptions/prescriptions_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';
@@ -64,6 +65,12 @@ void main() async {
errorHandlerService: getIt(),
),
),
+ ChangeNotifierProvider(
+ create: (_) => PrescriptionsViewModel(
+ prescriptionsRepo: 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 4cf90f5..297ed2b 100644
--- a/lib/presentation/home/widgets/small_service_card.dart
+++ b/lib/presentation/home/widgets/small_service_card.dart
@@ -3,6 +3,7 @@ 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/presentation/lab/lab_orders_page.dart';
+import 'package:hmg_patient_app_new/presentation/prescriptions/prescriptions_list_page.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
import '../../../core/utils/utils.dart';
@@ -70,6 +71,11 @@ class SmallServiceCard extends StatelessWidget {
);
break;
case "prescriptions":
+ Navigator.of(context).push(
+ FadePage(
+ page: PrescriptionsListPage(),
+ ),
+ );
break;
case "insurance_update":
break;
diff --git a/lib/presentation/lab/lab_orders_page.dart b/lib/presentation/lab/lab_orders_page.dart
index 03c9eb0..8a0ce26 100644
--- a/lib/presentation/lab/lab_orders_page.dart
+++ b/lib/presentation/lab/lab_orders_page.dart
@@ -161,46 +161,59 @@ class _LabOrdersPageState extends State {
],
),
),
- AnimatedCrossFade(
- firstChild: SizedBox.shrink(),
- secondChild: Padding(
- padding: EdgeInsets.symmetric(horizontal: 16.h, vertical: 8.h),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- ...model.patientLabOrders[index].testDetails!.map((detail) {
- return Padding(
- padding: EdgeInsets.only(bottom: 8.h),
- child: '● ${detail.description}'.toText14(weight: FontWeight.w500),
- );
- }).toList(),
- SizedBox(height: 16.h),
- 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,
+ AnimatedSwitcher(
duration: Duration(milliseconds: 300),
+ switchInCurve: Curves.easeIn,
+ switchOutCurve: Curves.easeOut,
+ transitionBuilder: (Widget child, Animation animation) {
+ return FadeTransition(
+ opacity: animation,
+ child: SizeTransition(
+ sizeFactor: animation,
+ axisAlignment: 0.0,
+ child: child,
+ ),
+ );
+ },
+ child: isExpanded
+ ? Container(
+ key: ValueKey(index),
+ padding: EdgeInsets.symmetric(horizontal: 16.h, vertical: 8.h),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ ...model.patientLabOrders[index].testDetails!.map((detail) {
+ return Padding(
+ padding: EdgeInsets.only(bottom: 8.h),
+ child: '● ${detail.description}'.toText14(weight: FontWeight.w500),
+ );
+ }).toList(),
+ SizedBox(height: 16.h),
+ 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,
+ ),
+ ],
+ ),
+ ],
+ ),
+ )
+ : SizedBox.shrink(key: ValueKey(-index)),
),
],
),
diff --git a/lib/presentation/prescriptions/prescriptions_list_page.dart b/lib/presentation/prescriptions/prescriptions_list_page.dart
new file mode 100644
index 0000000..c678a8e
--- /dev/null
+++ b/lib/presentation/prescriptions/prescriptions_list_page.dart
@@ -0,0 +1,293 @@
+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/features/prescriptions/prescriptions_view_model.dart';
+import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
+import 'package:hmg_patient_app_new/theme/colors.dart';
+import 'package: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';
+
+class PrescriptionsListPage extends StatefulWidget {
+ const PrescriptionsListPage({super.key});
+
+ @override
+ State createState() => _PrescriptionsListPageState();
+}
+
+class _PrescriptionsListPageState extends State {
+ int? expandedIndex;
+
+ late PrescriptionsViewModel prescriptionsViewModel;
+
+ @override
+ void initState() {
+ scheduleMicrotask(() {
+ prescriptionsViewModel.initPrescriptionsViewModel();
+ });
+ super.initState();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ prescriptionsViewModel = Provider.of(context, listen: false);
+ return Scaffold(
+ backgroundColor: AppColors.bgScaffoldColor,
+ appBar: AppBar(
+ title: LocaleKeys.prescriptions.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: [
+ LocaleKeys.prescriptions.tr(context: context).toText24(isBold: true),
+ SizedBox(height: 16.h),
+ // Build Tab Bar
+ SizedBox(height: 16.h),
+ // Clinic & Hospital Sort
+ Row(
+ children: [
+ CustomButton(
+ text: LocaleKeys.byClinic.tr(context: context),
+ onPressed: () {
+ model.setIsSortByClinic(true);
+ },
+ backgroundColor: model.isSortByClinic ? AppColors.bgRedLightColor : AppColors.whiteColor,
+ borderColor: model.isSortByClinic ? AppColors.primaryRedColor : AppColors.textColor.withOpacity(0.2),
+ textColor: model.isSortByClinic ? AppColors.primaryRedColor : AppColors.blackColor,
+ fontSize: 12,
+ fontWeight: FontWeight.w500,
+ borderRadius: 10,
+ padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ height: 40.h,
+ ),
+ SizedBox(width: 8.h),
+ CustomButton(
+ text: LocaleKeys.byHospital.tr(context: context),
+ onPressed: () {
+ model.setIsSortByClinic(false);
+ },
+ backgroundColor: model.isSortByClinic ? AppColors.whiteColor : AppColors.bgRedLightColor,
+ borderColor: model.isSortByClinic ? AppColors.textColor.withOpacity(0.2) : AppColors.primaryRedColor,
+ textColor: model.isSortByClinic ? AppColors.blackColor : AppColors.primaryRedColor,
+ fontSize: 12,
+ fontWeight: FontWeight.w500,
+ borderRadius: 10,
+ padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ height: 40.h,
+ ),
+ ],
+ ),
+ SizedBox(height: 20.h),
+ // Expandable list
+ ListView.builder(
+ itemCount: model.isPrescriptionsOrdersLoading ? 4 : model.patientPrescriptionOrdersViewList.length,
+ physics: NeverScrollableScrollPhysics(),
+ shrinkWrap: true,
+ padding: const EdgeInsets.only(left: 0, right: 8),
+ itemBuilder: (context, index) {
+ final isExpanded = expandedIndex == index;
+ return model.isPrescriptionsOrdersLoading
+ ? 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: "${model.patientPrescriptionOrdersViewList[index].prescriptionsList!.length} Prescriptions Available",
+ onPressed: () {},
+ backgroundColor: AppColors.greyColor,
+ borderColor: AppColors.greyColor,
+ textColor: AppColors.blackColor,
+ fontSize: 10,
+ fontWeight: FontWeight.w500,
+ borderRadius: 8,
+ padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ height: 30.h,
+ ),
+ Icon(isExpanded ? Icons.expand_less : Icons.expand_more),
+ ],
+ ),
+ SizedBox(height: 8.h),
+ model.patientPrescriptionOrdersViewList[index].filterName!.toText16(isBold: true)
+ ],
+ ),
+ ),
+ AnimatedSwitcher(
+ duration: Duration(milliseconds: 500),
+ switchInCurve: Curves.easeIn,
+ switchOutCurve: Curves.easeOut,
+ transitionBuilder: (Widget child, Animation animation) {
+ return FadeTransition(
+ opacity: animation,
+ child: SizeTransition(
+ sizeFactor: animation,
+ axisAlignment: 0.0,
+ child: child,
+ ),
+ );
+ },
+ child: isExpanded
+ ? Container(
+ key: ValueKey(index),
+ padding: EdgeInsets.symmetric(horizontal: 16.h, vertical: 8.h),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ ...model.patientPrescriptionOrdersViewList[index].prescriptionsList!.map((prescription) {
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ Image.network(
+ prescription.doctorImageURL!,
+ width: 24.h,
+ height: 24.h,
+ fit: BoxFit.fill,
+ ).circle(100),
+ SizedBox(width: 8.h),
+ Expanded(child: prescription.doctorName!.toText14(weight: FontWeight.w500)),
+ ],
+ ),
+ SizedBox(height: 8.h),
+ Row(
+ children: [
+ CustomButton(
+ text: DateUtil.formatDateToDate(DateUtil.convertStringToDate(prescription.appointmentDate), 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.isSortByClinic ? prescription.name! : prescription.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,
+ ),
+ ],
+ ),
+ SizedBox(height: 8.h),
+ Row(
+ children: [
+ Expanded(
+ flex: 6,
+ child: CustomButton(
+ text: prescription.isHomeMedicineDeliverySupported!
+ ? LocaleKeys.resendOrder.tr(context: context)
+ : LocaleKeys.prescriptionDeliveryError.tr(context: context),
+ onPressed: () {},
+ backgroundColor: prescription.isHomeMedicineDeliverySupported! ? AppColors.successColor.withOpacity(0.15) : AppColors.greyF7Color,
+ borderColor: AppColors.successColor.withOpacity(0.01),
+ textColor: prescription.isHomeMedicineDeliverySupported! ? AppColors.successColor : AppColors.textColor.withOpacity(0.35),
+ fontSize: prescription.isHomeMedicineDeliverySupported! ? 14 : 12,
+ fontWeight: FontWeight.w500,
+ borderRadius: 12,
+ padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ height: 40.h,
+ icon: AppAssets.prescription_refill_icon,
+ iconColor: prescription.isHomeMedicineDeliverySupported! ? AppColors.successColor : AppColors.textColor.withOpacity(0.35),
+ iconSize: 14.h,
+ ),
+ ),
+ SizedBox(width: 8.h),
+ Expanded(
+ flex: 1,
+ child: Container(
+ height: 40.h,
+ width: 40.h,
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.textColor,
+ borderRadius: 10.h,
+ ),
+ child: Padding(
+ padding: EdgeInsets.all(8.h),
+ child: Utils.buildSvgWithAssets(
+ icon: AppAssets.forward_arrow_icon,
+ width: 10.h,
+ height: 10.h,
+ fit: BoxFit.contain,
+ ),
+ ),
+ ),
+ ),
+ ],
+ ),
+ SizedBox(height: 12.h),
+ Divider(color: AppColors.borderOnlyColor.withOpacity(0.05), height: 1.h),
+ SizedBox(height: 12.h),
+ ],
+ );
+ }).toList(),
+ ],
+ ),
+ )
+ : SizedBox.shrink(),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ),
+ ),
+ );
+ },
+ ),
+ ],
+ );
+ }),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/theme/colors.dart b/lib/theme/colors.dart
index 5e9dbdc..d9cf167 100644
--- a/lib/theme/colors.dart
+++ b/lib/theme/colors.dart
@@ -41,12 +41,12 @@ static const Color infoColor = Color(0xFF0B85F7);
static const Color warningColor = Color(0xFFFFCC00);
static const Color greyColor = Color(0xFFEFEFF0);
-static const Color successLightColor = Color(0xFF18C27326);
-static const Color errorLightColor = Color(0xFFED1C2B1A);
-static const Color alertLightColor = Color(0xFFD48D0526);
-static const Color infoLightColor = Color(0xFF0B85F726);
-static const Color warningLightColor = Color(0xFFFFCC0026);
-static const Color greyLightColor = Color(0xFFEFEFF026);
+static const Color successLightColor = Color(0xFF18C273);
+static const Color errorLightColor = Color(0xFFED1C2B);
+static const Color alertLightColor = Color(0xFFD48D05);
+static const Color infoLightColor = Color(0xFF0B85F7);
+static const Color warningLightColor = Color(0xFFFFCC00);
+static const Color greyLightColor = Color(0xFFEFEFF0);
static const Color bottomNAVBorder = Color(0xFFEEEEEE);
}
diff --git a/pubspec.yaml b/pubspec.yaml
index 4c2b81f..1263e33 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -98,8 +98,8 @@ flutter:
# weight: 700
- asset: assets/fonts/poppins/Poppins-SemiBold.ttf
weight: 600
-# - asset: assets/fonts/poppins/Poppins-Medium.ttf
-# weight: 500
+ - asset: assets/fonts/poppins/Poppins-Medium.ttf
+ weight: 500
- asset: assets/fonts/poppins/Poppins-Regular.ttf
weight: 400
# - asset: assets/fonts/poppins/Poppins-Light.ttf
@@ -114,8 +114,8 @@ flutter:
fonts:
- asset: assets/fonts/gess_two/GE_SS_Two_Bold.otf
weight: 600
-# - asset: assets/fonts/gess_two/GE_SS_Two_Medium.otf
-# weight: 500
+ - asset: assets/fonts/gess_two/GE_SS_Two_Medium.otf
+ weight: 500
- asset: assets/fonts/gess_two/GE_SS_Two_Light.otf
weight: 400