diff --git a/lib/config/config.dart b/lib/config/config.dart index cb04fc46..71bdbe45 100644 --- a/lib/config/config.dart +++ b/lib/config/config.dart @@ -369,7 +369,8 @@ const GET_PATIENT_CLINIC = 'Services/DoctorApplication.svc/REST/GetPatientCondit ///Pharmacy Intervention API's const GET_MEDICINE_WITH_INTERVAL = 'Services/DoctorApplication.svc/REST/MedicineWithInterventionAccessLevel3'; -const IS_INFECTIOUS_DISEASE = 'Services/DoctorApplication.svc/REST/IsInfectiousDiseasesConsultant'; +const IS_INFECTIOUS_DISEASE_CONSULTANT = 'Services/DoctorApplication.svc/REST/IsInfectiousDiseasesConsultant'; +const IS_INFECTIOUS_DISEASE_PENDING = 'Services/DoctorApplication.svc/REST/IsInterventionAccessLevel3Pending'; const INFECTIOUS_HISTORY = 'Services/DoctorApplication.svc/REST/InterventionHistory'; const UPDATE_INFECTIOUS_STATUS = 'Services/DoctorApplication.svc/REST/UpdateInterventionStatus'; diff --git a/lib/config/localized_values.dart b/lib/config/localized_values.dart index 93e20fdd..2f2cd4c9 100644 --- a/lib/config/localized_values.dart +++ b/lib/config/localized_values.dart @@ -1234,6 +1234,12 @@ const Map> localizedValues = { "ar": "هل أنت متأكد من أنك تريد حذف التشخيص" }, "activate": {"en": "Activate", "ar":"فعل"}, + "noInterventionFound": {"en": "No Intervention Found", "ar":"لم يتم العثور على تدخل"}, + "interventionRejectedSuccessfully": {"en": "Intervention Rejected Successfully", "ar":"رفض التدخل بنجاح"}, + "interventionAcceptedSuccessfully": {"en": "Intervention Accepted Successfully", "ar":"تم قبول التدخل بنجاح"}, + "dateFromCanNotBeEmpty": {"en": "Date From Can Not Be Empty", "ar":"التاريخ من لا يمكن أن يكون فارغا"}, + "dateToCanNotBeEmpty": {"en": "Date To Can Not Be Empty", "ar":"التاريخ إلى لا يمكن أن يكون فارغا"}, + "commentedBy": {"en": "Commented By", "ar":"معلق عليها"}, "unableToPerformTheAction": {"en": "Unable To Perform The Action", "ar":"فعل"}, "pharmacyRemarks": {"en": "Pharmacy Remarks", "ar":"ملاحظات الصيدلة"}, "authorizedBy": {"en": "Authorized By", "ar":"مرخص من قبل"}, @@ -1244,5 +1250,6 @@ const Map> localizedValues = { "diagnosisAlreadyResolved": {"en": "Diagnosis Already Resolved", "ar":"تم حل التشخيص بالفعل"}, "selectReaction": {"en": "Select Reaction", "ar":"حدد رد الفعل"}, "progressNoteCanNotBeEmpty": {"en": "Progress Note Can Not Be Empty", "ar":"تعذر تنفيذ الإجراء"}, + "youHavePendingInterventions": {"en": "You Have Pending Interventions. That need your attention", "ar":"لديك تدخلات معلقة. التي تحتاج إلى اهتمامك"}, }; diff --git a/lib/core/viewModel/dashboard_view_model.dart b/lib/core/viewModel/dashboard_view_model.dart index cc9ae0b6..6485448a 100644 --- a/lib/core/viewModel/dashboard_view_model.dart +++ b/lib/core/viewModel/dashboard_view_model.dart @@ -36,20 +36,29 @@ class DashboardViewModel extends BaseViewModel { bool isInfectiousDiseaseConsultant = false; + bool isInfectiousDiseasePending = false; + List get specialClinicalCareList => _specialClinicsService.specialClinicalCareList; Future getInfectiousDiseaseConsultantStatus() async { - setState(ViewState.BusyLocal); bool result = await _service.getInfectiousDiseaseConsultantStatus(); if (_service.hasError) { error = _service.error; - setState(ViewState.ErrorLocal); return; } isInfectiousDiseaseConsultant = result; print('the result is ${result}'); - setState(ViewState.Idle); + } + + Future getPendingInfectiousDiseaseStatus() async { + bool result = await _service.getPendingInterventionDiseaseStatus(); + if (_service.hasError) { + error = _service.error; + return; + } + isInfectiousDiseasePending = result; + print('the result is ${result}'); } Future startHomeScreenServices(ProjectViewModel projectsProvider, @@ -58,12 +67,13 @@ class DashboardViewModel extends BaseViewModel { await getDoctorProfile(isGetProfile: true); final results = await Future.wait([ + getInfectiousDiseaseConsultantStatus(), + getPendingInfectiousDiseaseStatus(), projectsProvider.getDoctorClinicsList(), _dashboardService.getDashboard(), _dashboardService.checkDoctorHasLiveCare(), _specialClinicsService.getSpecialClinicalCareList(), _dashboardService.checkDoctorHasRadiologyFindings(), - getInfectiousDiseaseConsultantStatus() ]); if (_dashboardService.hasError) { diff --git a/lib/screens/home/home_screen.dart b/lib/screens/home/home_screen.dart index e2700987..3977673d 100644 --- a/lib/screens/home/home_screen.dart +++ b/lib/screens/home/home_screen.dart @@ -78,16 +78,24 @@ class _HomeScreenState extends State { model .startHomeScreenServices(projectsProvider, authenticationViewModel) .then((value) { - if (model.radiologyCriticalFindingModel != null) { - print("onModelReady radiologyCriticalFindingModel!!!"); - // showRadiologyFindingDialog(model); - } else { - print("onModelReady radiologyCriticalFindingModel EMPTYYYY!!!"); - } + WidgetsBinding.instance.addPostFrameCallback((_) async { + if (model.radiologyCriticalFindingModel != null) { + print("onModelReady radiologyCriticalFindingModel!!!"); + await showRadiologyFindingDialog(model); + if (model.isInfectiousDiseasePending) { + showPendingInfectiousDiseaseDialog(model); + } + } else { + if (model.isInfectiousDiseasePending) { + showPendingInfectiousDiseaseDialog(model); + } + } + }); }); }, builder: (_, model, w) => AppScaffold( baseViewModel: model, + isLoading: model.state == ViewState.BusyLocal, isShowAppBar: false, body: ListView(children: [ Column(children: [ @@ -347,16 +355,30 @@ class _HomeScreenState extends State { ); } - showRadiologyFindingDialog(DashboardViewModel model) { - Utils.showConfirmationDialog( - context, model.radiologyCriticalFindingModel!.notificationMesssage!, + showRadiologyFindingDialog(DashboardViewModel model) async{ + await Utils.showConfirmationDialog( + context, model.radiologyCriticalFindingModel?.notificationMesssage ??'test radiology', () async { - Navigator.of(context).pop(); GifLoaderDialogUtils.showMyDialog(context); await model.acknowledgeRadiologyCriticalFinding( - model.radiologyCriticalFindingModel!.invoiceNo.toString(), - model.radiologyCriticalFindingModel!.invoiceLineItemNo.toString()); + model.radiologyCriticalFindingModel?.invoiceNo?.toString() ?? '', + model.radiologyCriticalFindingModel?.invoiceLineItemNo?.toString() ?? ''); GifLoaderDialogUtils.hideDialog(context); + Navigator.of(context).pop(); + }, isShowCancelButton: false); + } + + showPendingInfectiousDiseaseDialog(DashboardViewModel model) { + Utils.showConfirmationDialog( + context, TranslationBase.of(context).youHavePendingInterventions, + () async { + Navigator.pop(context); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => PharmacyIntervention(), + settings: RouteSettings(name: 'PharmacyIntervention'), + )); }, isShowCancelButton: false); } @@ -467,7 +489,7 @@ class _HomeScreenState extends State { )); changeColorIndex(); - if(model.isInfectiousDiseaseConsultant) { + if (model.isInfectiousDiseaseConsultant) { patientCards.add(HomePatientCard( gradient: backgroundColors[2], backgroundIconColor: backgroundIconColors[2], diff --git a/lib/screens/pharmacy_intervention/PharmacyIntervention.dart b/lib/screens/pharmacy_intervention/PharmacyIntervention.dart index 0af5c894..2f2c3c07 100644 --- a/lib/screens/pharmacy_intervention/PharmacyIntervention.dart +++ b/lib/screens/pharmacy_intervention/PharmacyIntervention.dart @@ -1,23 +1,17 @@ -import 'dart:ui'; import 'package:doctor_app_flutter/core/enum/view_state.dart'; import 'package:doctor_app_flutter/core/model/pharmacy-intervention-model/intervention_history.dart'; -import 'package:doctor_app_flutter/core/model/pharmacy-intervention-model/pharmacy_intervention_item.dart'; -import 'package:doctor_app_flutter/widgets/shared/app_texts_widget.dart'; - +import 'package:doctor_app_flutter/icons_app/doctor_app_icons.dart'; +import 'package:doctor_app_flutter/screens/pharmacy_intervention/widgets/InterventionCardItem.dart'; +import 'package:doctor_app_flutter/screens/pharmacy_intervention/widgets/InterventionHistoryBottomSheet.dart'; +import 'package:doctor_app_flutter/screens/pharmacy_intervention/widgets/NoInveterventionFound.dart'; +import 'package:doctor_app_flutter/screens/pharmacy_intervention/widgets/PharmacyInterventionDialog.dart'; +import 'package:doctor_app_flutter/utils/dr_app_toast_msg.dart'; import 'viewmodel/pharmacy_intervention_view_model.dart'; -import 'package:doctor_app_flutter/core/viewModel/project_view_model.dart'; import 'package:doctor_app_flutter/screens/base/base_view.dart'; import 'package:doctor_app_flutter/screens/patients/patient_search/patient_search_header.dart'; import 'package:doctor_app_flutter/utils/translations_delegate_base_utils.dart'; import 'package:doctor_app_flutter/widgets/shared/app_scaffold_widget.dart'; -import 'package:doctor_app_flutter/widgets/shared/buttons/app_buttons_widget.dart'; -import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:intl/intl.dart'; -import 'package:two_dimensional_scrollables/two_dimensional_scrollables.dart'; - -import '../../config/config.dart'; class PharmacyIntervention extends StatefulWidget { @override @@ -27,9 +21,11 @@ class PharmacyIntervention extends StatefulWidget { class _PharmacyInterventionState extends State { @override Widget build(BuildContext context) { - ProjectViewModel projectsProvider = Provider.of(context); - - return BaseView(builder: (_, model, __) { + return BaseView(onModelReady: (model) { + WidgetsBinding.instance.addPostFrameCallback((_) { + model.getPharmacyIntervention(); + }); + }, builder: (_, model, __) { if (model.interventionHistoryList != null) { WidgetsBinding.instance.addPostFrameCallback((_) { showBottomSheet( @@ -43,29 +39,33 @@ class _PharmacyInterventionState extends State { isShowAppBar: true, isLoading: model.state == ViewState.BusyLocal, appBar: PatientSearchHeader( - title: TranslationBase - .of(context) - .pharmacyApproval, + title: TranslationBase.of(context).pharmacyApproval, fontSize: 18, showSearchIcon: true, onSearchPressed: () { SearchDialog(context, model); }, ), - appBarTitle: TranslationBase - .of(context) - .pharmacyApproval, + appBarTitle: TranslationBase.of(context).pharmacyApproval, body: Column( mainAxisSize: MainAxisSize.max, children: [ - Expanded( - child: ListView.builder( - itemCount: model.medicationList?.medication?.length ?? 0, - itemBuilder: (context, index) => - InterventionCardItem( - medication: model.medicationList!.medication![index], - model: model, - ))) + if (model.medicationList == null || model.medicationList?.medication?.isEmpty == true) ...{ + Expanded( + child: + NoInterventionFound() + , + ) + } else ...{ + Expanded( + child: ListView.builder( + itemCount: model.medicationList?.medication?.length ?? 0, + itemBuilder: (context, index) => InterventionCardItem( + medication: + model.medicationList!.medication![index], + model: model, + ))) + } ], ), ); @@ -89,12 +89,6 @@ class _PharmacyInterventionState extends State { void _collapse() => _animateSheet(sheet.snapSizes!.first); - void _anchor() => _animateSheet(sheet.snapSizes!.last); - - void _expand() => _animateSheet(sheet.maxChildSize); - - void _hide() => _animateSheet(sheet.minChildSize); - void _animateSheet(double size) { _controller.animateTo( size, @@ -112,9 +106,11 @@ class _PharmacyInterventionState extends State { DraggableScrollableSheet get sheet => (_sheet.currentWidget as DraggableScrollableSheet); - void showBottomSheet(BuildContext context, - PharmacyInterventionViewModel model, - List interventionHistory,) { + void showBottomSheet( + BuildContext context, + PharmacyInterventionViewModel model, + List interventionHistory, + ) { showModalBottomSheet( isDismissible: true, context: context, @@ -124,18 +120,18 @@ class _PharmacyInterventionState extends State { builder: (_) { return DraggableScrollableSheet( key: _sheet, - initialChildSize: 0.5, - minChildSize: 0.5, + initialChildSize: 0.7, + minChildSize: 0.7, maxChildSize: 1, snapSizes: [ - 0.5, // constraints.maxHeight, - 0.9, + 0.7, // constraints.maxHeight, + 1, ], expand: false, controller: _controller, - builder: (_, controller) => - InterventionHistoryBottomSheet( + builder: (_, controller) => InterventionHistoryBottomSheet( interventionList: interventionHistory, + model: model, controller: controller, )); }, @@ -148,1122 +144,39 @@ class _PharmacyInterventionState extends State { barrierDismissible: true, // user must tap button! builder: (_) { return PharmacyInterventionDialog( - dateFrom: model.fromDate, - dateTo: model.toDate, - admissionNumber: model.admissionId, - nursingStation: model.nursingStationId, - patientID: model.patientID, + dateFrom: model.fromDate, + dateTo: model.toDate, + admissionNumber: model.admissionId, + nursingStation: model.nursingStationId, + patientID: model.patientID, onDispose: (dateFrom, dateTo, admissionNumber, patientId, nursingStation) { - if (dateFrom == model.fromDate && dateTo == model.toDate && - admissionNumber == model.admissionId && patientId == model.patientID && + if (dateFrom == model.fromDate && + dateTo == model.toDate && + admissionNumber == model.admissionId && + patientId == model.patientID && nursingStation == model.nursingStationId) { Navigator.of(context).pop(); return; } - + if (dateFrom.isEmpty && dateTo.isNotEmpty) { + DrAppToastMsg.showErrorToast( + TranslationBase.of(context).dateFromCanNotBeEmpty); + return; + } + if (dateFrom.isNotEmpty && dateTo.isEmpty) { + DrAppToastMsg.showErrorToast( + TranslationBase.of(context).dateToCanNotBeEmpty); + return; + } model.getPharmacyIntervention( admissionId: admissionNumber, patientID: patientId, nursingStationId: nursingStation, toDate: dateTo, - fromDate: dateFrom - ); + fromDate: dateFrom); Navigator.of(context).pop(); }); }); } } - -class InterventionCardItem extends StatelessWidget { - final Medication medication; - final PharmacyInterventionViewModel model; - - const InterventionCardItem( - {super.key, required this.medication, required this.model}); - - @override - Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.all(8.0), - child: Card( - color: Colors.white, - elevation: 5, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - children: [ - InterventionCardBody( - medication: medication, - model: model, - ), - InterventionCardFooter(model: model, medication: medication,) - ], - ), - ), - ), - ); - } -} - -class InterventionCardFooter extends StatelessWidget { - final PharmacyInterventionViewModel model; - final Medication medication; - const InterventionCardFooter({super.key, required this.model, required this.medication}); - - @override - Widget build(BuildContext context) { - return Column(children: [ - Row(children: [ - Expanded( - child: AppButton( - title: TranslationBase - .of(context) - .details, - hasBorder: true, - borderColor: Colors.grey, - color: Colors.grey, - fontColor: Colors.white, - onPressed: () async { - model.getInterventionHistory( - admissionNumber: medication.admissionNo?.toString() ?? '', - prescriptionNumber: medication.prescriptionNo?.toString() ?? '', - orderNumber: medication.orderNo?.toString() ?? '', - itemID: medication.itemID?.toString() ?? '', - ); - }, - ), - ), - ]), - SizedBox( - height: 8, - ), - Row(children: [ - Expanded( - child: AppButton( - title: TranslationBase - .of(context) - .reject, - hasBorder: true, - borderColor: Color(0xFFB8382B), - color: AppGlobal.appRedColor, - fontColor: Colors.white, - onPressed: () async { - model.updateInterventionDiseaseStatus( - admissionNo: medication.admissionNo?.toString() ?? '', - prescriptionNo: medication.prescriptionNo?.toString() ?? '', - orderNo: medication.orderNo?.toString() ?? '', - itemID: medication.itemID?.toString() ?? '', - interventionID: medication.?.toString() ?? '', - prescriptionNo: medication.prescriptionNo?.toString() ?? '', - orderNo: medication.orderNo?.toString() ?? '', - itemID: medication.itemID?.toString() ?? '', - ) - }, - ), - ), - SizedBox( - width: 6, - ), - Expanded( - child: AppButton( - title: TranslationBase - .of(context) - .accept, - hasBorder: true, - borderColor: AppGlobal.appGreenColor, - color: AppGlobal.appGreenColor, - fontColor: Colors.white, - onPressed: () async {}, - ), - ), - ]), - ]); - } -} - -class InterventionCardBody extends StatelessWidget { - final Medication medication; - final PharmacyInterventionViewModel model; - - const InterventionCardBody( - {super.key, required this.medication, required this.model}); - - @override - Widget build(BuildContext context) { - return Column( - children: [ - SizedBox( - height: 10, - ), - Row( - children: [ - Expanded( - child: InterventionDetails( - title: TranslationBase - .of(context) - .accessLevel, - data: medication.accessLevel.toString() ?? '', - ), - ), - Expanded( - child: InterventionDetails( - title: TranslationBase - .of(context) - .patientID, - data: medication.patientID.toString() ?? '', - )) - ], - ), - SizedBox( - height: 10, - ), - Row( - children: [ - Expanded( - child: InterventionDetails( - title: TranslationBase - .of(context) - .patientName, - data: medication.patientName.toString() ?? '', - ), - ), - Expanded( - child: InterventionDetails( - title: TranslationBase - .of(context) - .nursingStation, - data: medication.nursingStation.toString() ?? '', - )) - ], - ), - SizedBox( - height: 10, - ), - Row( - children: [ - Expanded( - child: InterventionDetails( - title: TranslationBase - .of(context) - .admissionNumber, - data: medication.admissionNo.toString() ?? '', - ), - ), - Expanded( - child: InterventionDetails( - title: TranslationBase - .of(context) - .medication, - data: medication.medication.toString() ?? '', - )) - ], - ), - SizedBox( - height: 10, - ), - Row( - children: [ - Expanded( - child: InterventionDetails( - title: TranslationBase - .of(context) - .dosageDetails, - data: medication.dosageDetail.toString() ?? '', - ), - ), - Expanded( - child: InterventionDetails( - title: TranslationBase - .of(context) - .doctorComments, - data: medication.doctorComments.toString() ?? '', - )) - ], - ), - SizedBox( - height: 10, - ), - Row( - children: [ - Expanded( - child: InterventionDetails( - title: TranslationBase - .of(context) - .startDate, - data: model.getDate(medication.startDatetime.toString() ?? ''), - ), - ), - Expanded( - child: InterventionDetails( - title: TranslationBase - .of(context) - .stopDate, - data: model.getDate(medication.stopDatetime.toString() ?? ''), - )) - ], - ), - SizedBox( - height: 10, - ), - Row( - children: [ - Expanded( - child: InterventionDetails( - title: TranslationBase - .of(context) - .status, - data: medication.status.toString() ?? '', - ), - ), - Expanded( - child: InterventionDetails( - title: TranslationBase - .of(context) - .doctor, - data: medication.doctorName.toString() ?? '', - )) - ], - ), - SizedBox( - height: 10, - ), - Row( - children: [ - Expanded( - child: InterventionDetails( - title: TranslationBase - .of(context) - .authorizedBy, - data: medication.authorizedBy.toString() ?? '-', - ), - ), - Expanded( - child: InterventionDetails( - title: TranslationBase - .of(context) - .pharmacyRemarks, - data: medication.pharmacyRemarks.toString() ?? '-', - )) - ], - ), - SizedBox( - height: 10, - ), - ], - ); - } -} - -class InterventionDetails extends StatelessWidget { - final String title; - final String data; - - const InterventionDetails( - {super.key, required this.title, required this.data}); - - @override - Widget build(BuildContext context) { - return Column( - children: [ - Text( - title, - textAlign: TextAlign.center, - style: TextStyle( - color: Colors.black, - fontWeight: FontWeight.w600, - fontSize: 13, - ), - ), - SizedBox( - height: 8, - ), - Text( - data, - textAlign: TextAlign.center, - style: TextStyle( - color: Colors.grey, - fontWeight: FontWeight.w400, - fontSize: 12, - ), - ), - ], - ); - } -} - -class InterventionHistoryBottomSheet extends StatelessWidget { - final List interventionList; - final ScrollController controller; - - const InterventionHistoryBottomSheet( - {super.key, required this.interventionList, required this.controller}); - - @override - Widget build(BuildContext context) { - return Material( - color: Color(0xFFF7F7F7), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(20), topRight: Radius.circular(20))), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 32), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - AppText( - TranslationBase - .of(context) - .histories, - fontWeight: FontWeight.w700, - fontSize: 24, - color: Color(0xFF2B353E), - ), - SizedBox( - height: 16, - ), - Expanded( - child: Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded( - child: ListView.separated( - shrinkWrap: true, - controller: controller, - itemCount: interventionList.length, - itemBuilder: (context, index) => - Material( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10)), - color: Colors.white, - child: InterventionHistoryItem( - interventionHistory: interventionList[index], - ), - ), - separatorBuilder: (_, __) => Divider(), - )) - ], - ), - ) - ], - ), - ), - ); - } -} - -class InterventionHistoryItem extends StatelessWidget { - final InterventionHistory interventionHistory; - - const InterventionHistoryItem({super.key, required this.interventionHistory}); - - @override - Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - AppText( - interventionHistory.commentedByName ?? '', - fontWeight: FontWeight.w600, - fontSize: 12, - color: Color(0xFF2B353E), - ), - SizedBox( - height: 4, - ), - AppText( - "${TranslationBase - .of(context) - .remarks}: ${interventionHistory.remark?.isNotEmpty == true - ? interventionHistory.remark - : TranslationBase - .of(context) - .noRemarks}", - fontWeight: FontWeight.w600, - fontSize: 12, - color: Color(0xFF2B353E), - ), - ], - ), - ); - } -} - -class TableCell extends StatelessWidget { - final String text; - - const TableCell(this.text, {super.key}); - - @override - Widget build(BuildContext context) { - return Container( - width: 150, // Adjust column width - padding: const EdgeInsets.all(8.0), - decoration: BoxDecoration( - border: Border.all(color: Colors.black), - ), - child: Text(text), - ); - } -} - -class TableHeaderCell extends StatelessWidget { - final String text; - - const TableHeaderCell(this.text, {super.key}); - - @override - Widget build(BuildContext context) { - return Container( - width: 150, // Adjust column width - padding: const EdgeInsets.all(8.0), - decoration: BoxDecoration( - color: Colors.grey[300], - border: Border.all(color: Colors.black), - ), - child: Text( - text, - style: const TextStyle(fontWeight: FontWeight.bold), - ), - ); - } -} - -class DataTable extends StatelessWidget { - int? _rowCount = 100; - int? _columnCount = 100; - - @override - Widget build(BuildContext context) { - return Scaffold( - body: TableView.builder( - cellBuilder: _buildCell, - columnCount: _columnCount, - columnBuilder: _buildColumn, - rowCount: _rowCount, - rowBuilder: _buildRowSpan, - pinnedRowCount: 1, - diagonalDragBehavior: DiagonalDragBehavior.free, - verticalDetails: ScrollableDetails.vertical( - controller: ScrollController(), - physics: BouncingScrollPhysics(), - ), - horizontalDetails: ScrollableDetails.horizontal( - controller: ScrollController(), - physics: BouncingScrollPhysics(), - ), - ), - ); - } - - TableViewCell _buildCell(BuildContext context, TableVicinity vicinity) { - final Color boxColor = - switch ((vicinity.row.isEven, vicinity.column.isEven)) { - (true, false) || (false, true) => Colors.white, - (false, false) => Colors.indigo[100]!, - (true, true) => Colors.indigo[200]! - }; - return TableViewCell( - child: ColoredBox( - color: boxColor, - child: Center( - child: Text('${vicinity.column}:${vicinity.row}'), - ), - ), - ); - } - - TableSpan _buildRowSpan(int index) { - return const TableSpan( - extent: MinSpanExtent(FixedSpanExtent(10), FixedSpanExtent(300))); - } - - TableSpan _buildColumn(int index) { - return const TableSpan( - extent: MinSpanExtent(FixedSpanExtent(50), FixedSpanExtent(300))); - } -} - -class TableExample extends StatefulWidget { - const TableExample({super.key, required this.model}); - - final PharmacyInterventionViewModel model; - - @override - State createState() => _TableExampleState(); -} - -class _TableExampleState extends State { - late final ScrollController _verticalController = ScrollController(); - int _rowCount = 0; - int _columnCount = 14; - final List headersList = []; - - @override - void dispose() { - _verticalController.dispose(); - super.dispose(); - } - - @override - void initState() { - print('the length is ${widget.model.medicationList?.medication?.length}'); - _rowCount = ((widget.model.medicationList?.medication?.length ?? 0) + 1); - super.initState(); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - body: TableView.builder( - verticalDetails: ScrollableDetails.vertical( - controller: _verticalController, - ), - cellBuilder: _buildCell, - columnCount: _columnCount, - pinnedRowCount: 1, - columnBuilder: _buildColumnSpan, - rowCount: _rowCount, - rowBuilder: _buildRowSpan, - ), - persistentFooterButtons: [ - TextButton( - onPressed: () { - _verticalController.jumpTo(0); - }, - child: const Text('Jump to Top'), - ), - ], - ); - } - - TableViewCell _buildCell(BuildContext context, TableVicinity vicinity) { - if (vicinity.row == 0) { - var title = ''; - switch (vicinity.column) { - case 0: - title = TranslationBase - .of(context) - .accessLevel; - break; - case 1: - title = TranslationBase - .of(context) - .patientID; - break; - case 2: - title = TranslationBase - .of(context) - .patientName; - break; - case 3: - title = TranslationBase - .of(context) - .nursingStation; - break; - case 4: - title = TranslationBase - .of(context) - .admissionNumber; - break; - case 5: - title = TranslationBase - .of(context) - .medication; - break; - case 6: - title = TranslationBase - .of(context) - .dosageDetails; - break; - case 7: - title = TranslationBase - .of(context) - .doctorComments; - break; - case 8: - title = TranslationBase - .of(context) - .startDate; - break; - case 9: - title = TranslationBase - .of(context) - .stopDate; - break; - case 10: - title = TranslationBase - .of(context) - .status; - break; - case 11: - title = TranslationBase - .of(context) - .doctor; - break; - case 12: - title = TranslationBase - .of(context) - .authorizedBy; - break; - case 13: - title = TranslationBase - .of(context) - .pharmacyRemarks; - break; - } - - return TableViewCell( - child: ColoredBox( - color: Colors.grey, - child: Center( - child: Text(title), - ), - ), - ); - } - return TableViewCell( - child: Center( - child: Padding( - padding: const EdgeInsets.all(2.0), - child: Text( - widget.model.medicationList?.medication?[vicinity.row - 1] - .getValue(vicinity.column) - .toString() ?? - '', - textAlign: TextAlign.center, - maxLines: 2, - overflow: TextOverflow.ellipsis, - ), - ), - ), - ); - } - - TableSpan _buildColumnSpan(int index) { - const TableSpanDecoration decoration = TableSpanDecoration( - border: TableSpanBorder( - trailing: BorderSide(), - ), - ); - - switch (index) { - case 0: - return TableSpan( - foregroundDecoration: decoration, - extent: const FractionalTableSpanExtent(0.3), - onEnter: (_) => print('Entered column $index'), - cursor: SystemMouseCursors.contextMenu, - ); - break; - case 1: - return TableSpan( - foregroundDecoration: decoration, - extent: const FractionalTableSpanExtent(0.4), - onEnter: (_) => print('Entered column $index'), - cursor: SystemMouseCursors.contextMenu, - ); - break; - case 2: - return TableSpan( - foregroundDecoration: decoration, - extent: const FractionalTableSpanExtent(0.5), - onEnter: (_) => print('Entered column $index'), - cursor: SystemMouseCursors.contextMenu, - ); - break; - case 3: - return TableSpan( - foregroundDecoration: decoration, - extent: const FractionalTableSpanExtent(0.4), - onEnter: (_) => print('Entered column $index'), - cursor: SystemMouseCursors.contextMenu, - ); - break; - case 4: - return TableSpan( - foregroundDecoration: decoration, - extent: const FractionalTableSpanExtent(0.5), - onEnter: (_) => print('Entered column $index'), - cursor: SystemMouseCursors.contextMenu, - ); - break; - case 5: - return TableSpan( - foregroundDecoration: decoration, - extent: const FractionalTableSpanExtent(0.7), - onEnter: (_) => print('Entered column $index'), - cursor: SystemMouseCursors.contextMenu, - ); - break; - case 6: - return TableSpan( - foregroundDecoration: decoration, - extent: const FractionalTableSpanExtent(0.7), - onEnter: (_) => print('Entered column $index'), - cursor: SystemMouseCursors.contextMenu, - ); - break; - case 7: - return TableSpan( - foregroundDecoration: decoration, - extent: const FractionalTableSpanExtent(0.8), - onEnter: (_) => print('Entered column $index'), - cursor: SystemMouseCursors.contextMenu, - ); - break; - case 8: - case 9: - case 10: - return TableSpan( - foregroundDecoration: decoration, - extent: const FractionalTableSpanExtent(0.4), - onEnter: (_) => print('Entered column $index'), - cursor: SystemMouseCursors.contextMenu, - ); - case 11: - case 12: - return TableSpan( - foregroundDecoration: decoration, - extent: const FractionalTableSpanExtent(0.6), - onEnter: (_) => print('Entered column $index'), - cursor: SystemMouseCursors.contextMenu, - ); - case 13: - return TableSpan( - foregroundDecoration: decoration, - extent: const FractionalTableSpanExtent(0.7), - onEnter: (_) => print('Entered column $index'), - cursor: SystemMouseCursors.contextMenu, - ); - break; - } - // switch (index % 5) { - // case 0: - // return TableSpan( - // foregroundDecoration: decoration, - // extent: const FixedTableSpanExtent(100), - // onEnter: (_) => print('Entered column $index'), - // recognizerFactories: { - // TapGestureRecognizer: - // GestureRecognizerFactoryWithHandlers( - // () => TapGestureRecognizer(), - // (TapGestureRecognizer t) => - // t.onTap = () => print('Tap column $index'), - // ), - // }, - // ); - // case 1: - // return TableSpan( - // foregroundDecoration: decoration, - // extent: const FractionalTableSpanExtent(0.5), - // onEnter: (_) => print('Entered column $index'), - // cursor: SystemMouseCursors.contextMenu, - // ); - // case 2: - // return TableSpan( - // foregroundDecoration: decoration, - // extent: const FixedTableSpanExtent(140), - // onEnter: (_) => print('Entered column $index'), - // ); - // case 3: - // return TableSpan( - // foregroundDecoration: decoration, - // extent: const FixedTableSpanExtent(200), - // onEnter: (_) => print('Entered column $index'), - // ); - // case 4: - // return TableSpan( - // foregroundDecoration: decoration, - // extent: const FixedTableSpanExtent(200), - // onEnter: (_) => print('Entered column $index'), - // ); - // } - throw AssertionError( - 'This should be unreachable, as every index is accounted for in the ' - 'switch clauses.', - ); - } - - TableSpan _buildRowSpan(int index) { - final TableSpanDecoration decoration = TableSpanDecoration( - border: const TableSpanBorder( - trailing: BorderSide( - width: 1, - ), - ), - ); - if (index == 0) { - TableSpan( - backgroundDecoration: decoration, - extent: const FixedTableSpanExtent(30), - recognizerFactories: { - TapGestureRecognizer: - GestureRecognizerFactoryWithHandlers( - () => TapGestureRecognizer(), - (TapGestureRecognizer t) => - t.onTap = () => print('Tap row $index'), - ), - }, - ); - } - return TableSpan( - backgroundDecoration: decoration, - extent: const FixedTableSpanExtent(65), - cursor: SystemMouseCursors.click, - ); - // switch (index) { - // case 0: - // return TableSpan( - // backgroundDecoration: decoration, - // extent: const FixedTableSpanExtent(30), - // recognizerFactories: { - // TapGestureRecognizer: - // GestureRecognizerFactoryWithHandlers( - // () => TapGestureRecognizer(), - // (TapGestureRecognizer t) => - // t.onTap = () => print('Tap row $index'), - // ), - // }, - // ); - // case 1: - // return TableSpan( - // backgroundDecoration: decoration, - // extent: const FixedTableSpanExtent(65), - // cursor: SystemMouseCursors.click, - // ); - // case 2: - // return TableSpan( - // backgroundDecoration: decoration, - // extent: const FractionalTableSpanExtent(0.15), - // ); - // } - throw AssertionError( - 'This should be unreachable, as every index is accounted for in the ' - 'switch clauses.', - ); - } -} - -class PharmacyInterventionDialog extends StatefulWidget { - final Function( - String, // dataFrom - String, // dateTo - String, // admissionNumber - String, // patient ID - String, // nursingStation - ) onDispose; - - final String dateFrom; - final String dateTo; - final String admissionNumber; - final String patientID; - final String nursingStation; - - const PharmacyInterventionDialog({super.key, required this.onDispose, required this.dateFrom, required this.dateTo, required this.admissionNumber, required this.patientID, required this.nursingStation}); - - @override - State createState() => - _PharmacyInterventionDialogState(); -} - -class _PharmacyInterventionDialogState - extends State { - final TextEditingController admissionNumber = TextEditingController(); - final TextEditingController nursingStation = TextEditingController(); - - final TextEditingController patientId = TextEditingController(); - - String dateFrom = ''; - - String dateTo = ''; - - @override - void initState() { - initData(); - super.initState(); - } - - void initData() { - admissionNumber.text = widget.admissionNumber; - nursingStation.text = widget.nursingStation; - patientId.text = widget.patientID; - dateTo = getDate(widget.dateTo); - dateFrom = getDate(widget.dateFrom); - } - - @override - Widget build(BuildContext context) { - return Dialog( - backgroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - child: Padding( - padding: const EdgeInsets.all(24), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - _titleAndTextField(TranslationBase - .of(context) - .nursingStation, - nursingStation, TextInputType.number), - SizedBox( - height: 4, - ), - _titleAndTextField(TranslationBase - .of(context) - .admissionNumber, - admissionNumber, TextInputType.number), - SizedBox( - height: 4, - ), - _titleAndTextField(TranslationBase - .of(context) - .patientID, patientId, - TextInputType.number), - SizedBox( - height: 4, - ), - _dateSelection(TranslationBase - .of(context) - .dateFrom, (date) { - setState(() { - dateFrom = date; - }); - }, dateFrom), - SizedBox( - height: 4, - ), - _dateSelection(TranslationBase - .of(context) - .dateTo, (date) { - setState(() { - dateTo = date; - }); - }, dateTo), - SizedBox( - height: 8, - ), - Row(children: [ - Expanded( - child: AppButton( - title: TranslationBase - .of(context) - .search, - hasBorder: true, - borderColor: Color(0xFFB8382B), - color: AppGlobal.appRedColor, - fontColor: Colors.white, - onPressed: () async { - //(dateFrom, dateTo, admissionNumber, patientId, nursingStation) - widget.onDispose( - dateFrom, - dateTo, - nursingStation.text, - patientId.text, - nursingStation.text); - }, - ), - ), - ]), - ], - ), - ), - ); - } - - Widget _dateSelection(String title, Function(String) onDateSelected, - String selectedDate) { - return GestureDetector( - onTap: () => _selectDate(onDateSelected), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Text(title), - Expanded( - child: ListTile( - title: Text( - selectedDate, - ), - trailing: Icon(Icons.arrow_drop_down_outlined), - ), - ) - ], - ), - ); - } - - Future _selectDate(Function(String) updateDate) async { - final DateTime? picked = await showDatePicker( - context: context, - initialDate: DateTime.now(), - firstDate: DateTime(DateTime - .now() - .year - 150), - lastDate: DateTime(DateTime - .now() - .year + 150), - initialEntryMode: DatePickerEntryMode.calendar, - builder: (_, child) { - return Theme( - data: ThemeData.light().copyWith( - colorScheme: ColorScheme.fromSwatch( - primarySwatch: Colors.red, - accentColor: AppGlobal.appRedColor, - ), - dialogBackgroundColor: Colors.white, - ), - child: child!, - ); - }); - if (picked != null) { - updateDate(getFormattedDate(picked)); - } - // } - } - - Widget _titleAndTextField(String title, TextEditingController controller, - TextInputType? inputType) { - return Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - mainAxisSize: MainAxisSize.min, - children: [ - Text(title), - Expanded( - child: TextFormField( - keyboardType: inputType, - decoration: InputDecoration( - hintText: '', - focusedBorder: InputBorder.none, - enabledBorder: InputBorder.none, - contentPadding: EdgeInsetsDirectional.only(start: 10.0), - ), - textAlign: TextAlign.end, - controller: controller, - ), - ) - ], - ); - } - - void initFromDate() { - var time = DateTime.now(); - dateFrom = getFormattedDate(time); - } - - String getFormattedDate(DateTime time) { - return DateFormat('yyyy-MM-dd').format(time); - } - String getDate(String dateTime) { - if (dateTime.isEmpty) return ''; - List splitedDate = dateTime.split('-'); - DateTime now = DateTime(int.parse(splitedDate[0]), int.parse(splitedDate[1]), int.parse(splitedDate[2])); - return DateFormat('yyyy-MM-dd').format(now); - } - -} diff --git a/lib/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_service.dart b/lib/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_service.dart index 936f0e89..afb69112 100644 --- a/lib/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_service.dart +++ b/lib/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_service.dart @@ -1,25 +1,37 @@ import 'dart:async'; +import 'dart:ffi'; import 'package:doctor_app_flutter/config/config.dart'; import 'package:doctor_app_flutter/config/shared_pref_kay.dart'; import 'package:doctor_app_flutter/core/model/pharmacy-intervention-model/intervention_history.dart'; import 'package:doctor_app_flutter/core/model/pharmacy-intervention-model/pharmacy_intervention_item.dart'; import 'package:doctor_app_flutter/core/service/base/base_service.dart'; +import 'package:doctor_app_flutter/utils/dr_app_toast_msg.dart'; +import 'package:intl/intl.dart'; class PharmacyInterventionService extends BaseService { Future getMedicationList( - {String nursingStationId = '', - String admissionId = '', - String patientID = '', + {String nursingStationId = '0', + String admissionId = '0', + String patientID = '0', String fromDate = '', String toDate = ''}) async { - var request = { - "nursingStationID": nursingStationId, - "admissionNo": admissionId, - "patientID": patientID, - "fromDate": fromDate, - "toDate": toDate, + Map request = { + "NursingStationID": num.parse((nursingStationId.isEmpty)?'0':nursingStationId), + "AdmissionNo": num.parse((admissionId.isEmpty)?'0':admissionId), + "PatientID": num.parse((patientID.isEmpty)?'0':patientID), }; + + print("the date is ${convertToISO8601(fromDate).toString()}"); + print("the to Date is ${convertToISO8601(fromDate).toString()}"); + if(fromDate.isNotEmpty){ + var temp = { + "InterventionFromDate": convertToISO8601(fromDate).toString(), + "InterventionToDate": convertToISO8601(toDate).toString(), + }; + request.addAll(temp); + } + hasError = false; MedicationList? result; await baseAppClient.post(GET_MEDICINE_WITH_INTERVAL, @@ -27,6 +39,7 @@ class PharmacyInterventionService extends BaseService { result = MedicationList.fromJson(response['List_MedicineWithIntervention']); }, onFailure: (String error, int statusCode) { hasError = true; + DrAppToastMsg.showErrorToast(error); super.error = super.error??'' + "\n" + error; }, body: request); @@ -34,6 +47,18 @@ class PharmacyInterventionService extends BaseService { return result; } + String convertToISO8601(String dateString) { + try { + DateFormat inputFormat = DateFormat('yyyy-MM-dd'); // Adjust format if needed + DateTime parsedDate = inputFormat.parse(dateString); + String iso8601String = parsedDate.toIso8601String().toString(); + print('the data is $iso8601String'); + return iso8601String; // Remove milliseconds + } catch (e) { + return "Invalid date format: $e"; + } + } + /// /// it will be called only for the doctor that are associated to vida plus /// project @@ -46,17 +71,37 @@ class PharmacyInterventionService extends BaseService { } hasError = false; var success = false; - await baseAppClient.post(IS_INFECTIOUS_DISEASE, + await baseAppClient.post(IS_INFECTIOUS_DISEASE_CONSULTANT, onSuccess: (dynamic response, int statusCode) { success = response['IsInfectiousDiseases']; }, onFailure: (String error, int statusCode) { hasError = true; + DrAppToastMsg.showErrorToast(error); super.error = super.error! + "\n" + error; }, body: {}); return success; } + Future getPendingInterventionDiseaseStatus() async { + String vidaToken = await sharedPref.getString(VIDA_AUTH_TOKEN_ID); + if(vidaToken.isEmpty){ + return false; + } + hasError = false; + var success = false; + await baseAppClient.post(IS_INFECTIOUS_DISEASE_PENDING, + onSuccess: (dynamic response, int statusCode) { + success = response['IsPending']; + }, onFailure: (String error, int statusCode) { + hasError = true; + DrAppToastMsg.showErrorToast(error); + + super.error = super.error! + "\n" + error; + }, body: {}); + return success; + } + Future getInfectiousDiseaseHistory({ String admissionNumber = '', String prescriptionNumber = '', @@ -78,44 +123,25 @@ class PharmacyInterventionService extends BaseService { response['List_MedicineInterventionHistory']); }, onFailure: (String error, int statusCode) { hasError = true; + DrAppToastMsg.showErrorToast(error); + super.error = super.error! + "\n" + error; }, body: request); return result; } - Future updateInterventionStatus({ - String admissionNo = '', - String prescriptionNo = '', - String orderNo = '', - String itemID = '', - String interventionID = '', - String isAccepted = '', - String remarks = '', - String authorizeID = '', - String lineItemNo = '', - String status = '', - }) async { - var request = { - "AdmissionNo": admissionNo, - "PrescriptionNo": prescriptionNo, - "OrderNo": orderNo, - "ItemID": itemID, - "InterventionID": interventionID, - "IsAccepted": isAccepted, - "Remarks": remarks, - "AuthorizeID": authorizeID, - "LineItemNo": lineItemNo, - "Status": status, - }; - + Future updateInterventionStatus( + Map request + ) async { hasError = false; var result = false; - await baseAppClient.post(INFECTIOUS_HISTORY, + await baseAppClient.post(UPDATE_INFECTIOUS_STATUS, onSuccess: (dynamic response, int statusCode) { result = response['IsAccepted']; }, onFailure: (String error, int statusCode) { hasError = true; + DrAppToastMsg.showErrorToast(error); super.error = super.error! + "\n" + error; }, body: request); return result; diff --git a/lib/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_view_model.dart b/lib/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_view_model.dart index 1e50d722..0f732dc6 100644 --- a/lib/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_view_model.dart +++ b/lib/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_view_model.dart @@ -1,14 +1,17 @@ +import 'package:doctor_app_flutter/config/shared_pref_kay.dart'; import 'package:doctor_app_flutter/core/enum/view_state.dart'; import 'package:doctor_app_flutter/core/model/pharmacy-intervention-model/intervention_history.dart'; import 'package:doctor_app_flutter/core/model/pharmacy-intervention-model/pharmacy_intervention_item.dart'; import 'package:doctor_app_flutter/core/viewModel/base_view_model.dart'; import 'package:doctor_app_flutter/locator.dart'; import 'package:doctor_app_flutter/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_service.dart'; +import 'package:doctor_app_flutter/utils/dr_app_toast_msg.dart'; import 'package:intl/intl.dart'; class PharmacyInterventionViewModel extends BaseViewModel { PharmacyInterventionService _service = locator(); MedicationList? medicationList; + // MedicationList? medicationList = MedicationList.fromJson({ // "entityList": [ // { @@ -85,7 +88,10 @@ class PharmacyInterventionViewModel extends BaseViewModel { // "success": null // }); + Medication? currentlySelectedMedication; + InterventionHistoryList? interventionHistoryList; + // InterventionHistoryList? interventionHistoryList = InterventionHistoryList.fromJson({ // "entityList": [ // { @@ -501,9 +507,9 @@ class PharmacyInterventionViewModel extends BaseViewModel { } Future getPharmacyIntervention( - {String nursingStationId = '', - String admissionId = '', - String patientID = '', + {String nursingStationId = '0', + String admissionId = '0', + String patientID = '0', String fromDate = '', String toDate = ''}) async { setState(ViewState.BusyLocal); @@ -522,6 +528,7 @@ class PharmacyInterventionViewModel extends BaseViewModel { if (_service.hasError || result == null) { error = _service.error; + medicationList = null; setState(ViewState.ErrorLocal); return; } @@ -542,45 +549,60 @@ class PharmacyInterventionViewModel extends BaseViewModel { } Future updateInterventionDiseaseStatus({ - String admissionNo = '', - String prescriptionNo = '', - String orderNo = '', - String itemID = '', - String interventionID = '', - String isAccepted = '', + bool isAccepted = false, String remarks = '', - String authorizeID = '', - String lineItemNo = '', - String status = '', + String interventionID = '', + String errorMessage = '', + String successMessage = '' }) async { + Map? user = await sharedPref.getObj(LOGGED_IN_USER); + var userId = user?['List_MemberInformation'][0]['MemberID']; + + var requestJson = { + "PatientID":currentlySelectedMedication?.patientID ?? '', + 'AdmissionNo': currentlySelectedMedication?.admissionNo.toString() ?? '', + "PrescriptionNo": + currentlySelectedMedication?.prescriptionNo.toString() ?? '', + "OrderNo": currentlySelectedMedication?.orderNo.toString() ?? '', + "ItemID": currentlySelectedMedication?.itemID.toString() ?? '', + "LineItemNo": currentlySelectedMedication?.lineItemNo.toString() ?? '', + "Remarks": remarks ?? '', + "InterventionID": interventionID, + "AuthorizeID": userId, + "Status": currentlySelectedMedication?.status.toString() ?? '', + "IsAccepted": isAccepted + }; setState(ViewState.BusyLocal); - bool result = await _service.getInfectiousDiseaseConsultantStatus(); + bool result = await _service.updateInterventionStatus(requestJson); + if (_service.hasError) { error = _service.error; setState(ViewState.ErrorLocal); + DrAppToastMsg.showErrorToast(errorMessage); return; } - isInfectiousDiseaseConsultant = result; + DrAppToastMsg.showSuccesToast(successMessage); + getPharmacyIntervention(); setState(ViewState.Idle); } Future getInterventionHistory({ - String admissionNumber = '', - String prescriptionNumber = '', - String orderNumber = '', - String itemID = '', + Medication? medication, }) async { + currentlySelectedMedication = null; setState(ViewState.BusyLocal); - InterventionHistoryList? result = await _service.getInfectiousDiseaseHistory( - admissionNumber: admissionNumber, - prescriptionNumber: prescriptionNumber, - orderNumber: orderNumber, - itemID: itemID); - if (_service.hasError ) { + InterventionHistoryList? result = + await _service.getInfectiousDiseaseHistory( + admissionNumber: medication?.admissionNo?.toString() ?? '', + prescriptionNumber: medication?.prescriptionNo?.toString() ?? '', + orderNumber: medication?.orderNo?.toString() ?? '', + itemID: medication?.itemID?.toString() ?? ''); + if (_service.hasError) { error = _service.error; setState(ViewState.ErrorLocal); return; } + currentlySelectedMedication = medication; interventionHistoryList = result; setState(ViewState.Idle); } diff --git a/lib/screens/pharmacy_intervention/widgets/InterventionCardBody.dart b/lib/screens/pharmacy_intervention/widgets/InterventionCardBody.dart new file mode 100644 index 00000000..86e67f0a --- /dev/null +++ b/lib/screens/pharmacy_intervention/widgets/InterventionCardBody.dart @@ -0,0 +1,179 @@ +import 'package:doctor_app_flutter/core/model/pharmacy-intervention-model/pharmacy_intervention_item.dart'; +import 'package:doctor_app_flutter/screens/pharmacy_intervention/PharmacyIntervention.dart'; +import 'package:doctor_app_flutter/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_view_model.dart'; +import 'package:doctor_app_flutter/screens/pharmacy_intervention/widgets/InterventionDetails.dart'; +import 'package:doctor_app_flutter/utils/translations_delegate_base_utils.dart'; +import 'package:flutter/material.dart'; + +class InterventionCardBody extends StatelessWidget { + final Medication medication; + final PharmacyInterventionViewModel model; + + const InterventionCardBody( + {super.key, required this.medication, required this.model}); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + SizedBox( + height: 10, + ), + Row( + children: [ + Expanded( + child: InterventionDetails( + title: TranslationBase + .of(context) + .accessLevel, + data: medication.accessLevel.toString() ?? '', + ), + ), + Expanded( + child: InterventionDetails( + title: TranslationBase + .of(context) + .patientID, + data: medication.patientID.toString() ?? '', + )) + ], + ), + SizedBox( + height: 10, + ), + Row( + children: [ + Expanded( + child: InterventionDetails( + title: TranslationBase + .of(context) + .patientName, + data: medication.patientName.toString() ?? '', + ), + ), + Expanded( + child: InterventionDetails( + title: TranslationBase + .of(context) + .nursingStation, + data: medication.nursingStation.toString() ?? '', + )) + ], + ), + SizedBox( + height: 10, + ), + Row( + children: [ + Expanded( + child: InterventionDetails( + title: TranslationBase + .of(context) + .admissionNumber, + data: medication.admissionNo.toString() ?? '', + ), + ), + Expanded( + child: InterventionDetails( + title: TranslationBase + .of(context) + .medication, + data: medication.medication.toString() ?? '', + )) + ], + ), + SizedBox( + height: 10, + ), + Row( + children: [ + Expanded( + child: InterventionDetails( + title: TranslationBase + .of(context) + .dosageDetails, + data: medication.dosageDetail.toString() ?? '', + ), + ), + Expanded( + child: InterventionDetails( + title: TranslationBase + .of(context) + .doctorComments, + data: medication.doctorComments.toString() ?? '', + )) + ], + ), + SizedBox( + height: 10, + ), + Row( + children: [ + Expanded( + child: InterventionDetails( + title: TranslationBase + .of(context) + .startDate, + data: model.getDate(medication.startDatetime.toString() ?? ''), + ), + ), + Expanded( + child: InterventionDetails( + title: TranslationBase + .of(context) + .stopDate, + data: model.getDate(medication.stopDatetime.toString() ?? ''), + )) + ], + ), + SizedBox( + height: 10, + ), + Row( + children: [ + Expanded( + child: InterventionDetails( + title: TranslationBase + .of(context) + .status, + data: medication.status.toString() ?? '', + ), + ), + Expanded( + child: InterventionDetails( + title: TranslationBase + .of(context) + .doctor, + data: medication.doctorName.toString() ?? '', + )) + ], + ), + SizedBox( + height: 10, + ), + Row( + children: [ + Expanded( + child: InterventionDetails( + title: TranslationBase + .of(context) + .authorizedBy, + data: medication.authorizedBy.toString() ?? '-', + ), + ), + Expanded( + child: InterventionDetails( + title: TranslationBase + .of(context) + .pharmacyRemarks, + data: medication.pharmacyRemarks.toString() ?? '-', + )) + ], + ), + SizedBox( + height: 10, + ), + ], + ); + } +} diff --git a/lib/screens/pharmacy_intervention/widgets/InterventionCardFooter.dart b/lib/screens/pharmacy_intervention/widgets/InterventionCardFooter.dart new file mode 100644 index 00000000..a3a1b1d2 --- /dev/null +++ b/lib/screens/pharmacy_intervention/widgets/InterventionCardFooter.dart @@ -0,0 +1,37 @@ +import 'package:doctor_app_flutter/core/model/pharmacy-intervention-model/pharmacy_intervention_item.dart'; +import 'package:doctor_app_flutter/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_view_model.dart'; +import 'package:doctor_app_flutter/utils/translations_delegate_base_utils.dart'; +import 'package:doctor_app_flutter/widgets/shared/buttons/app_buttons_widget.dart'; +import 'package:flutter/material.dart'; + +class InterventionCardFooter extends StatelessWidget { + final PharmacyInterventionViewModel model; + final Medication medication; + + const InterventionCardFooter( + {super.key, required this.model, required this.medication}); + + @override + Widget build(BuildContext context) { + return Column(children: [ + Row(children: [ + Expanded( + child: AppButton( + title: TranslationBase + .of(context) + .details, + hasBorder: true, + borderColor: Colors.grey, + color: Colors.grey, + fontColor: Colors.white, + onPressed: () async { + model.getInterventionHistory( + medication: medication + ); + }, + ), + ), + ]), + ]); + } +} diff --git a/lib/screens/pharmacy_intervention/widgets/InterventionCardItem.dart b/lib/screens/pharmacy_intervention/widgets/InterventionCardItem.dart new file mode 100644 index 00000000..b68ea2b3 --- /dev/null +++ b/lib/screens/pharmacy_intervention/widgets/InterventionCardItem.dart @@ -0,0 +1,40 @@ +import 'package:doctor_app_flutter/core/model/pharmacy-intervention-model/pharmacy_intervention_item.dart'; +import 'package:doctor_app_flutter/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_view_model.dart'; +import 'package:doctor_app_flutter/screens/pharmacy_intervention/widgets/InterventionCardBody.dart'; +import 'package:doctor_app_flutter/screens/pharmacy_intervention/widgets/InterventionCardFooter.dart'; +import 'package:flutter/material.dart'; + +class InterventionCardItem extends StatelessWidget { + final Medication medication; + final PharmacyInterventionViewModel model; + + const InterventionCardItem( + {super.key, required this.medication, required this.model}); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(8.0), + child: Card( + color: Colors.white, + elevation: 5, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + InterventionCardBody( + medication: medication, + model: model, + ), + InterventionCardFooter( + model: model, + medication: medication, + ) + ], + ), + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/screens/pharmacy_intervention/widgets/InterventionDetails.dart b/lib/screens/pharmacy_intervention/widgets/InterventionDetails.dart new file mode 100644 index 00000000..2f5e6e47 --- /dev/null +++ b/lib/screens/pharmacy_intervention/widgets/InterventionDetails.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; + +class InterventionDetails extends StatelessWidget { + final String title; + final String data; + + const InterventionDetails( + {super.key, required this.title, required this.data}); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + Text( + title, + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.black, + fontWeight: FontWeight.w600, + fontSize: 13, + ), + ), + SizedBox( + height: 8, + ), + Text( + data, + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.grey, + fontWeight: FontWeight.w400, + fontSize: 12, + ), + ), + ], + ); + } +} diff --git a/lib/screens/pharmacy_intervention/widgets/InterventionHistoryBottomSheet.dart b/lib/screens/pharmacy_intervention/widgets/InterventionHistoryBottomSheet.dart new file mode 100644 index 00000000..2ba7b174 --- /dev/null +++ b/lib/screens/pharmacy_intervention/widgets/InterventionHistoryBottomSheet.dart @@ -0,0 +1,87 @@ +import 'package:doctor_app_flutter/core/model/pharmacy-intervention-model/intervention_history.dart'; +import 'package:doctor_app_flutter/screens/pharmacy_intervention/PharmacyIntervention.dart'; +import 'package:doctor_app_flutter/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_view_model.dart'; +import 'package:doctor_app_flutter/screens/pharmacy_intervention/widgets/intervention_history_item.dart'; +import 'package:doctor_app_flutter/utils/translations_delegate_base_utils.dart'; +import 'package:doctor_app_flutter/widgets/shared/app_texts_widget.dart'; +import 'package:flutter/material.dart'; + +class InterventionHistoryBottomSheet extends StatelessWidget { + final List interventionList; + final ScrollController controller; + final PharmacyInterventionViewModel model; + + const InterventionHistoryBottomSheet( + {super.key, required this.interventionList, required this.controller, required this.model}); + + @override + Widget build(BuildContext context) { + return Material( + color: Color(0xFFF7F7F7), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(20), topRight: Radius.circular(20))), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 32), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + AppText( + TranslationBase + .of(context) + .histories, + fontWeight: FontWeight.w700, + fontSize: 24, + color: Color(0xFF2B353E), + ), + SizedBox( + height: 16, + ), + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: ListView.separated( + shrinkWrap: true, + controller: controller, + itemCount: interventionList.length, + itemBuilder: (context, index) => + Material( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10)), + color: Colors.white, + child: InterventionHistoryItem( + interventionHistory: interventionList[index], + onAcceptClick: (intervention) { + model.updateInterventionDiseaseStatus( + isAccepted: true, + interventionID: interventionList[index].interventionId.toString(), + successMessage: TranslationBase.of(context).interventionRejectedSuccessfully, + errorMessage: TranslationBase.of(context).unableToPerformTheAction + ); + Navigator.pop(context); + }, + onRejectClick: (intervention) { + model.updateInterventionDiseaseStatus( + interventionID: interventionList[index].interventionId.toString(), + successMessage: TranslationBase.of(context).interventionAcceptedSuccessfully, + errorMessage: TranslationBase.of(context).unableToPerformTheAction + ); + Navigator.pop(context); + + }, + ), + ), + separatorBuilder: (_, __) => Divider(), + )) + ], + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/screens/pharmacy_intervention/widgets/NoInveterventionFound.dart b/lib/screens/pharmacy_intervention/widgets/NoInveterventionFound.dart new file mode 100644 index 00000000..27fed780 --- /dev/null +++ b/lib/screens/pharmacy_intervention/widgets/NoInveterventionFound.dart @@ -0,0 +1,20 @@ +import 'package:doctor_app_flutter/utils/translations_delegate_base_utils.dart'; +import 'package:flutter/material.dart'; + +class NoInterventionFound extends StatelessWidget{ + @override + Widget build(BuildContext context) { + return Center( + child: Text( + TranslationBase.of(context).noInterventionFound, + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.black, + fontWeight: FontWeight.w600, + fontSize: 13, + ), + ), + ); + } + +} \ No newline at end of file diff --git a/lib/screens/pharmacy_intervention/widgets/PharmacyInterventionDialog.dart b/lib/screens/pharmacy_intervention/widgets/PharmacyInterventionDialog.dart new file mode 100644 index 00000000..2e698683 --- /dev/null +++ b/lib/screens/pharmacy_intervention/widgets/PharmacyInterventionDialog.dart @@ -0,0 +1,236 @@ +import 'package:doctor_app_flutter/config/config.dart'; +import 'package:doctor_app_flutter/utils/translations_delegate_base_utils.dart'; +import 'package:doctor_app_flutter/widgets/shared/buttons/app_buttons_widget.dart'; +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; + +class PharmacyInterventionDialog extends StatefulWidget { + final Function( + String, // dataFrom + String, // dateTo + String, // admissionNumber + String, // patient ID + String, // nursingStation + ) onDispose; + + final String dateFrom; + final String dateTo; + final String admissionNumber; + final String patientID; + final String nursingStation; + + const PharmacyInterventionDialog({super.key, + required this.onDispose, + required this.dateFrom, + required this.dateTo, + required this.admissionNumber, + required this.patientID, + required this.nursingStation}); + + @override + State createState() => + _PharmacyInterventionDialogState(); +} + +class _PharmacyInterventionDialogState + extends State { + final TextEditingController admissionNumber = TextEditingController(); + final TextEditingController nursingStation = TextEditingController(); + + final TextEditingController patientId = TextEditingController(); + + String dateFrom = ''; + + String dateTo = ''; + + @override + void initState() { + initData(); + super.initState(); + } + + void initData() { + admissionNumber.text = (widget.admissionNumber == '0')?'':widget.admissionNumber; + nursingStation.text = (widget.nursingStation == '0')?'':widget.nursingStation; + patientId.text = (widget.patientID == '0' )?'':widget.patientID; + dateTo = getDate(widget.dateTo); + dateFrom = getDate(widget.dateFrom); + } + + @override + Widget build(BuildContext context) { + return Dialog( + backgroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + child: Padding( + padding: const EdgeInsets.all(24), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + IconButton( + icon: Icon(Icons.close), + onPressed: () { + Navigator.pop(context); + }, + ), + SizedBox(height: 8,), + _titleAndTextField(TranslationBase + .of(context) + .nursingStation, + nursingStation, TextInputType.number), + SizedBox( + height: 4, + ), + _titleAndTextField(TranslationBase + .of(context) + .admissionNumber, + admissionNumber, TextInputType.number), + SizedBox( + height: 4, + ), + _titleAndTextField(TranslationBase + .of(context) + .patientID, patientId, + TextInputType.number), + SizedBox( + height: 4, + ), + _dateSelection(TranslationBase + .of(context) + .dateFrom, (date) { + setState(() { + dateFrom = date; + }); + }, dateFrom), + SizedBox( + height: 4, + ), + _dateSelection(TranslationBase + .of(context) + .dateTo, (date) { + setState(() { + dateTo = date; + }); + }, dateTo), + SizedBox( + height: 8, + ), + Row(children: [ + Expanded( + child: AppButton( + title: TranslationBase + .of(context) + .search, + hasBorder: true, + borderColor: Color(0xFFB8382B), + color: AppGlobal.appRedColor, + fontColor: Colors.white, + onPressed: () async { + //(dateFrom, dateTo, admissionNumber, patientId, nursingStation) + widget.onDispose(dateFrom, dateTo, nursingStation.text, + patientId.text, nursingStation.text); + }, + ), + ), + ]), + ], + ), + ), + ); + } + + Widget _dateSelection(String title, Function(String) onDateSelected, + String selectedDate) { + return GestureDetector( + onTap: () => _selectDate(onDateSelected), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text(title), + Expanded( + child: ListTile( + title: Text( + selectedDate, + ), + trailing: Icon(Icons.arrow_drop_down_outlined), + ), + ) + ], + ), + ); + } + + Future _selectDate(Function(String) updateDate) async { + final DateTime? picked = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(DateTime + .now() + .year - 150), + lastDate: DateTime(DateTime + .now() + .year + 150), + initialEntryMode: DatePickerEntryMode.calendar, + builder: (_, child) { + return Theme( + data: ThemeData.light().copyWith( + colorScheme: ColorScheme.fromSwatch( + primarySwatch: Colors.red, + accentColor: AppGlobal.appRedColor, + ), + dialogBackgroundColor: Colors.white, + ), + child: child!, + ); + }); + if (picked != null) { + updateDate(getFormattedDate(picked)); + } + // } + } + + Widget _titleAndTextField(String title, TextEditingController controller, + TextInputType? inputType) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisSize: MainAxisSize.min, + children: [ + Text(title), + Expanded( + child: TextFormField( + keyboardType: inputType, + decoration: InputDecoration( + hintText: '', + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + contentPadding: EdgeInsetsDirectional.only(start: 10.0), + ), + textAlign: TextAlign.end, + controller: controller, + ), + ) + ], + ); + } + + void initFromDate() { + var time = DateTime.now(); + dateFrom = getFormattedDate(time); + } + + String getFormattedDate(DateTime time) { + return DateFormat('yyyy-MM-dd').format(time); + } + + String getDate(String dateTime) { + if (dateTime.isEmpty) return ''; + List splitedDate = dateTime.split('-'); + DateTime now = DateTime(int.parse(splitedDate[0]), + int.parse(splitedDate[1]), int.parse(splitedDate[2])); + return DateFormat('yyyy-MM-dd').format(now); + } +} \ No newline at end of file diff --git a/lib/screens/pharmacy_intervention/widgets/intervention_history_item.dart b/lib/screens/pharmacy_intervention/widgets/intervention_history_item.dart new file mode 100644 index 00000000..1b56d282 --- /dev/null +++ b/lib/screens/pharmacy_intervention/widgets/intervention_history_item.dart @@ -0,0 +1,105 @@ +import 'package:doctor_app_flutter/config/config.dart'; +import 'package:doctor_app_flutter/core/model/pharmacy-intervention-model/intervention_history.dart'; +import 'package:doctor_app_flutter/utils/translations_delegate_base_utils.dart'; +import 'package:doctor_app_flutter/widgets/shared/app_texts_widget.dart'; +import 'package:doctor_app_flutter/widgets/shared/buttons/app_buttons_widget.dart'; +import 'package:flutter/material.dart'; + +class InterventionHistoryItem extends StatelessWidget { + final InterventionHistory interventionHistory; + final Function(InterventionHistory) onAcceptClick; + + // string is index here + final Function(InterventionHistory) onRejectClick; + + const InterventionHistoryItem({ + super.key, + required this.interventionHistory, + required this.onAcceptClick, + required this.onRejectClick, + }); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + AppText( + interventionHistory.interventionDesc ?? '', + fontWeight: FontWeight.w600, + fontSize: 12, + color: Color(0xFF2B353E), + ), + SizedBox( + height: 4, + ), + AppText( + "${TranslationBase + .of(context) + .commentedBy}: ${interventionHistory.commentedByName}", + fontWeight: FontWeight.w600, + fontSize: 12, + color: Color(0xFF2B353E), + ), + AppText( + "${TranslationBase + .of(context) + .remarks}: ${interventionHistory.remark?.isNotEmpty == true + ? interventionHistory.remark + : TranslationBase + .of(context) + .noRemarks}", + fontWeight: FontWeight.w600, + fontSize: 12, + color: Color(0xFF2B353E), + ), + SizedBox(height: 8,), + Row(children: [ + Expanded( + child: SizedBox( + height: 48, + child: AppButton( + title: TranslationBase + .of(context) + .reject, + hasBorder: true, + borderColor: Color(0xFFB8382B), + color: AppGlobal.appRedColor, + fontColor: Colors.white, + onPressed: () async { + onRejectClick(interventionHistory); + }, + ), + ), + ), + SizedBox( + width: 6, + ), + Expanded( + child: SizedBox( + height: 48, + child: AppButton( + title: TranslationBase + .of(context) + .accept, + hasBorder: true, + borderColor: AppGlobal.appGreenColor, + color: AppGlobal.appGreenColor, + fontColor: Colors.white, + onPressed: () async { + onAcceptClick(interventionHistory); + }, + ), + ), + ), + ]), + SizedBox(height: 4,), + + ], + ), + ); + } + +} diff --git a/lib/utils/translations_delegate_base_utils.dart b/lib/utils/translations_delegate_base_utils.dart index b91d8a44..f275e001 100644 --- a/lib/utils/translations_delegate_base_utils.dart +++ b/lib/utils/translations_delegate_base_utils.dart @@ -1977,6 +1977,22 @@ class TranslationBase { localizedValues['pharmacyRemarks']![locale.languageCode]!; String get unableToPerformTheAction => localizedValues['unableToPerformTheAction']![locale.languageCode]!; + + + String get interventionRejectedSuccessfully => + localizedValues['interventionRejectedSuccessfully']![locale.languageCode]!; + String get interventionAcceptedSuccessfully => + localizedValues['interventionAcceptedSuccessfully']![locale.languageCode]!; + + String get commentedBy => + localizedValues['commentedBy']![locale.languageCode]!; + + String get noInterventionFound => + localizedValues['noInterventionFound']![locale.languageCode]!; + + String get youHavePendingInterventions => localizedValues['youHavePendingInterventions']![locale.languageCode]!; + String get dateToCanNotBeEmpty => localizedValues['dateToCanNotBeEmpty']![locale.languageCode]!; + String get dateFromCanNotBeEmpty => localizedValues['dateFromCanNotBeEmpty']![locale.languageCode]!; } class TranslationBaseDelegate extends LocalizationsDelegate { diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index 148474f0..bce2f9b0 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -26,8 +26,8 @@ class Utils { get currentLanguage => null; - static showConfirmationDialog(BuildContext context, String message, Function okFunction, {bool isShowCancelButton = true}) { - return showDialog( + static showConfirmationDialog(BuildContext context, String message, Function okFunction, {bool isShowCancelButton = true}) async { + return await showDialog( context: context, barrierDismissible: false, // user must tap button! builder: (_) { @@ -42,7 +42,7 @@ class Utils { ), actions: [ AppButton( - onPressed: okFunction(), + onPressed:() => okFunction(), title: TranslationBase.of(context).noteConfirm, fontColor: Colors.white, color: AppGlobal.appGreenColor,