prescription details page implementation contd.

pull/10/head
haroon amjad 2 months ago
parent 8bc49929d4
commit 712e11c69a

@ -0,0 +1,8 @@
<svg width="14" height="13" viewBox="0 0 14 13" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4.66667 6.35482C4.26396 6.35482 3.9375 6.68128 3.9375 7.08398C3.9375 7.48669 4.26396 7.81315 4.66667 7.81315H4.6719C5.07461 7.81315 5.40107 7.48669 5.40107 7.08398C5.40107 6.68128 5.07461 6.35482 4.6719 6.35482H4.66667Z" fill="#2E3039"/>
<path d="M6.99738 6.35482C6.59468 6.35482 6.26822 6.68128 6.26822 7.08398C6.26822 7.48669 6.59468 7.81315 6.99738 7.81315H7.00262C7.40532 7.81315 7.73178 7.48669 7.73178 7.08398C7.73178 6.68128 7.40532 6.35482 7.00262 6.35482H6.99738Z" fill="#2E3039"/>
<path d="M9.3281 6.35482C8.92539 6.35482 8.59893 6.68128 8.59893 7.08398C8.59893 7.48669 8.92539 7.81315 9.3281 7.81315H9.33333C9.73604 7.81315 10.0625 7.48669 10.0625 7.08398C10.0625 6.68128 9.73604 6.35482 9.33333 6.35482H9.3281Z" fill="#2E3039"/>
<path d="M4.66667 8.68815C4.26396 8.68815 3.9375 9.01461 3.9375 9.41732C3.9375 9.82003 4.26396 10.1465 4.66667 10.1465H4.6719C5.07461 10.1465 5.40107 9.82003 5.40107 9.41732C5.40107 9.01461 5.07461 8.68815 4.6719 8.68815H4.66667Z" fill="#2E3039"/>
<path d="M6.99738 8.68815C6.59468 8.68815 6.26822 9.01461 6.26822 9.41732C6.26822 9.82003 6.59468 10.1465 6.99738 10.1465H7.00262C7.40532 10.1465 7.73178 9.82003 7.73178 9.41732C7.73178 9.01461 7.40532 8.68815 7.00262 8.68815H6.99738Z" fill="#2E3039"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.08333 0.667318C4.08333 0.345152 3.82217 0.0839844 3.5 0.0839844C3.17783 0.0839844 2.91667 0.345152 2.91667 0.667318V0.929148C2.47265 1.06999 2.08678 1.29145 1.76051 1.64417C1.2772 2.16666 1.06913 2.8214 0.970761 3.61237C0.874981 4.38253 0.874989 5.36552 0.875 6.60207L0.875 6.98255C0.874989 8.2191 0.874981 9.20211 0.970761 9.97227C1.06913 10.7632 1.2772 11.418 1.76051 11.9405C2.2498 12.4694 2.87312 12.7032 3.62561 12.8126C4.34666 12.9174 5.26336 12.9173 6.39986 12.9173H7.60011C8.73661 12.9173 9.65334 12.9174 10.3744 12.8126C11.1269 12.7032 11.7502 12.4694 12.2395 11.9405C12.7228 11.418 12.9309 10.7632 13.0292 9.97227C13.125 9.2021 13.125 8.21911 13.125 6.98254V6.6021C13.125 5.36553 13.125 4.38254 13.0292 3.61237C12.9309 2.8214 12.7228 2.16666 12.2395 1.64417C11.9132 1.29145 11.5274 1.06999 11.0833 0.929147V0.667318C11.0833 0.345152 10.8222 0.0839844 10.5 0.0839844C10.1778 0.0839844 9.91667 0.345152 9.91667 0.667318V0.720827C9.27673 0.667291 8.50865 0.667304 7.60013 0.667318L6.39988 0.667318C5.49136 0.667304 4.72327 0.667291 4.08333 0.720827V0.667318ZM2.62373 4.75065C2.3562 4.75065 2.22244 4.75065 2.13725 4.83475C2.05206 4.91884 2.05034 5.05091 2.04692 5.31503C2.04183 5.70771 2.04167 6.14726 2.04167 6.64255V6.94209C2.04167 8.22826 2.04273 9.13855 2.12851 9.82829C2.21274 10.5056 2.36987 10.8811 2.61696 11.1483C2.85808 11.4089 3.18774 11.57 3.79342 11.658C4.42084 11.7492 5.25248 11.7507 6.44583 11.7507H7.55417C8.74752 11.7507 9.57916 11.7492 10.2066 11.658C10.8123 11.57 11.1419 11.4089 11.383 11.1483C11.6301 10.8811 11.7873 10.5056 11.8715 9.82829C11.9573 9.13855 11.9583 8.22826 11.9583 6.94209V6.64255C11.9583 6.14726 11.9582 5.70771 11.9531 5.31503C11.9497 5.05091 11.9479 4.91884 11.8628 4.83475C11.7776 4.75065 11.6438 4.75065 11.3763 4.75065L2.62373 4.75065Z" fill="#2E3039"/>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

@ -0,0 +1,5 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.61828 8.81338C8.56618 8.81254 8.50595 8.81251 8.43164 8.81251C8.12098 8.81251 7.86914 8.56067 7.86914 8.25001C7.86914 7.93935 8.12098 7.68751 8.43164 7.68751L8.45747 7.68751C8.61131 7.68745 8.77766 7.68738 8.91807 7.70626C9.08256 7.72837 9.2927 7.78525 9.46955 7.9621C9.6464 8.13895 9.70328 8.34909 9.7254 8.51358C9.74427 8.654 9.74421 8.82034 9.74415 8.97418L9.74414 12.75C9.74414 13.0607 9.4923 13.3125 9.18164 13.3125C8.87098 13.3125 8.61914 13.0607 8.61914 12.75L8.61914 9.00001C8.61914 8.9257 8.61912 8.86547 8.61828 8.81338Z" fill="#898A8D"/>
<path d="M8.99414 5.25C8.57993 5.25 8.24414 5.58579 8.24414 6C8.24414 6.41421 8.57993 6.75 8.99414 6.75H9.00088C9.41509 6.75 9.75088 6.41421 9.75088 6C9.75088 5.58579 9.41509 5.25 9.00088 5.25H8.99414Z" fill="#898A8D"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.9375 9C0.9375 13.4528 4.5472 17.0625 9 17.0625C13.4528 17.0625 17.0625 13.4528 17.0625 9C17.0625 4.5472 13.4528 0.9375 9 0.9375C4.5472 0.9375 0.9375 4.5472 0.9375 9ZM9 15.9375C5.16852 15.9375 2.0625 12.8315 2.0625 9C2.0625 5.16852 5.16852 2.0625 9 2.0625C12.8315 2.0625 15.9375 5.16852 15.9375 9C15.9375 12.8315 12.8315 15.9375 9 15.9375Z" fill="#898A8D"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

@ -0,0 +1,3 @@
<svg width="14" height="13" viewBox="0 0 14 13" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6.99772 0.228516C7.6098 0.228516 8.09193 0.690826 8.39973 1.31463L9.42758 3.38736C9.45875 3.45151 9.53263 3.54184 9.64371 3.62447C9.75466 3.70702 9.86332 3.75256 9.9348 3.76457L11.7954 4.07626C12.4675 4.18919 13.0308 4.51864 13.2137 5.09229C13.3964 5.66547 13.1287 6.26112 12.6454 6.74531L12.6449 6.74578L11.1995 8.20318C11.1422 8.26094 11.078 8.36976 11.0378 8.51152C10.9978 8.65233 10.9942 8.78058 11.0124 8.86345L11.0126 8.8646L11.4262 10.6675C11.5977 11.4179 11.5409 12.1619 11.0116 12.551C10.4806 12.9413 9.7549 12.7683 9.09564 12.3756L7.35149 11.3346C7.27825 11.2908 7.15246 11.2554 7.00064 11.2554C6.84993 11.2554 6.7215 11.2904 6.64349 11.3358L6.64239 11.3364L4.90168 12.3754C4.2432 12.7694 3.5184 12.9394 2.98731 12.5486C2.45845 12.1596 2.39875 11.4169 2.57081 10.6671L2.98427 8.8646L2.98453 8.86345C3.00266 8.78058 2.99911 8.65233 2.95913 8.51152C2.91888 8.36976 2.85471 8.26094 2.79742 8.20318L1.35091 6.74472C0.87071 6.26055 0.603871 5.66542 0.785136 5.09308C0.96693 4.51907 1.52917 4.18923 2.20169 4.07622L4.06077 3.76479L4.06136 3.76469C4.12952 3.75287 4.23658 3.70784 4.34728 3.62508C4.45819 3.54217 4.53226 3.45164 4.56349 3.38736L4.56506 3.38416L5.59161 1.31408L5.59202 1.31327C5.90273 0.689977 6.38635 0.228516 6.99772 0.228516Z" fill="#FFAF15"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

@ -64,6 +64,9 @@ class AppAssets {
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';
static const String rating_icon = '$svgBasePath/rating_icon.svg';
static const String doctor_calendar_icon = '$svgBasePath/doctor_calendar_icon.svg';
static const String prescription_remarks_icon = '$svgBasePath/prescription_remarks_icon.svg';
//bottom navigation//

@ -0,0 +1,144 @@
class PrescriptionDetailResponseModel {
String? address;
num? appointmentNo;
String? clinic;
dynamic companyName;
num? days;
String? doctorName;
num? doseDailyQuantity;
String? frequency;
num? frequencyNumber;
dynamic image;
dynamic imageExtension;
String? imageSRCUrl;
dynamic imageString;
String? imageThumbUrl;
String? isCovered;
String? itemDescription;
num? itemID;
String? orderDate;
num? patientID;
String? patientName;
String? phoneOffice1;
dynamic prescriptionQR;
num? prescriptionTimes;
dynamic productImage;
dynamic productImageBase64;
String? productImageString;
num? projectID;
String? projectName;
String? remarks;
String? route;
String? sKU;
num? scaleOffset;
String? startDate;
PrescriptionDetailResponseModel(
{this.address,
this.appointmentNo,
this.clinic,
this.companyName,
this.days,
this.doctorName,
this.doseDailyQuantity,
this.frequency,
this.frequencyNumber,
this.image,
this.imageExtension,
this.imageSRCUrl,
this.imageString,
this.imageThumbUrl,
this.isCovered,
this.itemDescription,
this.itemID,
this.orderDate,
this.patientID,
this.patientName,
this.phoneOffice1,
this.prescriptionQR,
this.prescriptionTimes,
this.productImage,
this.productImageBase64,
this.productImageString,
this.projectID,
this.projectName,
this.remarks,
this.route,
this.sKU,
this.scaleOffset,
this.startDate});
PrescriptionDetailResponseModel.fromJson(Map<String, dynamic> json) {
address = json['Address'];
appointmentNo = json['AppointmentNo'];
clinic = json['Clinic'];
companyName = json['CompanyName'];
days = json['Days'];
doctorName = json['DoctorName'];
doseDailyQuantity = json['DoseDailyQuantity'];
frequency = json['Frequency'];
frequencyNumber = json['FrequencyNumber'];
image = json['Image'];
imageExtension = json['ImageExtension'];
imageSRCUrl = json['ImageSRCUrl'];
imageString = json['ImageString'];
imageThumbUrl = json['ImageThumbUrl'];
isCovered = json['IsCovered'];
itemDescription = json['ItemDescription'];
itemID = json['ItemID'];
orderDate = json['OrderDate'];
patientID = json['PatientID'];
patientName = json['PatientName'];
phoneOffice1 = json['PhoneOffice1'];
prescriptionQR = json['PrescriptionQR'];
prescriptionTimes = json['PrescriptionTimes'];
productImage = json['ProductImage'];
productImageBase64 = json['ProductImageBase64'];
productImageString = json['ProductImageString'];
projectID = json['ProjectID'];
projectName = json['ProjectName'];
remarks = json['Remarks'];
route = json['Route'];
sKU = json['SKU'];
scaleOffset = json['ScaleOffset'];
startDate = json['StartDate'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['Address'] = address;
data['AppointmentNo'] = appointmentNo;
data['Clinic'] = clinic;
data['CompanyName'] = companyName;
data['Days'] = days;
data['DoctorName'] = doctorName;
data['DoseDailyQuantity'] = doseDailyQuantity;
data['Frequency'] = frequency;
data['FrequencyNumber'] = frequencyNumber;
data['Image'] = image;
data['ImageExtension'] = imageExtension;
data['ImageSRCUrl'] = imageSRCUrl;
data['ImageString'] = imageString;
data['ImageThumbUrl'] = imageThumbUrl;
data['IsCovered'] = isCovered;
data['ItemDescription'] = itemDescription;
data['ItemID'] = itemID;
data['OrderDate'] = orderDate;
data['PatientID'] = patientID;
data['PatientName'] = patientName;
data['PhoneOffice1'] = phoneOffice1;
data['PrescriptionQR'] = prescriptionQR;
data['PrescriptionTimes'] = prescriptionTimes;
data['ProductImage'] = productImage;
data['ProductImageBase64'] = productImageBase64;
data['ProductImageString'] = productImageString;
data['ProjectID'] = projectID;
data['ProjectName'] = projectName;
data['Remarks'] = remarks;
data['Route'] = route;
data['SKU'] = sKU;
data['ScaleOffset'] = scaleOffset;
data['StartDate'] = startDate;
return data;
}
}

@ -4,10 +4,13 @@ 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/features/prescriptions/models/resp_models/prescription_detail_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});
Future<Either<Failure, GenericApiModel<List<PrescriptionDetailResponseModel>>>> getPatientPrescriptionDetails({required PatientPrescriptionsResponseModel prescriptionsResponseModel});
}
class PrescriptionsRepoImp implements PrescriptionsRepo {
@ -72,4 +75,67 @@ class PrescriptionsRepoImp implements PrescriptionsRepo {
return Left(UnknownFailure(e.toString()));
}
}
@override
Future<Either<Failure, GenericApiModel<List<PrescriptionDetailResponseModel>>>> getPatientPrescriptionDetails({required PatientPrescriptionsResponseModel prescriptionsResponseModel}) async {
final mapDevice = {
"AppointmentNo": prescriptionsResponseModel.appointmentNo.toString(),
"SetupID": prescriptionsResponseModel.setupID,
"EpisodeID": prescriptionsResponseModel.episodeID.toString(),
"ClinicID": prescriptionsResponseModel.clinicID.toString(),
"ProjectID": prescriptionsResponseModel.projectID.toString(),
"DischargeNo": prescriptionsResponseModel.dischargeNo.toString(),
"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<PrescriptionDetailResponseModel>>? apiResponse;
Failure? failure;
await apiClient.post(
prescriptionsResponseModel.isInOutPatient! ? GET_PRESCRIPTION_REPORT_ENH : GET_PRESCRIPTION_REPORT,
body: mapDevice,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus}) {
try {
final list = prescriptionsResponseModel.isInOutPatient! ? response['ListPRM'] : response['INP_GetPrescriptionReport_List'];
if (list == null || list.isEmpty) {
throw Exception("prescription list is empty");
}
final prescriptionOrders = list.map((item) => PrescriptionDetailResponseModel.fromJson(item as Map<String, dynamic>)).toList().cast<PrescriptionDetailResponseModel>();
apiResponse = GenericApiModel<List<PrescriptionDetailResponseModel>>(
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()));
}
}
}

@ -1,21 +1,26 @@
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/models/resp_models/prescription_detail_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;
bool isPrescriptionsDetailsLoading = false;
PrescriptionsRepo prescriptionsRepo;
ErrorHandlerService errorHandlerService;
// Prescription Orders Lists
List<PatientPrescriptionsResponseModel> patientPrescriptionOrders = [];
List<PrescriptionsList> patientPrescriptionOrdersByClinic = [];
List<PrescriptionsList> patientPrescriptionOrdersByHospital = [];
List<PrescriptionsList> patientPrescriptionOrdersViewList = [];
// Prescription Details List
List<PrescriptionDetailResponseModel> prescriptionDetailsList = [];
bool isSortByClinic = true;
PrescriptionsViewModel({required this.prescriptionsRepo, required this.errorHandlerService});
@ -26,11 +31,18 @@ class PrescriptionsViewModel extends ChangeNotifier {
patientPrescriptionOrdersByHospital.clear();
patientPrescriptionOrdersViewList.clear();
isPrescriptionsOrdersLoading = true;
isPrescriptionsDetailsLoading = true;
isSortByClinic = true;
getPatientPrescriptionOrders();
notifyListeners();
}
setPrescriptionsDetailsLoading() {
isPrescriptionsDetailsLoading = true;
prescriptionDetailsList.clear();
notifyListeners();
}
setIsSortByClinic(bool value) {
isSortByClinic = value;
if (isSortByClinic) {
@ -79,4 +91,24 @@ class PrescriptionsViewModel extends ChangeNotifier {
},
);
}
Future<void> getPrescriptionDetails(PatientPrescriptionsResponseModel prescriptionsResponseModel, {Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await prescriptionsRepo.getPatientPrescriptionDetails(prescriptionsResponseModel: prescriptionsResponseModel);
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) {
prescriptionDetailsList = apiResponse.data!;
isPrescriptionsDetailsLoading = false;
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
}
},
);
}
}

@ -0,0 +1,313 @@
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/models/resp_models/patient_prescriptions_response_model.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 PrescriptionDetailPage extends StatefulWidget {
PrescriptionDetailPage({super.key, required this.prescriptionsResponseModel});
PatientPrescriptionsResponseModel prescriptionsResponseModel;
@override
State<PrescriptionDetailPage> createState() => _PrescriptionDetailPageState();
}
class _PrescriptionDetailPageState extends State<PrescriptionDetailPage> {
late PrescriptionsViewModel prescriptionsViewModel;
@override
void initState() {
scheduleMicrotask(() {
prescriptionsViewModel.getPrescriptionDetails(widget.prescriptionsResponseModel);
});
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: SingleChildScrollView(
child: Consumer<PrescriptionsViewModel>(builder: (context, prescriptionVM, child) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.prescriptions.tr(context: context).toText24(isBold: true).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 24.h),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.h,
hasShadow: true,
),
child: Padding(
padding: EdgeInsets.all(16.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisSize: MainAxisSize.min,
children: [
Image.network(
widget.prescriptionsResponseModel.doctorImageURL!,
width: 24.h,
height: 24.h,
fit: BoxFit.fill,
).circle(100),
SizedBox(width: 8.h),
Expanded(child: widget.prescriptionsResponseModel.doctorName!.toText16(isBold: true)),
],
),
SizedBox(height: 16.h),
Wrap(
direction: Axis.horizontal,
spacing: 6.h,
runSpacing: 6.h,
children: [
Row(
mainAxisSize: MainAxisSize.min,
children: [
CustomButton(
icon: AppAssets.doctor_calendar_icon,
iconColor: AppColors.textColor,
iconSize: 13.h,
text: DateUtil.formatDateToDate(DateUtil.convertStringToDate(widget.prescriptionsResponseModel.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: 30.h,
),
],
),
Row(
mainAxisSize: MainAxisSize.min,
children: [
CustomButton(
text: widget.prescriptionsResponseModel.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: 30.h,
),
],
),
Row(
mainAxisSize: MainAxisSize.min,
children: [
CustomButton(
icon: AppAssets.rating_icon,
iconColor: AppColors.ratingColorYellow,
iconSize: 13.h,
text: "Rating: ${widget.prescriptionsResponseModel.decimalDoctorRate}",
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: 30.h,
),
],
),
Row(
mainAxisSize: MainAxisSize.min,
children: [
CustomButton(
text: widget.prescriptionsResponseModel.name!,
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: 30.h,
),
],
),
],
),
],
),
),
).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 16.h),
ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: prescriptionVM.isPrescriptionsDetailsLoading ? 5 : prescriptionVM.prescriptionDetailsList.length,
itemBuilder: (context, index) {
return prescriptionVM.isPrescriptionsDetailsLoading
? 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: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.all(16.h),
child: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Image.network(
prescriptionVM.prescriptionDetailsList[index].imageSRCUrl!,
width: 60.h,
height: 60.h,
fit: BoxFit.fill,
).circle(100),
SizedBox(width: 8.h),
Expanded(
child: prescriptionVM.prescriptionDetailsList[index].itemDescription!.toText16(isBold: true, maxlines: 2),
),
],
),
SizedBox(height: 16.h),
Wrap(
direction: Axis.horizontal,
spacing: 6.h,
runSpacing: 6.h,
children: [
Row(
mainAxisSize: MainAxisSize.min,
children: [
CustomButton(
text: "${LocaleKeys.route.tr(context: context)}: ${prescriptionVM.prescriptionDetailsList[index].route}",
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: 30.h,
),
],
),
Row(
mainAxisSize: MainAxisSize.min,
children: [
CustomButton(
text: "${LocaleKeys.frequency.tr(context: context)}: ${prescriptionVM.prescriptionDetailsList[index].frequency}",
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: 30.h,
),
],
),
Row(
mainAxisSize: MainAxisSize.min,
children: [
CustomButton(
text: "${LocaleKeys.dailyDoses.tr(context: context)}: ${prescriptionVM.prescriptionDetailsList[index].doseDailyQuantity}",
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: 30.h,
),
],
),
Row(
mainAxisSize: MainAxisSize.min,
children: [
CustomButton(
text: "${LocaleKeys.days.tr(context: context)}: ${prescriptionVM.prescriptionDetailsList[index].days}",
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: 30.h,
),
],
),
],
),
SizedBox(height: 8.h),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Utils.buildSvgWithAssets(icon: AppAssets.prescription_remarks_icon, width: 18.h, height: 18.h),
SizedBox(width: 9.h),
Expanded(child: "${LocaleKeys.remarks.tr(context: context)}: ${prescriptionVM.prescriptionDetailsList[index].remarks!}".toText10(isBold: true)),
],
)
],
),
),
)
],
),
),
),
),
);
},
).paddingSymmetrical(24.h, 0.h),
],
);
}),
),
);
}
}

@ -11,9 +11,11 @@ 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/presentation/prescriptions/prescription_detail_page.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/shimmer/movies_shimmer_widget.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
import 'package:provider/provider.dart';
class PrescriptionsListPage extends StatefulWidget {
@ -45,248 +47,252 @@ class _PrescriptionsListPageState extends State<PrescriptionsListPage> {
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)
],
),
body: SingleChildScrollView(
child: Consumer<PrescriptionsViewModel>(builder: (context, model, child) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.prescriptions.tr(context: context).toText24(isBold: true).paddingSymmetrical(24.h, 0.h),
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,
),
],
).paddingSymmetrical(24.h, 0.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),
),
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: AppColors.greyColor,
borderColor: AppColors.greyColor,
textColor: AppColors.blackColor,
fontSize: 12,
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: 8,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 24.h,
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),
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,
),
),
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,
),
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(),
),
],
),
).onPress(() {
model.setPrescriptionsDetailsLoading();
Navigator.of(context).push(
FadePage(
page: PrescriptionDetailPage(prescriptionsResponseModel: prescription),
),
);
}),
),
],
),
SizedBox(height: 12.h),
Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h),
SizedBox(height: 12.h),
],
);
}).toList(),
],
),
)
: SizedBox.shrink(),
),
],
),
),
),
),
);
},
),
],
);
}),
),
),
);
},
).paddingSymmetrical(24.h, 0.h),
],
);
}),
),
);
}

@ -32,6 +32,7 @@ class AppColors {
static const Color borderOnlyColor = Color(0xFF2E3039);
static const Color dividerColor = Color(0xFFD2D2D2);
static const Color warningColorYellow = Color(0xFFF4A308);
static const Color ratingColorYellow = Color(0xFFFFAF15);
//Chips
static const Color successColor = Color(0xff18C273);

Loading…
Cancel
Save