diff --git a/lib/models/anicllary-orders/ancillary_order_list_model.dart b/lib/models/anicllary-orders/ancillary_order_list_model.dart index 9aefe844..f29ddd62 100644 --- a/lib/models/anicllary-orders/ancillary_order_list_model.dart +++ b/lib/models/anicllary-orders/ancillary_order_list_model.dart @@ -10,21 +10,11 @@ class AncillaryOrdersListModel { String? setupID; int? statusCode; - AncillaryOrdersListModel( - {this.ancillaryOrderList, - this.errCode, - this.message, - this.patientID, - this.patientName, - this.patientType, - this.projectID, - this.projectName, - this.setupID, - this.statusCode}); + AncillaryOrdersListModel({this.ancillaryOrderList, this.errCode, this.message, this.patientID, this.patientName, this.patientType, this.projectID, this.projectName, this.setupID, this.statusCode}); AncillaryOrdersListModel.fromJson(Map json) { if (json['AncillaryOrderList'] != null) { - ancillaryOrderList =[]; + ancillaryOrderList = []; json['AncillaryOrderList'].forEach((v) { ancillaryOrderList!.add(new AncillaryOrderList.fromJson(v)); }); @@ -43,8 +33,7 @@ class AncillaryOrdersListModel { Map toJson() { final Map data = new Map(); if (this.ancillaryOrderList != null) { - data['AncillaryOrderList'] = - this.ancillaryOrderList!.map((v) => v.toJson()).toList(); + data['AncillaryOrderList'] = this.ancillaryOrderList!.map((v) => v.toJson()).toList(); } data['ErrCode'] = this.errCode; data['Message'] = this.message; @@ -68,16 +57,10 @@ class AncillaryOrderList { String? doctorName; String? orderDate; int? orderNo; + bool? isAllowCheckIn; + String? procedureIDs; - AncillaryOrderList( - {this.appointmentDate, - this.appointmentNo, - this.clinicID, - this.clinicName, - this.doctorID, - this.doctorName, - this.orderDate, - this.orderNo}); + AncillaryOrderList({this.appointmentDate, this.appointmentNo, this.clinicID, this.clinicName, this.doctorID, this.doctorName, this.orderDate, this.orderNo, this.isAllowCheckIn, this.procedureIDs}); AncillaryOrderList.fromJson(Map json) { appointmentDate = json['AppointmentDate']; @@ -88,6 +71,8 @@ class AncillaryOrderList { doctorName = json['DoctorName']; orderDate = json['OrderDate']; orderNo = json['OrderNo']; + isAllowCheckIn = json['IsCheckInAllow']; + procedureIDs = json['ProcedureIds'] != null ? json['ProcedureIds'] : ""; } Map toJson() { diff --git a/lib/pages/AlHabibMedicalService/ancillary-orders/ancillaryOrdersDetails.dart b/lib/pages/AlHabibMedicalService/ancillary-orders/ancillaryOrdersDetails.dart index 61b7eb59..6c7590ca 100644 --- a/lib/pages/AlHabibMedicalService/ancillary-orders/ancillaryOrdersDetails.dart +++ b/lib/pages/AlHabibMedicalService/ancillary-orders/ancillaryOrdersDetails.dart @@ -851,7 +851,8 @@ class _AnicllaryOrdersState extends State with SingleTic addAdvancedNumberRequest(String advanceNumber, String paymentReference, dynamic appointmentID, AppoitmentAllHistoryResultList appo) { DoctorsListService service = new DoctorsListService(); service.addAdvancedNumberRequest(advanceNumber, paymentReference, appointmentID, localContext).then((res) { - autoGenerateInvoice(); + // autoGenerateInvoice(); + showAlertDialog("123123123", widget.projectID); }).catchError((err) { GifLoaderDialogUtils.hideDialog(localContext); AppToast.showErrorToast(message: err.toString()); diff --git a/lib/pages/BookAppointment/QRCode.dart b/lib/pages/BookAppointment/QRCode.dart index e27a55bb..cba84e86 100644 --- a/lib/pages/BookAppointment/QRCode.dart +++ b/lib/pages/BookAppointment/QRCode.dart @@ -40,8 +40,9 @@ class QRCode extends StatefulWidget { late String? appoQR; AuthenticatedUser? authUser; AppSharedPreferences sharedPref = AppSharedPreferences(); + bool? isAncillaryOrderCheckIn; - QRCode({required this.patientShareResponse, required this.appoQR, this.appointment}); + QRCode({required this.patientShareResponse, required this.appoQR, this.appointment, this.isAncillaryOrderCheckIn}); @override _QRCodeState createState() => _QRCodeState(); diff --git a/lib/pages/ToDoList/ToDo.dart b/lib/pages/ToDoList/ToDo.dart index bd860008..168162f1 100644 --- a/lib/pages/ToDoList/ToDo.dart +++ b/lib/pages/ToDoList/ToDo.dart @@ -1,10 +1,12 @@ import 'dart:developer'; import 'dart:io'; +import 'package:barcode_scan2/barcode_scan2.dart'; import 'package:diplomaticquarterapp/analytics/google-analytics.dart'; import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/core/enum/PayfortEnums.dart'; import 'package:diplomaticquarterapp/core/model/ImagesInfo.dart'; +import 'package:diplomaticquarterapp/core/model/privilege/ProjectDetailListModel.dart'; import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/models/Appointments/AppoimentAllHistoryResultList.dart'; import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart'; @@ -34,15 +36,18 @@ import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; import 'package:diplomaticquarterapp/uitl/app_toast.dart'; import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; +import 'package:diplomaticquarterapp/uitl/location_util.dart'; import 'package:diplomaticquarterapp/uitl/penguin_method_channel.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/uitl/utils.dart'; import 'package:diplomaticquarterapp/uitl/utils_new.dart'; import 'package:diplomaticquarterapp/widgets/avatar/large_avatar.dart'; +import 'package:diplomaticquarterapp/widgets/bottom_options/bottom_sheet.dart'; import 'package:diplomaticquarterapp/widgets/data_display/medical/doctor_card.dart'; import 'package:diplomaticquarterapp/widgets/dialogs/confirm_dialog.dart'; import 'package:diplomaticquarterapp/widgets/in_app_browser/InAppBrowser.dart'; import 'package:diplomaticquarterapp/widgets/my_rich_text.dart'; +import 'package:diplomaticquarterapp/widgets/nfc/nfc_reader_sheet.dart'; import 'package:diplomaticquarterapp/widgets/others/app_expandable_notifier.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; @@ -50,6 +55,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_countdown_timer/countdown_timer_controller.dart'; import 'package:flutter_countdown_timer/current_remaining_time.dart'; import 'package:flutter_countdown_timer/flutter_countdown_timer.dart'; +import 'package:flutter_nfc_kit/flutter_nfc_kit.dart'; import 'package:flutter_rating_bar/flutter_rating_bar.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:permission_handler/permission_handler.dart'; @@ -97,6 +103,9 @@ class _ToDoState extends State with SingleTickerProviderStateMixin { List ancillaryLists = []; List obGyneAppoList = []; String? transID; + bool _supportsNFC = false; + late LocationUtils locationUtils; + ProjectDetailListModel projectDetailListModel = ProjectDetailListModel(); @override void initState() { @@ -124,6 +133,9 @@ class _ToDoState extends State with SingleTickerProviderStateMixin { Widget build(BuildContext context) { toDoProvider = Provider.of(context); projectViewModel = Provider.of(context); + FlutterNfcKit.nfcAvailability.then((value) { + _supportsNFC = (value == NFCAvailability.available); + }); return AppScaffold( appBarTitle: TranslationBase.of(context).todoList, imagesInfo: imagesInfo, @@ -441,6 +453,23 @@ class _ToDoState extends State with SingleTickerProviderStateMixin { isLiveCareAppointment: false, date: DateUtil.convertStringToDate(ancillaryLists[0].ancillaryOrderList![index].orderDate), isSortByClinic: true, + isAllowCheckInAncillary: ancillaryLists[0].ancillaryOrderList![index].isAllowCheckIn!, + onAncillaryCheckInTap: () { + AppoitmentAllHistoryResultList appo = new AppoitmentAllHistoryResultList(); + appo.doctorTitle = TranslationBase.of(context).dr.toString(); + appo.doctorNameObj = ancillaryLists[0].ancillaryOrderList![index].doctorName; + appo.doctorID = ancillaryLists[0].ancillaryOrderList![index].doctorID; + appo.doctorImageURL = "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown.png"; + appo.doctorSpeciality = [""]; + appo.projectName = ancillaryLists[0].projectName; + appo.appointmentDate = ancillaryLists[0].ancillaryOrderList![index].orderDate; + appo.isLiveCareAppointment = true; + appo.doctorRate = 5; + appo.actualDoctorRate = 0; + appo.noOfPatientsRate = 0; + + navigateToQR(context, "", new PatientShareResponse(), appo, true); + }, ); }, itemCount: ancillaryLists[0].ancillaryOrderList!.length, @@ -1150,7 +1179,7 @@ class _ToDoState extends State with SingleTickerProviderStateMixin { patientShareResponse.clinicID = appo.clinicID; patientShareResponse.projectID = appo.projectID; patientShareResponse.isFollowup = appo.isFollowup; - navigateToQR(context, "", patientShareResponse, appo); + navigateToQR(context, "", patientShareResponse, appo, false); projectViewModel.analytics.todoList.to_do_list_check_in(appo); // } else { // Utils.showErrorToast(TranslationBase.of(context).NFCNotSupported); @@ -1164,9 +1193,83 @@ class _ToDoState extends State with SingleTickerProviderStateMixin { }); } - Future navigateToQR(context, String appoQR, PatientShareResponse patientShareResponse, AppoitmentAllHistoryResultList appintment) async { - Navigator.push(context, FadePage(page: QRCode(patientShareResponse: patientShareResponse, appoQR: appoQR, appointment: appintment))).then((value) { - getPatientAppointmentHistory(); + Future navigateToQR(context, String appoQR, PatientShareResponse patientShareResponse, AppoitmentAllHistoryResultList appintment, bool isAncillaryOrderCheckIn) async { + showMyBottomSheet(context, + callBackFunc: () {}, + child: Padding( + padding: const EdgeInsets.all(21.0), + child: Column( + children: [ + Text(TranslationBase.of(context).scanQRHospital, + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.w600, + letterSpacing: -0.48, + )), + mHeight(21), + GridView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: (MediaQuery.of(context).size.width < 550) ? 3 : 5, childAspectRatio: 1 / 1, crossAxisSpacing: 8, mainAxisSpacing: 12), + children: [ + attendanceMethod(TranslationBase.of(context).scanNFC, "assets/images/nfc/contactless.svg", true, () { + if (_supportsNFC) { + Future.delayed(const Duration(milliseconds: 500), () { + showNfcReader(context, onNcfScan: (String nfcId) { + Future.delayed(const Duration(milliseconds: 100), () { + print(nfcId); + // getProjectIDFromNFC(nfcId, true); + // Navigator.push(context, FadePage(page: EROnlineCheckInPaymentDetails())); + }); + }, onCancel: () { + Navigator.of(context).pop(); + }); + }); + } else { + //NFCNotSupported + AppToast.showErrorToast(message: TranslationBase.of(context).NFCNotSupported); + } + }), + attendanceMethod(TranslationBase.of(context).pharmaLiveCareScanQR, "assets/images/new/services/qr_code.svg", true, () async { + String onlineCheckInQRCode = (await BarcodeScanner.scan().then((value) => value.rawContent)); + if (onlineCheckInQRCode != "") { + print(onlineCheckInQRCode); + // getProjectIDFromNFC(onlineCheckInQRCode, true); + // sendNfcCheckInRequest(onlineCheckInQRCode, 2); + } else {} + }), + attendanceMethod(TranslationBase.of(context).checkInViaLocation, "assets/images/new/services/location.svg", true, () {}) + ], + ), + ], + ), + )); + + // Navigator.push(context, FadePage(page: QRCode(patientShareResponse: patientShareResponse, appoQR: appoQR, appointment: appintment, isAncillaryOrderCheckIn: isAncillaryOrderCheckIn))) + // .then((value) { + // if (isAncillaryOrderCheckIn) { + // Utils.showErrorToast("isAncillaryOrderCheckIn"); + // } else { + // getPatientAppointmentHistory(); + // } + // }); + } + + startLocationCheckIn() async { + GifLoaderDialogUtils.showMyDialog(context); + locationUtils = new LocationUtils(isShowConfirmDialog: true, context: context); + locationUtils.getCurrentLocation(callBack: (value) { + projectDetailListModel = Utils.getProjectDetailObj(projectViewModel, widget.appointment!.projectID); + double dist = Utils.distance(value.latitude, value.longitude, double.parse(projectDetailListModel.latitude!), double.parse(projectDetailListModel.longitude!)).ceilToDouble() * 1000; + print(dist); + if (dist <= projectDetailListModel.geofenceRadius!) { + GifLoaderDialogUtils.hideDialog(context); + // sendNfcCheckInRequest(projectDetailListModel.checkInQrCode!, 2); + } else { + GifLoaderDialogUtils.hideDialog(context); + AppToast.showErrorToast(message: TranslationBase.of(context).locationCheckInError); + } }); } @@ -1595,6 +1698,29 @@ class _ToDoState extends State with SingleTickerProviderStateMixin { }); } + Widget attendanceMethod(String title, String image, bool isEnabled, VoidCallback onPress) => InkWell( + onTap: () { + Navigator.pop(context); + onPress(); + }, + child: Container( + decoration: containerColorRadiusBorderWidth(Colors.white, 15, CustomColors.darkGreyColor, 1), + clipBehavior: Clip.antiAlias, + padding: const EdgeInsets.only(left: 10, right: 10, top: 14, bottom: 14), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded(child: SvgPicture.asset(image, color: Colors.black, alignment: Alignment.topLeft)), + Text( + title, + style: TextStyle(color: Colors.black, fontSize: 14, letterSpacing: -0.68, fontWeight: FontWeight.bold), + ), + // title.toText17(isBold: true, color: Colors.white), + ], + ), + ), + ); + ancillaryOrdersDetails(item, projectId) { Navigator.push( context, diff --git a/lib/widgets/data_display/medical/doctor_card.dart b/lib/widgets/data_display/medical/doctor_card.dart index ceddea82..3452887d 100644 --- a/lib/widgets/data_display/medical/doctor_card.dart +++ b/lib/widgets/data_display/medical/doctor_card.dart @@ -4,7 +4,9 @@ import 'package:diplomaticquarterapp/theme/colors.dart'; import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/uitl/utils.dart'; +import 'package:diplomaticquarterapp/uitl/utils_new.dart'; import 'package:diplomaticquarterapp/widgets/avatar/large_avatar.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart'; import 'package:flutter/material.dart'; import 'package:flutter_countdown_timer/countdown_timer_controller.dart'; import 'package:flutter_countdown_timer/current_remaining_time.dart'; @@ -37,6 +39,8 @@ class DoctorCard extends StatelessWidget { final bool isLabOrderResult; final int? resultStatus; final String? resultStatusDesc; + final bool isAllowCheckInAncillary; + final VoidCallback? onAncillaryCheckInTap; DoctorCard( {this.name, @@ -60,7 +64,9 @@ class DoctorCard extends StatelessWidget { this.projectID = 0, this.isLabOrderResult = false, this.resultStatus = 0, - this.resultStatusDesc = ""}); + this.resultStatusDesc = "", + this.isAllowCheckInAncillary = false, + this.onAncillaryCheckInTap}); late ProjectViewModel projectViewModel; @@ -68,7 +74,7 @@ class DoctorCard extends StatelessWidget { Widget build(BuildContext context) { projectViewModel = Provider.of(context); return Container( - height: 135, + height: isAllowCheckInAncillary ? 155 : 135, decoration: BoxDecoration( borderRadius: BorderRadius.all( Radius.circular(10.0), @@ -272,6 +278,33 @@ class DoctorCard extends StatelessWidget { ), ], ), + if (isAllowCheckInAncillary) + Column( + children: [ + mHeight(5), + InkWell( + onTap: () { + onAncillaryCheckInTap!(); + }, + child: SizedBox( + width: MediaQuery.of(context).size.width * 0.8, + child: Container( + padding: EdgeInsets.symmetric(vertical: 8, horizontal: 14), + decoration: BoxDecoration( + color: CustomColors.accentColor, + border: Border.all(color: Colors.white, width: 1), + borderRadius: BorderRadius.circular(6), + ), + child: Text( + TranslationBase.of(context).checkinOptions, + textAlign: TextAlign.center, + style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Colors.white, letterSpacing: -0.4), + ), + ), + ), + ), + ], + ), ], ), ), diff --git a/lib/widgets/otp_widget.dart b/lib/widgets/otp_widget.dart index d606090d..b20dcf05 100644 --- a/lib/widgets/otp_widget.dart +++ b/lib/widgets/otp_widget.dart @@ -233,7 +233,7 @@ class OTPWidgetState extends State with SingleTickerProviderStateMixi height: widget.pinBoxHeight, child: TextField( autofocus: !kIsWeb ? widget.autoFocus : false, - enableInteractiveSelection: false, + enableInteractiveSelection: true, focusNode: focusNode, controller: widget.controller, keyboardType: widget.keyboardType, @@ -260,7 +260,7 @@ class OTPWidgetState extends State with SingleTickerProviderStateMixi border: InputBorder.none, ), cursorColor: Colors.transparent, - showCursor: false, + showCursor: true, maxLength: widget.maxLength, onChanged: _onTextChanged, ),