prescription orders list page implemented

pull/10/head
haroon amjad 2 months ago
parent 6f07bc7c2c
commit 8bc49929d4

@ -0,0 +1,3 @@
<svg width="18" height="12" viewBox="0 0 18 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M17.7495 6.00047C17.7495 5.62691 17.5839 5.28034 17.427 5.02011C17.2577 4.7393 17.0301 4.44937 16.7803 4.16669C16.2794 3.59962 15.6257 2.99064 14.9913 2.43977C14.3532 1.88567 13.7173 1.37546 13.2423 1.00468C13.0044 0.818986 12.8059 0.66755 12.6665 0.562239C12.5968 0.509569 12.5418 0.468397 12.5039 0.440203L12.4604 0.407818L12.4488 0.399264L12.4448 0.396304C12.1113 0.150642 11.6414 0.221533 11.3957 0.555035C11.1501 0.888521 11.2213 1.358 11.5547 1.60367L11.5674 1.61308L11.6075 1.64285C11.6429 1.66925 11.6953 1.7085 11.7623 1.75911C11.8964 1.86036 12.0885 2.00695 12.3193 2.18713C12.7818 2.5481 13.3959 3.04099 14.0078 3.57235C14.6234 4.10694 15.2197 4.66576 15.6562 5.15983C15.6838 5.19108 15.7105 5.2218 15.7364 5.25195L0.999512 5.25196C0.585298 5.25196 0.249512 5.58774 0.249512 6.00195C0.249512 6.41617 0.585299 6.75196 0.999512 6.75196L15.7338 6.75195C15.7088 6.78116 15.6829 6.81088 15.6562 6.84111C15.2197 7.33518 14.6234 7.89401 14.0078 8.4286C13.3959 8.95995 12.7818 9.45285 12.3193 9.81382C12.0885 9.99399 11.8964 10.1406 11.7623 10.2418C11.6953 10.2925 11.6429 10.3317 11.6075 10.3581L11.5674 10.3879L11.5547 10.3973C11.2213 10.6429 11.1501 11.1124 11.3957 11.4459C11.6414 11.7794 12.1113 11.8503 12.4448 11.6046L12.4488 11.6017L12.4604 11.5931L12.5039 11.5607C12.5418 11.5326 12.5968 11.4914 12.6665 11.4387C12.8059 11.3334 13.0044 11.182 13.2423 10.9963C13.7173 10.6255 14.3532 10.1153 14.9913 9.56118C15.6257 9.01031 16.2794 8.40133 16.7803 7.83425C17.0301 7.55158 17.2577 7.26165 17.427 6.98083C17.5829 6.72217 17.7475 6.37819 17.7495 6.0072" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

@ -0,0 +1,5 @@
<svg width="17" height="14" viewBox="0 0 17 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.54506 0.437605L3.32411 0.437604C2.84467 0.437559 2.4139 0.437518 2.06523 0.484153C1.68457 0.535068 1.29404 0.653291 0.974158 0.971528C0.793763 1.15099 0.677307 1.3528 0.600865 1.5626L5.49996 1.5626C6.43194 1.5626 7.18746 2.31812 7.18746 3.2501C7.18746 4.15168 6.48043 4.88812 5.59059 4.93521C5.65332 5.11182 5.68746 5.30198 5.68746 5.5001C5.68746 6.43208 4.93194 7.1876 3.99996 7.1876L0.437465 7.1876L0.437466 9.21693C0.437448 9.53248 0.437432 9.81647 0.458872 10.0518C0.481892 10.3045 0.534171 10.5718 0.682959 10.8282C0.843783 11.1053 1.0751 11.3355 1.35366 11.4955C1.61136 11.6435 2.12009 11.7101 2.37407 11.733C2.68727 12.7906 3.67059 13.5626 4.83516 13.5626C5.99726 13.5626 6.97888 12.7939 7.29424 11.7397L9.70556 11.7397C10.0209 12.7939 11.0025 13.5626 12.1646 13.5626C13.3292 13.5626 14.3125 12.7906 14.6257 11.733C14.8797 11.7101 15.3884 11.6435 15.6461 11.4955C15.9247 11.3355 16.156 11.1053 16.3168 10.8282C16.4656 10.5718 16.5179 10.3045 16.5409 10.0518C16.5624 9.81644 16.5624 9.53251 16.5623 9.21692L16.5624 7.18478C16.5628 6.94077 16.5632 6.69385 16.4958 6.45188C16.4285 6.20991 16.3004 5.99839 16.1739 5.78936L14.8845 3.65164C14.7411 3.41373 14.6079 3.19281 14.4767 3.01653C14.3315 2.8214 14.1572 2.63587 13.9109 2.49714C13.6646 2.35841 13.415 2.30518 13.1721 2.28169C12.9527 2.26047 12.6937 2.2605 12.4149 2.26052L11.4066 2.26052C11.3555 1.88182 11.2149 1.28976 10.895 0.971527C10.5751 0.65329 10.1846 0.535068 9.80393 0.484153C9.45526 0.437518 9.0245 0.437559 8.54506 0.437605ZM11.4322 8.56412C11.6645 8.49536 11.9105 8.45843 12.1652 8.45843C13.3244 8.45843 14.3041 9.22339 14.6219 10.2736C14.9602 10.2736 15.097 10.0518 15.097 9.91677L15.097 6.84114L13.1897 3.71885L11.4322 3.71885L11.4322 8.56412ZM4.83571 9.91677C4.22852 9.91677 3.73629 10.4065 3.73629 11.0105C3.73629 11.6146 4.22852 12.1043 4.83571 12.1043C5.44291 12.1043 5.93514 11.6146 5.93514 11.0105C5.93514 10.4065 5.44291 9.91677 4.83571 9.91677ZM11.0658 11.0105C11.0658 10.4065 11.558 9.91677 12.1652 9.91677C12.7724 9.91677 13.2646 10.4065 13.2646 11.0105C13.2646 11.6146 12.7724 12.1043 12.1652 12.1043C11.558 12.1043 11.0658 11.6146 11.0658 11.0105Z" fill="#18C273"/>
<path d="M0.999965 2.6876C0.689305 2.6876 0.437465 2.93944 0.437466 3.2501C0.437465 3.56076 0.689305 3.8126 0.999965 3.8126L5.49996 3.8126C5.81062 3.8126 6.06246 3.56076 6.06246 3.2501C6.06247 2.93944 5.81063 2.6876 5.49996 2.6876L0.999965 2.6876Z" fill="#18C273"/>
<path d="M0.999965 4.9376C0.689305 4.9376 0.437464 5.18944 0.437465 5.5001C0.437464 5.81076 0.689305 6.0626 0.999965 6.0626L3.99996 6.0626C4.31062 6.0626 4.56246 5.81076 4.56246 5.5001C4.56246 5.18944 4.31063 4.9376 3.99997 4.9376L0.999965 4.9376Z" fill="#18C273"/>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

@ -781,5 +781,6 @@
"myFiles" : "ملفاتي",
"resultsPending": "النتائج معلقة",
"resultsAvailable": "النتائج متاحة",
"viewReport": "عرض التقرير"
"viewReport": "عرض التقرير",
"prescriptionDeliveryError": "هذه العيادة لا تدعم إعادة التعبئة والتسليم."
}

@ -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"
}

@ -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';

@ -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<MyAppointmentsRepo>(() => MyAppointmentsRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
getIt.registerLazySingleton<LabRepo>(() => LabRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
getIt.registerLazySingleton<RadiologyRepo>(() => RadiologyRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
getIt.registerLazySingleton<PrescriptionsRepo>(() => PrescriptionsRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
// ViewModels
// Global/shared VMs LazySingleton
@ -80,6 +83,13 @@ class AppDependencies {
),
);
getIt.registerLazySingleton<PrescriptionsViewModel>(
() => PrescriptionsViewModel(
prescriptionsRepo: getIt(),
errorHandlerService: getIt(),
),
);
getIt.registerLazySingleton<AuthenticationViewModel>(
() => AuthenticationViewModel(
authenticationRepo: getIt(),

@ -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<String>? 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<String, dynamic> 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<String>();
strAppointmentDate = json['StrAppointmentDate'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
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<PatientPrescriptionsResponseModel>? prescriptionsList = [];
PrescriptionsList({this.filterName, PatientPrescriptionsResponseModel? prescriptions}) {
prescriptionsList!.add(prescriptions!);
}
}

@ -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<Either<Failure, GenericApiModel<List<PatientPrescriptionsResponseModel>>>> getPatientPrescriptionOrders({required String patientId});
}
class PrescriptionsRepoImp implements PrescriptionsRepo {
final ApiClient apiClient;
final LoggerService loggerService;
PrescriptionsRepoImp({required this.loggerService, required this.apiClient});
@override
Future<Either<Failure, GenericApiModel<List<PatientPrescriptionsResponseModel>>>> 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<List<PatientPrescriptionsResponseModel>>? 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<String, dynamic>)).toList().cast<PatientPrescriptionsResponseModel>();
apiResponse = GenericApiModel<List<PatientPrescriptionsResponseModel>>(
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()));
}
}
}

@ -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<PatientPrescriptionsResponseModel> patientPrescriptionOrders = [];
List<PrescriptionsList> patientPrescriptionOrdersByClinic = [];
List<PrescriptionsList> patientPrescriptionOrdersByHospital = [];
List<PrescriptionsList> 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<void> 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<PrescriptionsList> 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<PrescriptionsList> 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);
}
}
},
);
}
}

@ -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<String, dynamic>)).toList().cast<PatientRadiologyResponseModel>();
}
// final list = response['ListPLO'];
// if (list == null || list.isEmpty) {
// throw Exception("lab list is empty");
// }
apiResponse = GenericApiModel<List<PatientRadiologyResponseModel>>(
messageStatus: messageStatus,

@ -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';

@ -780,5 +780,6 @@ abstract class LocaleKeys {
static const resultsPending = 'resultsPending';
static const resultsAvailable = 'resultsAvailable';
static const viewReport = 'viewReport';
static const prescriptionDeliveryError = 'prescriptionDeliveryError';
}

@ -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<PrescriptionsViewModel>(
create: (_) => PrescriptionsViewModel(
prescriptionsRepo: getIt(),
errorHandlerService: getIt(),
),
),
ChangeNotifierProvider<AuthenticationViewModel>(
create: (_) => AuthenticationViewModel(
authenticationRepo: getIt(),

@ -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;

@ -161,46 +161,59 @@ class _LabOrdersPageState extends State<LabOrdersPage> {
],
),
),
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<double> animation) {
return FadeTransition(
opacity: animation,
child: SizeTransition(
sizeFactor: animation,
axisAlignment: 0.0,
child: child,
),
);
},
child: isExpanded
? Container(
key: ValueKey<int>(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<int>(-index)),
),
],
),

@ -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<PrescriptionsListPage> createState() => _PrescriptionsListPageState();
}
class _PrescriptionsListPageState extends State<PrescriptionsListPage> {
int? expandedIndex;
late PrescriptionsViewModel prescriptionsViewModel;
@override
void initState() {
scheduleMicrotask(() {
prescriptionsViewModel.initPrescriptionsViewModel();
});
super.initState();
}
@override
Widget build(BuildContext context) {
prescriptionsViewModel = Provider.of<PrescriptionsViewModel>(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<PrescriptionsViewModel>(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<double> animation) {
return FadeTransition(
opacity: animation,
child: SizeTransition(
sizeFactor: animation,
axisAlignment: 0.0,
child: child,
),
);
},
child: isExpanded
? Container(
key: ValueKey<int>(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(),
),
],
),
),
),
),
),
);
},
),
],
);
}),
),
),
);
}
}

@ -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);
}

@ -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

Loading…
Cancel
Save