From 6d989e3fc3cc465b3814bd8899205681a856b335 Mon Sep 17 00:00:00 2001 From: Elham Rababah Date: Thu, 20 May 2021 14:19:30 +0300 Subject: [PATCH 1/2] finish new service for live care --- .../patient/LiveCarePatientServices.dart | 17 ++ .../viewModel/LiveCarePatientViewModel.dart | 24 ++ .../profile/in_patient_profile_screen.dart | 227 ------------------ .../patient_profile_screen.dart | 79 +++--- .../profile_gird_for_other.dart | 108 ++++++--- .../radiology/radiology_home_page.dart | 14 +- .../vital_sign/vital_sign_details_screen.dart | 36 +-- .../prescription/prescriptions_page.dart | 14 +- lib/screens/procedures/procedure_screen.dart | 15 +- .../profile/PatientProfileButton.dart | 5 +- 10 files changed, 198 insertions(+), 341 deletions(-) delete mode 100644 lib/screens/patients/profile/in_patient_profile_screen.dart diff --git a/lib/core/service/patient/LiveCarePatientServices.dart b/lib/core/service/patient/LiveCarePatientServices.dart index a0c94af0..e4443b9b 100644 --- a/lib/core/service/patient/LiveCarePatientServices.dart +++ b/lib/core/service/patient/LiveCarePatientServices.dart @@ -1,12 +1,18 @@ import 'package:doctor_app_flutter/config/config.dart'; import 'package:doctor_app_flutter/core/model/live_care/PendingPatientERForDoctorAppRequestModel.dart'; import 'package:doctor_app_flutter/core/service/base/base_service.dart'; +import 'package:doctor_app_flutter/models/livecare/end_call_req.dart'; import 'package:doctor_app_flutter/models/patient/patiant_info_model.dart'; class LiveCarePatientServices extends BaseService{ List _patientList = []; List get patientList => _patientList; + bool _isFinished = false; + bool get isFinished => _isFinished; + + var endCallResponse = {}; + Future getPendingPatientERForDoctorApp(PendingPatientERForDoctorAppRequestModel pendingPatientERForDoctorAppRequestModel) async{ hasError = false; await baseAppClient.post( @@ -25,4 +31,15 @@ class LiveCarePatientServices extends BaseService{ ); } + Future endCall(EndCallReq endCallReq) async { + + await baseAppClient.post(END_CALL, onSuccess: (response, statusCode) async { + _isFinished = true; + endCallResponse = response; + }, onFailure: (String error, int statusCode) { + _isFinished = true; + throw error; + }, body: endCallReq.toJson()); + } + } \ No newline at end of file diff --git a/lib/core/viewModel/LiveCarePatientViewModel.dart b/lib/core/viewModel/LiveCarePatientViewModel.dart index 803ea92a..0cce5f86 100644 --- a/lib/core/viewModel/LiveCarePatientViewModel.dart +++ b/lib/core/viewModel/LiveCarePatientViewModel.dart @@ -3,6 +3,7 @@ import 'package:doctor_app_flutter/core/model/live_care/PendingPatientERForDocto import 'package:doctor_app_flutter/core/service/home/dasboard_service.dart'; import 'package:doctor_app_flutter/core/service/patient/LiveCarePatientServices.dart'; import 'package:doctor_app_flutter/core/viewModel/base_view_model.dart'; +import 'package:doctor_app_flutter/models/livecare/end_call_req.dart'; import 'package:doctor_app_flutter/models/patient/patiant_info_model.dart'; import '../../locator.dart'; @@ -13,6 +14,8 @@ class LiveCarePatientViewModel extends BaseViewModel { LiveCarePatientServices _liveCarePatientServices = locator(); + bool get isFinished => _liveCarePatientServices.isFinished; + DashboardService _dashboardService = locator(); @@ -33,6 +36,27 @@ class LiveCarePatientViewModel extends BaseViewModel { } } + Future endCall(request, isPatient, doctorID) async { + + EndCallReq endCallReq = new EndCallReq(); + endCallReq.doctorId = doctorID; //profile["DoctorID"]; + endCallReq.generalid = 'Cs2020@2016\$2958'; + endCallReq.vCID = request.vCID; //["VC_ID"]; + endCallReq.isDestroy = isPatient; + + setState(ViewState.BusyLocal); + await _liveCarePatientServices + .endCall(endCallReq); + if (_liveCarePatientServices.hasError) { + error = _liveCarePatientServices.error; + + setState(ViewState.ErrorLocal); + } else { + filterData = _liveCarePatientServices.patientList; + setState(ViewState.Idle); + } + } + searchData(String str) { var strExist= str.length > 0 ? true : false; if (strExist) { diff --git a/lib/screens/patients/profile/in_patient_profile_screen.dart b/lib/screens/patients/profile/in_patient_profile_screen.dart deleted file mode 100644 index 8b1c3b7e..00000000 --- a/lib/screens/patients/profile/in_patient_profile_screen.dart +++ /dev/null @@ -1,227 +0,0 @@ -import 'package:doctor_app_flutter/core/viewModel/patient_view_model.dart'; -import 'package:doctor_app_flutter/models/patient/patiant_info_model.dart'; -import 'package:doctor_app_flutter/screens/base/base_view.dart'; -import 'package:doctor_app_flutter/util/translations_delegate_base.dart'; -import 'package:doctor_app_flutter/widgets/patients/profile/PatientProfileButton.dart'; -import 'package:doctor_app_flutter/widgets/patients/profile/patient-profile-header-new-design-app-bar.dart'; -import 'package:doctor_app_flutter/widgets/patients/profile/patient-profile-header-new-design.dart'; -import 'package:doctor_app_flutter/widgets/patients/profile/patient-profile-header-new-design_in_patient.dart'; -import 'package:doctor_app_flutter/widgets/shared/app_scaffold_widget.dart'; -import 'package:flutter/material.dart'; -import '../../../routes.dart'; - - -class InPatientProfileScreen extends StatefulWidget { - @override - _InPatientProfileScreenState createState() => _InPatientProfileScreenState(); -} - -class _InPatientProfileScreenState extends Statewith SingleTickerProviderStateMixin { - PatiantInformtion patient; - - bool isFromSearch = false; - - bool isInpatient = false; - - bool isDischargedPatient = false; - String patientType; - String arrivalType; - String from; - String to; - - - @override - void didChangeDependencies() { - super.didChangeDependencies(); - final routeArgs = ModalRoute.of(context).settings.arguments as Map; - patient = routeArgs['patient']; - patientType = routeArgs['patientType']; - arrivalType = routeArgs['arrivalType']; - from = routeArgs['from']; - to = routeArgs['to']; - if (routeArgs.containsKey("isSearch")) { - isFromSearch = routeArgs['isSearch']; - } - if (routeArgs.containsKey("isInpatient")) { - isInpatient = routeArgs['isInpatient']; - } - if (routeArgs.containsKey("isDischargedPatient")) { - isDischargedPatient = routeArgs['isDischargedPatient']; - } - - } - - @override - Widget build(BuildContext context) { - return BaseView( - builder: (_, patientViewModel, w) => AppScaffold( - baseViewModel: patientViewModel, - appBarTitle: TranslationBase.of(context).patientProfile, - isShowAppBar: true, - appBar: PatientProfileHeaderNewDesignAppBar(patient,arrivalType??'0',patientType), - body: SingleChildScrollView( - child: Container( - margin: EdgeInsets.only(top: 10), - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 15.0,horizontal: 15), - child: GridView.count( - shrinkWrap: true, - physics: NeverScrollableScrollPhysics(), - crossAxisSpacing: 10, - mainAxisSpacing: 10, - childAspectRatio: 1 / 1.0, - crossAxisCount: 3, - children: [ - PatientProfileButton( - patient: patient, - patientType: patientType, - arrivalType: arrivalType, - from: from, - to: to, - nameLine1: TranslationBase.of(context).vital, - nameLine2: TranslationBase.of(context).signs, - route: VITAL_SIGN_DETAILS, - isInPatient: true, - icon: 'patient/vital_signs.png'), - PatientProfileButton( - patient: patient, - patientType: patientType, - arrivalType: arrivalType, - route: LAB_RESULT, - isInPatient: true, - nameLine1: TranslationBase.of(context).lab, - nameLine2: TranslationBase.of(context).result, - icon: 'patient/lab_results.png'), - PatientProfileButton( - - patient: patient, - patientType: patientType, - arrivalType: arrivalType, - isInPatient: isInpatient, - route: RADIOLOGY_PATIENT, - nameLine1: TranslationBase.of(context).radiology, - nameLine2: TranslationBase.of(context).result, - icon: 'patient/health_summary.png'), - PatientProfileButton( - patient: patient, - patientType: patientType, - arrivalType: arrivalType, - route: ORDER_PRESCRIPTION_NEW, - nameLine1: TranslationBase.of(context).patient, - nameLine2: TranslationBase.of(context).prescription, - icon: 'patient/order_prescription.png'), - PatientProfileButton( - patient: patient, - patientType: patientType, - arrivalType: arrivalType, - route: PROGRESS_NOTE, - isDischargedPatient: isDischargedPatient, - nameLine1: TranslationBase.of(context).progress, - nameLine2: TranslationBase.of(context).note, - icon: 'patient/Progress_notes.png'), - PatientProfileButton( - patient: patient, - patientType: patientType, - arrivalType: arrivalType, - route: ORDER_NOTE, - isDischargedPatient: isDischargedPatient, - nameLine1: "Order", //"Text", - nameLine2: - "Sheet", //TranslationBase.of(context).orders, - icon: 'patient/Progress_notes.png'), - PatientProfileButton( - patient: patient, - patientType: patientType, - arrivalType: arrivalType, - route: ORDER_PROCEDURE, - nameLine1: TranslationBase.of(context).orders, - nameLine2: TranslationBase.of(context).procedures, - icon: 'patient/Order_Procedures.png'), - PatientProfileButton( - patient: patient, - patientType: patientType, - arrivalType: arrivalType, - route: HEALTH_SUMMARY, - nameLine1: "Health", - //TranslationBase.of(context).medicalReport, - nameLine2: "Summary", - //TranslationBase.of(context).summaryReport, - icon: 'patient/health_summary.png'), - PatientProfileButton( - patient: patient, - patientType: patientType, - arrivalType: arrivalType, - isDisable: true, - route: HEALTH_SUMMARY, - nameLine1: "Medical", //Health - //TranslationBase.of(context).medicalReport, - nameLine2: "Report", //Report - //TranslationBase.of(context).summaryReport, - icon: 'patient/health_summary.png'), - PatientProfileButton( - patient: patient, - patientType: patientType, - arrivalType: arrivalType, - route: REFER_IN_PATIENT_TO_DOCTOR, - isInPatient: true, - nameLine1: TranslationBase.of(context).referral, - nameLine2: TranslationBase.of(context).patient, - icon: 'patient/refer_patient.png'), - PatientProfileButton( - patient: patient, - patientType: patientType, - arrivalType: arrivalType, - route: PATIENT_INSURANCE_APPROVALS_NEW, - nameLine1: TranslationBase.of(context).insurance, - nameLine2: TranslationBase.of(context).approvals, - icon: 'patient/vital_signs.png'), - PatientProfileButton( - - patient: patient, - patientType: patientType, - arrivalType: arrivalType, - isDisable: true, - route: null, - nameLine1: "Discharge", - nameLine2: "Summery", - icon: 'patient/patient_sick_leave.png'), - PatientProfileButton( - - patient: patient, - patientType: patientType, - arrivalType: arrivalType, - route: ADD_SICKLEAVE, - nameLine1: TranslationBase.of(context).patientSick, - nameLine2: TranslationBase.of(context).leave, - icon: 'patient/patient_sick_leave.png'), - ], - ), - ), - ), - ), - )); - } -} - -class AvatarWidget extends StatelessWidget { - final Widget avatarIcon; - - AvatarWidget(this.avatarIcon); - - @override - Widget build(BuildContext context) { - return Container( - decoration: BoxDecoration( - boxShadow: [ - BoxShadow( - color: Color.fromRGBO(0, 0, 0, 0.08), - offset: Offset(0.0, 5.0), - blurRadius: 16.0) - ], - borderRadius: BorderRadius.all(Radius.circular(35.0)), - color: Color(0xffCCCCCC), - ), - child: avatarIcon, - ); - } -} diff --git a/lib/screens/patients/profile/profile_screen/patient_profile_screen.dart b/lib/screens/patients/profile/profile_screen/patient_profile_screen.dart index dc4324ec..344c5394 100644 --- a/lib/screens/patients/profile/profile_screen/patient_profile_screen.dart +++ b/lib/screens/patients/profile/profile_screen/patient_profile_screen.dart @@ -1,3 +1,4 @@ +import 'package:doctor_app_flutter/core/viewModel/LiveCarePatientViewModel.dart'; import 'package:doctor_app_flutter/core/viewModel/SOAP_view_model.dart'; import 'package:doctor_app_flutter/core/viewModel/patient_view_model.dart'; import 'package:doctor_app_flutter/models/SOAP/PostEpisodeReqModel.dart'; @@ -85,9 +86,9 @@ class _PatientProfileScreenState extends State @override Widget build(BuildContext context) { final screenSize = MediaQuery.of(context).size; - return BaseView( - builder: (_, patientViewModel, w) => AppScaffold( - baseViewModel: patientViewModel, + return BaseView( + builder: (_, model, w) => AppScaffold( + baseViewModel: model, appBarTitle: TranslationBase.of(context).patientProfile, isShowAppBar: false, body: Column( @@ -119,34 +120,35 @@ class _PatientProfileScreenState extends State child: isSearchAndOut ? ProfileGridForSearch( patient: patient, - patientType: patientType, - arrivalType: arrivalType, - isInpatient: isInpatient, - from: from, - to: to, - ) - : isInpatient - ? ProfileGridForInPatient( - patient: patient, - patientType: patientType, - arrivalType: arrivalType, - isInpatient: isInpatient, - from: from, - to: to, - isDischargedPatient: - isDischargedPatient, - isFromSearch: isFromSearch, - ) - : ProfileGridForOther( - patient: patient, - patientType: patientType, - arrivalType: arrivalType, - isInpatient: isInpatient, - from: from, - to: to, - ), - ), - SizedBox( + patientType: patientType, + arrivalType: arrivalType, + isInpatient: isInpatient, + from: from, + to: to, + ) + : isInpatient + ? ProfileGridForInPatient( + patient: patient, + patientType: patientType, + arrivalType: arrivalType, + isInpatient: isInpatient, + from: from, + to: to, + isDischargedPatient: + isDischargedPatient, + isFromSearch: isFromSearch, + ) + : ProfileGridForOther( + patient: patient, + patientType: patientType, + arrivalType: arrivalType, + isInpatient: isInpatient, + isFromLiveCare: isFromLiveCare, + from: from, + to: to, + ), + ), + SizedBox( height: MediaQuery.of(context).size.height * 0.05, ) ], @@ -270,14 +272,19 @@ class _PatientProfileScreenState extends State child: Center( child: AppButton( fontWeight: FontWeight.w700, - color: Colors.green[600], - title: TranslationBase + color: model.isFinished?Colors.red[600]:Colors.green[600], + title: model.isFinished?"End":TranslationBase .of(context) .initiateCall, onPressed: () async { - Navigator.push(context, MaterialPageRoute( - builder: (BuildContext context) => - EndCallScreen(patient:patient))); + if(model.isFinished) { + Navigator.push(context, MaterialPageRoute( + builder: (BuildContext context) => + EndCallScreen(patient:patient))); + } else { + // TODO Call initiateCall service + } + }, ), ), diff --git a/lib/screens/patients/profile/profile_screen/profile_gird_for_other.dart b/lib/screens/patients/profile/profile_screen/profile_gird_for_other.dart index 86ccd6d1..fee8b1e1 100644 --- a/lib/screens/patients/profile/profile_screen/profile_gird_for_other.dart +++ b/lib/screens/patients/profile/profile_screen/profile_gird_for_other.dart @@ -14,6 +14,7 @@ class ProfileGridForOther extends StatelessWidget { final String arrivalType; final double height; final bool isInpatient; + final bool isFromLiveCare; String from; String to; @@ -25,7 +26,8 @@ class ProfileGridForOther extends StatelessWidget { this.height, this.isInpatient, this.from, - this.to}) + this.to, + this.isFromLiveCare}) : super(key: key); @override @@ -74,41 +76,67 @@ class ProfileGridForOther extends StatelessWidget { 'patient/Order_Procedures.png', isInPatient: isInpatient), PatientProfileCardModel( - TranslationBase.of(context).insurance, - TranslationBase.of(context).service, + TranslationBase + .of(context) + .insurance, + TranslationBase + .of(context) + .service, PATIENT_INSURANCE_APPROVALS_NEW, 'patient/vital_signs.png', isInPatient: isInpatient), PatientProfileCardModel( - TranslationBase.of(context).patientSick, - TranslationBase.of(context).leave, + TranslationBase + .of(context) + .patientSick, + TranslationBase + .of(context) + .leave, ADD_SICKLEAVE, 'patient/patient_sick_leave.png', isInPatient: isInpatient), - if (patient.appointmentNo != null && patient.appointmentNo != 0) - PatientProfileCardModel( - TranslationBase.of(context).patient, - TranslationBase.of(context).ucaf, - PATIENT_UCAF_REQUEST, - 'patient/ucaf.png', - isInPatient: isInpatient, - isDisable: patient.patientStatusType != 43 ? true : false), - if (patient.appointmentNo != null && patient.appointmentNo != 0) - PatientProfileCardModel( - TranslationBase.of(context).referral, - TranslationBase.of(context).patient, - REFER_PATIENT_TO_DOCTOR, - 'patient/refer_patient.png', - isInPatient: isInpatient, - isDisable: patient.patientStatusType != 43 ? true : false), - if (patient.appointmentNo != null && patient.appointmentNo != 0) + if (isFromLiveCare || + (patient.appointmentNo != null && patient.appointmentNo != 0)) PatientProfileCardModel( - TranslationBase.of(context).admission, - TranslationBase.of(context).request, + TranslationBase + .of(context) + .patient, + TranslationBase + .of(context) + .ucaf, + PATIENT_UCAF_REQUEST, + 'patient/ucaf.png', + isInPatient: isInpatient, + isDisable: patient.patientStatusType != 43 || + patient.appointmentNo == null ? true : false), + if (isFromLiveCare || + (patient.appointmentNo != null && patient.appointmentNo != 0)) + PatientProfileCardModel( + TranslationBase + .of(context) + .referral, + TranslationBase + .of(context) + .patient, + REFER_PATIENT_TO_DOCTOR, + 'patient/refer_patient.png', + isInPatient: isInpatient, + isDisable: patient.patientStatusType != 43 || + patient.appointmentNo == null ? true : false), + if (isFromLiveCare || + (patient.appointmentNo != null && patient.appointmentNo != 0)) + PatientProfileCardModel( + TranslationBase + .of(context) + .admission, + TranslationBase + .of(context) + .request, PATIENT_ADMISSION_REQUEST, 'patient/admission_req.png', isInPatient: isInpatient, - isDisable: patient.patientStatusType != 43 ? true : false), + isDisable: patient.patientStatusType != 43 || + patient.appointmentNo == null ? true : false), ]; return Column( @@ -124,20 +152,22 @@ class ProfileGridForOther extends StatelessWidget { itemCount: cardsList.length, staggeredTileBuilder: (int index) => StaggeredTile.fit(1), itemBuilder: (BuildContext context, int index) => PatientProfileButton( - patient: patient, - patientType: patientType, - arrivalType: arrivalType, - from: from, - to: to, - nameLine1: cardsList[index].nameLine1, - nameLine2: cardsList[index].nameLine2, - route: cardsList[index].route, - icon: cardsList[index].icon, - isInPatient: cardsList[index].isInPatient, - isDischargedPatient: cardsList[index].isDischargedPatient, - isDisable: cardsList[index].isDisable, - onTap: cardsList[index].onTap, - isLoading: cardsList[index].isLoading, + patient: patient, + patientType: patientType, + arrivalType: arrivalType, + from: from, + to: to, + nameLine1: cardsList[index].nameLine1, + nameLine2: cardsList[index].nameLine2, + route: cardsList[index].route, + icon: cardsList[index].icon, + isInPatient: cardsList[index].isInPatient, + isDischargedPatient: cardsList[index].isDischargedPatient, + isDisable: cardsList[index].isDisable, + onTap: cardsList[index].onTap, + isLoading: cardsList[index].isLoading, + isFromLiveCare: isFromLiveCare + ), ), ), diff --git a/lib/screens/patients/profile/radiology/radiology_home_page.dart b/lib/screens/patients/profile/radiology/radiology_home_page.dart index 4b8d224e..7d70b677 100644 --- a/lib/screens/patients/profile/radiology/radiology_home_page.dart +++ b/lib/screens/patients/profile/radiology/radiology_home_page.dart @@ -25,6 +25,7 @@ class _RadiologyHomePageState extends State { PatiantInformtion patient; String arrivalType; bool isInpatient; + bool isFromLiveCare; @override void didChangeDependencies() { @@ -34,6 +35,7 @@ class _RadiologyHomePageState extends State { patientType = routeArgs['patientType']; arrivalType = routeArgs['arrivalType']; isInpatient = routeArgs['isInpatient']; + isFromLiveCare = routeArgs['isFromLiveCare']; print(arrivalType); } @@ -97,21 +99,25 @@ class _RadiologyHomePageState extends State { fontSize: 13, ), AppText( - TranslationBase.of(context).result, + TranslationBase + .of(context) + .result, bold: true, fontSize: 22, ), ], ), ), - if (patient.patientStatusType != null && - patient.patientStatusType == 43) + if ((patient.patientStatusType != null && + patient.patientStatusType == 43) || + (isFromLiveCare && patient.appointmentNo != null)) AddNewOrder( onTap: () { Navigator.push( context, MaterialPageRoute( - builder: (context) => AddSelectedRadiologyOrder( + builder: (context) => + AddSelectedRadiologyOrder( patient: patient, model: model, )), diff --git a/lib/screens/patients/profile/vital_sign/vital_sign_details_screen.dart b/lib/screens/patients/profile/vital_sign/vital_sign_details_screen.dart index a6f36784..4f3deeb3 100644 --- a/lib/screens/patients/profile/vital_sign/vital_sign_details_screen.dart +++ b/lib/screens/patients/profile/vital_sign/vital_sign_details_screen.dart @@ -9,9 +9,9 @@ import 'package:doctor_app_flutter/util/translations_delegate_base.dart'; import 'package:doctor_app_flutter/widgets/patients/profile/patient-profile-header-new-design-app-bar.dart'; import 'package:doctor_app_flutter/widgets/shared/app_scaffold_widget.dart'; import 'package:doctor_app_flutter/widgets/shared/app_texts_widget.dart'; +import 'package:doctor_app_flutter/widgets/shared/errors/error_message.dart'; import 'package:doctor_app_flutter/widgets/transitions/fade_page.dart'; import 'package:flutter/material.dart'; -import 'package:hexcolor/hexcolor.dart'; class VitalSignDetailsScreen extends StatelessWidget { int appointmentNo; @@ -39,6 +39,7 @@ class VitalSignDetailsScreen extends StatelessWidget { builder: (_, mode, widget) => AppScaffold( baseViewModel: mode, isShowAppBar: true, + backgroundColor: Theme.of(context).scaffoldBackgroundColor, appBar: PatientProfileHeaderNewDesignAppBar( patient, patientType, arrivalType), appBarTitle: TranslationBase.of(context).vitalSign, @@ -587,31 +588,18 @@ class VitalSignDetailsScreen extends StatelessWidget { ), ), ], - ), - ), - ), - ], - ) - : Center( - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - SizedBox( - height: 100, - ), - Image.asset('assets/images/no-data.png'), - Padding( - padding: const EdgeInsets.all(8.0), - child: AppText( - TranslationBase.of(context).vitalSignEmptyMsg, - fontWeight: FontWeight.normal, - color: HexColor("#B8382B"), - fontSize: SizeConfig.textMultiplier * 2.5, - ), - ) - ], ), ), + ), + ], + ) + : Container( + color: Theme + .of(context) + .scaffoldBackgroundColor, + child: ErrorMessage(error: TranslationBase + .of(context) + .vitalSignEmptyMsg,)), ), ); } diff --git a/lib/screens/prescription/prescriptions_page.dart b/lib/screens/prescription/prescriptions_page.dart index a7367cf3..9bfd9b49 100644 --- a/lib/screens/prescription/prescriptions_page.dart +++ b/lib/screens/prescription/prescriptions_page.dart @@ -26,8 +26,8 @@ class PrescriptionsPage extends StatelessWidget { String patientType = routeArgs['patientType']; String arrivalType = routeArgs['arrivalType']; bool isInpatient = routeArgs['isInpatient']; + bool isFromLiveCare = routeArgs['isFromLiveCare']; bool isSelectInpatient = routeArgs['isSelectInpatient']; - ProjectViewModel projectViewModel = Provider.of(context); return BaseView( onModelReady: (model) => isSelectInpatient ? model.getPrescriptionsInPatient(patient) @@ -86,21 +86,25 @@ class PrescriptionsPage extends StatelessWidget { fontSize: 13, ), AppText( - TranslationBase.of(context).prescriptions, + TranslationBase + .of(context) + .prescriptions, bold: true, fontSize: 22, ), ], ), ), - if (patient.patientStatusType != null && - patient.patientStatusType == 43) + if ((patient.patientStatusType != null && + patient.patientStatusType == 43) || + (isFromLiveCare && patient.appointmentNo != null)) AddNewOrder( onTap: () { addPrescriptionForm(context, model, patient, model.prescriptionList); }, - label: TranslationBase.of(context) + label: TranslationBase + .of(context) .applyForNewPrescriptionsOrder, ), ...List.generate( diff --git a/lib/screens/procedures/procedure_screen.dart b/lib/screens/procedures/procedure_screen.dart index b964392e..1829957d 100644 --- a/lib/screens/procedures/procedure_screen.dart +++ b/lib/screens/procedures/procedure_screen.dart @@ -5,7 +5,6 @@ import 'package:doctor_app_flutter/core/viewModel/procedure_View_model.dart'; import 'package:doctor_app_flutter/models/doctor/doctor_profile_model.dart'; import 'package:doctor_app_flutter/models/patient/patiant_info_model.dart'; import 'package:doctor_app_flutter/screens/base/base_view.dart'; -import 'package:doctor_app_flutter/screens/procedures/add-procedure-form.dart'; import 'package:doctor_app_flutter/screens/procedures/add_procedure_homeScreen.dart'; import 'package:doctor_app_flutter/screens/procedures/update-procedure.dart'; import 'package:doctor_app_flutter/util/helpers.dart'; @@ -14,6 +13,7 @@ import 'package:doctor_app_flutter/widgets/patients/profile/patient-profile-head import 'package:doctor_app_flutter/widgets/shared/app_scaffold_widget.dart'; import 'package:doctor_app_flutter/widgets/shared/app_texts_widget.dart'; import 'package:flutter/material.dart'; + import 'ProcedureCard.dart'; class ProcedureScreen extends StatelessWidget { @@ -31,6 +31,7 @@ class ProcedureScreen extends StatelessWidget { PatiantInformtion patient = routeArgs['patient']; String patientType = routeArgs['patientType']; String arrivalType = routeArgs['arrivalType']; + bool isFromLiveCare = routeArgs['isFromLiveCare']; bool isInpatient = routeArgs['isInpatient']; return BaseView( onModelReady: (model) => model.getProcedure( @@ -91,21 +92,25 @@ class ProcedureScreen extends StatelessWidget { fontSize: 13, ), AppText( - TranslationBase.of(context).procedure, + TranslationBase + .of(context) + .procedure, bold: true, fontSize: 22, ), ], ), ), - if (patient.patientStatusType != null && - patient.patientStatusType == 43) + if ((patient.patientStatusType != null && + patient.patientStatusType == 43) || + (isFromLiveCare && patient.appointmentNo != null)) InkWell( onTap: () { Navigator.push( context, MaterialPageRoute( - builder: (context) => AddProcedureHome( + builder: (context) => + AddProcedureHome( patient: patient, model: model, )), diff --git a/lib/widgets/patients/profile/PatientProfileButton.dart b/lib/widgets/patients/profile/PatientProfileButton.dart index c5580568..ef285150 100644 --- a/lib/widgets/patients/profile/PatientProfileButton.dart +++ b/lib/widgets/patients/profile/PatientProfileButton.dart @@ -7,6 +7,7 @@ import 'package:doctor_app_flutter/widgets/shared/dr_app_circular_progress_Indei import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +// ignore: must_be_immutable class PatientProfileButton extends StatelessWidget { final String nameLine1; final String nameLine2; @@ -26,6 +27,7 @@ class PatientProfileButton extends StatelessWidget { final bool isSelectInpatient; final bool isDartIcon; final IconData dartIcon; + final bool isFromLiveCare; PatientProfileButton({ Key key, @@ -45,7 +47,7 @@ class PatientProfileButton extends StatelessWidget { this.isDischargedPatient = false, this.isSelectInpatient = false, this.isDartIcon = false, - this.dartIcon, + this.dartIcon, this.isFromLiveCare = false, }) : super(key: key); @override @@ -142,6 +144,7 @@ class PatientProfileButton extends StatelessWidget { 'isInpatient': isInPatient, 'isDischargedPatient': isDischargedPatient, 'isSelectInpatient': isSelectInpatient, + "isFromLiveCare":isFromLiveCare }); } } From b6cb6362f606ca4f03bb56e62271f28826c171b2 Mon Sep 17 00:00:00 2001 From: hussam al-habibeh Date: Thu, 20 May 2021 14:54:43 +0300 Subject: [PATCH 2/2] adding validation and voice speach to prescription form --- .../prescription/add_prescription_form.dart | 677 +++++++++++------- 1 file changed, 426 insertions(+), 251 deletions(-) diff --git a/lib/screens/prescription/add_prescription_form.dart b/lib/screens/prescription/add_prescription_form.dart index a3c6e589..e80534c1 100644 --- a/lib/screens/prescription/add_prescription_form.dart +++ b/lib/screens/prescription/add_prescription_form.dart @@ -5,10 +5,12 @@ import 'package:doctor_app_flutter/core/enum/viewstate.dart'; import 'package:doctor_app_flutter/core/model/Prescriptions/post_prescrition_req_model.dart'; import 'package:doctor_app_flutter/core/model/Prescriptions/prescription_model.dart'; import 'package:doctor_app_flutter/core/model/search_drug/get_medication_response_model.dart'; +import 'package:doctor_app_flutter/core/provider/robot_provider.dart'; import 'package:doctor_app_flutter/core/viewModel/medicine_view_model.dart'; import 'package:doctor_app_flutter/core/viewModel/prescription_view_model.dart'; import 'package:doctor_app_flutter/core/viewModel/project_view_model.dart'; +import 'package:doctor_app_flutter/icons_app/doctor_app_icons.dart'; import 'package:doctor_app_flutter/models/SOAP/GetAssessmentReqModel.dart'; import 'package:doctor_app_flutter/models/patient/patiant_info_model.dart'; import 'package:doctor_app_flutter/screens/base/base_view.dart'; @@ -23,12 +25,16 @@ 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:doctor_app_flutter/widgets/shared/dialogs/dailog-list-select.dart'; import 'package:doctor_app_flutter/widgets/shared/network_base_view.dart'; +import 'package:doctor_app_flutter/widgets/shared/speech-text-popup.dart'; import 'package:doctor_app_flutter/widgets/shared/text_fields/app-textfield-custom.dart'; import 'package:doctor_app_flutter/widgets/shared/text_fields/app_text_form_field.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:hexcolor/hexcolor.dart'; +import 'package:permission_handler/permission_handler.dart'; import 'package:provider/provider.dart'; +import 'package:speech_to_text/speech_recognition_error.dart'; +import 'package:speech_to_text/speech_to_text.dart' as stt; addPrescriptionForm(context, PrescriptionViewModel model, PatiantInformtion patient, prescription) { @@ -102,6 +108,13 @@ class PrescriptionFormWidget extends StatefulWidget { } class _PrescriptionFormWidgetState extends State { + String routeError; + String frequencyError; + String doseTimeError; + String durationError; + String unitError; + String strengthError; + int selectedType; TextEditingController durationController = TextEditingController(); TextEditingController strengthController = TextEditingController(); @@ -124,6 +137,9 @@ class _PrescriptionFormWidgetState extends State { TextEditingController drugIdController = TextEditingController(); TextEditingController doseController = TextEditingController(); final searchController = TextEditingController(); + stt.SpeechToText speech = stt.SpeechToText(); + var event = RobotProvider(); + var reconizedWord; var notesList; var filteredNotesList; @@ -188,6 +204,60 @@ class _PrescriptionFormWidgetState extends State { }); } + onVoiceText() async { + new SpeechToText(context: context).showAlertDialog(context); + var lang = TranslationBase.of(AppGlobal.CONTEX).locale.languageCode; + bool available = await speech.initialize( + onStatus: statusListener, onError: errorListener); + if (available) { + speech.listen( + onResult: resultListener, + listenMode: stt.ListenMode.confirmation, + localeId: lang == 'en' ? 'en-US' : 'ar-SA', + ); + } else { + print("The user has denied the use of speech recognition."); + } + } + + void errorListener(SpeechRecognitionError error) { + event.setValue({"searchText": 'null'}); + //SpeechToText.closeAlertDialog(context); + print(error); + } + + void statusListener(String status) { + reconizedWord = status == 'listening' ? 'Lisening...' : 'Sorry....'; + } + + void requestPermissions() async { + Map statuses = await [ + Permission.microphone, + ].request(); + } + + void resultListener(result) { + reconizedWord = result.recognizedWords; + event.setValue({"searchText": reconizedWord}); + + if (result.finalResult == true) { + setState(() { + SpeechToText.closeAlertDialog(context); + speech.stop(); + indicationController.text += reconizedWord + '\n'; + }); + } else { + print(result.finalResult); + } + } + + Future initSpeechState() async { + bool hasSpeech = await speech.initialize( + onError: errorListener, onStatus: statusListener); + print(hasSpeech); + if (!mounted) return; + } + @override Widget build(BuildContext context) { ListSelectDialog drugDialog; @@ -244,7 +314,7 @@ class _PrescriptionFormWidgetState extends State { (BuildContext context, ScrollController scrollController) { return SingleChildScrollView( child: Container( - height: MediaQuery.of(context).size.height * 1.45, + height: MediaQuery.of(context).size.height * 1.65, color: Color(0xffF8F8F8), child: Padding( padding: EdgeInsets.symmetric( @@ -437,11 +507,6 @@ class _PrescriptionFormWidgetState extends State { SizedBox( height: spaceBetweenTextFileds), Container( - //height: screenSize.height * 0.062, - height: MediaQuery.of(context) - .size - .height * - 0.0749, width: double.infinity, child: Row( children: [ @@ -451,44 +516,43 @@ class _PrescriptionFormWidgetState extends State { .size .width * 0.35, - child: TextField( - decoration: - textFieldSelectorDecorationStreangrh( - strengthController - .text, - 'Strength', //strengthController.text, - false), - enabled: true, - controller: - strengthController, - onChanged: - (String value) { - setState(() { - strengthChar = - value.length; - }); - if (strengthChar >= 5) { - DrAppToastMsg - .showErrorToast( - TranslationBase.of( - context) - .only5DigitsAllowedForStrength, - ); - } - }, - keyboardType: TextInputType - .numberWithOptions( - decimal: true, - )), + child: AppTextFieldCustom( + height: 40, + validationError: + strengthError, + hintText: 'Strength', + isTextFieldHasSuffix: false, + enabled: true, + controller: + strengthController, + onChanged: (String value) { + setState(() { + strengthChar = + value.length; + }); + if (strengthChar >= 5) { + DrAppToastMsg + .showErrorToast( + TranslationBase.of( + context) + .only5DigitsAllowedForStrength, + ); + } + }, + inputType: TextInputType + .numberWithOptions( + decimal: true, + ), + // keyboardType: TextInputType + // .numberWithOptions( + // decimal: true, + // ), + ), ), SizedBox( width: 5.0, ), Container( - // height: MediaQuery.of(context) - // .size - // .height * - // 0.06, color: Colors.white, width: MediaQuery.of(context) .size @@ -538,23 +602,23 @@ class _PrescriptionFormWidgetState extends State { ); } : null, - child: TextField( - decoration: - textFieldSelectorDecoration( - 'Select', - model.itemMedicineListUnit - .length == - 1 - ? units = model - .itemMedicineListUnit[0] - [ - 'description'] - : units != - null - ? units['description'] - .toString() - : null, - true), + child: AppTextFieldCustom( + hintText: 'Select', + isTextFieldHasSuffix: + true, + dropDownText: model + .itemMedicineListUnit + .length == + 1 + ? units = model + .itemMedicineListUnit[0] + ['description'] + : units != null + ? units['description'] + .toString() + : null, + validationError: + unitError, enabled: false), ), ), @@ -564,7 +628,7 @@ class _PrescriptionFormWidgetState extends State { SizedBox( height: spaceBetweenTextFileds), Container( - height: screenSize.height * 0.070, + //height: screenSize.height * 0.070, color: Colors.white, child: InkWell( onTap: @@ -613,23 +677,44 @@ class _PrescriptionFormWidgetState extends State { ); } : null, - child: TextField( - decoration: - textFieldSelectorDecoration( - TranslationBase.of( - context) - .route, - model.itemMedicineListRoute - .length == - 1 - ? model.itemMedicineListRoute[ - 0] - ['description'] - : route != null - ? route[ - 'description'] - : null, - true), + child: AppTextFieldCustom( + // decoration: + // textFieldSelectorDecoration( + // TranslationBase.of( + // context) + // .route, + // model.itemMedicineListRoute + // .length == + // 1 + // ? model.itemMedicineListRoute[ + // 0] + // ['description'] + // : route != null + // ? route[ + // 'description'] + // : null, + // true), + hintText: + TranslationBase.of(context) + .route, + dropDownText: model + .itemMedicineListRoute + .length == + 1 + ? model.itemMedicineListRoute[ + 0]['description'] + : route != null + ? route['description'] + : null, + isTextFieldHasSuffix: true, + //height: 45, + validationError: + model.itemMedicineListRoute + .length != + 1 + ? routeError + : null, + enabled: false, ), ), @@ -637,7 +722,7 @@ class _PrescriptionFormWidgetState extends State { SizedBox( height: spaceBetweenTextFileds), Container( - height: screenSize.height * 0.070, + //height: screenSize.height * 0.070, color: Colors.white, child: InkWell( onTap: @@ -704,23 +789,22 @@ class _PrescriptionFormWidgetState extends State { ); } : null, - child: TextField( - decoration: - textFieldSelectorDecoration( - TranslationBase.of( - context) - .frequency, - model.itemMedicineList - .length == - 1 - ? model.itemMedicineList[ - 0] - ['description'] - : frequency != null - ? frequency[ - 'description'] - : null, - true), + child: AppTextFieldCustom( + isTextFieldHasSuffix: true, + hintText: + TranslationBase.of(context) + .frequency, + dropDownText: model + .itemMedicineList + .length == + 1 + ? model.itemMedicineList[0] + ['description'] + : frequency != null + ? frequency[ + 'description'] + : null, + validationError: frequencyError, enabled: false, ), ), @@ -728,7 +812,7 @@ class _PrescriptionFormWidgetState extends State { SizedBox( height: spaceBetweenTextFileds), Container( - height: screenSize.height * 0.070, + //height: screenSize.height * 0.070, color: Colors.white, child: InkWell( onTap: @@ -770,17 +854,18 @@ class _PrescriptionFormWidgetState extends State { ); } : null, - child: TextField( - decoration: - textFieldSelectorDecoration( - TranslationBase.of( - context) - .doseTime, - doseTime != null - ? doseTime['nameEn'] - : null, - true), + child: AppTextFieldCustom( + hintText: + TranslationBase.of(context) + .doseTime, + isTextFieldHasSuffix: true, + dropDownText: doseTime != null + ? doseTime['nameEn'] + : null, + //height: 45, + enabled: false, + validationError: doseTimeError, ), ), ), @@ -894,7 +979,7 @@ class _PrescriptionFormWidgetState extends State { SizedBox( height: spaceBetweenTextFileds), Container( - height: screenSize.height * 0.070, + //height: screenSize.height * 0.070, color: Colors.white, child: InkWell( onTap: @@ -963,16 +1048,15 @@ class _PrescriptionFormWidgetState extends State { ); } : null, - child: TextField( - decoration: - textFieldSelectorDecoration( - TranslationBase.of( - context) - .duration, - duration != null - ? duration['nameEn'] - : null, - true), + child: AppTextFieldCustom( + validationError: durationError, + isTextFieldHasSuffix: true, + dropDownText: duration != null + ? duration['nameEn'] + : null, + hintText: + TranslationBase.of(context) + .duration, enabled: false, ), ), @@ -1101,14 +1185,36 @@ class _PrescriptionFormWidgetState extends State { width: 1.0, color: HexColor("#CCCCCC"))), - child: TextFields( - maxLines: 6, - minLines: 4, - hintText: - TranslationBase.of(context) + child: Stack( + children: [ + TextFields( + maxLines: 6, + minLines: 4, + hintText: TranslationBase.of( + context) .instruction, - controller: instructionController, - //keyboardType: TextInputType.number, + controller: + instructionController, + //keyboardType: TextInputType.number, + ), + Positioned( + top: + 0, //MediaQuery.of(context).size.height * 0, + right: 15, + child: IconButton( + icon: Icon( + DoctorApp.speechtotext, + color: Colors.black, + size: 35, + ), + onPressed: () { + initSpeechState().then( + (value) => + {onVoiceText()}); + }, + ), + ), + ], ), ), SizedBox( @@ -1125,139 +1231,205 @@ class _PrescriptionFormWidgetState extends State { context) .addMedication, fontWeight: FontWeight.w600, - onPressed: () { - formKey.currentState.save(); - // Navigator.pop(context); - // openDrugToDrug(); - if (frequency == null || + onPressed: () async { + if (route != null && + duration != null && + doseTime != null && + frequency != null && + units != null && + selectedDate != null && strengthController - .text == - "" || - doseTime == null || - duration == null || - selectedDate == null) { - DrAppToastMsg.showErrorToast( - TranslationBase.of( - context) - .pleaseFillAllFields); - return; - } - if (_selectedMedication - .isNarcotic == - true) { - DrAppToastMsg.showErrorToast( - TranslationBase.of( - context) - .narcoticMedicineCanOnlyBePrescribedFromVida); - Navigator.pop(context); - return; - } + .text != + "") { + if (_selectedMedication + .isNarcotic == + true) { + DrAppToastMsg.showErrorToast( + TranslationBase.of( + context) + .narcoticMedicineCanOnlyBePrescribedFromVida); + Navigator.pop(context); + return; + } - if (double.parse( - strengthController - .text) > - 1000.0) { - DrAppToastMsg.showErrorToast( - "1000 is the MAX for the strength"); - return; - } - if (double.parse( - strengthController - .text) < - 0.0) { - DrAppToastMsg.showErrorToast( - "strength can't be zero"); - return; - } + if (double.parse( + strengthController + .text) > + 1000.0) { + DrAppToastMsg + .showErrorToast( + "1000 is the MAX for the strength"); + return; + } + if (double.parse( + strengthController + .text) < + 0.0) { + DrAppToastMsg + .showErrorToast( + "strength can't be zero"); + return; + } - if (formKey.currentState - .validate()) { - Navigator.pop(context); - openDrugToDrug(model); - { - // postProcedure( - // icdCode: model - // .patientAssessmentList - // .isNotEmpty - // ? model - // .patientAssessmentList[ - // 0] - // .icdCode10ID - // .isEmpty - // ? "test" - // : model - // .patientAssessmentList[ - // 0] - // .icdCode10ID - // .toString() - // : "test", - // // icdCode: model - // // .patientAssessmentList - // // .map((value) => value - // // .icdCode10ID - // // .trim()) - // // .toList() - // // .join(' '), - // dose: strengthController - // .text, - // doseUnit: model - // .itemMedicineListUnit - // .length == - // 1 - // ? model - // .itemMedicineListUnit[ - // 0][ - // 'parameterCode'] - // .toString() - // : units['parameterCode'] - // .toString(), - // patient: widget.patient, - // doseTimeIn: - // doseTime['id'] - // .toString(), - // model: widget.model, - // duration: duration['id'] - // .toString(), - // frequency: model - // .itemMedicineList - // .length == - // 1 - // ? model - // .itemMedicineList[ - // 0][ - // 'parameterCode'] - // .toString() - // : frequency[ - // 'parameterCode'] - // .toString(), - // route: model.itemMedicineListRoute - // .length == - // 1 - // ? model - // .itemMedicineListRoute[ - // 0][ - // 'parameterCode'] - // .toString() - // : route['parameterCode'] - // .toString(), - // drugId: - // _selectedMedication - // .itemId - // .toString(), - // strength: - // strengthController - // .text, - // indication: - // indicationController - // .text, - // instruction: - // instructionController - // .text, - // doseTime: selectedDate, - // ); + if (formKey.currentState + .validate()) { + Navigator.pop(context); + openDrugToDrug(model); + { + // postProcedure( + // icdCode: model + // .patientAssessmentList + // .isNotEmpty + // ? model + // .patientAssessmentList[ + // 0] + // .icdCode10ID + // .isEmpty + // ? "test" + // : model + // .patientAssessmentList[ + // 0] + // .icdCode10ID + // .toString() + // : "test", + // // icdCode: model + // // .patientAssessmentList + // // .map((value) => value + // // .icdCode10ID + // // .trim()) + // // .toList() + // // .join(' '), + // dose: strengthController + // .text, + // doseUnit: model + // .itemMedicineListUnit + // .length == + // 1 + // ? model + // .itemMedicineListUnit[ + // 0][ + // 'parameterCode'] + // .toString() + // : units['parameterCode'] + // .toString(), + // patient: widget.patient, + // doseTimeIn: + // doseTime['id'] + // .toString(), + // model: widget.model, + // duration: duration['id'] + // .toString(), + // frequency: model + // .itemMedicineList + // .length == + // 1 + // ? model + // .itemMedicineList[ + // 0][ + // 'parameterCode'] + // .toString() + // : frequency[ + // 'parameterCode'] + // .toString(), + // route: model.itemMedicineListRoute + // .length == + // 1 + // ? model + // .itemMedicineListRoute[ + // 0][ + // 'parameterCode'] + // .toString() + // : route['parameterCode'] + // .toString(), + // drugId: + // _selectedMedication + // .itemId + // .toString(), + // strength: + // strengthController + // .text, + // indication: + // indicationController + // .text, + // instruction: + // instructionController + // .text, + // doseTime: selectedDate, + // ); + } } + } else { + setState(() { + if (duration == null) { + durationError = + TranslationBase.of( + context) + .fieldRequired; + } else { + durationError = null; + } + if (doseTime == null) { + doseTimeError = + TranslationBase.of( + context) + .fieldRequired; + } else { + doseTimeError = null; + } + if (route == null) { + routeError = + TranslationBase.of( + context) + .fieldRequired; + } else { + routeError = null; + } + if (frequency == null) { + frequencyError = + TranslationBase.of( + context) + .fieldRequired; + } else { + frequencyError = null; + } + if (units == null) { + unitError = + TranslationBase.of( + context) + .fieldRequired; + } else { + unitError = null; + } + if (strengthController + .text == + "") { + strengthError = + TranslationBase.of( + context) + .fieldRequired; + } else { + strengthError = null; + } + }); } + formKey.currentState.save(); + // Navigator.pop(context); + // openDrugToDrug(); + // if (frequency == null || + // strengthController + // .text == + // "" || + // doseTime == null || + // duration == null || + // selectedDate == null) { + // DrAppToastMsg.showErrorToast( + // TranslationBase.of( + // context) + // .pleaseFillAllFields); + // return; + // } + { // Navigator.push( // context, @@ -1430,17 +1602,20 @@ class _PrescriptionFormWidgetState extends State { // .join(' '), dose: strengthController.text, doseUnit: model.itemMedicineListUnit.length == 1 - ? model.itemMedicineListUnit[0]['parameterCode'].toString() + ? model.itemMedicineListUnit[0]['parameterCode'] + .toString() : units['parameterCode'].toString(), patient: widget.patient, doseTimeIn: doseTime['id'].toString(), model: widget.model, duration: duration['id'].toString(), frequency: model.itemMedicineList.length == 1 - ? model.itemMedicineList[0]['parameterCode'].toString() + ? model.itemMedicineList[0]['parameterCode'] + .toString() : frequency['parameterCode'].toString(), route: model.itemMedicineListRoute.length == 1 - ? model.itemMedicineListRoute[0]['parameterCode'].toString() + ? model.itemMedicineListRoute[0]['parameterCode'] + .toString() : route['parameterCode'].toString(), drugId: _selectedMedication.itemId.toString(), strength: strengthController.text,