Sickleave implementation done.
							parent
							
								
									b240293064
								
							
						
					
					
						commit
						de717edfe8
					
				| @ -0,0 +1,176 @@ | ||||
| class PatientSickLeavesResponseModel { | ||||
|   String? setupID; | ||||
|   int? projectID; | ||||
|   int? patientID; | ||||
|   int? patientType; | ||||
|   int? clinicID; | ||||
|   int? doctorID; | ||||
|   int? requestNo; | ||||
|   String? requestDate; | ||||
|   int? sickLeaveDays; | ||||
|   int? appointmentNo; | ||||
|   int? admissionNo; | ||||
|   dynamic reportDate; | ||||
|   num? actualDoctorRate; | ||||
|   String? appointmentDate; | ||||
|   String? clinicName; | ||||
|   double? decimalDoctorRate; | ||||
|   String? doctorImageURL; | ||||
|   String? doctorName; | ||||
|   num? doctorRate; | ||||
|   num? doctorStarsRate; | ||||
|   String? doctorTitle; | ||||
|   int? employeeID; | ||||
|   String? endDate; | ||||
|   int? gender; | ||||
|   String? genderDescription; | ||||
|   bool? isActiveDoctorProfile; | ||||
|   bool? isDoctorAllowVedioCall; | ||||
|   bool? isExecludeDoctor; | ||||
|   bool? isInOutPatient; | ||||
|   String? isInOutPatientDescription; | ||||
|   String? isInOutPatientDescriptionN; | ||||
|   bool? isLiveCareAppointment; | ||||
|   dynamic medicalDirectorApprovedStatus; | ||||
|   int? noOfPatientsRate; | ||||
|   dynamic patientName; | ||||
|   String? projectName; | ||||
|   String? qR; | ||||
|   List<String>? speciality; | ||||
|   String? startDate; | ||||
|   int? status; | ||||
|   String? strRequestDate; | ||||
| 
 | ||||
|   PatientSickLeavesResponseModel( | ||||
|       {this.setupID, | ||||
|       this.projectID, | ||||
|       this.patientID, | ||||
|       this.patientType, | ||||
|       this.clinicID, | ||||
|       this.doctorID, | ||||
|       this.requestNo, | ||||
|       this.requestDate, | ||||
|       this.sickLeaveDays, | ||||
|       this.appointmentNo, | ||||
|       this.admissionNo, | ||||
|       this.reportDate, | ||||
|       this.actualDoctorRate, | ||||
|       this.appointmentDate, | ||||
|       this.clinicName, | ||||
|       this.decimalDoctorRate, | ||||
|       this.doctorImageURL, | ||||
|       this.doctorName, | ||||
|       this.doctorRate, | ||||
|       this.doctorStarsRate, | ||||
|       this.doctorTitle, | ||||
|       this.employeeID, | ||||
|       this.endDate, | ||||
|       this.gender, | ||||
|       this.genderDescription, | ||||
|       this.isActiveDoctorProfile, | ||||
|       this.isDoctorAllowVedioCall, | ||||
|       this.isExecludeDoctor, | ||||
|       this.isInOutPatient, | ||||
|       this.isInOutPatientDescription, | ||||
|       this.isInOutPatientDescriptionN, | ||||
|       this.isLiveCareAppointment, | ||||
|       this.medicalDirectorApprovedStatus, | ||||
|       this.noOfPatientsRate, | ||||
|       this.patientName, | ||||
|       this.projectName, | ||||
|       this.qR, | ||||
|       this.speciality, | ||||
|       this.startDate, | ||||
|       this.status, | ||||
|       this.strRequestDate}); | ||||
| 
 | ||||
|   PatientSickLeavesResponseModel.fromJson(Map<String, dynamic> json) { | ||||
|     setupID = json['SetupID']; | ||||
|     projectID = json['ProjectID']; | ||||
|     patientID = json['PatientID']; | ||||
|     patientType = json['PatientType']; | ||||
|     clinicID = json['ClinicID']; | ||||
|     doctorID = json['DoctorID']; | ||||
|     requestNo = json['RequestNo']; | ||||
|     requestDate = json['RequestDate']; | ||||
|     sickLeaveDays = json['SickLeaveDays']; | ||||
|     appointmentNo = json['AppointmentNo']; | ||||
|     admissionNo = json['AdmissionNo']; | ||||
|     reportDate = json['ReportDate']; | ||||
|     actualDoctorRate = json['ActualDoctorRate']; | ||||
|     appointmentDate = json['AppointmentDate']; | ||||
|     clinicName = json['ClinicName']; | ||||
|     decimalDoctorRate = json['DecimalDoctorRate']; | ||||
|     doctorImageURL = json['DoctorImageURL']; | ||||
|     doctorName = json['DoctorName']; | ||||
|     doctorRate = json['DoctorRate']; | ||||
|     doctorStarsRate = json['DoctorStarsRate']; | ||||
|     doctorTitle = json['DoctorTitle']; | ||||
|     employeeID = json['EmployeeID']; | ||||
|     endDate = json['EndDate']; | ||||
|     gender = json['Gender']; | ||||
|     genderDescription = json['GenderDescription']; | ||||
|     isActiveDoctorProfile = json['IsActiveDoctorProfile']; | ||||
|     isDoctorAllowVedioCall = json['IsDoctorAllowVedioCall']; | ||||
|     isExecludeDoctor = json['IsExecludeDoctor']; | ||||
|     isInOutPatient = json['IsInOutPatient']; | ||||
|     isInOutPatientDescription = json['IsInOutPatientDescription']; | ||||
|     isInOutPatientDescriptionN = json['IsInOutPatientDescriptionN']; | ||||
|     isLiveCareAppointment = json['IsLiveCareAppointment']; | ||||
|     medicalDirectorApprovedStatus = json['MedicalDirectorApprovedStatus']; | ||||
|     noOfPatientsRate = json['NoOfPatientsRate']; | ||||
|     patientName = json['PatientName']; | ||||
|     projectName = json['ProjectName']; | ||||
|     qR = json['QR']; | ||||
|     speciality = json['Speciality'].cast<String>(); | ||||
|     startDate = json['StartDate']; | ||||
|     status = json['Status']; | ||||
|     strRequestDate = json['StrRequestDate']; | ||||
|   } | ||||
| 
 | ||||
|   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['PatientType'] = this.patientType; | ||||
|     data['ClinicID'] = this.clinicID; | ||||
|     data['DoctorID'] = this.doctorID; | ||||
|     data['RequestNo'] = this.requestNo; | ||||
|     data['RequestDate'] = this.requestDate; | ||||
|     data['SickLeaveDays'] = this.sickLeaveDays; | ||||
|     data['AppointmentNo'] = this.appointmentNo; | ||||
|     data['AdmissionNo'] = this.admissionNo; | ||||
|     data['ReportDate'] = this.reportDate; | ||||
|     data['ActualDoctorRate'] = this.actualDoctorRate; | ||||
|     data['AppointmentDate'] = this.appointmentDate; | ||||
|     data['ClinicName'] = this.clinicName; | ||||
|     data['DecimalDoctorRate'] = this.decimalDoctorRate; | ||||
|     data['DoctorImageURL'] = this.doctorImageURL; | ||||
|     data['DoctorName'] = this.doctorName; | ||||
|     data['DoctorRate'] = this.doctorRate; | ||||
|     data['DoctorStarsRate'] = this.doctorStarsRate; | ||||
|     data['DoctorTitle'] = this.doctorTitle; | ||||
|     data['EmployeeID'] = this.employeeID; | ||||
|     data['EndDate'] = this.endDate; | ||||
|     data['Gender'] = this.gender; | ||||
|     data['GenderDescription'] = this.genderDescription; | ||||
|     data['IsActiveDoctorProfile'] = this.isActiveDoctorProfile; | ||||
|     data['IsDoctorAllowVedioCall'] = this.isDoctorAllowVedioCall; | ||||
|     data['IsExecludeDoctor'] = this.isExecludeDoctor; | ||||
|     data['IsInOutPatient'] = this.isInOutPatient; | ||||
|     data['IsInOutPatientDescription'] = this.isInOutPatientDescription; | ||||
|     data['IsInOutPatientDescriptionN'] = this.isInOutPatientDescriptionN; | ||||
|     data['IsLiveCareAppointment'] = this.isLiveCareAppointment; | ||||
|     data['MedicalDirectorApprovedStatus'] = this.medicalDirectorApprovedStatus; | ||||
|     data['NoOfPatientsRate'] = this.noOfPatientsRate; | ||||
|     data['PatientName'] = this.patientName; | ||||
|     data['ProjectName'] = this.projectName; | ||||
|     data['QR'] = this.qR; | ||||
|     data['Speciality'] = this.speciality; | ||||
|     data['StartDate'] = this.startDate; | ||||
|     data['Status'] = this.status; | ||||
|     data['StrRequestDate'] = this.strRequestDate; | ||||
|     return data; | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,88 @@ | ||||
| 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/utils/size_utils.dart'; | ||||
| import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; | ||||
| import 'package:hmg_patient_app_new/features/medical_file/medical_file_view_model.dart'; | ||||
| import 'package:hmg_patient_app_new/features/medical_file/models/patient_sickleave_response_model.dart'; | ||||
| import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; | ||||
| import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.dart'; | ||||
| import 'package:hmg_patient_app_new/theme/colors.dart'; | ||||
| import 'package:provider/provider.dart'; | ||||
| 
 | ||||
| import 'widgets/patient_sick_leave_card.dart'; | ||||
| 
 | ||||
| class PatientSickleavesListPage extends StatefulWidget { | ||||
|   const PatientSickleavesListPage({super.key}); | ||||
| 
 | ||||
|   @override | ||||
|   State<PatientSickleavesListPage> createState() => _PatientSickleavesListPageState(); | ||||
| } | ||||
| 
 | ||||
| class _PatientSickleavesListPageState extends State<PatientSickleavesListPage> { | ||||
|   late MedicalFileViewModel medicalFileViewModel; | ||||
| 
 | ||||
|   @override | ||||
|   void initState() { | ||||
|     scheduleMicrotask(() { | ||||
|       medicalFileViewModel.setIsPatientSickLeaveListLoading(true); | ||||
|       medicalFileViewModel.getPatientSickLeaveList(onError: (error) { | ||||
|         Navigator.of(context).pop(); | ||||
|         Navigator.of(context).pop(); | ||||
|       }); | ||||
|     }); | ||||
|     super.initState(); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     medicalFileViewModel = Provider.of<MedicalFileViewModel>(context, listen: false); | ||||
|     return Scaffold( | ||||
|       backgroundColor: AppColors.bgScaffoldColor, | ||||
|       body: CollapsingListView( | ||||
|         title: "${LocaleKeys.sick.tr(context: context)} ${LocaleKeys.sickSubtitle.tr(context: context)}", | ||||
|         child: SingleChildScrollView( | ||||
|           child: Consumer<MedicalFileViewModel>(builder: (context, medicalFileVM, child) { | ||||
|             return Column( | ||||
|               crossAxisAlignment: CrossAxisAlignment.start, | ||||
|               children: [ | ||||
|                 ListView.separated( | ||||
|                   scrollDirection: Axis.vertical, | ||||
|                   itemCount: medicalFileVM.isPatientSickLeaveListLoading ? 3 : medicalFileVM.patientSickLeaveList.length, | ||||
|                   shrinkWrap: true, | ||||
|                   physics: NeverScrollableScrollPhysics(), | ||||
|                   itemBuilder: (context, index) { | ||||
|                     return medicalFileVM.isPatientSickLeaveListLoading | ||||
|                         ? PatientSickLeaveCard( | ||||
|                             patientSickLeavesResponseModel: PatientSickLeavesResponseModel(), | ||||
|                             isLoading: true, | ||||
|                           ).paddingSymmetrical(24.h, 0.0) | ||||
|                         : medicalFileVM.patientSickLeaveList.isNotEmpty | ||||
|                             ? AnimationConfiguration.staggeredList( | ||||
|                                 position: index, | ||||
|                                 duration: const Duration(milliseconds: 1000), | ||||
|                                 child: SlideAnimation( | ||||
|                                   verticalOffset: 100.0, | ||||
|                                   child: FadeInAnimation( | ||||
|                                     child: PatientSickLeaveCard( | ||||
|                                       patientSickLeavesResponseModel: medicalFileVM.patientSickLeaveList.first, | ||||
|                                       isLoading: false, | ||||
|                                     ).paddingSymmetrical(24.h, 0.0), | ||||
|                                   ), | ||||
|                                 ), | ||||
|                               ) | ||||
|                             : SizedBox.shrink(); | ||||
|                   }, | ||||
|                   separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 8.h), | ||||
|                 ), | ||||
|                 SizedBox(height: 60.h), | ||||
|               ], | ||||
|             ); | ||||
|           }), | ||||
|         ), | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,191 @@ | ||||
| import 'package:easy_localization/easy_localization.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:hmg_patient_app_new/core/app_assets.dart'; | ||||
| import 'package:hmg_patient_app_new/core/app_state.dart'; | ||||
| import 'package:hmg_patient_app_new/core/dependencies.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/medical_file/medical_file_view_model.dart'; | ||||
| import 'package:hmg_patient_app_new/features/medical_file/models/patient_sickleave_response_model.dart'; | ||||
| import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; | ||||
| import 'package:hmg_patient_app_new/presentation/medical_file/patient_sickleaves_list_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/chip/app_custom_chip_widget.dart'; | ||||
| import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart'; | ||||
| import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; | ||||
| import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart'; | ||||
| import 'package:open_filex/open_filex.dart'; | ||||
| import 'package:provider/provider.dart'; | ||||
| 
 | ||||
| class PatientSickLeaveCard extends StatelessWidget { | ||||
|   PatientSickLeaveCard({super.key, required this.patientSickLeavesResponseModel, this.isLoading = false}); | ||||
| 
 | ||||
|   late MedicalFileViewModel medicalFileViewModel; | ||||
|   PatientSickLeavesResponseModel patientSickLeavesResponseModel; | ||||
|   bool isLoading; | ||||
| 
 | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     AppState _appState = getIt.get<AppState>(); | ||||
|     medicalFileViewModel = Provider.of<MedicalFileViewModel>(context, listen: false); | ||||
|     return Container( | ||||
|       decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24, hasShadow: true), | ||||
|       child: Padding( | ||||
|         padding: EdgeInsets.all(16.h), | ||||
|         child: Column( | ||||
|           crossAxisAlignment: CrossAxisAlignment.start, | ||||
|           children: [ | ||||
|             Row( | ||||
|               mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|               children: [ | ||||
|                 "${LocaleKeys.sick.tr(context: context)} ${LocaleKeys.sickSubtitle.tr(context: context)}".toText16(isBold: true), | ||||
|                 AppCustomChipWidget( | ||||
|                   labelText: isLoading ? "" : getStatusText(context), | ||||
|                   backgroundColor: getStatusColor().withOpacity(0.15), | ||||
|                   textColor: getStatusColor(), | ||||
|                 ).toShimmer2(isShow: isLoading, width: 100.h), | ||||
|               ], | ||||
|             ), | ||||
|             SizedBox(height: 16.h), | ||||
|             Row( | ||||
|               crossAxisAlignment: CrossAxisAlignment.start, | ||||
|               children: [ | ||||
|                 Image.network( | ||||
|                   isLoading ? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png" : patientSickLeavesResponseModel.doctorImageURL!, | ||||
|                   width: 30.h, | ||||
|                   height: 30.h, | ||||
|                   fit: BoxFit.fill, | ||||
|                 ).circle(100).toShimmer2(isShow: isLoading), | ||||
|                 SizedBox(width: 16.h), | ||||
|                 Expanded( | ||||
|                   child: Column( | ||||
|                     crossAxisAlignment: CrossAxisAlignment.start, | ||||
|                     children: [ | ||||
|                       (isLoading ? "" : patientSickLeavesResponseModel.doctorName!).toText16(isBold: true).toShimmer2(isShow: isLoading), | ||||
|                       SizedBox(height: 8.h), | ||||
|                       Wrap( | ||||
|                         direction: Axis.horizontal, | ||||
|                         spacing: 3.h, | ||||
|                         runSpacing: 4.h, | ||||
|                         children: [ | ||||
|                           AppCustomChipWidget( | ||||
|                             icon: AppAssets.doctor_calendar_icon, | ||||
|                             labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(patientSickLeavesResponseModel.appointmentDate), false), | ||||
|                           ).toShimmer2(isShow: isLoading), | ||||
|                           AppCustomChipWidget(labelText: isLoading ? "Pending Activation" : patientSickLeavesResponseModel.clinicName!).toShimmer2(isShow: isLoading), | ||||
|                         ], | ||||
|                       ), | ||||
|                     ], | ||||
|                   ), | ||||
|                 ), | ||||
|               ], | ||||
|             ), | ||||
|             SizedBox(height: 16.h), | ||||
|             Row( | ||||
|               children: [ | ||||
|                 isLoading | ||||
|                     ? Container().toShimmer2(isShow: true, height: 40.h, width: 100.h, radius: 12.h) | ||||
|                     : Expanded( | ||||
|                         flex: 6, | ||||
|                         child: CustomButton( | ||||
|                           text: "Download Report".needTranslation, | ||||
|                           onPressed: () async { | ||||
|                             LoaderBottomSheet.showLoader(); | ||||
|                             await medicalFileViewModel.getPatientSickLeavePDF(patientSickLeavesResponseModel, _appState.getAuthenticatedUser()!).then((val) async { | ||||
|                               LoaderBottomSheet.hideLoader(); | ||||
|                               if (medicalFileViewModel.patientSickLeavePDFBase64.isNotEmpty) { | ||||
|                                 String path = await Utils.createFileFromString(medicalFileViewModel.patientSickLeavePDFBase64, "pdf"); | ||||
|                                 try { | ||||
|                                   OpenFilex.open(path); | ||||
|                                 } catch (ex) { | ||||
|                                   showCommonBottomSheetWithoutHeight( | ||||
|                                     context, | ||||
|                                     child: Utils.getErrorWidget(loadingText: "Cannot open file".needTranslation), | ||||
|                                     callBackFunc: () {}, | ||||
|                                     isFullScreen: false, | ||||
|                                     isCloseButtonVisible: true, | ||||
|                                   ); | ||||
|                                 } | ||||
|                               } | ||||
|                             }); | ||||
|                           }, | ||||
|                           backgroundColor: AppColors.secondaryLightRedColor, | ||||
|                           borderColor: AppColors.secondaryLightRedColor, | ||||
|                           textColor: AppColors.primaryRedColor, | ||||
|                           fontSize: 14, | ||||
|                           fontWeight: FontWeight.w500, | ||||
|                           borderRadius: 12, | ||||
|                           padding: EdgeInsets.fromLTRB(10, 0, 10, 0), | ||||
|                           height: 40.h, | ||||
|                           icon: AppAssets.download, | ||||
|                           iconColor: AppColors.primaryRedColor, | ||||
|                           iconSize: 14.h, | ||||
|                         ).toShimmer2(isShow: isLoading), | ||||
|                       ), | ||||
|                 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(10.h), | ||||
|                       child: Utils.buildSvgWithAssets( | ||||
|                         icon: AppAssets.forward_arrow_icon, | ||||
|                         width: 10.h, | ||||
|                         height: 10.h, | ||||
|                         fit: BoxFit.contain, | ||||
|                       ), | ||||
|                     ), | ||||
|                   ).toShimmer2(isShow: isLoading).onPress(() { | ||||
|                     Navigator.of(context).push( | ||||
|                       FadePage( | ||||
|                         page: PatientSickleavesListPage(), | ||||
|                       ), | ||||
|                     ); | ||||
|                   }), | ||||
|                 ), | ||||
|               ], | ||||
|             ), | ||||
|           ], | ||||
|         ), | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   String getStatusText(BuildContext context) { | ||||
|     String statusText = ""; | ||||
|     if (patientSickLeavesResponseModel.status == 1) { | ||||
|       statusText = LocaleKeys.pendingActivation.tr(context: context); | ||||
|     } else if (patientSickLeavesResponseModel.status == 2) { | ||||
|       statusText = LocaleKeys.ready.tr(context: context); | ||||
|     } else if (patientSickLeavesResponseModel.status == 3) { | ||||
|       statusText = LocaleKeys.awaitingApproval.tr(context: context); | ||||
|     } else { | ||||
|       statusText = ""; | ||||
|     } | ||||
|     return statusText; | ||||
|   } | ||||
| 
 | ||||
|   Color getStatusColor() { | ||||
|     Color statusColor = Colors.white; | ||||
|     if (patientSickLeavesResponseModel.status == 1) { | ||||
|       statusColor = Color(0xffCC9B14); | ||||
|     } else if (patientSickLeavesResponseModel.status == 2) { | ||||
|       statusColor = Color(0xff359846); | ||||
|     } else if (patientSickLeavesResponseModel.status == 3) { | ||||
|       statusColor = Color(0xffD02127); | ||||
|     } else { | ||||
|       statusColor = Colors.white; | ||||
|     } | ||||
|     return statusColor; | ||||
|   } | ||||
| } | ||||
					Loading…
					
					
				
		Reference in New Issue
	
	 Haroon Amjad
						Haroon Amjad