From e347a35d108c48d2bf75e557321098872b36fe2e Mon Sep 17 00:00:00 2001 From: "taha.alam" Date: Tue, 29 Oct 2024 10:54:10 +0300 Subject: [PATCH 01/14] WD:pharmacy intervention approval ui addition --- lib/config/localized_values.dart | 7 + lib/screens/home/home_patient_card.dart | 6 +- lib/screens/home/home_screen.dart | 25 ++ .../patient_search/patient_search_header.dart | 21 +- .../PharmacyIntervention.dart | 309 ++++++++++++++++++ .../translations_delegate_base_utils.dart | 6 + 6 files changed, 369 insertions(+), 5 deletions(-) create mode 100644 lib/screens/pharmaacy_intervention/PharmacyIntervention.dart diff --git a/lib/config/localized_values.dart b/lib/config/localized_values.dart index c31788f9..a96a0258 100644 --- a/lib/config/localized_values.dart +++ b/lib/config/localized_values.dart @@ -64,6 +64,10 @@ const Map> localizedValues = { "en": "Search\nMedicines", "ar": "بحث\nعن الدواء" }, + "interventionPharmacyApproval": { + "en": "Intervention\nPharmacy Approval", + "ar": "التدخل\nموافقة الصيدلية" + }, "searchMedicine": {"en": "Search Medicines", "ar": "بحث عن الدواء"}, "myReferralPatient": {"en": "My Referral Patient", "ar": "مرضى الاحالة"}, "referPatient": {"en": "Referral Patient", "ar": "إحالة مريض"}, @@ -300,6 +304,7 @@ const Map> localizedValues = { "dateTime": {"en": "DATE / TIME:", "ar": "التاريخ / الوقت:"}, "date": {"en": "Date", "ar": "التاريخ"}, "admissionNo": {"en": "ADMISSION #: ", "ar": "قبول #:"}, + "admissionNumber": {"en": "Admission No.", "ar": "رقم القبول"}, "losNo": {"en": "LOS #:", "ar": "LOS #:"}, "area": {"en": "AREA:", "ar": "المنطقة"}, "room": {"en": "ROOM:", "ar": "الغرفة"}, @@ -1154,12 +1159,14 @@ const Map> localizedValues = { "doctorSchedule": {"en": "Doctor Schedule", "ar":"جدول الطبيب"}, "doctorRota": {"en": "Doctor Rota", "ar":"دوران الطبيب"}, "dateFrom": {"en": "Date From", "ar":"التاريخ من"}, + "dateTo": {"en": "Date To", "ar":"التاريخ إلى"}, "searchFindSchedule": {"en": "Search and find out the doctor’s schedule ", "ar":"بحث ومعرفة جدول الطبيب"}, "onePrimaryDiagnosis": {"en": "There has to be at-least 1 principal diagnosis", "ar":"يجب أن يكون هناك تشخيص رئيسي واحد على الأقل"}, "principalDiagnosisCannot": {"en": "Principal Diagnosis cannot modify once the order created", "ar":"لا يمكن تعديل التشخيص الرئيسي بمجرد إنشاء الطلب"}, "afterOrderCreation": {"en": "After order created, you cannot modify the principal diagnosis, Do you want to continue?", "ar":"بعد إنشاء الطلب، لا يمكنك تعديل التشخيص الأساسي، هل تريد المتابعة؟"}, "principalCoveredOrNot": {"en": "Principal Diagnosis is not covered for this patient", "ar":"لا يتم تغطية التشخيص الرئيسي لهذا المريض"}, "complexDiagnosis": {"en": "Complex Diagnosis", "ar":"التشخيص المعقد"}, + "pharmacyInterventionApproval": {"en": "Pharmacy Intervention Approval", "ar":"الموافقة على التدخل الصيدلي"}, diff --git a/lib/screens/home/home_patient_card.dart b/lib/screens/home/home_patient_card.dart index d2050b7e..f5c502a6 100644 --- a/lib/screens/home/home_patient_card.dart +++ b/lib/screens/home/home_patient_card.dart @@ -13,6 +13,7 @@ class HomePatientCard extends StatelessWidget { final VoidCallback? onTap; final double? iconSize; final LinearGradient? gradient; + final double? fontSize; HomePatientCard({ this.backgroundColor, @@ -24,6 +25,7 @@ class HomePatientCard extends StatelessWidget { this.onTap, this.iconSize = 30, this.gradient, + this.fontSize }); @override @@ -40,7 +42,7 @@ class HomePatientCard extends StatelessWidget { gradient: gradient, margin: EdgeInsets.all(SizeConfig.widthMultiplier! * 1.121), child: Container( - padding: EdgeInsets.all(8), + padding: EdgeInsets.only(left : 8 ), child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, @@ -105,7 +107,7 @@ class HomePatientCard extends StatelessWidget { letterSpacing: -0.33, fontWeight: FontWeight.w600, fontSize: - SizeConfig.getTextMultiplierBasedOnWidth(width: width) * + fontSize?? SizeConfig.getTextMultiplierBasedOnWidth(width: width) * (SizeConfig.isHeightVeryShort ? 11 : 10), ), ), diff --git a/lib/screens/home/home_screen.dart b/lib/screens/home/home_screen.dart index 491efdd1..52655121 100644 --- a/lib/screens/home/home_screen.dart +++ b/lib/screens/home/home_screen.dart @@ -33,6 +33,7 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:provider/provider.dart'; import 'package:sticky_headers/sticky_headers/widget.dart'; +import '../pharmaacy_intervention/PharmacyIntervention.dart'; import 'label.dart'; class HomeScreen extends StatefulWidget { @@ -55,6 +56,12 @@ class _HomeScreenState extends State { var clinicId; AuthenticationViewModel authenticationViewModel = AuthenticationViewModel(); int colorIndex = 0; + double width = SizeConfig.heightMultiplier! * + (SizeConfig.isHeightVeryShort + ? 16 + : SizeConfig.isHeightLarge + ? 15 + : 13); @override Widget build(BuildContext context) { @@ -473,6 +480,24 @@ class _HomeScreenState extends State { }, )); changeColorIndex(); + patientCards.add(HomePatientCard( + gradient: backgroundColors[2], + backgroundIconColor: backgroundIconColors[2], + cardIcon: DoctorApp.search_medicines, + textColor: textColors[2], + text: TranslationBase.of(context).interventionPharmacyApproval, + fontSize: SizeConfig.getTextMultiplierBasedOnWidth(width: width) * + (SizeConfig.isHeightVeryShort ? 10: 9), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => PharmacyIntervention(), + settings: RouteSettings(name: 'PharmacyIntervention'), + )); + }, + )); + changeColorIndex(); return [...List.generate(patientCards.length, (index) => patientCards[index]).toList()]; } diff --git a/lib/screens/patients/patient_search/patient_search_header.dart b/lib/screens/patients/patient_search/patient_search_header.dart index d10a163b..a9a69a6a 100644 --- a/lib/screens/patients/patient_search/patient_search_header.dart +++ b/lib/screens/patients/patient_search/patient_search_header.dart @@ -1,10 +1,17 @@ import 'package:doctor_app_flutter/widgets/shared/app_texts_widget.dart'; import 'package:flutter/material.dart'; -class PatientSearchHeader extends StatelessWidget implements PreferredSizeWidget { +class PatientSearchHeader extends StatelessWidget + implements PreferredSizeWidget { final String? title; + final bool showSearchIcon; + final VoidCallback? onSearchPressed; + final double? fontSize; - const PatientSearchHeader({Key? key, this.title}) : super(key: key); + + const PatientSearchHeader( + {Key? key, this.title, this.showSearchIcon = false, this.onSearchPressed, this.fontSize}) + : super(key: key); @override Widget build(BuildContext context) { @@ -25,13 +32,21 @@ class PatientSearchHeader extends StatelessWidget implements PreferredSizeWidget Expanded( child: AppText( title!, - fontSize: 24.0, + fontSize:fontSize ?? 24.0, fontWeight: FontWeight.w700, color: Color(0xFF2B353E), fontFamily: 'Poppins', letterSpacing: -1.44, ), ), + Visibility( + visible: showSearchIcon, + child: IconButton( + icon: Icon(Icons.search), + color: Color(0xFF2B353E), //Colors.black, + onPressed: () => onSearchPressed?.call(), + ), + ), ]), ), ); diff --git a/lib/screens/pharmaacy_intervention/PharmacyIntervention.dart b/lib/screens/pharmaacy_intervention/PharmacyIntervention.dart new file mode 100644 index 00000000..917917fc --- /dev/null +++ b/lib/screens/pharmaacy_intervention/PharmacyIntervention.dart @@ -0,0 +1,309 @@ +import 'dart:ui'; +import 'package:doctor_app_flutter/core/viewModel/project_view_model.dart'; +import 'package:doctor_app_flutter/screens/patients/ReferralDischargedPatientPage.dart'; +import 'package:doctor_app_flutter/screens/patients/patient_search/patient_search_header.dart'; +import 'package:doctor_app_flutter/screens/patients/profile/referral/refer_details/referred-patient-screen.dart'; +import 'package:doctor_app_flutter/utils/tab_utils.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/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:intl/intl.dart'; + +import '../../config/config.dart'; + +class PharmacyIntervention extends StatefulWidget { + @override + _PharmacyIntervention createState() => _PharmacyIntervention(); +} + +class _PharmacyIntervention extends State + with SingleTickerProviderStateMixin { + TabController? _tabController; + int index = 0; + List listOfPharmacyIntervention = List.empty(); + + @override + void initState() { + super.initState(); + _tabController = TabController(length: 3, vsync: this); + _tabController!.addListener(_handleTabSelection); + } + + _handleTabSelection() { + setState(() { + index = _tabController!.index; + }); + } + + @override + void dispose() { + super.dispose(); + _tabController!.dispose(); + } + + @override + Widget build(BuildContext context) { + ProjectViewModel projectsProvider = Provider.of(context); + + return AppScaffold( + isShowAppBar: true, + appBar: PatientSearchHeader( + title: TranslationBase.of(context).pharmacyInterventionApproval, + fontSize: 18, + showSearchIcon: true, + onSearchPressed: () { + SearchDialog(); + }, + ), + appBarTitle: TranslationBase.of(context).pharmacyInterventionApproval, + body: Column( + children: [ + SizedBox( + height: 56, + child: Row( + mainAxisSize: MainAxisSize.max, + children: [ + Expanded( + child: Container( + decoration: TabUtils.getBoxTabsBoxDecoration( + isActive: index == 0, + isFirst: true, + projectViewModel: projectsProvider), + child: Center( + child: TabUtils.getTabText( + title: TranslationBase.of(context).pending, + isActive: index == 0)), + ), + ), + Expanded( + child: Container( + decoration: TabUtils.getBoxTabsBoxDecoration( + isActive: index == 1, + isMiddle: true, + projectViewModel: projectsProvider), + child: Center( + child: TabUtils.getTabText( + title: TranslationBase.of(context).accepted, + isActive: index == 1)), + ), + ), + Expanded( + child: Container( + decoration: TabUtils.getBoxTabsBoxDecoration( + isActive: index == 2, + isLast: true, + projectViewModel: projectsProvider), + child: Center( + child: TabUtils.getTabText( + title: TranslationBase.of(context).rejected, + isActive: index == 2), + ), + ), + ), + ], + ), + ), + Expanded( + child: ListView.builder( + itemCount: listOfPharmacyIntervention.length, + itemBuilder: (context, item) => SizedBox.shrink()), + ) + ], + )); + } + + void SearchDialog() { + showDialog( + context: context, + barrierDismissible: true, // user must tap button! + builder: (_) { + return PharmacyInterventionDialog( + onDispose: (dateFrom, dateTo, admissionNumber, patientId) {}); + }); + } +} + +class PharmacyInterventionDialog extends StatefulWidget { + final Function( + String, + String, + String, + String, + ) onDispose; + + const PharmacyInterventionDialog({super.key, required this.onDispose}); + + @override + State createState() => + _PharmacyInterventionDialogState(); +} + +class _PharmacyInterventionDialogState + extends State { + final TextEditingController admissionNumber = TextEditingController(); + + final TextEditingController patientId = TextEditingController(); + + String dateFrom = ''; + + String dateTo = ''; + + + @override + void initState() { + super.initState(); + initFromDate(); + } + + @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).admissionNumber, admissionNumber), + SizedBox(height: 4,), + + _titleAndTextField( + TranslationBase.of(context).patientID, patientId), + 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 {}, + ), + ), + ]), + ], + ), + ), + ); + } + + 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 { + // if (calenderType == CalenderType.Hijri) { + // JDateModel hijriDate = JDateModel(dateTime: DateTime.now()); + // final JPickerValue? pickedH = await showGlobalDatePicker( + // context: context, + // pickerType: PickerType.JHijri, + // startDate: birthDateInHijri ?? hijriDate, + // endDate: JDateModel( + // jhijri: JHijri(fDate: hijriDate.dateTime), + // ), + // + // // firstDate: new HijriCalendar() + // // ..hYear = 1438 + // // ..hMonth = 12 + // // ..hDay = 25, + // pickerMode: DatePickerMode.day, + // ); + // if (pickedH != null && birthDateInHijri != pickedH) updateDate(pickedH); + // } else { + 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) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisSize: MainAxisSize.min, + children: [ + Text(title), + Expanded( + child: TextFormField( + 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('MM/dd/yyyy').format(time); + } +} diff --git a/lib/utils/translations_delegate_base_utils.dart b/lib/utils/translations_delegate_base_utils.dart index e2579e3d..a6ab1858 100644 --- a/lib/utils/translations_delegate_base_utils.dart +++ b/lib/utils/translations_delegate_base_utils.dart @@ -110,6 +110,7 @@ class TranslationBase { String get searchMedicine => localizedValues['searchMedicine']![locale.languageCode]!; String get searchMedicineDashboard => localizedValues['searchMedicineDashboard']![locale.languageCode]!; + String get interventionPharmacyApproval => localizedValues['interventionPharmacyApproval']![locale.languageCode]!; String get myReferralPatient => localizedValues['myReferralPatient']![locale.languageCode]!; @@ -1454,6 +1455,7 @@ class TranslationBase { String get doctorRota => localizedValues['doctorRota']![locale.languageCode]!; String get dateFrom => localizedValues['dateFrom']![locale.languageCode]!; + String get dateTo => localizedValues['dateTo']![locale.languageCode]!; String get searchFindSchedule => localizedValues['searchFindSchedule']![locale.languageCode]!; String get onePrimaryDiagnosis => localizedValues['onePrimaryDiagnosis']![locale.languageCode]!; @@ -1463,6 +1465,10 @@ class TranslationBase { String get complexDiagnosis => localizedValues['complexDiagnosis']![locale.languageCode]!; String get updateAssessmentDetails => localizedValues['updateAssessmentDetails']![locale.languageCode]!; + String get pharmacyInterventionApproval => + localizedValues['pharmacyInterventionApproval']![locale.languageCode]!; + String get admissionNumber => + localizedValues['admissionNumber']![locale.languageCode]!; } class TranslationBaseDelegate extends LocalizationsDelegate { From 4d31e14d6e7fb6caf0911f8bb263f053483bb173 Mon Sep 17 00:00:00 2001 From: "taha.alam" Date: Tue, 24 Dec 2024 15:07:26 +0300 Subject: [PATCH 02/14] WD: nursing station added to the PharmacyIntervention.dart dialog --- lib/config/localized_values.dart | 2 + .../PharmacyIntervention.dart | 101 ++++++++---------- .../translations_delegate_base_utils.dart | 4 + 3 files changed, 52 insertions(+), 55 deletions(-) diff --git a/lib/config/localized_values.dart b/lib/config/localized_values.dart index a96a0258..f7e38d5d 100644 --- a/lib/config/localized_values.dart +++ b/lib/config/localized_values.dart @@ -1160,6 +1160,7 @@ const Map> localizedValues = { "doctorRota": {"en": "Doctor Rota", "ar":"دوران الطبيب"}, "dateFrom": {"en": "Date From", "ar":"التاريخ من"}, "dateTo": {"en": "Date To", "ar":"التاريخ إلى"}, + "nursingStation": {"en": "Nursing Station", "ar":"محطة التمريض"}, "searchFindSchedule": {"en": "Search and find out the doctor’s schedule ", "ar":"بحث ومعرفة جدول الطبيب"}, "onePrimaryDiagnosis": {"en": "There has to be at-least 1 principal diagnosis", "ar":"يجب أن يكون هناك تشخيص رئيسي واحد على الأقل"}, "principalDiagnosisCannot": {"en": "Principal Diagnosis cannot modify once the order created", "ar":"لا يمكن تعديل التشخيص الرئيسي بمجرد إنشاء الطلب"}, @@ -1167,6 +1168,7 @@ const Map> localizedValues = { "principalCoveredOrNot": {"en": "Principal Diagnosis is not covered for this patient", "ar":"لا يتم تغطية التشخيص الرئيسي لهذا المريض"}, "complexDiagnosis": {"en": "Complex Diagnosis", "ar":"التشخيص المعقد"}, "pharmacyInterventionApproval": {"en": "Pharmacy Intervention Approval", "ar":"الموافقة على التدخل الصيدلي"}, + "pharmacyApproval": {"en": "Pharmacy Approval", "ar":"موافقة الصيدلية"}, diff --git a/lib/screens/pharmaacy_intervention/PharmacyIntervention.dart b/lib/screens/pharmaacy_intervention/PharmacyIntervention.dart index 917917fc..9001080f 100644 --- a/lib/screens/pharmaacy_intervention/PharmacyIntervention.dart +++ b/lib/screens/pharmaacy_intervention/PharmacyIntervention.dart @@ -51,14 +51,14 @@ class _PharmacyIntervention extends State return AppScaffold( isShowAppBar: true, appBar: PatientSearchHeader( - title: TranslationBase.of(context).pharmacyInterventionApproval, + title: TranslationBase.of(context).pharmacyApproval, fontSize: 18, showSearchIcon: true, onSearchPressed: () { SearchDialog(); }, ), - appBarTitle: TranslationBase.of(context).pharmacyInterventionApproval, + appBarTitle: TranslationBase.of(context).pharmacyApproval, body: Column( children: [ SizedBox( @@ -144,6 +144,7 @@ class PharmacyInterventionDialog extends StatefulWidget { class _PharmacyInterventionDialogState extends State { final TextEditingController admissionNumber = TextEditingController(); + final TextEditingController nursingStation = TextEditingController(); final TextEditingController patientId = TextEditingController(); @@ -151,7 +152,6 @@ class _PharmacyInterventionDialogState String dateTo = ''; - @override void initState() { super.initState(); @@ -170,27 +170,37 @@ class _PharmacyInterventionDialogState child: Column( mainAxisSize: MainAxisSize.min, children: [ - _titleAndTextField( - TranslationBase.of(context).admissionNumber, admissionNumber), - SizedBox(height: 4,), - - _titleAndTextField( - TranslationBase.of(context).patientID, patientId), - SizedBox(height: 4,), - + _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,), - + SizedBox( + height: 4, + ), _dateSelection(TranslationBase.of(context).dateTo, (date) { setState(() { dateTo = date; }); }, dateTo), - SizedBox(height: 8,), + SizedBox( + height: 8, + ), Row(children: [ Expanded( child: AppButton( @@ -212,7 +222,7 @@ class _PharmacyInterventionDialogState Widget _dateSelection( String title, Function(String) onDateSelected, String selectedDate) { return GestureDetector( - onTap: ()=> _selectDate(onDateSelected), + onTap: () => _selectDate(onDateSelected), child: Row( mainAxisSize: MainAxisSize.min, children: [ @@ -231,52 +241,32 @@ class _PharmacyInterventionDialogState } Future _selectDate(Function(String) updateDate) async { - // if (calenderType == CalenderType.Hijri) { - // JDateModel hijriDate = JDateModel(dateTime: DateTime.now()); - // final JPickerValue? pickedH = await showGlobalDatePicker( - // context: context, - // pickerType: PickerType.JHijri, - // startDate: birthDateInHijri ?? hijriDate, - // endDate: JDateModel( - // jhijri: JHijri(fDate: hijriDate.dateTime), - // ), - // - // // firstDate: new HijriCalendar() - // // ..hYear = 1438 - // // ..hMonth = 12 - // // ..hDay = 25, - // pickerMode: DatePickerMode.day, - // ); - // if (pickedH != null && birthDateInHijri != pickedH) updateDate(pickedH); - // } else { 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, + 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, ), - dialogBackgroundColor: Colors.white, - ), - child: child!, - ); - } - - ); + child: child!, + ); + }); if (picked != null) { - updateDate(getFormattedDate(picked)); } // } } - Widget _titleAndTextField(String title, TextEditingController controller) { + Widget _titleAndTextField(String title, TextEditingController controller, + TextInputType? inputType) { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisSize: MainAxisSize.min, @@ -284,6 +274,7 @@ class _PharmacyInterventionDialogState Text(title), Expanded( child: TextFormField( + keyboardType: inputType, decoration: InputDecoration( hintText: '', focusedBorder: InputBorder.none, @@ -300,10 +291,10 @@ class _PharmacyInterventionDialogState void initFromDate() { var time = DateTime.now(); - dateFrom = getFormattedDate(time); + dateFrom = getFormattedDate(time); } - String getFormattedDate(DateTime time){ + String getFormattedDate(DateTime time) { return DateFormat('MM/dd/yyyy').format(time); } } diff --git a/lib/utils/translations_delegate_base_utils.dart b/lib/utils/translations_delegate_base_utils.dart index a6ab1858..9d21b156 100644 --- a/lib/utils/translations_delegate_base_utils.dart +++ b/lib/utils/translations_delegate_base_utils.dart @@ -1467,8 +1467,12 @@ class TranslationBase { localizedValues['updateAssessmentDetails']![locale.languageCode]!; String get pharmacyInterventionApproval => localizedValues['pharmacyInterventionApproval']![locale.languageCode]!; + String get pharmacyApproval => + localizedValues['pharmacyApproval']![locale.languageCode]!; String get admissionNumber => localizedValues['admissionNumber']![locale.languageCode]!; + String get nursingStation => + localizedValues['nursingStation']![locale.languageCode]!; } class TranslationBaseDelegate extends LocalizationsDelegate { From 8456ed853075184de635255f6364e16aad7f17ad Mon Sep 17 00:00:00 2001 From: "taha.alam" Date: Thu, 26 Dec 2024 11:28:27 +0300 Subject: [PATCH 03/14] WIP: Infectious disease approval --- lib/config/config.dart | 6 + lib/config/localized_values.dart | 7 +- .../intervention_history.dart | 57 + .../pharmacy_intervention_item.dart | 159 +++ lib/core/viewModel/dashboard_view_model.dart | 52 +- lib/locator.dart | 4 + lib/screens/home/home_screen.dart | 294 ++-- .../PharmacyIntervention.dart | 300 ----- .../PharmacyIntervention.dart | 1196 +++++++++++++++++ .../pharmacy_intervention_service.dart | 110 ++ .../pharmacy_intervention_view_model.dart | 608 +++++++++ .../translations_delegate_base_utils.dart | 10 + 12 files changed, 2389 insertions(+), 414 deletions(-) create mode 100644 lib/core/model/pharmacy-intervention-model/intervention_history.dart create mode 100644 lib/core/model/pharmacy-intervention-model/pharmacy_intervention_item.dart delete mode 100644 lib/screens/pharmaacy_intervention/PharmacyIntervention.dart create mode 100644 lib/screens/pharmacy_intervention/PharmacyIntervention.dart create mode 100644 lib/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_service.dart create mode 100644 lib/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_view_model.dart diff --git a/lib/config/config.dart b/lib/config/config.dart index 9effc423..cb04fc46 100644 --- a/lib/config/config.dart +++ b/lib/config/config.dart @@ -367,6 +367,12 @@ const CREATE_PROGRESS_NOTE = 'Services/DoctorApplication.svc/REST/PostProgressNo const GET_PATIENT_CLINIC = 'Services/DoctorApplication.svc/REST/GetPatientConditionProgress'; +///Pharmacy Intervention API's +const GET_MEDICINE_WITH_INTERVAL = 'Services/DoctorApplication.svc/REST/MedicineWithInterventionAccessLevel3'; +const IS_INFECTIOUS_DISEASE = 'Services/DoctorApplication.svc/REST/IsInfectiousDiseasesConsultant'; +const INFECTIOUS_HISTORY = 'Services/DoctorApplication.svc/REST/InterventionHistory'; +const UPDATE_INFECTIOUS_STATUS = 'Services/DoctorApplication.svc/REST/UpdateInterventionStatus'; + var selectedPatientType = 1; //*********change value to decode json from Dropdown ************ diff --git a/lib/config/localized_values.dart b/lib/config/localized_values.dart index 68c5c61e..93e20fdd 100644 --- a/lib/config/localized_values.dart +++ b/lib/config/localized_values.dart @@ -1234,10 +1234,15 @@ const Map> localizedValues = { "ar": "هل أنت متأكد من أنك تريد حذف التشخيص" }, "activate": {"en": "Activate", "ar":"فعل"}, + "unableToPerformTheAction": {"en": "Unable To Perform The Action", "ar":"فعل"}, + "pharmacyRemarks": {"en": "Pharmacy Remarks", "ar":"ملاحظات الصيدلة"}, + "authorizedBy": {"en": "Authorized By", "ar":"مرخص من قبل"}, + "dosageDetails": {"en": "Dosage Details", "ar":"تفاصيل الجرعة"}, + "accessLevel": {"en": "Access Level", "ar":"مستوى الوصول"}, "resolved": {"en": "Resolved", "ar":"تم الحل"}, "diagnosisAlreadyDeleted": {"en": "Diagnosis Already Deleted", "ar":"تم حذف التشخيص بالفعل"}, "diagnosisAlreadyResolved": {"en": "Diagnosis Already Resolved", "ar":"تم حل التشخيص بالفعل"}, "selectReaction": {"en": "Select Reaction", "ar":"حدد رد الفعل"}, - "progressNoteCanNotBeEmpty": {"en": "Progress Note Can Not Be Empty", "ar":"ملاحظة التقدم لا يمكن أن تكون فارغة"}, + "progressNoteCanNotBeEmpty": {"en": "Progress Note Can Not Be Empty", "ar":"تعذر تنفيذ الإجراء"}, }; diff --git a/lib/core/model/pharmacy-intervention-model/intervention_history.dart b/lib/core/model/pharmacy-intervention-model/intervention_history.dart new file mode 100644 index 00000000..7c57fb3b --- /dev/null +++ b/lib/core/model/pharmacy-intervention-model/intervention_history.dart @@ -0,0 +1,57 @@ +class InterventionHistoryList{ + List? history = []; + InterventionHistoryList.fromJson(Map json){ + var entryList = json['entityList'] ?? {}; + List tempList = []; + for(var item in entryList){ + var medication = InterventionHistory.fromJson(item); + tempList.add(medication); + } + history?.addAll(tempList); + } +} + +class InterventionHistory { + String? authizationFormText; + int? authorizedAction; + int? commentedBy; + String? commentedByName; + String? interventionDesc; + int? interventionId; + String? remark; + + InterventionHistory({ + this.authizationFormText, + this.authorizedAction, + this.commentedBy, + this.commentedByName, + this.interventionDesc, + this.interventionId, + this.remark, + }); + + factory InterventionHistory.fromJson(Map json) { + print('the remark is ${json['remark']}'); + return InterventionHistory( + authizationFormText: json['authizationFormText'] ?? '', + authorizedAction: json['authorizedAction'] ?? '', + commentedBy: json['commentedBy'] ?? '', + commentedByName: json['commentedByName'] ?? '', + interventionDesc: json['interventionDesc'] ?? '', + interventionId: json['interventionId'] ?? '', + remark: json['remark'] ?? '', + ); + } + + Map toJson() { + return { + 'authizationFormText': authizationFormText, + 'authorizedAction': authorizedAction, + 'commentedBy': commentedBy, + 'commentedByName': commentedByName, + 'interventionDesc': interventionDesc, + 'interventionId': interventionId, + 'remark': remark, + }; + } +} \ No newline at end of file diff --git a/lib/core/model/pharmacy-intervention-model/pharmacy_intervention_item.dart b/lib/core/model/pharmacy-intervention-model/pharmacy_intervention_item.dart new file mode 100644 index 00000000..7f565636 --- /dev/null +++ b/lib/core/model/pharmacy-intervention-model/pharmacy_intervention_item.dart @@ -0,0 +1,159 @@ +class MedicationList{ + List? medication = []; + MedicationList.fromJson(Map json){ + var entryList = json['entityList'] ?? {}; + List tempList = []; + for(var item in entryList){ + var medication = Medication.fromJson(item); + tempList.add(medication); + } + medication?.addAll(tempList); + } +} + +class Medication { + int? accessLevel; + int? admissionNo; + String? authorizedBy; + String? authorizedByName; + String? createdBy; + String? doctorComments; + String? doctorName; + String? dosageDetail; + int? itemID; + int? lineItemNo; + String? medication; + String? nursingStation; + int? orderNo; + int? patientID; + String? patientName; + String? pharmacyRemarks; + int? prescriptionNo; + DateTime? startDatetime; + int? status; + String? statusName; + DateTime? stopDatetime; + + Medication({ + this.accessLevel, + this.admissionNo, + this.authorizedBy, + this.authorizedByName, + this.createdBy, + this.doctorComments, + this.doctorName, + this.dosageDetail, + this.itemID, + this.lineItemNo, + this.medication, + this.nursingStation, + this.orderNo, + this.patientID, + this.patientName, + this.pharmacyRemarks, + this.prescriptionNo, + this.startDatetime, + this.status, + this.statusName, + this.stopDatetime, + }); + + dynamic? getValue(int index){ + switch (index) { + case 0: + return this.accessLevel; + case 1: + return this.patientID; + break; + case 2: + return this.patientName; + break; + case 3: + return this.nursingStation; + break; + case 4: + return this.admissionNo; + break; + case 5: + return this.medication; + break; + case 6: + return this.dosageDetail; + break; + case 7: + return this.doctorComments; + break; + case 8: + return this.startDatetime; + break; + case 9: + return this.stopDatetime; + break; + case 10: + return this.status; + break; + case 11: + return this.doctorName; + break; + case 12: + return this.authorizedBy; + break; + case 13: + return this.pharmacyRemarks; + break; + } + return index; + } + + factory Medication.fromJson(Map json) { + return Medication( + accessLevel: json['accessLevel'] ?? '', + admissionNo: json['admissionNo']?? '', + authorizedBy: json['authorizedby']?? '-', + authorizedByName: json['authorizedbyName']?? '', + createdBy: json['createdBy']?? '', + doctorComments: json['doctorComments']?? '', + doctorName: json['doctorName']?? '', + dosageDetail: json['dosageDetail']?? '', + itemID: json['itemID']?? '', + lineItemNo: json['lineItemNo']?? '', + medication: json['medication']?? '', + nursingStation: json['nursingStation']?? '', + orderNo: json['orderNo']?? '', + patientID: json['patientID']?? '', + patientName: json['patientName']?? '', + pharmacyRemarks: json['pharmacyRemarks']?? '-', + prescriptionNo: json['prescriptionNo']?? '', + startDatetime: json['startDatetime'] != null ? DateTime.parse(json['startDatetime']) : null, + status: json['status']?? '', + statusName: json['statusName']?? '', + stopDatetime: json['stopDatetime'] != null ? DateTime.parse(json['stopDatetime']) : null, + ); + } + + Map toJson() { + return { + 'accessLevel': accessLevel, + 'admissionNo': admissionNo, + 'authorizedby': authorizedBy, + 'authorizedbyName': authorizedByName, + 'createdBy': createdBy, + 'doctorComments': doctorComments, + 'doctorName': doctorName, + 'dosageDetail': dosageDetail, + 'itemID': itemID, + 'lineItemNo': lineItemNo, + 'medication': medication, + 'nursingStation': nursingStation, + 'orderNo': orderNo, + 'patientID': patientID, + 'patientName': patientName, + 'pharmacyRemarks': pharmacyRemarks, + 'prescriptionNo': prescriptionNo, + 'startDatetime': startDatetime?.toIso8601String(), + 'status': status, + 'statusName': statusName, + 'stopDatetime': stopDatetime?.toIso8601String(), + }; + } +} \ No newline at end of file diff --git a/lib/core/viewModel/dashboard_view_model.dart b/lib/core/viewModel/dashboard_view_model.dart index 3ca7d4d5..31e9f363 100644 --- a/lib/core/viewModel/dashboard_view_model.dart +++ b/lib/core/viewModel/dashboard_view_model.dart @@ -4,6 +4,7 @@ import 'package:doctor_app_flutter/core/service/home/dasboard_service.dart'; import 'package:doctor_app_flutter/core/service/home/doctor_reply_service.dart'; import 'package:doctor_app_flutter/core/service/special_clinics/special_clinic_service.dart'; import 'package:doctor_app_flutter/core/viewModel/project_view_model.dart'; +import 'package:doctor_app_flutter/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_service.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import '../../locator.dart'; @@ -16,12 +17,16 @@ import 'base_view_model.dart'; class DashboardViewModel extends BaseViewModel { final FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance; DashboardService _dashboardService = locator(); - SpecialClinicsService _specialClinicsService = locator(); + PharmacyInterventionService _service = locator(); + SpecialClinicsService _specialClinicsService = + locator(); DoctorReplyService _doctorReplyService = locator(); - List get dashboardItemsList => _dashboardService.dashboardItemsList; + List get dashboardItemsList => + _dashboardService.dashboardItemsList; - RadiologyCriticalFindingModel? get radiologyCriticalFindingModel => _dashboardService.radiologyCriticalFindingModel; + RadiologyCriticalFindingModel? get radiologyCriticalFindingModel => + _dashboardService.radiologyCriticalFindingModel; bool get hasVirtualClinic => _dashboardService.hasVirtualClinic; @@ -29,9 +34,25 @@ class DashboardViewModel extends BaseViewModel { int get notRepliedCount => _doctorReplyService.notRepliedCount; - List get specialClinicalCareList => _specialClinicsService.specialClinicalCareList; + bool isInfectiousDiseaseConsultant = false; - Future startHomeScreenServices(ProjectViewModel projectsProvider, AuthenticationViewModel authProvider) async { + 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; + setState(ViewState.Idle); + } + + Future startHomeScreenServices(ProjectViewModel projectsProvider, + AuthenticationViewModel authProvider) async { setState(ViewState.Busy); await getDoctorProfile(isGetProfile: true); @@ -40,7 +61,8 @@ class DashboardViewModel extends BaseViewModel { _dashboardService.getDashboard(), _dashboardService.checkDoctorHasLiveCare(), _specialClinicsService.getSpecialClinicalCareList(), - _dashboardService.checkDoctorHasRadiologyFindings() + _dashboardService.checkDoctorHasRadiologyFindings(), + getInfectiousDiseaseConsultantStatus() ]); if (_dashboardService.hasError) { @@ -53,7 +75,8 @@ class DashboardViewModel extends BaseViewModel { } Future setFirebaseNotification(AuthenticationViewModel authProvider) async { - _firebaseMessaging.requestPermission(sound: true, badge: true, alert: true, provisional: true); + _firebaseMessaging.requestPermission( + sound: true, badge: true, alert: true, provisional: true); _firebaseMessaging.getToken().then((String? token) async { if (token != '') { @@ -74,8 +97,10 @@ class DashboardViewModel extends BaseViewModel { await _dashboardService.checkDoctorHasLiveCare(); } - Future acknowledgeRadiologyCriticalFinding(String invoiceNo, String invoiceLineItemNo) async { - await _dashboardService.acknowledgeDoctorHasRadiologyFindings(invoiceNo, invoiceLineItemNo); + Future acknowledgeRadiologyCriticalFinding( + String invoiceNo, String invoiceLineItemNo) async { + await _dashboardService.acknowledgeDoctorHasRadiologyFindings( + invoiceNo, invoiceLineItemNo); } Future getSpecialClinicalCareList() async { @@ -88,7 +113,8 @@ class DashboardViewModel extends BaseViewModel { // setState(ViewState.Idle); } - Future changeClinic(dynamic clinicId, AuthenticationViewModel authProvider) async { + Future changeClinic( + dynamic clinicId, AuthenticationViewModel authProvider) async { setState(ViewState.BusyLocal); await getDoctorProfile(); ClinicModel clinicModel = ClinicModel( @@ -104,13 +130,15 @@ class DashboardViewModel extends BaseViewModel { getPatientCount(DashboardModel inPatientCount) { int value = 0; - inPatientCount.summaryoptions!.forEach((result) => {value += result.value!}); + inPatientCount.summaryoptions! + .forEach((result) => {value += result.value!}); return value.toString(); } GetSpecialClinicalCareListResponseModel getSpecialClinic(clinicId) { - GetSpecialClinicalCareListResponseModel special = GetSpecialClinicalCareListResponseModel(); + GetSpecialClinicalCareListResponseModel special = + GetSpecialClinicalCareListResponseModel(); specialClinicalCareList.forEach((element) { if (element.clinicID == clinicId) { special = element; diff --git a/lib/locator.dart b/lib/locator.dart index e82934bd..36441baf 100644 --- a/lib/locator.dart +++ b/lib/locator.dart @@ -14,6 +14,8 @@ import 'package:doctor_app_flutter/core/viewModel/profile/discharge_summary_view import 'package:doctor_app_flutter/core/viewModel/profile/operation_report_view_model.dart'; import 'package:doctor_app_flutter/core/viewModel/scan_qr_view_model.dart'; import 'package:doctor_app_flutter/core/viewModel/sick_leave_view_model.dart'; +import 'package:doctor_app_flutter/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_service.dart'; +import 'package:doctor_app_flutter/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_view_model.dart'; import 'package:get_it/get_it.dart'; import 'core/service/AnalyticsService.dart'; import 'core/service/NavigationService.dart'; @@ -117,6 +119,7 @@ void setupLocator() { locator.registerLazySingleton(() => VteAssessmentService()); locator.registerLazySingleton(() => InterventionMedicationService()); locator.registerLazySingleton(() => ERSignInService()); + locator.registerLazySingleton(() => PharmacyInterventionService()); /// View Model locator.registerFactory(() => DoctorReplayViewModel()); @@ -151,4 +154,5 @@ void setupLocator() { locator.registerFactory(() => VteAssessmentViewModel()); locator.registerFactory(() => InterventionMedicationViewModel()); locator.registerFactory(() => ERSignInViewModel()); + locator.registerFactory(() => PharmacyInterventionViewModel()); } diff --git a/lib/screens/home/home_screen.dart b/lib/screens/home/home_screen.dart index 52655121..5225d347 100644 --- a/lib/screens/home/home_screen.dart +++ b/lib/screens/home/home_screen.dart @@ -18,6 +18,7 @@ import 'package:doctor_app_flutter/screens/patients/In_patient/in_patient_screen import 'package:doctor_app_flutter/screens/patients/out_patient/out_patient_screen.dart'; import 'package:doctor_app_flutter/screens/patients/patient_search/patient_search_screen.dart'; import 'package:doctor_app_flutter/screens/patients/profile/referral/referral_details/patient_referral_screen.dart'; +import 'package:doctor_app_flutter/screens/pharmacy_intervention/PharmacyIntervention.dart'; import 'package:doctor_app_flutter/utils/date-utils.dart'; import 'package:doctor_app_flutter/utils/dr_app_toast_msg.dart'; import 'package:doctor_app_flutter/utils/translations_delegate_base_utils.dart'; @@ -33,7 +34,6 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:provider/provider.dart'; import 'package:sticky_headers/sticky_headers/widget.dart'; -import '../pharmaacy_intervention/PharmacyIntervention.dart'; import 'label.dart'; class HomeScreen extends StatefulWidget { @@ -60,8 +60,8 @@ class _HomeScreenState extends State { (SizeConfig.isHeightVeryShort ? 16 : SizeConfig.isHeightLarge - ? 15 - : 13); + ? 15 + : 13); @override Widget build(BuildContext context) { @@ -75,7 +75,9 @@ class _HomeScreenState extends State { return BaseView( onModelReady: (model) async { - model.startHomeScreenServices(projectsProvider, authenticationViewModel).then((value) { + model + .startHomeScreenServices(projectsProvider, authenticationViewModel) + .then((value) { if (model.radiologyCriticalFindingModel != null) { print("onModelReady radiologyCriticalFindingModel!!!"); showRadiologyFindingDialog(model); @@ -97,9 +99,12 @@ class _HomeScreenState extends State { //TODO Elham* make it componet Container( width: 40, - margin: EdgeInsets.only(left: projectsProvider.isArabic ? 0 : 32, right: projectsProvider.isArabic ? 23 : 0), + margin: EdgeInsets.only( + left: projectsProvider.isArabic ? 0 : 32, + right: projectsProvider.isArabic ? 23 : 0), child: IconButton( - icon: SvgPicture.asset('assets/images/svgs/menu.svg', height: 25, width: 10), + icon: SvgPicture.asset('assets/images/svgs/menu.svg', + height: 25, width: 10), iconSize: 15, color: Colors.black, onPressed: () => Scaffold.of(context).openDrawer(), @@ -112,69 +117,117 @@ class _HomeScreenState extends State { children: [ Container( width: MediaQuery.of(context).size.width * .6, - child: projectsProvider.doctorClinicsList.length > 0 + child: projectsProvider.doctorClinicsList.length > + 0 ? Stack( children: [ DropdownButtonHideUnderline( child: DropdownButton( dropdownColor: Colors.white, - iconEnabledColor: AppGlobal.appTextColor, + iconEnabledColor: + AppGlobal.appTextColor, icon: Icon(Icons.keyboard_arrow_down), isExpanded: true, - value: clinicId == null ? projectsProvider.doctorClinicsList[0].clinicID : clinicId, + value: clinicId == null + ? projectsProvider + .doctorClinicsList[0].clinicID + : clinicId, iconSize: 25, elevation: 16, - selectedItemBuilder: (BuildContext context) { - return projectsProvider.doctorClinicsList.map((item) { + selectedItemBuilder: + (BuildContext context) { + return projectsProvider + .doctorClinicsList + .map((item) { return Row( mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.end, + mainAxisAlignment: + MainAxisAlignment.end, children: [ Column( - mainAxisAlignment: MainAxisAlignment.center, + mainAxisAlignment: + MainAxisAlignment + .center, children: [ Container( - padding: EdgeInsets.all(0), - margin: EdgeInsets.all(2), - decoration: new BoxDecoration( - color: AppGlobal.appRedColor, - borderRadius: BorderRadius.circular(20), + padding: + EdgeInsets.all(0), + margin: + EdgeInsets.all(2), + decoration: + new BoxDecoration( + color: AppGlobal + .appRedColor, + borderRadius: + BorderRadius + .circular( + 20), ), - constraints: BoxConstraints( + constraints: + BoxConstraints( minWidth: 20, minHeight: 20, ), child: Center( child: AppText( - projectsProvider.doctorClinicsList.length.toString(), - color: Colors.white, - letterSpacing: -0.72, - fontWeight: FontWeight.w600, - fontSize: projectsProvider.isArabic ? 10 : 12, - textAlign: TextAlign.center, + projectsProvider + .doctorClinicsList + .length + .toString(), + color: + Colors.white, + letterSpacing: + -0.72, + fontWeight: + FontWeight + .w600, + fontSize: + projectsProvider + .isArabic + ? 10 + : 12, + textAlign: + TextAlign + .center, ), )), ], ), - AppText(Utils.convertToTitleCase(item.clinicName), - fontSize: 14, letterSpacing: -0.96, color: AppGlobal.appTextColor, fontWeight: FontWeight.bold, textAlign: TextAlign.end), + AppText( + Utils.convertToTitleCase( + item.clinicName), + fontSize: 14, + letterSpacing: -0.96, + color: AppGlobal + .appTextColor, + fontWeight: + FontWeight.bold, + textAlign: TextAlign.end), ], ); }).toList(); }, onChanged: (newValue) async { clinicId = newValue; - GifLoaderDialogUtils.showMyDialog(context); - await model.changeClinic(newValue, authenticationViewModel); - GifLoaderDialogUtils.hideDialog(context); - if (model.state == ViewState.ErrorLocal) { - DrAppToastMsg.showErrorToast(model.error); + GifLoaderDialogUtils.showMyDialog( + context); + await model.changeClinic(newValue, + authenticationViewModel); + GifLoaderDialogUtils.hideDialog( + context); + if (model.state == + ViewState.ErrorLocal) { + DrAppToastMsg.showErrorToast( + model.error); } }, - items: projectsProvider.doctorClinicsList.map((item) { + items: projectsProvider + .doctorClinicsList + .map((item) { return DropdownMenuItem( child: AppText( - Utils.convertToTitleCase(item.clinicName), + Utils.convertToTitleCase( + item.clinicName), fontSize: 14, letterSpacing: -0.96, color: AppGlobal.appTextColor, @@ -187,7 +240,8 @@ class _HomeScreenState extends State { )), ], ) - : AppText(TranslationBase.of(context).noClinic), + : AppText( + TranslationBase.of(context).noClinic), ), ], ), @@ -217,16 +271,22 @@ class _HomeScreenState extends State { ? FractionallySizedBox( widthFactor: 0.90, child: Container( - child: Column(mainAxisAlignment: MainAxisAlignment.start, children: [ - SizedBox( - height: 10, - ), - sliderActiveIndex == 1 - ? DashboardSliderItemWidget(model.dashboardItemsList[4]) - : sliderActiveIndex == 0 - ? DashboardSliderItemWidget(model.dashboardItemsList[3]) - : DashboardSliderItemWidget(model.dashboardItemsList[6]), - ]))) + child: Column( + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + SizedBox( + height: 10, + ), + sliderActiveIndex == 1 + ? DashboardSliderItemWidget( + model.dashboardItemsList[4]) + : sliderActiveIndex == 0 + ? DashboardSliderItemWidget( + model.dashboardItemsList[3]) + : DashboardSliderItemWidget( + model.dashboardItemsList[6]), + ]))) : SizedBox(), ], ) @@ -265,9 +325,12 @@ class _HomeScreenState extends State { : SizeConfig.isHeightLarge ? 15 : 13), - child: ListView(scrollDirection: Axis.horizontal, children: [ - ...homePatientsCardsWidget(model, projectsProvider), - ])), + child: ListView( + scrollDirection: Axis.horizontal, + children: [ + ...homePatientsCardsWidget( + model, projectsProvider), + ])), SizedBox( height: 20, ), @@ -285,32 +348,44 @@ class _HomeScreenState extends State { } showRadiologyFindingDialog(DashboardViewModel model) { - Utils.showConfirmationDialog(context, model.radiologyCriticalFindingModel!.notificationMesssage!, () async { + Utils.showConfirmationDialog( + context, model.radiologyCriticalFindingModel!.notificationMesssage!, + () async { Navigator.of(context).pop(); GifLoaderDialogUtils.showMyDialog(context); - await model.acknowledgeRadiologyCriticalFinding(model.radiologyCriticalFindingModel!.invoiceNo.toString(), model.radiologyCriticalFindingModel!.invoiceLineItemNo.toString()); + await model.acknowledgeRadiologyCriticalFinding( + model.radiologyCriticalFindingModel!.invoiceNo.toString(), + model.radiologyCriticalFindingModel!.invoiceLineItemNo.toString()); GifLoaderDialogUtils.hideDialog(context); }, isShowCancelButton: false); } - List homePatientsCardsWidget(DashboardViewModel model, projectsProvider) { + List homePatientsCardsWidget( + DashboardViewModel model, projectsProvider) { colorIndex = 0; - List backgroundColors =[]; - backgroundColors.add(LinearGradient(begin: Alignment(-1.0, -2.0), end: Alignment(1.0, 2.0), colors: [ - AppGlobal.appRedColor, - Color(0xFFAD3B3B), - ])); //AppGlobal.appRedColor; - backgroundColors.add(LinearGradient(begin: Alignment.center, end: Alignment.center, colors: [ + List backgroundColors = []; + backgroundColors.add(LinearGradient( + begin: Alignment(-1.0, -2.0), + end: Alignment(1.0, 2.0), + colors: [ + AppGlobal.appRedColor, + Color(0xFFAD3B3B), + ])); //AppGlobal.appRedColor; + backgroundColors.add( + LinearGradient(begin: Alignment.center, end: Alignment.center, colors: [ Color(0xFFC9C9C9), Color(0xFFC9C9C9), ])); - backgroundColors.add(LinearGradient(begin: Alignment.center, end: Alignment.center, colors: [Color(0xFF71787E), AppGlobal.appTextColor])); + backgroundColors.add(LinearGradient( + begin: Alignment.center, + end: Alignment.center, + colors: [Color(0xFF71787E), AppGlobal.appTextColor])); List backgroundIconColors = []; backgroundIconColors.add(Colors.white12); - backgroundIconColors.add( Colors.white38); + backgroundIconColors.add(Colors.white38); backgroundIconColors.add(Colors.white10); - List textColors =[]; + List textColors = []; textColors.add(Colors.white); textColors.add(Color(0xFF353E47)); textColors.add(Colors.white); @@ -324,7 +399,8 @@ class _HomeScreenState extends State { cardIcon: DoctorApp.livecare, textColor: textColors[colorIndex], iconSize: 21, - text: "${TranslationBase.of(context).liveCare}\n${TranslationBase.of(context).patients}", + text: + "${TranslationBase.of(context).liveCare}\n${TranslationBase.of(context).patients}", onTap: () { // TODO MOSA TEST // PatiantInformtion patient = PatiantInformtion( @@ -382,31 +458,56 @@ class _HomeScreenState extends State { context, FadePage( page: InPatientScreen( - specialClinic: model.getSpecialClinic(clinicId ?? projectsProvider.doctorClinicsList[0].clinicID), + specialClinic: model.getSpecialClinic( + clinicId ?? projectsProvider.doctorClinicsList[0].clinicID), ), ), ); }, )); changeColorIndex(); - //TODO Keep commented - // patientCards.add(HomePatientCard( - // gradient: backgroundColors[colorIndex], - // backgroundIconColor: backgroundIconColors[colorIndex], - // //TODO Elham* match the of the icon - // cardIcon: DoctorApp.arrival_patients, - // textColor: textColors[colorIndex], - // text: TranslationBase.of(context).registerNewPatient, - // onTap: () { - // Navigator.push( - // context, - // FadePage( - // page: RegisterPatientPage(), - // ), - // ); - // }, - // )); - // changeColorIndex(); + + if(model.isInfectiousDiseaseConsultant) { + patientCards.add(HomePatientCard( + gradient: backgroundColors[2], + backgroundIconColor: backgroundIconColors[2], + cardIcon: DoctorApp.search_medicines, + textColor: textColors[2], + text: TranslationBase.of(context).interventionPharmacyApproval, + fontSize: SizeConfig.getTextMultiplierBasedOnWidth(width: width) * + (SizeConfig.isHeightVeryShort ? 10 : 9), + onTap: () { + if (!model.isInfectiousDiseaseConsultant) { + DrAppToastMsg.showErrorToast( + TranslationBase.of(context).unableToPerformTheAction); + } + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => PharmacyIntervention(), + settings: RouteSettings(name: 'PharmacyIntervention'), + )); + }, + )); + //TODO Keep commented + // patientCards.add(HomePatientCard( + // gradient: backgroundColors[colorIndex], + // backgroundIconColor: backgroundIconColors[colorIndex], + // //TODO Elham* match the of the icon + // cardIcon: DoctorApp.arrival_patients, + // textColor: textColors[colorIndex], + // text: TranslationBase.of(context).registerNewPatient, + // onTap: () { + // Navigator.push( + // context, + // FadePage( + // page: RegisterPatientPage(), + // ), + // ); + // }, + // )); + changeColorIndex(); + } patientCards.add(HomePatientCard( gradient: backgroundColors[colorIndex], @@ -415,13 +516,19 @@ class _HomeScreenState extends State { textColor: textColors[colorIndex], text: TranslationBase.of(context).myOutPatient_2lines, onTap: () { - String date = AppDateUtils.convertDateToFormat(DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day), 'yyyy-MM-dd'); + String date = AppDateUtils.convertDateToFormat( + DateTime( + DateTime.now().year, DateTime.now().month, DateTime.now().day), + 'yyyy-MM-dd'); Navigator.push( context, MaterialPageRoute( builder: (context) => OutPatientsScreen( - patientSearchRequestModel: PatientSearchRequestModel(from: date, to: date, doctorID: authenticationViewModel.doctorProfile!.doctorID), + patientSearchRequestModel: PatientSearchRequestModel( + from: date, + to: date, + doctorID: authenticationViewModel.doctorProfile!.doctorID), ), settings: RouteSettings(name: 'OutPatientsScreen'), )); @@ -480,26 +587,11 @@ class _HomeScreenState extends State { }, )); changeColorIndex(); - patientCards.add(HomePatientCard( - gradient: backgroundColors[2], - backgroundIconColor: backgroundIconColors[2], - cardIcon: DoctorApp.search_medicines, - textColor: textColors[2], - text: TranslationBase.of(context).interventionPharmacyApproval, - fontSize: SizeConfig.getTextMultiplierBasedOnWidth(width: width) * - (SizeConfig.isHeightVeryShort ? 10: 9), - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => PharmacyIntervention(), - settings: RouteSettings(name: 'PharmacyIntervention'), - )); - }, - )); - changeColorIndex(); - return [...List.generate(patientCards.length, (index) => patientCards[index]).toList()]; + return [ + ...List.generate(patientCards.length, (index) => patientCards[index]) + .toList() + ]; } changeColorIndex() { diff --git a/lib/screens/pharmaacy_intervention/PharmacyIntervention.dart b/lib/screens/pharmaacy_intervention/PharmacyIntervention.dart deleted file mode 100644 index 9001080f..00000000 --- a/lib/screens/pharmaacy_intervention/PharmacyIntervention.dart +++ /dev/null @@ -1,300 +0,0 @@ -import 'dart:ui'; -import 'package:doctor_app_flutter/core/viewModel/project_view_model.dart'; -import 'package:doctor_app_flutter/screens/patients/ReferralDischargedPatientPage.dart'; -import 'package:doctor_app_flutter/screens/patients/patient_search/patient_search_header.dart'; -import 'package:doctor_app_flutter/screens/patients/profile/referral/refer_details/referred-patient-screen.dart'; -import 'package:doctor_app_flutter/utils/tab_utils.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/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:intl/intl.dart'; - -import '../../config/config.dart'; - -class PharmacyIntervention extends StatefulWidget { - @override - _PharmacyIntervention createState() => _PharmacyIntervention(); -} - -class _PharmacyIntervention extends State - with SingleTickerProviderStateMixin { - TabController? _tabController; - int index = 0; - List listOfPharmacyIntervention = List.empty(); - - @override - void initState() { - super.initState(); - _tabController = TabController(length: 3, vsync: this); - _tabController!.addListener(_handleTabSelection); - } - - _handleTabSelection() { - setState(() { - index = _tabController!.index; - }); - } - - @override - void dispose() { - super.dispose(); - _tabController!.dispose(); - } - - @override - Widget build(BuildContext context) { - ProjectViewModel projectsProvider = Provider.of(context); - - return AppScaffold( - isShowAppBar: true, - appBar: PatientSearchHeader( - title: TranslationBase.of(context).pharmacyApproval, - fontSize: 18, - showSearchIcon: true, - onSearchPressed: () { - SearchDialog(); - }, - ), - appBarTitle: TranslationBase.of(context).pharmacyApproval, - body: Column( - children: [ - SizedBox( - height: 56, - child: Row( - mainAxisSize: MainAxisSize.max, - children: [ - Expanded( - child: Container( - decoration: TabUtils.getBoxTabsBoxDecoration( - isActive: index == 0, - isFirst: true, - projectViewModel: projectsProvider), - child: Center( - child: TabUtils.getTabText( - title: TranslationBase.of(context).pending, - isActive: index == 0)), - ), - ), - Expanded( - child: Container( - decoration: TabUtils.getBoxTabsBoxDecoration( - isActive: index == 1, - isMiddle: true, - projectViewModel: projectsProvider), - child: Center( - child: TabUtils.getTabText( - title: TranslationBase.of(context).accepted, - isActive: index == 1)), - ), - ), - Expanded( - child: Container( - decoration: TabUtils.getBoxTabsBoxDecoration( - isActive: index == 2, - isLast: true, - projectViewModel: projectsProvider), - child: Center( - child: TabUtils.getTabText( - title: TranslationBase.of(context).rejected, - isActive: index == 2), - ), - ), - ), - ], - ), - ), - Expanded( - child: ListView.builder( - itemCount: listOfPharmacyIntervention.length, - itemBuilder: (context, item) => SizedBox.shrink()), - ) - ], - )); - } - - void SearchDialog() { - showDialog( - context: context, - barrierDismissible: true, // user must tap button! - builder: (_) { - return PharmacyInterventionDialog( - onDispose: (dateFrom, dateTo, admissionNumber, patientId) {}); - }); - } -} - -class PharmacyInterventionDialog extends StatefulWidget { - final Function( - String, - String, - String, - String, - ) onDispose; - - const PharmacyInterventionDialog({super.key, required this.onDispose}); - - @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() { - super.initState(); - initFromDate(); - } - - @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 {}, - ), - ), - ]), - ], - ), - ), - ); - } - - 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('MM/dd/yyyy').format(time); - } -} diff --git a/lib/screens/pharmacy_intervention/PharmacyIntervention.dart b/lib/screens/pharmacy_intervention/PharmacyIntervention.dart new file mode 100644 index 00000000..1d12ce9f --- /dev/null +++ b/lib/screens/pharmacy_intervention/PharmacyIntervention.dart @@ -0,0 +1,1196 @@ +import 'dart:ui'; +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 '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 + State createState() => _PharmacyInterventionState(); +} + +class _PharmacyInterventionState extends State { + @override + Widget build(BuildContext context) { + ProjectViewModel projectsProvider = Provider.of(context); + + return BaseView(builder: (_, model, __) { + if (model.interventionHistoryList != null) { + WidgetsBinding.instance.addPostFrameCallback((_) { + showBottomSheet( + context, + model, + model.interventionHistoryList!.history!, + ); + }); + } + return AppScaffold( + isShowAppBar: true, + appBar: PatientSearchHeader( + title: TranslationBase + .of(context) + .pharmacyApproval, + fontSize: 18, + showSearchIcon: true, + onSearchPressed: () { + SearchDialog(context); + }, + ), + 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, + ))) + ], + ), + ); + }); + } + + final _sheet = GlobalKey(); + + final _controller = DraggableScrollableController(); + + @override + void initState() { + super.initState(); + _controller.addListener(_onChanged); + } + + void _onChanged() { + final currentSize = _controller.size; + if (currentSize <= 0.05) _collapse(); + } + + 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, + duration: const Duration(milliseconds: 50), + curve: Curves.easeInOut, + ); + } + @override + void dispose() { + super.dispose(); + _controller.dispose(); + } + + DraggableScrollableSheet get sheet => + (_sheet.currentWidget as DraggableScrollableSheet); + + void showBottomSheet(BuildContext context, + PharmacyInterventionViewModel model, + List interventionHistory,) { + showModalBottomSheet( + isDismissible: true, + context: context, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(20), topRight: Radius.circular(20))), + builder: (_) { + return DraggableScrollableSheet( + key: _sheet, + initialChildSize: 0.5, + minChildSize: 0.5, + maxChildSize: 1, + snapSizes: [ + 0.5 ,// constraints.maxHeight, + 0.9, + ], + expand: false, + controller: _controller, + builder:(_, controller) => + InterventionHistoryBottomSheet( + interventionList: interventionHistory, + controller: controller, + )); + }, + ).then((value) => model.toggleShowBottomSheetValue()); + } + + void SearchDialog(BuildContext context) { + showDialog( + context: context, + barrierDismissible: true, // user must tap button! + builder: (_) { + return PharmacyInterventionDialog( + onDispose: (dateFrom, dateTo, admissionNumber, patientId) {}); + }); + } +} + +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) + ], + ), + ), + ), + ); + } +} + +class InterventionCardFooter extends StatelessWidget { + final PharmacyInterventionViewModel model; + + const InterventionCardFooter({super.key, required this.model}); + + @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 {}, + ), + ), + ]), + 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 {}, + ), + ), + 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, + String, + String, + String, + ) onDispose; + + const PharmacyInterventionDialog({super.key, required this.onDispose}); + + @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() { + super.initState(); + // initFromDate(); + } + + @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 {}, + ), + ), + ]), + ], + ), + ), + ); + } + + 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('MM/dd/yyyy').format(time); + } +} diff --git a/lib/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_service.dart b/lib/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_service.dart new file mode 100644 index 00000000..1017bcd7 --- /dev/null +++ b/lib/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_service.dart @@ -0,0 +1,110 @@ +import 'dart:async'; + +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/core/model/pharmacy-intervention-model/pharmacy_intervention_item.dart'; +import 'package:doctor_app_flutter/core/service/base/base_service.dart'; + +class PharmacyInterventionService extends BaseService { + FutureOr getMedicationList( + {String nursingStationId = '', + String admissionId = '', + String patientID = '', + String fromDate = '', + String toDate = ''}) async { + var request = { + "nursingStationID": nursingStationId, + "admissionNo": admissionId, + "patientID": patientID, + "fromDate": fromDate, + "toDate": toDate, + }; + hasError = false; + await baseAppClient.post(GET_MEDICINE_WITH_INTERVAL, + onSuccess: (dynamic response, int statusCode) { + return MedicationList.fromJson(response['List_MedicineWithIntervention']); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = super.error! + "\n" + error; + return null; + }, body: request); + + return null; + } + + FutureOr getInfectiousDiseaseConsultantStatus() async { + hasError = false; + await baseAppClient.post(IS_INFECTIOUS_DISEASE, + onSuccess: (dynamic response, int statusCode) { + return response['IsInfectiousDiseases']; + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = super.error! + "\n" + error; + return false; + }, body: {}); + return false; + } + + FutureOr getInfectiousDiseaseHistory({ + String admissionNumber = '', + String prescriptionNumber = '', + String orderNumber = '', + String itemID = '', + }) async { + var request = { + "AdmissionNo": admissionNumber, + "PrescriptionNo": prescriptionNumber, + "OrderNo": orderNumber, + "ItemID": itemID, + }; + + hasError = false; + await baseAppClient.post(INFECTIOUS_HISTORY, + onSuccess: (dynamic response, int statusCode) { + return InterventionHistoryList.fromJson( + response['List_MedicineInterventionHistory']); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = super.error! + "\n" + error; + return null; + }, body: request); + return null; + } + + FutureOr 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, + }; + + hasError = false; + await baseAppClient.post(INFECTIOUS_HISTORY, + onSuccess: (dynamic response, int statusCode) { + return response['IsAccepted']; + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = super.error! + "\n" + error; + return false; + }, body: request); + return false; + } +} diff --git a/lib/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_view_model.dart b/lib/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_view_model.dart new file mode 100644 index 00000000..811c7bf3 --- /dev/null +++ b/lib/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_view_model.dart @@ -0,0 +1,608 @@ +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:intl/intl.dart'; + +class PharmacyInterventionViewModel extends BaseViewModel { + PharmacyInterventionService _service = locator(); + MedicationList? medicationList; + // MedicationList? medicationList = MedicationList.fromJson({ + // "entityList": [ + // { + // "accessLevel": 4, + // "admissionNo": 2020000098, + // "authorizedby": null, + // "authorizedbyName": null, + // "createdBy": "1485", + // "doctorComments": "asdf", + // "doctorName": null, + // "dosageDetail": "0/VIALS/BID/Parenteral", + // "itemID": 107476, + // "lineItemNo": 1, + // "medication": "TARGOPLANIN 200 MG INJ VIAL 1'S", + // "nursingStation": "New Pediatric Building 1st Floor ", + // "orderNo": 1448172, + // "patientID": 3120412, + // "patientName": "HABAB AABER CHINAN", + // "pharmacyRemarks": null, + // "prescriptionNo": 2686564, + // "startDatetime": "2024-12-24T10:33:18", + // "status": 62, + // "statusName": "RejectWithIntervention", + // "stopDatetime": "2024-12-24T20:00:00" + // },{ + // "accessLevel": 4, + // "patientID": 3648880, + // "patientName": "JEHAD BADEI ALI", + // "nursingStation": "New Pediatric Building 3rd Floor ", + // "admissionNo": 2022000100, + // "orderNo": 1447979, + // "prescriptionNo": 2686333, + // "lineItemNo": 3, + // "itemID": 67507, + // "medication": "DIPEPTIVEN 20% CONCENTRATED -100ML", + // "dosageDetail": "1 MG/BOTTLE/As Directed/Oral", + // "doctorComments": "Test PHR: (Pharmacy Intervention Accepted)Test", + // "startDatetime": "2024-05-08T12:56:00", + // "stopDatetime": "2024-05-08T12:57:00", + // "status": 52, + // "statusName": "Discontinue", + // "createdBy": "2804", + // "authorizedby": null, + // "doctorName": null, + // "authorizedbyName": null, + // "pharmacyRemarks": null + // }, + // { + // "accessLevel": 4, + // "patientID": 3648880, + // "patientName": "JEHAD BADEI ALI", + // "nursingStation": "New Pediatric Building 3rd Floor ", + // "admissionNo": 2022000100, + // "orderNo": 1447979, + // "prescriptionNo": 2686333, + // "lineItemNo": 3, + // "itemID": 67507, + // "medication": "DIPEPTIVEN 20% CONCENTRATED -100ML", + // "dosageDetail": "1 MG/BOTTLE/As Directed/Oral", + // "doctorComments": "Test PHR: (Pharmacy Intervention Accepted)Test", + // "startDatetime": "2024-05-08T12:56:00", + // "stopDatetime": "2024-05-08T12:57:00", + // "status": 52, + // "statusName": "Discontinue", + // "createdBy": "2804", + // "authorizedby": null, + // "doctorName": null, + // "authorizedbyName": null, + // "pharmacyRemarks": null + // } + // ], + // "rowcount": 1, + // "statusMessage": null, + // "success": null + // }); + + InterventionHistoryList? interventionHistoryList; + // InterventionHistoryList? interventionHistoryList = InterventionHistoryList.fromJson({ + // "entityList": [ + // { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 1005, + // "commentedByName": "TEMP - PHARMACIST ", + // "interventionDesc": "Drug information :administration related", + // "interventionId": 29, + // "remark": "asdfasdf" + // }, + // { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 0, + // "commentedByName": "lorem ipsum1 ", + // "interventionDesc": "", + // "interventionId": 1485, + // "remark": "loremIpsum" + // }, { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 1005, + // "commentedByName": "TEMP - PHARMACIST ", + // "interventionDesc": "Drug information :administration related", + // "interventionId": 29, + // "remark": "asdfasdf" + // }, + // { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 0, + // "commentedByName": "lorem ipsum1 ", + // "interventionDesc": "", + // "interventionId": 1485, + // "remark": "loremIpsum" + // }, { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 1005, + // "commentedByName": "TEMP - PHARMACIST ", + // "interventionDesc": "Drug information :administration related", + // "interventionId": 29, + // "remark": "asdfasdf" + // }, + // { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 0, + // "commentedByName": "lorem ipsum1 ", + // "interventionDesc": "", + // "interventionId": 1485, + // "remark": "loremIpsum" + // }, { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 1005, + // "commentedByName": "TEMP - PHARMACIST ", + // "interventionDesc": "Drug information :administration related", + // "interventionId": 29, + // "remark": "asdfasdf" + // }, + // { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 0, + // "commentedByName": "lorem ipsum1 ", + // "interventionDesc": "", + // "interventionId": 1485, + // "remark": "loremIpsum" + // }, { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 1005, + // "commentedByName": "TEMP - PHARMACIST ", + // "interventionDesc": "Drug information :administration related", + // "interventionId": 29, + // "remark": "asdfasdf" + // }, + // { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 0, + // "commentedByName": "lorem ipsum1 ", + // "interventionDesc": "", + // "interventionId": 1485, + // "remark": "loremIpsum" + // }, { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 1005, + // "commentedByName": "TEMP - PHARMACIST ", + // "interventionDesc": "Drug information :administration related", + // "interventionId": 29, + // "remark": "asdfasdf" + // }, + // { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 0, + // "commentedByName": "lorem ipsum1 ", + // "interventionDesc": "", + // "interventionId": 1485, + // "remark": "loremIpsum" + // }, { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 1005, + // "commentedByName": "TEMP - PHARMACIST ", + // "interventionDesc": "Drug information :administration related", + // "interventionId": 29, + // "remark": "asdfasdf" + // }, + // { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 0, + // "commentedByName": "lorem ipsum1 ", + // "interventionDesc": "", + // "interventionId": 1485, + // "remark": "loremIpsum" + // }, { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 1005, + // "commentedByName": "TEMP - PHARMACIST ", + // "interventionDesc": "Drug information :administration related", + // "interventionId": 29, + // "remark": "asdfasdf" + // }, + // { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 0, + // "commentedByName": "lorem ipsum1 ", + // "interventionDesc": "", + // "interventionId": 1485, + // "remark": "loremIpsum" + // }, { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 1005, + // "commentedByName": "TEMP - PHARMACIST ", + // "interventionDesc": "Drug information :administration related", + // "interventionId": 29, + // "remark": "asdfasdf" + // }, + // { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 0, + // "commentedByName": "lorem ipsum1 ", + // "interventionDesc": "", + // "interventionId": 1485, + // "remark": "loremIpsum" + // }, { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 1005, + // "commentedByName": "TEMP - PHARMACIST ", + // "interventionDesc": "Drug information :administration related", + // "interventionId": 29, + // "remark": "asdfasdf" + // }, + // { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 0, + // "commentedByName": "lorem ipsum1 ", + // "interventionDesc": "", + // "interventionId": 1485, + // "remark": "loremIpsum" + // }, { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 1005, + // "commentedByName": "TEMP - PHARMACIST ", + // "interventionDesc": "Drug information :administration related", + // "interventionId": 29, + // "remark": "asdfasdf" + // }, + // { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 0, + // "commentedByName": "lorem ipsum1 ", + // "interventionDesc": "", + // "interventionId": 1485, + // "remark": "loremIpsum" + // }, { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 1005, + // "commentedByName": "TEMP - PHARMACIST ", + // "interventionDesc": "Drug information :administration related", + // "interventionId": 29, + // "remark": "asdfasdf" + // }, + // { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 0, + // "commentedByName": "lorem ipsum1 ", + // "interventionDesc": "", + // "interventionId": 1485, + // "remark": "loremIpsum" + // }, { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 1005, + // "commentedByName": "TEMP - PHARMACIST ", + // "interventionDesc": "Drug information :administration related", + // "interventionId": 29, + // "remark": "asdfasdf" + // }, + // { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 0, + // "commentedByName": "lorem ipsum1 ", + // "interventionDesc": "", + // "interventionId": 1485, + // "remark": "loremIpsum" + // }, { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 1005, + // "commentedByName": "TEMP - PHARMACIST ", + // "interventionDesc": "Drug information :administration related", + // "interventionId": 29, + // "remark": "asdfasdf" + // }, + // { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 0, + // "commentedByName": "lorem ipsum1 ", + // "interventionDesc": "", + // "interventionId": 1485, + // "remark": "loremIpsum" + // }, { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 1005, + // "commentedByName": "TEMP - PHARMACIST ", + // "interventionDesc": "Drug information :administration related", + // "interventionId": 29, + // "remark": "asdfasdf" + // }, + // { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 0, + // "commentedByName": "lorem ipsum1 ", + // "interventionDesc": "", + // "interventionId": 1485, + // "remark": "loremIpsum" + // }, { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 1005, + // "commentedByName": "TEMP - PHARMACIST ", + // "interventionDesc": "Drug information :administration related", + // "interventionId": 29, + // "remark": "asdfasdf" + // }, + // { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 0, + // "commentedByName": "lorem ipsum1 ", + // "interventionDesc": "", + // "interventionId": 1485, + // "remark": "loremIpsum" + // }, { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 1005, + // "commentedByName": "TEMP - PHARMACIST ", + // "interventionDesc": "Drug information :administration related", + // "interventionId": 29, + // "remark": "asdfasdf" + // }, + // { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 0, + // "commentedByName": "lorem ipsum1 ", + // "interventionDesc": "", + // "interventionId": 1485, + // "remark": "loremIpsum" + // }, { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 1005, + // "commentedByName": "TEMP - PHARMACIST ", + // "interventionDesc": "Drug information :administration related", + // "interventionId": 29, + // "remark": "asdfasdf" + // }, + // { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 0, + // "commentedByName": "lorem ipsum1 ", + // "interventionDesc": "", + // "interventionId": 1485, + // "remark": "loremIpsum" + // }, { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 1005, + // "commentedByName": "TEMP - PHARMACIST ", + // "interventionDesc": "Drug information :administration related", + // "interventionId": 29, + // "remark": "asdfasdf" + // }, + // { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 0, + // "commentedByName": "lorem ipsum1 ", + // "interventionDesc": "", + // "interventionId": 1485, + // "remark": "loremIpsum" + // }, { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 1005, + // "commentedByName": "TEMP - PHARMACIST ", + // "interventionDesc": "Drug information :administration related", + // "interventionId": 29, + // "remark": "asdfasdf" + // }, + // { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 0, + // "commentedByName": "lorem ipsum1 ", + // "interventionDesc": "", + // "interventionId": 1485, + // "remark": "loremIpsum" + // }, { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 1005, + // "commentedByName": "TEMP - PHARMACIST ", + // "interventionDesc": "Drug information :administration related", + // "interventionId": 29, + // "remark": "asdfasdf" + // }, + // { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 0, + // "commentedByName": "lorem ipsum1 ", + // "interventionDesc": "", + // "interventionId": 1485, + // "remark": "loremIpsum" + // }, { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 1005, + // "commentedByName": "TEMP - PHARMACIST ", + // "interventionDesc": "Drug information :administration related", + // "interventionId": 29, + // "remark": "asdfasdf" + // }, + // { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 0, + // "commentedByName": "lorem ipsum1 ", + // "interventionDesc": "", + // "interventionId": 1485, + // "remark": "loremIpsum" + // }, { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 1005, + // "commentedByName": "TEMP - PHARMACIST ", + // "interventionDesc": "Drug information :administration related", + // "interventionId": 29, + // "remark": "asdfasdf" + // }, + // { + // "authizationFormText": "Intervention Approval Level 3", + // "authorizedAction": 51, + // "commentedBy": 0, + // "commentedByName": "lorem ipsum1 ", + // "interventionDesc": "", + // "interventionId": 1485, + // "remark": "loremIpsum" + // }, + // ], + // "rowcount": 2, + // "statusMessage": null, + // "success": null + // }); + + bool isInfectiousDiseaseConsultant = false; + + String nursingStationId = ''; + String admissionId = ''; + String patientID = ''; + String fromDate = ''; + String toDate = ''; + + String getDate(String dateTime) { + if (dateTime.isEmpty) return ''; + DateTime now = DateTime.now(); + return DateFormat('dd MMM yyyy').format(now); + } + + Future getPharmacyIntervention( + {String nursingStationId = '', + String admissionId = '', + String patientID = '', + String fromDate = '', + String toDate = ''}) async { + setState(ViewState.BusyLocal); + MedicationList? result = await _service.getMedicationList( + nursingStationId: nursingStationId, + admissionId: admissionId, + patientID: patientID, + fromDate: fromDate, + toDate: toDate); + + this.nursingStationId = nursingStationId; + this.admissionId = admissionId; + this.patientID = patientID; + this.fromDate = fromDate; + this.toDate = toDate; + + if (_service.hasError || result == null) { + error = _service.error; + setState(ViewState.ErrorLocal); + return; + } + medicationList = result; + setState(ViewState.Idle); + } + + Future getInfectiousDiseaseConsultantStatus() async { + setState(ViewState.BusyLocal); + bool result = await _service.getInfectiousDiseaseConsultantStatus(); + if (_service.hasError) { + error = _service.error; + setState(ViewState.ErrorLocal); + return; + } + isInfectiousDiseaseConsultant = result; + setState(ViewState.Idle); + } + + Future updateInterventionDiseaseStatus({ + String admissionNo = '', + String prescriptionNo = '', + String orderNo = '', + String itemID = '', + String interventionID = '', + String isAccepted = '', + String remarks = '', + String authorizeID = '', + String lineItemNo = '', + String status = '', + }) async { + setState(ViewState.BusyLocal); + bool result = await _service.getInfectiousDiseaseConsultantStatus(); + if (_service.hasError) { + error = _service.error; + setState(ViewState.ErrorLocal); + return; + } + isInfectiousDiseaseConsultant = result; + setState(ViewState.Idle); + } + + Future getInterventionHistory({ + String admissionNo = '', + String prescriptionNo = '', + String orderNo = '', + String itemID = '', + String interventionID = '', + String isAccepted = '', + String remarks = '', + String authorizeID = '', + String lineItemNo = '', + String status = '', + }) async { + setState(ViewState.BusyLocal); + bool? result = await _service.updateInterventionStatus( + admissionNo: admissionNo, + prescriptionNo: prescriptionNo, + orderNo: orderNo, + itemID: itemID, + interventionID: interventionID, + isAccepted: isAccepted, + remarks: remarks, + authorizeID: authorizeID, + lineItemNo: lineItemNo, + status: status); + if (_service.hasError || !result) { + error = _service.error; + setState(ViewState.ErrorLocal); + return; + } + await getPharmacyIntervention( + nursingStationId: nursingStationId, + admissionId: admissionNo, + patientID: patientID, + fromDate: fromDate, + toDate: toDate); + setState(ViewState.Idle); + } + + toggleShowBottomSheetValue() { + interventionHistoryList = null; + } +} diff --git a/lib/utils/translations_delegate_base_utils.dart b/lib/utils/translations_delegate_base_utils.dart index c5e1fc08..b91d8a44 100644 --- a/lib/utils/translations_delegate_base_utils.dart +++ b/lib/utils/translations_delegate_base_utils.dart @@ -1967,6 +1967,16 @@ class TranslationBase { localizedValues['admissionNumber']![locale.languageCode]!; String get nursingStation => localizedValues['nursingStation']![locale.languageCode]!; + String get accessLevel => + localizedValues['accessLevel']![locale.languageCode]!; + String get dosageDetails => + localizedValues['dosageDetails']![locale.languageCode]!; + String get authorizedBy => + localizedValues['authorizedBy']![locale.languageCode]!; + String get pharmacyRemarks => + localizedValues['pharmacyRemarks']![locale.languageCode]!; + String get unableToPerformTheAction => + localizedValues['unableToPerformTheAction']![locale.languageCode]!; } class TranslationBaseDelegate extends LocalizationsDelegate { From 63675befe293615a873b7cfca3f7c67e417b6a89 Mon Sep 17 00:00:00 2001 From: "taha.alam" Date: Thu, 26 Dec 2024 16:03:28 +0300 Subject: [PATCH 04/14] WIP: api integration --- lib/client/base_app_client.dart | 30 ++--- lib/core/viewModel/dashboard_view_model.dart | 1 + lib/screens/home/home_screen.dart | 2 +- .../PharmacyIntervention.dart | 119 ++++++++++++++---- .../pharmacy_intervention_service.dart | 53 +++++--- .../pharmacy_intervention_view_model.dart | 37 ++---- pubspec.lock | 36 ++---- pubspec.yaml | 1 + .../flutter/generated_plugin_registrant.cc | 3 - windows/flutter/generated_plugins.cmake | 1 - 10 files changed, 167 insertions(+), 116 deletions(-) diff --git a/lib/client/base_app_client.dart b/lib/client/base_app_client.dart index 5747ccb4..4147cfed 100644 --- a/lib/client/base_app_client.dart +++ b/lib/client/base_app_client.dart @@ -44,17 +44,17 @@ class BaseAppClient { if (profile != null) { DoctorProfileModel doctorProfile = DoctorProfileModel.fromJson(profile); if (body == null || body['DoctorID'] == null) { - body!['DoctorID'] = doctorProfile.doctorID; + body!['DoctorID'] = doctorProfile.doctorID.toString(); } if (body['DoctorID'] == "") body['DoctorID'] = doctorProfile .doctorID; // changed from null; because create update episode not working - if (body['EditedBy'] == null) body['EditedBy'] = doctorProfile.doctorID; + if (body['EditedBy'] == null) body['EditedBy'] = doctorProfile.doctorID.toString(); if (body['ProjectID'] == null) { - body['ProjectID'] = doctorProfile.projectID; + body['ProjectID'] = doctorProfile.projectID.toString(); } - if (body['ClinicID'] == null) body['ClinicID'] = doctorProfile.clinicID; + if (body['ClinicID'] == null) body['ClinicID'] = doctorProfile.clinicID.toString(); } else { String? doctorID = await sharedPref.getString(DOCTOR_ID); if (body!['DoctorID'] == '') { @@ -78,21 +78,21 @@ class BaseAppClient { if (!isFallLanguage) { String? lang = await sharedPref.getString(APP_Language); if (lang != null && lang == 'ar') - body['LanguageID'] = 1; + body['LanguageID'] = '1'; else - body['LanguageID'] = 2; + body['LanguageID'] = '2'; } body['stamp'] = DateTime.now().toIso8601String(); - body['IPAdress'] = IP_ADDRESS; + body['IPAdress'] = IP_ADDRESS.toString(); if (body['VersionID'] == null) { - body['VersionID'] = VERSION_ID; + body['VersionID'] = VERSION_ID.toString(); } if (body['Channel'] == null) { - body['Channel'] = CHANNEL; + body['Channel'] = CHANNEL.toString(); } - body['SessionID'] = SESSION_ID; - body['IsLoginForDoctorApp'] = IS_LOGIN_FOR_DOCTOR_APP; - body['PatientOutSA'] = body['PatientOutSA'] ?? 0; // PATIENT_OUT_SA; + body['SessionID'] = SESSION_ID.toString(); + body['IsLoginForDoctorApp'] = IS_LOGIN_FOR_DOCTOR_APP.toString(); + body['PatientOutSA'] = body['PatientOutSA'] ?? '0'; // PATIENT_OUT_SA; if (body['VidaAuthTokenID'] == null) { body['VidaAuthTokenID'] = await sharedPref.getString(VIDA_AUTH_TOKEN_ID); @@ -109,9 +109,9 @@ class BaseAppClient { body['facilityId'] == 3) || body['ProjectID'] == 2 || body['ProjectID'] == 3) - body['PatientOutSA'] = true; + body['PatientOutSA'] = 'true'; else - body['PatientOutSA'] = false; + body['PatientOutSA'] = 'false'; // if (!body.containsKey('ProjectID')) { // if (projectID != null) { @@ -121,7 +121,7 @@ class BaseAppClient { // } // } - body['DeviceTypeID'] = Platform.isAndroid ? 1 : 2; + body['DeviceTypeID'] = Platform.isAndroid ? '1' : '2'; // body['ClinicID'] = 501; // body['ProjectID'] = 12; diff --git a/lib/core/viewModel/dashboard_view_model.dart b/lib/core/viewModel/dashboard_view_model.dart index 31e9f363..cc9ae0b6 100644 --- a/lib/core/viewModel/dashboard_view_model.dart +++ b/lib/core/viewModel/dashboard_view_model.dart @@ -48,6 +48,7 @@ class DashboardViewModel extends BaseViewModel { return; } isInfectiousDiseaseConsultant = result; + print('the result is ${result}'); setState(ViewState.Idle); } diff --git a/lib/screens/home/home_screen.dart b/lib/screens/home/home_screen.dart index 5225d347..e2700987 100644 --- a/lib/screens/home/home_screen.dart +++ b/lib/screens/home/home_screen.dart @@ -80,7 +80,7 @@ class _HomeScreenState extends State { .then((value) { if (model.radiologyCriticalFindingModel != null) { print("onModelReady radiologyCriticalFindingModel!!!"); - showRadiologyFindingDialog(model); + // showRadiologyFindingDialog(model); } else { print("onModelReady radiologyCriticalFindingModel EMPTYYYY!!!"); } diff --git a/lib/screens/pharmacy_intervention/PharmacyIntervention.dart b/lib/screens/pharmacy_intervention/PharmacyIntervention.dart index 1d12ce9f..0af5c894 100644 --- a/lib/screens/pharmacy_intervention/PharmacyIntervention.dart +++ b/lib/screens/pharmacy_intervention/PharmacyIntervention.dart @@ -1,4 +1,5 @@ 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'; @@ -40,6 +41,7 @@ class _PharmacyInterventionState extends State { } return AppScaffold( isShowAppBar: true, + isLoading: model.state == ViewState.BusyLocal, appBar: PatientSearchHeader( title: TranslationBase .of(context) @@ -47,7 +49,7 @@ class _PharmacyInterventionState extends State { fontSize: 18, showSearchIcon: true, onSearchPressed: () { - SearchDialog(context); + SearchDialog(context, model); }, ), appBarTitle: TranslationBase @@ -100,6 +102,7 @@ class _PharmacyInterventionState extends State { curve: Curves.easeInOut, ); } + @override void dispose() { super.dispose(); @@ -120,32 +123,54 @@ class _PharmacyInterventionState extends State { topLeft: Radius.circular(20), topRight: Radius.circular(20))), builder: (_) { return DraggableScrollableSheet( - key: _sheet, + key: _sheet, initialChildSize: 0.5, minChildSize: 0.5, maxChildSize: 1, snapSizes: [ - 0.5 ,// constraints.maxHeight, + 0.5, // constraints.maxHeight, 0.9, ], expand: false, controller: _controller, - builder:(_, controller) => - InterventionHistoryBottomSheet( - interventionList: interventionHistory, - controller: controller, - )); + builder: (_, controller) => + InterventionHistoryBottomSheet( + interventionList: interventionHistory, + controller: controller, + )); }, ).then((value) => model.toggleShowBottomSheetValue()); } - void SearchDialog(BuildContext context) { + void SearchDialog(BuildContext context, PharmacyInterventionViewModel model) { showDialog( context: context, barrierDismissible: true, // user must tap button! builder: (_) { return PharmacyInterventionDialog( - onDispose: (dateFrom, dateTo, admissionNumber, 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 && + nursingStation == model.nursingStationId) { + Navigator.of(context).pop(); + return; + } + + model.getPharmacyIntervention( + admissionId: admissionNumber, + patientID: patientId, + nursingStationId: nursingStation, + toDate: dateTo, + fromDate: dateFrom + ); + Navigator.of(context).pop(); + }); }); } } @@ -173,7 +198,7 @@ class InterventionCardItem extends StatelessWidget { medication: medication, model: model, ), - InterventionCardFooter(model: model) + InterventionCardFooter(model: model, medication: medication,) ], ), ), @@ -184,8 +209,8 @@ class InterventionCardItem extends StatelessWidget { class InterventionCardFooter extends StatelessWidget { final PharmacyInterventionViewModel model; - - const InterventionCardFooter({super.key, required this.model}); + final Medication medication; + const InterventionCardFooter({super.key, required this.model, required this.medication}); @override Widget build(BuildContext context) { @@ -200,7 +225,14 @@ class InterventionCardFooter extends StatelessWidget { borderColor: Colors.grey, color: Colors.grey, fontColor: Colors.white, - onPressed: () async {}, + onPressed: () async { + model.getInterventionHistory( + admissionNumber: medication.admissionNo?.toString() ?? '', + prescriptionNumber: medication.prescriptionNo?.toString() ?? '', + orderNumber: medication.orderNo?.toString() ?? '', + itemID: medication.itemID?.toString() ?? '', + ); + }, ), ), ]), @@ -217,7 +249,18 @@ class InterventionCardFooter extends StatelessWidget { borderColor: Color(0xFFB8382B), color: AppGlobal.appRedColor, fontColor: Colors.white, - onPressed: () async {}, + 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( @@ -1008,13 +1051,20 @@ class _TableExampleState extends State { class PharmacyInterventionDialog extends StatefulWidget { final Function( - String, - String, - String, - String, + String, // dataFrom + String, // dateTo + String, // admissionNumber + String, // patient ID + String, // nursingStation ) onDispose; - const PharmacyInterventionDialog({super.key, required this.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() => @@ -1034,8 +1084,16 @@ class _PharmacyInterventionDialogState @override void initState() { + initData(); super.initState(); - // initFromDate(); + } + + void initData() { + admissionNumber.text = widget.admissionNumber; + nursingStation.text = widget.nursingStation; + patientId.text = widget.patientID; + dateTo = getDate(widget.dateTo); + dateFrom = getDate(widget.dateFrom); } @override @@ -1101,7 +1159,15 @@ class _PharmacyInterventionDialogState borderColor: Color(0xFFB8382B), color: AppGlobal.appRedColor, fontColor: Colors.white, - onPressed: () async {}, + onPressed: () async { + //(dateFrom, dateTo, admissionNumber, patientId, nursingStation) + widget.onDispose( + dateFrom, + dateTo, + nursingStation.text, + patientId.text, + nursingStation.text); + }, ), ), ]), @@ -1191,6 +1257,13 @@ class _PharmacyInterventionDialogState } String getFormattedDate(DateTime time) { - return DateFormat('MM/dd/yyyy').format(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 1017bcd7..936f0e89 100644 --- a/lib/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_service.dart +++ b/lib/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_service.dart @@ -1,12 +1,13 @@ import 'dart:async'; 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'; class PharmacyInterventionService extends BaseService { - FutureOr getMedicationList( + Future getMedicationList( {String nursingStationId = '', String admissionId = '', String patientID = '', @@ -20,32 +21,43 @@ class PharmacyInterventionService extends BaseService { "toDate": toDate, }; hasError = false; - await baseAppClient.post(GET_MEDICINE_WITH_INTERVAL, + MedicationList? result; + await baseAppClient.post(GET_MEDICINE_WITH_INTERVAL, onSuccess: (dynamic response, int statusCode) { - return MedicationList.fromJson(response['List_MedicineWithIntervention']); + result = MedicationList.fromJson(response['List_MedicineWithIntervention']); }, onFailure: (String error, int statusCode) { hasError = true; - super.error = super.error! + "\n" + error; - return null; + super.error = super.error??'' + "\n" + error; + }, body: request); - return null; + return result; } - FutureOr getInfectiousDiseaseConsultantStatus() async { + /// + /// it will be called only for the doctor that are associated to vida plus + /// project + /// + Future getInfectiousDiseaseConsultantStatus() 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, onSuccess: (dynamic response, int statusCode) { - return response['IsInfectiousDiseases']; + success = response['IsInfectiousDiseases']; }, onFailure: (String error, int statusCode) { hasError = true; super.error = super.error! + "\n" + error; - return false; + }, body: {}); - return false; + return success; } - FutureOr getInfectiousDiseaseHistory({ + Future getInfectiousDiseaseHistory({ String admissionNumber = '', String prescriptionNumber = '', String orderNumber = '', @@ -59,19 +71,20 @@ class PharmacyInterventionService extends BaseService { }; hasError = false; - await baseAppClient.post(INFECTIOUS_HISTORY, + InterventionHistoryList? result; + await baseAppClient.post(INFECTIOUS_HISTORY, onSuccess: (dynamic response, int statusCode) { - return InterventionHistoryList.fromJson( + result = InterventionHistoryList.fromJson( response['List_MedicineInterventionHistory']); }, onFailure: (String error, int statusCode) { hasError = true; super.error = super.error! + "\n" + error; - return null; + }, body: request); - return null; + return result; } - FutureOr updateInterventionStatus({ + Future updateInterventionStatus({ String admissionNo = '', String prescriptionNo = '', String orderNo = '', @@ -97,14 +110,14 @@ class PharmacyInterventionService extends BaseService { }; hasError = false; - await baseAppClient.post(INFECTIOUS_HISTORY, + var result = false; + await baseAppClient.post(INFECTIOUS_HISTORY, onSuccess: (dynamic response, int statusCode) { - return response['IsAccepted']; + result = response['IsAccepted']; }, onFailure: (String error, int statusCode) { hasError = true; super.error = super.error! + "\n" + error; - return false; }, body: request); - return false; + 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 811c7bf3..1e50d722 100644 --- a/lib/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_view_model.dart +++ b/lib/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_view_model.dart @@ -565,40 +565,23 @@ class PharmacyInterventionViewModel extends BaseViewModel { } Future getInterventionHistory({ - String admissionNo = '', - String prescriptionNo = '', - String orderNo = '', + String admissionNumber = '', + String prescriptionNumber = '', + String orderNumber = '', String itemID = '', - String interventionID = '', - String isAccepted = '', - String remarks = '', - String authorizeID = '', - String lineItemNo = '', - String status = '', }) async { setState(ViewState.BusyLocal); - bool? result = await _service.updateInterventionStatus( - admissionNo: admissionNo, - prescriptionNo: prescriptionNo, - orderNo: orderNo, - itemID: itemID, - interventionID: interventionID, - isAccepted: isAccepted, - remarks: remarks, - authorizeID: authorizeID, - lineItemNo: lineItemNo, - status: status); - if (_service.hasError || !result) { + InterventionHistoryList? result = await _service.getInfectiousDiseaseHistory( + admissionNumber: admissionNumber, + prescriptionNumber: prescriptionNumber, + orderNumber: orderNumber, + itemID: itemID); + if (_service.hasError ) { error = _service.error; setState(ViewState.ErrorLocal); return; } - await getPharmacyIntervention( - nursingStationId: nursingStationId, - admissionId: admissionNo, - patientID: patientID, - fromDate: fromDate, - toDate: toDate); + interventionHistoryList = result; setState(ViewState.Idle); } diff --git a/pubspec.lock b/pubspec.lock index 685eba41..c92984e9 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -233,30 +233,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" - cloud_firestore: - dependency: "direct main" - description: - name: cloud_firestore - sha256: "31cfa4d65d6e9ea837234fffe121304034c30c9214c06207b4a35867e3757900" - url: "https://pub.dev" - source: hosted - version: "4.15.8" - cloud_firestore_platform_interface: - dependency: transitive - description: - name: cloud_firestore_platform_interface - sha256: a0097a26569b015faf8142e159e855241609ea9a1738b5fd1c40bfe8411b41a0 - url: "https://pub.dev" - source: hosted - version: "6.1.9" - cloud_firestore_web: - dependency: transitive - description: - name: cloud_firestore_web - sha256: ed680ece29a5750985119c09cdc276b460c3a2fa80e8c12f9b7241f6b4a7ca16 - url: "https://pub.dev" - source: hosted - version: "3.10.8" cloudflare_turnstile: dependency: "direct main" description: @@ -1586,6 +1562,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.2" + two_dimensional_scrollables: + dependency: "direct main" + description: + name: two_dimensional_scrollables + sha256: b6028c80e782e58a5d18f9491737aae4f70d72dc08050ac92006905c7c0b5e21 + url: "https://pub.dev" + source: hosted + version: "0.3.3" typed_data: dependency: transitive description: @@ -1710,10 +1694,10 @@ packages: dependency: transitive description: name: vm_service - sha256: f652077d0bdf60abe4c1f6377448e8655008eef28f128bc023f7b5e8dfeb48fc + sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" url: "https://pub.dev" source: hosted - version: "14.2.4" + version: "14.2.5" watcher: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 45856f38..2dcd7b8b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -132,6 +132,7 @@ dependencies: cloudflare_turnstile: ^3.0.1 # flutter_zoom_videosdk: ^1.10.11 # dart_jsonwebtoken: ^2.14.0 + two_dimensional_scrollables: ^0.3.3 dependency_overrides: diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index ad50cab8..c0183aab 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -6,7 +6,6 @@ #include "generated_plugin_registrant.h" -#include #include #include #include @@ -15,8 +14,6 @@ #include void RegisterPlugins(flutter::PluginRegistry* registry) { - CloudFirestorePluginCApiRegisterWithRegistrar( - registry->GetRegistrarForPlugin("CloudFirestorePluginCApi")); FirebaseCorePluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("FirebaseCorePluginCApi")); FlutterInappwebviewWindowsPluginCApiRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 3e03a259..14522e7e 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -3,7 +3,6 @@ # list(APPEND FLUTTER_PLUGIN_LIST - cloud_firestore firebase_core flutter_inappwebview_windows local_auth_windows From 9fa4fc445c87da7890797efc636cae4c875a1c4a Mon Sep 17 00:00:00 2001 From: "taha.alam" Date: Wed, 1 Jan 2025 10:36:43 +0300 Subject: [PATCH 05/14] WIP: Pharmacy intervention date handling for to and from date --- lib/config/config.dart | 3 +- lib/config/localized_values.dart | 7 + lib/core/viewModel/dashboard_view_model.dart | 18 +- lib/screens/home/home_screen.dart | 48 +- .../PharmacyIntervention.dart | 1207 +---------------- .../pharmacy_intervention_service.dart | 98 +- .../pharmacy_intervention_view_model.dart | 70 +- .../widgets/InterventionCardBody.dart | 179 +++ .../widgets/InterventionCardFooter.dart | 37 + .../widgets/InterventionCardItem.dart | 40 + .../widgets/InterventionDetails.dart | 38 + .../InterventionHistoryBottomSheet.dart | 87 ++ .../widgets/NoInveterventionFound.dart | 20 + .../widgets/PharmacyInterventionDialog.dart | 236 ++++ .../widgets/intervention_history_item.dart | 105 ++ .../translations_delegate_base_utils.dart | 16 + lib/utils/utils.dart | 6 +- 17 files changed, 987 insertions(+), 1228 deletions(-) create mode 100644 lib/screens/pharmacy_intervention/widgets/InterventionCardBody.dart create mode 100644 lib/screens/pharmacy_intervention/widgets/InterventionCardFooter.dart create mode 100644 lib/screens/pharmacy_intervention/widgets/InterventionCardItem.dart create mode 100644 lib/screens/pharmacy_intervention/widgets/InterventionDetails.dart create mode 100644 lib/screens/pharmacy_intervention/widgets/InterventionHistoryBottomSheet.dart create mode 100644 lib/screens/pharmacy_intervention/widgets/NoInveterventionFound.dart create mode 100644 lib/screens/pharmacy_intervention/widgets/PharmacyInterventionDialog.dart create mode 100644 lib/screens/pharmacy_intervention/widgets/intervention_history_item.dart 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, From 2ec7672b294fd79701aebe8e3b9fd359d247b7ce Mon Sep 17 00:00:00 2001 From: "taha.alam" Date: Wed, 1 Jan 2025 11:59:53 +0300 Subject: [PATCH 06/14] WD: Date from and date to added to the dialog and limit handled --- .../pharmacy_intervention_view_model.dart | 6 ++- .../widgets/PharmacyInterventionDialog.dart | 46 ++++++++++++++----- 2 files changed, 39 insertions(+), 13 deletions(-) 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 0f732dc6..809f3695 100644 --- a/lib/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_view_model.dart +++ b/lib/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_view_model.dart @@ -581,8 +581,10 @@ class PharmacyInterventionViewModel extends BaseViewModel { DrAppToastMsg.showErrorToast(errorMessage); return; } - DrAppToastMsg.showSuccesToast(successMessage); - getPharmacyIntervention(); + if(result) { + DrAppToastMsg.showSuccesToast(successMessage); + getPharmacyIntervention(); + } setState(ViewState.Idle); } diff --git a/lib/screens/pharmacy_intervention/widgets/PharmacyInterventionDialog.dart b/lib/screens/pharmacy_intervention/widgets/PharmacyInterventionDialog.dart index 2e698683..58fe5ce5 100644 --- a/lib/screens/pharmacy_intervention/widgets/PharmacyInterventionDialog.dart +++ b/lib/screens/pharmacy_intervention/widgets/PharmacyInterventionDialog.dart @@ -53,8 +53,8 @@ class _PharmacyInterventionDialogState 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); + dateTo = getDateString(widget.dateTo); + dateFrom = getDateString(widget.dateFrom); } @override @@ -102,10 +102,25 @@ class _PharmacyInterventionDialogState _dateSelection(TranslationBase .of(context) .dateFrom, (date) { + DateTime? fromDate = getDate(date); + DateTime? toDate =getDate(dateTo); + if(toDate == null){ + setState(() { + dateFrom = date; + }); + return; + } + if(fromDate!.compareTo(toDate!) == 1){ + setState(() { + dateFrom = date; + dateTo = ''; + }); + return; + } setState(() { dateFrom = date; }); - }, dateFrom), + }, dateFrom, false), SizedBox( height: 4, ), @@ -115,7 +130,7 @@ class _PharmacyInterventionDialogState setState(() { dateTo = date; }); - }, dateTo), + }, dateTo, true, selectedFromDate: dateFrom), SizedBox( height: 8, ), @@ -144,9 +159,9 @@ class _PharmacyInterventionDialogState } Widget _dateSelection(String title, Function(String) onDateSelected, - String selectedDate) { + String selectedDate, bool isToDateSelection,{String? selectedFromDate}) { return GestureDetector( - onTap: () => _selectDate(onDateSelected), + onTap: () => _selectDate(onDateSelected,selectedDate, isToDateSelection , selectedFromDate: selectedFromDate), child: Row( mainAxisSize: MainAxisSize.min, children: [ @@ -164,11 +179,13 @@ class _PharmacyInterventionDialogState ); } - Future _selectDate(Function(String) updateDate) async { + Future _selectDate(Function(String) updateDate , String date, bool toDateSelection, {String? selectedFromDate}) async { + DateTime? dateTime = getDate(date); + DateTime? fromDate = getDate(selectedFromDate??''); final DateTime? picked = await showDatePicker( context: context, - initialDate: DateTime.now(), - firstDate: DateTime(DateTime + initialDate:date.isNotEmpty? getDate(date) :fromDate != null? fromDate: DateTime.now(), + firstDate:(( date.isNotEmpty && dateTime != null ) ) ? dateTime: (toDateSelection && fromDate != null)?fromDate :DateTime(DateTime .now() .year - 150), lastDate: DateTime(DateTime @@ -226,11 +243,18 @@ class _PharmacyInterventionDialogState return DateFormat('yyyy-MM-dd').format(time); } - String getDate(String dateTime) { + String getDateString(String dateTime) { if (dateTime.isEmpty) return ''; + DateTime? now = getDate(dateTime); + if(now == null ) return ''; + return DateFormat('yyyy-MM-dd').format(now); + } + + DateTime? getDate(String dateTime){ + if (dateTime.isEmpty) return null; 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); + return now; } } \ No newline at end of file From 5a554a9ea630383e322b8845c576a0ea763c57b7 Mon Sep 17 00:00:00 2001 From: "taha.alam" Date: Wed, 1 Jan 2025 16:20:11 +0300 Subject: [PATCH 07/14] WD: await added for the get call --- .../viewmodel/pharmacy_intervention_view_model.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 809f3695..18976f69 100644 --- a/lib/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_view_model.dart +++ b/lib/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_view_model.dart @@ -583,7 +583,7 @@ class PharmacyInterventionViewModel extends BaseViewModel { } if(result) { DrAppToastMsg.showSuccesToast(successMessage); - getPharmacyIntervention(); + await getPharmacyIntervention(); } setState(ViewState.Idle); } From b25398b97b213e8c5cb681b000467763448097c6 Mon Sep 17 00:00:00 2001 From: "taha.alam" Date: Wed, 19 Feb 2025 13:29:41 +0300 Subject: [PATCH 08/14] WD: nursing stations added. --- lib/config/config.dart | 1 + .../nursing_station.dart | 73 ++++++ .../PharmacyIntervention.dart | 14 +- .../pharmacy_intervention_service.dart | 21 +- .../pharmacy_intervention_view_model.dart | 14 +- .../widgets/InterventionCardFooter.dart | 5 +- .../widgets/PharmacyInterventionDialog.dart | 231 +++++++++++------- 7 files changed, 262 insertions(+), 97 deletions(-) create mode 100644 lib/core/model/pharmacy-intervention-model/nursing_station.dart diff --git a/lib/config/config.dart b/lib/config/config.dart index 71bdbe45..dcac10e4 100644 --- a/lib/config/config.dart +++ b/lib/config/config.dart @@ -373,6 +373,7 @@ const IS_INFECTIOUS_DISEASE_CONSULTANT = 'Services/DoctorApplication.svc/REST/Is 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'; +const GET_NURSING_STATIONS = 'Services/DoctorApplication.svc/REST/GetWards'; var selectedPatientType = 1; diff --git a/lib/core/model/pharmacy-intervention-model/nursing_station.dart b/lib/core/model/pharmacy-intervention-model/nursing_station.dart new file mode 100644 index 00000000..a9949558 --- /dev/null +++ b/lib/core/model/pharmacy-intervention-model/nursing_station.dart @@ -0,0 +1,73 @@ +class NursingStation { + final List? entityList; + final int? rowcount; + final String? statusMessage; + final bool? success; + + NursingStation({ + this.entityList, + this.rowcount, + this.statusMessage, + this.success, + }); + + factory NursingStation.fromJson(Map json) { + return NursingStation( + entityList: (json['entityList'] as List?) + ?.map((e) => NursingStationEntity.fromJson(e as Map)) + .toList(), + rowcount: json['rowcount'] as int?, + statusMessage: json['statusMessage'] as String?, + success: json['success'] as bool?, + ); + } + + Map toJson() { + return { + 'entityList': entityList?.map((e) => e.toJson()).toList(), + 'rowcount': rowcount, + 'statusMessage': statusMessage, + 'success': success, + }; + } +} + +class NursingStationEntity { + final int? categoryID; + final String? description; + final String? descriptionN; + final int? floorID; + final bool? isActive; + final int? nursingStationID; + + NursingStationEntity({ + this.categoryID, + this.description, + this.descriptionN, + this.floorID, + this.isActive, + this.nursingStationID, + }); + + factory NursingStationEntity.fromJson(Map json) { + return NursingStationEntity( + categoryID: json['categoryID'] as int?, + description: json['description'] ??'${json['nursingStationID']}', + descriptionN: json['descriptionN'] as String?, + floorID: json['floorID'] as int?, + isActive: json['isActive'] as bool?, + nursingStationID: json['nursingStationID'] as int?, + ); + } + + Map toJson() { + return { + 'categoryID': categoryID, + 'description': description, + 'descriptionN': descriptionN, + 'floorID': floorID, + 'isActive': isActive, + 'nursingStationID': nursingStationID, + }; + } +} diff --git a/lib/screens/pharmacy_intervention/PharmacyIntervention.dart b/lib/screens/pharmacy_intervention/PharmacyIntervention.dart index 2f2c3c07..2249d039 100644 --- a/lib/screens/pharmacy_intervention/PharmacyIntervention.dart +++ b/lib/screens/pharmacy_intervention/PharmacyIntervention.dart @@ -23,7 +23,10 @@ class _PharmacyInterventionState extends State { Widget build(BuildContext context) { return BaseView(onModelReady: (model) { WidgetsBinding.instance.addPostFrameCallback((_) { - model.getPharmacyIntervention(); + Future.wait([ + model.getNursingStations(), + model.getPharmacyIntervention(), + ]); }); }, builder: (_, model, __) { if (model.interventionHistoryList != null) { @@ -147,8 +150,9 @@ class _PharmacyInterventionState extends State { dateFrom: model.fromDate, dateTo: model.toDate, admissionNumber: model.admissionId, - nursingStation: model.nursingStationId, + nursingStation: model.entity, patientID: model.patientID, + station: model.nursingStations, onDispose: (dateFrom, dateTo, admissionNumber, patientId, nursingStation) { if (dateFrom == model.fromDate && @@ -172,9 +176,11 @@ class _PharmacyInterventionState extends State { model.getPharmacyIntervention( admissionId: admissionNumber, patientID: patientId, - nursingStationId: nursingStation, + nursingStationId: + "${nursingStation?.nursingStationID ?? '0'}", toDate: dateTo, - fromDate: dateFrom); + fromDate: dateFrom, + entity: nursingStation); Navigator.of(context).pop(); }); }); diff --git a/lib/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_service.dart b/lib/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_service.dart index afb69112..7a615c1d 100644 --- a/lib/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_service.dart +++ b/lib/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_service.dart @@ -4,6 +4,7 @@ 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/nursing_station.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'; @@ -17,8 +18,8 @@ class PharmacyInterventionService extends BaseService { String fromDate = '', String toDate = ''}) async { Map request = { - "NursingStationID": num.parse((nursingStationId.isEmpty)?'0':nursingStationId), - "AdmissionNo": num.parse((admissionId.isEmpty)?'0':admissionId), + "NursingStationID": nursingStationId.isEmpty?'0':nursingStationId, + "AdmissionNo": admissionId.isEmpty ?'0': admissionId, "PatientID": num.parse((patientID.isEmpty)?'0':patientID), }; @@ -146,4 +147,20 @@ class PharmacyInterventionService extends BaseService { }, body: request); return result; } + + + Future getNursingStation() async{ + hasError = false; + NursingStation? station; + await baseAppClient.post(GET_NURSING_STATIONS, + onSuccess: (dynamic response, int statusCode) { + station = NursingStation.fromJson(response['AdmissionMasterList']); + }, onFailure: (String error, int statusCode) { + hasError = true; + DrAppToastMsg.showErrorToast(error); + + super.error = super.error! + "\n" + error; + }, body: {}); + return station; + } } 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 18976f69..f360447a 100644 --- a/lib/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_view_model.dart +++ b/lib/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_view_model.dart @@ -1,6 +1,7 @@ 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/nursing_station.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'; @@ -92,6 +93,8 @@ class PharmacyInterventionViewModel extends BaseViewModel { InterventionHistoryList? interventionHistoryList; + NursingStation? nursingStations; + // InterventionHistoryList? interventionHistoryList = InterventionHistoryList.fromJson({ // "entityList": [ // { @@ -499,6 +502,7 @@ class PharmacyInterventionViewModel extends BaseViewModel { String patientID = ''; String fromDate = ''; String toDate = ''; + NursingStationEntity? entity; String getDate(String dateTime) { if (dateTime.isEmpty) return ''; @@ -506,13 +510,20 @@ class PharmacyInterventionViewModel extends BaseViewModel { return DateFormat('dd MMM yyyy').format(now); } + Future getNursingStations() async { + nursingStations = await _service.getNursingStation(); + } + Future getPharmacyIntervention( {String nursingStationId = '0', String admissionId = '0', String patientID = '0', String fromDate = '', - String toDate = ''}) async { + String toDate = '', + NursingStationEntity? entity, + }) async { setState(ViewState.BusyLocal); + MedicationList? result = await _service.getMedicationList( nursingStationId: nursingStationId, admissionId: admissionId, @@ -525,6 +536,7 @@ class PharmacyInterventionViewModel extends BaseViewModel { this.patientID = patientID; this.fromDate = fromDate; this.toDate = toDate; + this.entity = entity; if (_service.hasError || result == null) { error = _service.error; diff --git a/lib/screens/pharmacy_intervention/widgets/InterventionCardFooter.dart b/lib/screens/pharmacy_intervention/widgets/InterventionCardFooter.dart index a3a1b1d2..6edbdd5d 100644 --- a/lib/screens/pharmacy_intervention/widgets/InterventionCardFooter.dart +++ b/lib/screens/pharmacy_intervention/widgets/InterventionCardFooter.dart @@ -1,3 +1,4 @@ +import 'package:doctor_app_flutter/config/config.dart'; 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'; @@ -21,8 +22,8 @@ class InterventionCardFooter extends StatelessWidget { .of(context) .details, hasBorder: true, - borderColor: Colors.grey, - color: Colors.grey, + borderColor: AppGlobal.appGreenColor, + color: AppGlobal.appGreenColor, fontColor: Colors.white, onPressed: () async { model.getInterventionHistory( diff --git a/lib/screens/pharmacy_intervention/widgets/PharmacyInterventionDialog.dart b/lib/screens/pharmacy_intervention/widgets/PharmacyInterventionDialog.dart index 58fe5ce5..305643a7 100644 --- a/lib/screens/pharmacy_intervention/widgets/PharmacyInterventionDialog.dart +++ b/lib/screens/pharmacy_intervention/widgets/PharmacyInterventionDialog.dart @@ -1,23 +1,28 @@ import 'package:doctor_app_flutter/config/config.dart'; +import 'package:doctor_app_flutter/core/model/pharmacy-intervention-model/nursing_station.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'; +import '../../../widgets/shared/app_texts_widget.dart'; +import '../../patients/profile/soap_update_vida_plus/assessment/widget/empty_dropdown.dart'; + class PharmacyInterventionDialog extends StatefulWidget { final Function( String, // dataFrom String, // dateTo String, // admissionNumber String, // patient ID - String, // nursingStation + NursingStationEntity?, // nursingStation ) onDispose; final String dateFrom; final String dateTo; final String admissionNumber; final String patientID; - final String nursingStation; + final NursingStationEntity? nursingStation; + final NursingStation? station; const PharmacyInterventionDialog({super.key, required this.onDispose, @@ -25,7 +30,9 @@ class PharmacyInterventionDialog extends StatefulWidget { required this.dateTo, required this.admissionNumber, required this.patientID, - required this.nursingStation}); + required this.nursingStation, + required this.station, + }); @override State createState() => @@ -35,7 +42,7 @@ class PharmacyInterventionDialog extends StatefulWidget { class _PharmacyInterventionDialogState extends State { final TextEditingController admissionNumber = TextEditingController(); - final TextEditingController nursingStation = TextEditingController(); + NursingStationEntity? nursingStation = null; final TextEditingController patientId = TextEditingController(); @@ -51,7 +58,7 @@ class _PharmacyInterventionDialogState void initData() { admissionNumber.text = (widget.admissionNumber == '0')?'':widget.admissionNumber; - nursingStation.text = (widget.nursingStation == '0')?'':widget.nursingStation; + nursingStation = widget.nursingStation; patientId.text = (widget.patientID == '0' )?'':widget.patientID; dateTo = getDateString(widget.dateTo); dateFrom = getDateString(widget.dateFrom); @@ -66,93 +73,92 @@ class _PharmacyInterventionDialogState ), 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) { - DateTime? fromDate = getDate(date); - DateTime? toDate =getDate(dateTo); - if(toDate == null){ + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + IconButton( + icon: Icon(Icons.close), + onPressed: () { + Navigator.pop(context); + }, + ), + SizedBox(height: 8,), + nursingStationView, + SizedBox( + height: 4, + ), + _titleAndTextField(TranslationBase + .of(context) + .admissionNumber, + admissionNumber, TextInputType.text), + SizedBox( + height: 4, + ), + _titleAndTextField(TranslationBase + .of(context) + .patientID, patientId, + TextInputType.number), + SizedBox( + height: 4, + ), + _dateSelection(TranslationBase + .of(context) + .dateFrom, (date) { + DateTime? fromDate = getDate(date); + DateTime? toDate = getDate(dateTo); + if (toDate == null) { + setState(() { + dateFrom = date; + }); + return; + } + if (fromDate!.compareTo(toDate!) == 1) { + setState(() { + dateFrom = date; + dateTo = ''; + }); + return; + } setState(() { dateFrom = date; }); - return; - } - if(fromDate!.compareTo(toDate!) == 1){ + }, dateFrom, false), + SizedBox( + height: 4, + ), + _dateSelection(TranslationBase + .of(context) + .dateTo, (date) { setState(() { - dateFrom = date; - dateTo = ''; + dateTo = date; }); - return; - } - setState(() { - dateFrom = date; - }); - }, dateFrom, false), - SizedBox( - height: 4, - ), - _dateSelection(TranslationBase - .of(context) - .dateTo, (date) { - setState(() { - dateTo = date; - }); - }, dateTo, true, selectedFromDate: dateFrom), - 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); - }, - ), + }, dateTo, true, selectedFromDate: dateFrom), + 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, admissionNumber.text, + patientId.text, nursingStation); + }, + ), + ), + ]), + ], + ), ), ), ); @@ -184,8 +190,11 @@ class _PharmacyInterventionDialogState DateTime? fromDate = getDate(selectedFromDate??''); final DateTime? picked = await showDatePicker( context: context, - initialDate:date.isNotEmpty? getDate(date) :fromDate != null? fromDate: DateTime.now(), - firstDate:(( date.isNotEmpty && dateTime != null ) ) ? dateTime: (toDateSelection && fromDate != null)?fromDate :DateTime(DateTime + initialDate: date.isNotEmpty ? getDate(date) : fromDate != null + ? fromDate + : DateTime.now(), + firstDate: (toDateSelection && fromDate != null) ? fromDate : ((date + .isNotEmpty && dateTime != null)) ? dateTime : DateTime(DateTime .now() .year - 150), lastDate: DateTime(DateTime @@ -257,4 +266,50 @@ class _PharmacyInterventionDialogState int.parse(splitedDate[1]), int.parse(splitedDate[2])); return now; } + + Widget get nursingStationView => + Row( + children: [ + Text(TranslationBase + .of(context) + .nursingStation,), + SizedBox(width: 10,), + widget.station?.entityList?.isEmpty == true ? Expanded( + child: EmptyDropDown()) + : Expanded( + child: DropdownButtonHideUnderline( + child: DropdownButton( + dropdownColor: Colors.white, + iconEnabledColor: Colors.black, + icon: Icon(Icons.keyboard_arrow_down), + isExpanded: true, + value: nursingStation == null + ? widget.station?.entityList?.first + : nursingStation, + iconSize: 25, + elevation: 16, + onChanged: (newValue) async { + if (newValue != null) + setState(() { + nursingStation = newValue ; + }); + }, + items: + widget.station?.entityList?.map((item) { + return DropdownMenuItem( + child: AppText( + item.description ?? '', + fontSize: 14, + letterSpacing: -0.96, + color: AppGlobal.appTextColor, + fontWeight: FontWeight.normal, + textAlign: TextAlign.left, + ), + value: item, + ); + }).toList(), + ), + ), + ) + ]); } \ No newline at end of file From ad4c1b226cc64c53b1047c05f0669e7e40a6fb8e Mon Sep 17 00:00:00 2001 From: "taha.alam" Date: Wed, 19 Feb 2025 14:41:19 +0300 Subject: [PATCH 09/14] WD: searchable dropdown added in intervention dialog --- .../widgets/PharmacyInterventionDialog.dart | 101 ++++++++++++------ 1 file changed, 69 insertions(+), 32 deletions(-) diff --git a/lib/screens/pharmacy_intervention/widgets/PharmacyInterventionDialog.dart b/lib/screens/pharmacy_intervention/widgets/PharmacyInterventionDialog.dart index 305643a7..ba90f915 100644 --- a/lib/screens/pharmacy_intervention/widgets/PharmacyInterventionDialog.dart +++ b/lib/screens/pharmacy_intervention/widgets/PharmacyInterventionDialog.dart @@ -2,6 +2,7 @@ import 'package:doctor_app_flutter/config/config.dart'; import 'package:doctor_app_flutter/core/model/pharmacy-intervention-model/nursing_station.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:dropdown_search/dropdown_search.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; @@ -277,39 +278,75 @@ class _PharmacyInterventionDialogState widget.station?.entityList?.isEmpty == true ? Expanded( child: EmptyDropDown()) : Expanded( - child: DropdownButtonHideUnderline( - child: DropdownButton( - dropdownColor: Colors.white, - iconEnabledColor: Colors.black, - icon: Icon(Icons.keyboard_arrow_down), - isExpanded: true, - value: nursingStation == null - ? widget.station?.entityList?.first - : nursingStation, - iconSize: 25, - elevation: 16, - onChanged: (newValue) async { - if (newValue != null) - setState(() { - nursingStation = newValue ; - }); - }, - items: - widget.station?.entityList?.map((item) { - return DropdownMenuItem( - child: AppText( - item.description ?? '', - fontSize: 14, - letterSpacing: -0.96, - color: AppGlobal.appTextColor, - fontWeight: FontWeight.normal, - textAlign: TextAlign.left, - ), - value: item, - ); - }).toList(), + child: DropdownSearch( + itemAsString:(item){ + return item.description??''; + } , + items: widget.station?.entityList ?? [], + popupProps: PopupProps.menu( + showSearchBox: true, + searchDelay: Duration(microseconds: 100), + searchFieldProps: TextFieldProps( + decoration: InputDecoration( + border: UnderlineInputBorder(), + hintText: TranslationBase.of(context).search + ) + ) ), - ), + dropdownButtonProps: DropdownButtonProps(color: AppGlobal.appRedColor,), + dropdownDecoratorProps: DropDownDecoratorProps( + textAlignVertical: TextAlignVertical.center, + dropdownSearchDecoration: InputDecoration( + border: InputBorder.none + ), + baseStyle: TextStyle( + fontSize: 14 + ) + ), + + selectedItem: nursingStation == null + ? widget.station?.entityList?.first + : nursingStation, + onChanged: (newValue) async { + if (newValue != null) + setState(() { + nursingStation = newValue ; + }); + }, + ) + // DropdownButtonHideUnderline( + // child: DropdownButton( + // dropdownColor: Colors.white, + // iconEnabledColor: Colors.black, + // icon: Icon(Icons.keyboard_arrow_down), + // isExpanded: true, + // value: nursingStation == null + // ? widget.station?.entityList?.first + // : nursingStation, + // iconSize: 25, + // elevation: 16, + // onChanged: (newValue) async { + // if (newValue != null) + // setState(() { + // nursingStation = newValue ; + // }); + // }, + // items: + // widget.station?.entityList?.map((item) { + // return DropdownMenuItem( + // child: AppText( + // item.description ?? '', + // fontSize: 14, + // letterSpacing: -0.96, + // color: AppGlobal.appTextColor, + // fontWeight: FontWeight.normal, + // textAlign: TextAlign.left, + // ), + // value: item, + // ); + // }).toList(), + // ), + // ), ) ]); } \ No newline at end of file From 7a693c00c9baa17f470d2696e482ddbebfd089af Mon Sep 17 00:00:00 2001 From: "taha.alam" Date: Wed, 26 Feb 2025 16:45:29 +0300 Subject: [PATCH 10/14] WD: from date selection bug and status display name changed --- .../pharmacy_intervention/widgets/InterventionCardBody.dart | 2 +- .../widgets/PharmacyInterventionDialog.dart | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/screens/pharmacy_intervention/widgets/InterventionCardBody.dart b/lib/screens/pharmacy_intervention/widgets/InterventionCardBody.dart index 86e67f0a..0e65e538 100644 --- a/lib/screens/pharmacy_intervention/widgets/InterventionCardBody.dart +++ b/lib/screens/pharmacy_intervention/widgets/InterventionCardBody.dart @@ -136,7 +136,7 @@ class InterventionCardBody extends StatelessWidget { title: TranslationBase .of(context) .status, - data: medication.status.toString() ?? '', + data: medication.statusName ?? '', ), ), Expanded( diff --git a/lib/screens/pharmacy_intervention/widgets/PharmacyInterventionDialog.dart b/lib/screens/pharmacy_intervention/widgets/PharmacyInterventionDialog.dart index ba90f915..8bd67c48 100644 --- a/lib/screens/pharmacy_intervention/widgets/PharmacyInterventionDialog.dart +++ b/lib/screens/pharmacy_intervention/widgets/PharmacyInterventionDialog.dart @@ -168,7 +168,9 @@ class _PharmacyInterventionDialogState Widget _dateSelection(String title, Function(String) onDateSelected, String selectedDate, bool isToDateSelection,{String? selectedFromDate}) { return GestureDetector( - onTap: () => _selectDate(onDateSelected,selectedDate, isToDateSelection , selectedFromDate: selectedFromDate), + onTap: () => _selectDate(onDateSelected, + (isToDateSelection == true) ? selectedDate : "", isToDateSelection, + selectedFromDate: selectedFromDate), child: Row( mainAxisSize: MainAxisSize.min, children: [ From aad885f5abc65b000a7bdd7f0db92bdd66555f2a Mon Sep 17 00:00:00 2001 From: "taha.alam" Date: Thu, 27 Feb 2025 15:04:06 +0300 Subject: [PATCH 11/14] WD: access level description added to the card of intervention --- .../pharmacy_intervention_item.dart | 4 +++- .../pharmacy_intervention/widgets/InterventionCardBody.dart | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/core/model/pharmacy-intervention-model/pharmacy_intervention_item.dart b/lib/core/model/pharmacy-intervention-model/pharmacy_intervention_item.dart index 7f565636..f0eb948b 100644 --- a/lib/core/model/pharmacy-intervention-model/pharmacy_intervention_item.dart +++ b/lib/core/model/pharmacy-intervention-model/pharmacy_intervention_item.dart @@ -32,6 +32,7 @@ class Medication { DateTime? startDatetime; int? status; String? statusName; + String? accessLevelDescription; DateTime? stopDatetime; Medication({ @@ -56,6 +57,7 @@ class Medication { this.status, this.statusName, this.stopDatetime, + this.accessLevelDescription, }); dynamic? getValue(int index){ @@ -107,7 +109,6 @@ class Medication { factory Medication.fromJson(Map json) { return Medication( - accessLevel: json['accessLevel'] ?? '', admissionNo: json['admissionNo']?? '', authorizedBy: json['authorizedby']?? '-', authorizedByName: json['authorizedbyName']?? '', @@ -127,6 +128,7 @@ class Medication { startDatetime: json['startDatetime'] != null ? DateTime.parse(json['startDatetime']) : null, status: json['status']?? '', statusName: json['statusName']?? '', + accessLevelDescription: json['accessLevelDescription']?? '', stopDatetime: json['stopDatetime'] != null ? DateTime.parse(json['stopDatetime']) : null, ); } diff --git a/lib/screens/pharmacy_intervention/widgets/InterventionCardBody.dart b/lib/screens/pharmacy_intervention/widgets/InterventionCardBody.dart index 0e65e538..e2fe3512 100644 --- a/lib/screens/pharmacy_intervention/widgets/InterventionCardBody.dart +++ b/lib/screens/pharmacy_intervention/widgets/InterventionCardBody.dart @@ -26,7 +26,7 @@ class InterventionCardBody extends StatelessWidget { title: TranslationBase .of(context) .accessLevel, - data: medication.accessLevel.toString() ?? '', + data: medication.accessLevelDescription ?? '', ), ), Expanded( From 1b50f5005aebc314d1f790dd1f546b0de1bbac98 Mon Sep 17 00:00:00 2001 From: "taha.alam" Date: Mon, 10 Mar 2025 13:23:30 +0300 Subject: [PATCH 12/14] WD: authorized by removed --- android/app/build.gradle | 2 +- lib/config/config.dart | 4 +- .../pharmacy_intervention_item.dart | 55 ------------------- .../widgets/InterventionCardBody.dart | 14 ++--- pubspec.lock | 16 ------ 5 files changed, 8 insertions(+), 83 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 2b7f59f8..37d3d2d9 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -30,7 +30,7 @@ android { signingConfigs { release { - storeFile file('/Users/mohamedmekawy/Documents/Work/DoctorApp/android/doctor_app_key') + storeFile file('../doctor_app_key') storePassword 'Hmgdoctor1234' keyAlias 'hmgdoctor' keyPassword 'Hmgdoctor1234' diff --git a/lib/config/config.dart b/lib/config/config.dart index 98984cbc..1eeef6c9 100644 --- a/lib/config/config.dart +++ b/lib/config/config.dart @@ -7,9 +7,9 @@ const ONLY_DATE = "[0-9/]"; const BASE_URL_LIVE_CARE = 'https://livecare.hmg.com/'; const DOCTOR_ROTATION = 'https://doctorrota.hmg.com/'; // const BASE_URL_LIVE_CARE = 'https://livecareuat.hmg.com/'; -const BASE_URL = 'https://hmgwebservices.com/'; +// const BASE_URL = 'https://hmgwebservices.com/'; -// const BASE_URL = 'https://uat.hmgwebservices.com/'; +const BASE_URL = 'https://uat.hmgwebservices.com/'; // const BASE_URL = 'https://webservices.hmg.com/'; diff --git a/lib/core/model/pharmacy-intervention-model/pharmacy_intervention_item.dart b/lib/core/model/pharmacy-intervention-model/pharmacy_intervention_item.dart index f0eb948b..d7d34f00 100644 --- a/lib/core/model/pharmacy-intervention-model/pharmacy_intervention_item.dart +++ b/lib/core/model/pharmacy-intervention-model/pharmacy_intervention_item.dart @@ -14,8 +14,6 @@ class MedicationList{ class Medication { int? accessLevel; int? admissionNo; - String? authorizedBy; - String? authorizedByName; String? createdBy; String? doctorComments; String? doctorName; @@ -38,8 +36,6 @@ class Medication { Medication({ this.accessLevel, this.admissionNo, - this.authorizedBy, - this.authorizedByName, this.createdBy, this.doctorComments, this.doctorName, @@ -60,58 +56,9 @@ class Medication { this.accessLevelDescription, }); - dynamic? getValue(int index){ - switch (index) { - case 0: - return this.accessLevel; - case 1: - return this.patientID; - break; - case 2: - return this.patientName; - break; - case 3: - return this.nursingStation; - break; - case 4: - return this.admissionNo; - break; - case 5: - return this.medication; - break; - case 6: - return this.dosageDetail; - break; - case 7: - return this.doctorComments; - break; - case 8: - return this.startDatetime; - break; - case 9: - return this.stopDatetime; - break; - case 10: - return this.status; - break; - case 11: - return this.doctorName; - break; - case 12: - return this.authorizedBy; - break; - case 13: - return this.pharmacyRemarks; - break; - } - return index; - } - factory Medication.fromJson(Map json) { return Medication( admissionNo: json['admissionNo']?? '', - authorizedBy: json['authorizedby']?? '-', - authorizedByName: json['authorizedbyName']?? '', createdBy: json['createdBy']?? '', doctorComments: json['doctorComments']?? '', doctorName: json['doctorName']?? '', @@ -137,8 +84,6 @@ class Medication { return { 'accessLevel': accessLevel, 'admissionNo': admissionNo, - 'authorizedby': authorizedBy, - 'authorizedbyName': authorizedByName, 'createdBy': createdBy, 'doctorComments': doctorComments, 'doctorName': doctorName, diff --git a/lib/screens/pharmacy_intervention/widgets/InterventionCardBody.dart b/lib/screens/pharmacy_intervention/widgets/InterventionCardBody.dart index e2fe3512..fc79a0b2 100644 --- a/lib/screens/pharmacy_intervention/widgets/InterventionCardBody.dart +++ b/lib/screens/pharmacy_intervention/widgets/InterventionCardBody.dart @@ -152,22 +152,18 @@ class InterventionCardBody extends StatelessWidget { height: 10, ), Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.start, children: [ Expanded( child: InterventionDetails( title: TranslationBase .of(context) - .authorizedBy, - data: medication.authorizedBy.toString() ?? '-', + .pharmacyRemarks, + data: medication.pharmacyRemarks.toString() ?? '-', ), ), - Expanded( - child: InterventionDetails( - title: TranslationBase - .of(context) - .pharmacyRemarks, - data: medication.pharmacyRemarks.toString() ?? '-', - )) + Expanded(child: SizedBox.shrink()) ], ), SizedBox( diff --git a/pubspec.lock b/pubspec.lock index c92984e9..c485105b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -345,22 +345,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.0" - device_info: - dependency: "direct main" - description: - name: device_info - sha256: f4a8156cb7b7480d969cb734907d18b333c8f0bc0b1ad0b342cdcecf30d62c48 - url: "https://pub.dev" - source: hosted - version: "2.0.3" - device_info_platform_interface: - dependency: transitive - description: - name: device_info_platform_interface - sha256: b148e0bf9640145d09a4f8dea96614076f889e7f7f8b5ecab1c7e5c2dbc73c1b - url: "https://pub.dev" - source: hosted - version: "2.0.1" dropdown_search: dependency: "direct main" description: From 45dab6bd5846a872495c32fd028c8a15cfe20949 Mon Sep 17 00:00:00 2001 From: Sultan Khan Date: Tue, 25 Mar 2025 12:48:03 +0300 Subject: [PATCH 13/14] bottomsheet added. --- lib/config/localized_values.dart | 2 +- lib/screens/home/home_screen.dart | 72 ++++++++++++++++--- .../translations_delegate_base_utils.dart | 1 + 3 files changed, 63 insertions(+), 12 deletions(-) diff --git a/lib/config/localized_values.dart b/lib/config/localized_values.dart index 5546e8e6..4e27e62c 100644 --- a/lib/config/localized_values.dart +++ b/lib/config/localized_values.dart @@ -1252,5 +1252,5 @@ const Map> localizedValues = { "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":"لديك تدخلات معلقة. التي تحتاج إلى اهتمامك"}, - + "open": {"en": "Open", "ar":"يفتح"}, }; diff --git a/lib/screens/home/home_screen.dart b/lib/screens/home/home_screen.dart index 9f378c72..857e48e8 100644 --- a/lib/screens/home/home_screen.dart +++ b/lib/screens/home/home_screen.dart @@ -26,6 +26,7 @@ import 'package:doctor_app_flutter/utils/utils.dart'; import 'package:doctor_app_flutter/widgets/patients/profile/profile-welcome-widget.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/buttons/app_buttons_widget.dart'; import 'package:doctor_app_flutter/widgets/shared/errors/error_message.dart'; import 'package:doctor_app_flutter/widgets/shared/loader/gif_loader_dialog_utils.dart'; import 'package:doctor_app_flutter/widgets/transitions/fade_page.dart'; @@ -34,6 +35,7 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:provider/provider.dart'; import 'package:sticky_headers/sticky_headers/widget.dart'; +import '../patients/profile/soap_update/shared_soap_widgets/bottom_sheet_title.dart'; import 'label.dart'; class HomeScreen extends StatefulWidget { @@ -311,17 +313,19 @@ class _HomeScreenState extends State { } 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); + // Utils.showConfirmationDialog( + // context, TranslationBase.of(context).youHavePendingInterventions, + // () async { + // Navigator.pop(context); + // Navigator.push( + // context, + // MaterialPageRoute( + // builder: (context) => PharmacyIntervention(), + // settings: RouteSettings(name: 'PharmacyIntervention'), + // )); + // }, isShowCancelButton: false); + + _showErrorBottomSheet(context, TranslationBase.of(context).youHavePendingInterventions); } List homePatientsCardsWidget( @@ -568,4 +572,50 @@ class _HomeScreenState extends State { colorIndex = 0; } } + void _showErrorBottomSheet(BuildContext context, String errorMessage) { + showModalBottomSheet( + context: context, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: Radius.circular(20)), + ), + backgroundColor: Colors.red[50], // Light red background + builder: (context) { + return Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.error_outline, color: Colors.red, size: 40), + const SizedBox(height: 10), + Text( + TranslationBase.of(context).pharmacyIntervention, + style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: Colors.red), + ), + const SizedBox(height: 25), + Text( + errorMessage, + style: TextStyle(fontSize: 16, color: Colors.black87), + textAlign: TextAlign.center, + ), + const SizedBox(height: 15), + SizedBox( + width: SizeConfig.realScreenWidth! * .4, + child:AppButton( + color: Colors.green, + onPressed: () => { // Navigator.pop(context); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => PharmacyIntervention(), + settings: RouteSettings(name: 'PharmacyIntervention'), + ))}, + title: TranslationBase.of(context).open, + + )), + ], + ), + ); + }, + ); + } } diff --git a/lib/utils/translations_delegate_base_utils.dart b/lib/utils/translations_delegate_base_utils.dart index 224ce272..c5370de5 100644 --- a/lib/utils/translations_delegate_base_utils.dart +++ b/lib/utils/translations_delegate_base_utils.dart @@ -1994,6 +1994,7 @@ class TranslationBase { String get youHavePendingInterventions => localizedValues['youHavePendingInterventions']![locale.languageCode]!; String get dateToCanNotBeEmpty => localizedValues['dateToCanNotBeEmpty']![locale.languageCode]!; String get dateFromCanNotBeEmpty => localizedValues['dateFromCanNotBeEmpty']![locale.languageCode]!; + String get open => localizedValues['open']![locale.languageCode]!; } class TranslationBaseDelegate extends LocalizationsDelegate { From 203c6985bd4a012f2dc7893f9cff69810646a02e Mon Sep 17 00:00:00 2001 From: Sultan Khan Date: Tue, 25 Mar 2025 13:02:12 +0300 Subject: [PATCH 14/14] no message --- lib/config/config.dart | 4 ++-- .../viewmodel/pharmacy_intervention_service.dart | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/config/config.dart b/lib/config/config.dart index 1eeef6c9..98984cbc 100644 --- a/lib/config/config.dart +++ b/lib/config/config.dart @@ -7,9 +7,9 @@ const ONLY_DATE = "[0-9/]"; const BASE_URL_LIVE_CARE = 'https://livecare.hmg.com/'; const DOCTOR_ROTATION = 'https://doctorrota.hmg.com/'; // const BASE_URL_LIVE_CARE = 'https://livecareuat.hmg.com/'; -// const BASE_URL = 'https://hmgwebservices.com/'; +const BASE_URL = 'https://hmgwebservices.com/'; -const BASE_URL = 'https://uat.hmgwebservices.com/'; +// const BASE_URL = 'https://uat.hmgwebservices.com/'; // const BASE_URL = 'https://webservices.hmg.com/'; diff --git a/lib/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_service.dart b/lib/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_service.dart index 7a615c1d..05c8542f 100644 --- a/lib/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_service.dart +++ b/lib/screens/pharmacy_intervention/viewmodel/pharmacy_intervention_service.dart @@ -78,7 +78,7 @@ class PharmacyInterventionService extends BaseService { }, onFailure: (String error, int statusCode) { hasError = true; DrAppToastMsg.showErrorToast(error); - super.error = super.error! + "\n" + error; + super.error = super.error ?? "" + "\n" + error; }, body: {}); return success;