From 032097487bb0b870dc2780b55ac2e9103e0d7c4d Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Tue, 13 Feb 2024 16:06:17 +0300 Subject: [PATCH] Queueing module implemented --- lib/config/config.dart | 13 +- lib/config/localized_values.dart | 82 +++++--- lib/core/viewModels/project_view_model.dart | 15 ++ .../patient_appointment_journey_model.dart | 77 ++++++++ .../patient_queue_no_response_model.dart | 56 ++++++ lib/pages/BookAppointment/QRCode.dart | 181 +++++++++++++++++- .../fragments/home_page_fragment2.dart | 3 +- lib/pages/landing/home_page_2.dart | 169 ++++++++++++++-- lib/pages/landing/landing_page.dart | 22 +-- .../patient_appointment_arrival_journey.dart | 140 ++++++++++++++ .../authentication/auth_provider.dart | 38 ++++ lib/uitl/translations_delegate_base.dart | 4 + 12 files changed, 729 insertions(+), 71 deletions(-) create mode 100644 lib/models/patient_appointment_journey_model.dart create mode 100644 lib/models/patient_queue_no_response_model.dart create mode 100644 lib/pages/landing/patient_appointment_arrival_journey.dart diff --git a/lib/config/config.dart b/lib/config/config.dart index 8e5bdc7b..31684d86 100644 --- a/lib/config/config.dart +++ b/lib/config/config.dart @@ -21,8 +21,8 @@ var PACKAGES_ORDERS = '/api/orders'; var PACKAGES_ORDER_HISTORY = '/api/orders/items'; var PACKAGES_TAMARA_OPT = '/api/orders/paymentoptions/tamara'; // var BASE_URL = 'http://10.50.100.198:4422/'; -var BASE_URL = 'https://uat.hmgwebservices.com/'; -// var BASE_URL = 'https://hmgwebservices.com/'; +// var BASE_URL = 'https://uat.hmgwebservices.com/'; +var BASE_URL = 'https://hmgwebservices.com/'; // var BASE_URL = 'http://10.20.200.111:1010/'; // var BASE_URL = 'https://uat.hmgwebservices.com/'; // var BASE_URL = 'https://hmgwebservices.com/'; @@ -59,6 +59,15 @@ var RC_BASE_URL = 'https://rc.hmg.com/'; // var RC_BASE_URL = 'https://ms.hmg.com/rc/'; + +// Queueing System URL + +var QUEUEING_SYSTEM_URL = "https://ms.hmg.com/nscapi/api/PatientCall/CheckInQueueNo_Get"; // UAT +// var QUEUEING_SYSTEM_URL = "https://ms.hmg.com/nscapi/api/PatientCall/CheckInQueueNo_Get"; // Prod + +var GET_PATIENT_JOURNEY_URL = "https://ms.hmg.com/nscapi/api/PatientCall/AppointmentJourney_Get"; // UAT +// var GET_PATIENT_JOURNEY_URL = "https://ms.hmg.com/nscapi/api/PatientCall/AppointmentJourney_Get"; // Prod + var PING_SERVICE = 'Services/Weather.svc/REST/CheckConnectivity'; var GET_PROJECT = 'Services/Lists.svc/REST/GetProject'; diff --git a/lib/config/localized_values.dart b/lib/config/localized_values.dart index 6bd06889..1728d5aa 100644 --- a/lib/config/localized_values.dart +++ b/lib/config/localized_values.dart @@ -182,7 +182,10 @@ const Map localizedValues = { 'passQRAppoAttend': {'en': 'Pass the QR code through the attendance devices available in the Hospital.', 'ar': 'تمرير الكود من خلال اجهزة تسجيل الحضور المتوفرة في الفرع.'}, 'sitWaitingQR': {'en': 'Sit in the waiting rooms until called by the nurse.', 'ar': 'الجلوس في غرف الانتظار لحين منادتك من قبل الممرضة.'}, 'attendRegisterCode': {'en': 'Attendance registration code', 'ar': 'رمز تسجيل الحضور'}, - 'scanQRHospital': {'en': 'Approach the Online Check-In board in the hospital & scan via NFC or QR Code to Check-In', 'ar': 'اقترب من لوحة تسجيل الوصول عبر الإنترنت في المستشفى وقم بالمسح الضوئي عبر NFC أو رمز الاستجابة السريعة لتسجيل الوصول'}, + 'scanQRHospital': { + 'en': 'Approach the Online Check-In board in the hospital & scan via NFC or QR Code to Check-In', + 'ar': 'اقترب من لوحة تسجيل الوصول عبر الإنترنت في المستشفى وقم بالمسح الضوئي عبر NFC أو رمز الاستجابة السريعة لتسجيل الوصول' + }, 'scanNFC': {'en': 'Scan NFC to Check-In', 'ar': 'مسح NFC لتسجيل الوصول'}, "sendEmail": {"en": "Send Email", "ar": "ارسال نسخة"}, "success": {"en": "Done successfully", "ar": "تم تنفذ الطلب بنجاح"}, @@ -1845,39 +1848,51 @@ const Map localizedValues = { "privacyPolicy": {"en": "Privacy Policy", "ar": "سياسة الخصوصية"}, "termsConditions": {"en": "Terms & Conditions", "ar": "الأحكام والشروط"}, "prescriptionDeliveryError": {"en": "This clinic does not support refill & delivery.", "ar": "هذه العيادة لا تدعم إعادة التعبئة والتسليم."}, - "liveCarePermissions": {"en": "LiveCare requires Camera, Microphone & Location permissions to enable virtual consultation between patient & doctor, Please allow these to proceed.", "ar": "يتطلب لايف كير أذونات الكاميرا والميكروفون والموقع، يرجى السماح لها بالمتابعة."}, - "lakumUnhold": { "en": "The account has already been activated", "ar": "لقد تم تفعيل الحساب من قبل" }, - "lakumDiscontinue": { "en": "The account is closed", "ar": "الحساب مغلق" }, - "lakumSuccess": { "en": "The account has been activated successfully", "ar": "تم تفعيل الحساب بنجاح" }, - "deleteAccount": { "en": "Deactivate Account", "ar": "ايقاف الحساب مؤقتاً" }, - "deactivateAccount": { "en": "Are you sure you want to deactivate your account?", "ar": "هل أنت متأكد أنك تريد ايقاف الحساب مؤقتاً حسابك؟" }, - "accountDeactivated": { "en": "Your account has been deactivated successfully", "ar": "تم ايقاف الحساب مؤقتاً بنجاح." }, - "accountDeactivatedMsg": { "en": "Your account has been deactivated. Would you like to reactivate it?", "ar": "حسابك معطل. هل ترغب في إعادة تنشيطه مرة أخرى؟" }, - "updateInsuranceManually": { "en": "Update Insurance Manually", "ar": "تحديث التأمين يدويا" }, - "or": { "en": "Update Insurance Manually", "ar": "تحديث التأمين يدويا" }, - "enterInsuranceDetails": { "en": "Please enter your insurance card details below:", "ar": "الرجاء إدخال تفاصيل بطاقة التأمين الخاصة بك أدناه:" }, - "cardHolderName": { "en": "Card Holder Name", "ar": "إسم صاحب البطاقة" }, - "membershipNo": { "en": "Membership No.", "ar": "رقم العضوية" }, - "policyNo": { "en": "Policy No.", "ar": "رقم وثيقة التأمين" }, - "paymentOnly": { "en": "Payment", "ar": "معلقة" }, - "pendingOnly": { "en": "Pending", "ar": "مدفوعات" }, - "insuranceClassName": { "en": "Insurance Class", "ar": "فئة التأمين" }, - "insuranceRequestSubmit": { "en": "Your insurance update request has been submitted successfully.", "ar": "تم تقديم طلب تحديث التأمين الخاص بك بنجاح." }, - "NFCNotSupported": { "en": "Your device does not support NFC. Please visit reception to Check-In", "ar": "جهازك لا يدعم NFC. يرجى زيارة مكتب الاستقبال لتسجيل الوصول" }, + "liveCarePermissions": { + "en": "LiveCare requires Camera, Microphone & Location permissions to enable virtual consultation between patient & doctor, Please allow these to proceed.", + "ar": "يتطلب لايف كير أذونات الكاميرا والميكروفون والموقع، يرجى السماح لها بالمتابعة." + }, + "lakumUnhold": {"en": "The account has already been activated", "ar": "لقد تم تفعيل الحساب من قبل"}, + "lakumDiscontinue": {"en": "The account is closed", "ar": "الحساب مغلق"}, + "lakumSuccess": {"en": "The account has been activated successfully", "ar": "تم تفعيل الحساب بنجاح"}, + "deleteAccount": {"en": "Deactivate Account", "ar": "ايقاف الحساب مؤقتاً"}, + "deactivateAccount": {"en": "Are you sure you want to deactivate your account?", "ar": "هل أنت متأكد أنك تريد ايقاف الحساب مؤقتاً حسابك؟"}, + "accountDeactivated": {"en": "Your account has been deactivated successfully", "ar": "تم ايقاف الحساب مؤقتاً بنجاح."}, + "accountDeactivatedMsg": {"en": "Your account has been deactivated. Would you like to reactivate it?", "ar": "حسابك معطل. هل ترغب في إعادة تنشيطه مرة أخرى؟"}, + "updateInsuranceManually": {"en": "Update Insurance Manually", "ar": "تحديث التأمين يدويا"}, + "or": {"en": "Update Insurance Manually", "ar": "تحديث التأمين يدويا"}, + "enterInsuranceDetails": {"en": "Please enter your insurance card details below:", "ar": "الرجاء إدخال تفاصيل بطاقة التأمين الخاصة بك أدناه:"}, + "cardHolderName": {"en": "Card Holder Name", "ar": "إسم صاحب البطاقة"}, + "membershipNo": {"en": "Membership No.", "ar": "رقم العضوية"}, + "policyNo": {"en": "Policy No.", "ar": "رقم وثيقة التأمين"}, + "paymentOnly": {"en": "Payment", "ar": "معلقة"}, + "pendingOnly": {"en": "Pending", "ar": "مدفوعات"}, + "insuranceClassName": {"en": "Insurance Class", "ar": "فئة التأمين"}, + "insuranceRequestSubmit": {"en": "Your insurance update request has been submitted successfully.", "ar": "تم تقديم طلب تحديث التأمين الخاص بك بنجاح."}, + "NFCNotSupported": {"en": "Your device does not support NFC. Please visit reception to Check-In", "ar": "جهازك لا يدعم NFC. يرجى زيارة مكتب الاستقبال لتسجيل الوصول"}, "enter-workplace-name": {"en": "Please enter your workplace name:", "ar": "رجاء إدخال مكان العمل:"}, "workplaceName": {"en": "Workplace name:", "ar": "مكان العمل:"}, "callLiveCareSupport": {"en": "Call LiveCare Support", "ar": "اتصل بدعم اللايف كير"}, - "needApproval": {"en": "Your sick leave is under process in medical administration, you will be notified once approved.", "ar": "جازتك المرضية تحت الإجراء في الإدارة الطبية ، سوف يتم إشعارك فور الموافقه عليها."}, + "needApproval": { + "en": "Your sick leave is under process in medical administration, you will be notified once approved.", + "ar": "جازتك المرضية تحت الإجراء في الإدارة الطبية ، سوف يتم إشعارك فور الموافقه عليها." + }, "pendingActivation": {"en": "Pending Activation", "ar": "في انتظار التنشيط"}, "awaitingApproval": {"en": "Awaiting Approval", "ar": "انتظر القبول"}, "liveCareSupportContact": {"en": "LiveCare Support Contact: ", "ar": "اتصل لايف كير: "}, "pharmaLiveCare": {"en": "Pharma LiveCare", "ar": "لايف كير الصيدلية"}, "pharmaLiveCare1": {"en": "What is Pharma LiveCare?", "ar": "ما هولايف كير الصيدلية؟"}, - "pharmaLiveCareDesc1": {"en": "Pharma LiveCare allows you to get consultation from your doctor virtually being in HMG Pharmacy booth.", "ar": "تتيح لك خدمة لايف كير الصيدلية الحصول على استشارة من طبيبك المتواجد فعليًا في كشك صيدلية د.سليمان الحبيب."}, + "pharmaLiveCareDesc1": { + "en": "Pharma LiveCare allows you to get consultation from your doctor virtually being in HMG Pharmacy booth.", + "ar": "تتيح لك خدمة لايف كير الصيدلية الحصول على استشارة من طبيبك المتواجد فعليًا في كشك صيدلية د.سليمان الحبيب." + }, "wherePharmaLiveCare": {"en": "Where can i find Pharma LiveCare?", "ar": "أين يمكنني أن أجد لايف كير الصيدلية؟"}, "pharmaLiveCareDesc2": {"en": "You can find the booth in HMG Pharmacies.", "ar": "يمكنك العثور على الكشك في صيدليات مستشفى د.سليمان الحبيب."}, "howPharmaLiveCare": {"en": "How can i use Pharma LiveCare?", "ar": "كيف يمكنني استخدام لايف كير الصيدلية؟"}, - "pharmaLiveCareDesc3": {"en": "Following the below steps you can easily benefit from the virtual consultation service:", "ar": "باتباع الخطوات التالية يمكنك الاستفادة بسهولة من خدمة الاستشارة الافتراضية:"}, + "pharmaLiveCareDesc3": { + "en": "Following the below steps you can easily benefit from the virtual consultation service:", + "ar": "باتباع الخطوات التالية يمكنك الاستفادة بسهولة من خدمة الاستشارة الافتراضية:" + }, "pharmaLiveCareScanQR": {"en": "Scan QR Code", "ar": "مسح رمز الاستجابة السريعة"}, "pharmaLiveCareScanQR1": {"en": "Scan the QR Code in the booth to make the connection", "ar": "امسح رمز الاستجابة السريعة في المقصورة لإجراء الاتصال"}, "pharmaLiveCareMakePayment": {"en": "Make Payment Online", "ar": "قم بالدفع عبر الإنترنت"}, @@ -1893,18 +1908,31 @@ const Map localizedValues = { "sickLeaveAdmittedPatient": {"en": "You cannot activate this sick leave since you're an admitted patient.", "ar": "لا يمكنك تفعيل هذه الإجازة المرضية لأنك مريض مقبل."}, "dischargeDate": {"en": "Discharge Date", "ar": "تاريخ التفريغ"}, "selectAdmissionText": {"en": "Please select one of the admissions from below to view medical reports:", "ar": "يرجى تحديد أحد حالات القبول من الأسفل لعرض التقارير الطبية:"}, - "invalidEligibility": {"en": "You cannot make online payment because you are not eligible to use the provided service.", "ar": "لا يمكنك إجراء الدفع عبر الإنترنت لأنك غير مؤهل لاستخدام الخدمة المقدمة."}, + "invalidEligibility": { + "en": "You cannot make online payment because you are not eligible to use the provided service.", + "ar": "لا يمكنك إجراء الدفع عبر الإنترنت لأنك غير مؤهل لاستخدام الخدمة المقدمة." + }, "invalidInsurance": {"en": "You cannot make online payment because you do not have a valid insurance.", "ar": "لا يمكنك إجراء الدفع عبر الإنترنت لأنه ليس لديك تأمين صالح."}, "continueCash": {"en": "Continue as cash", "ar": "تواصل نقدا"}, "updateInsurance": {"en": "Update insurance", "ar": "تحديث التأمين"}, "downloadReport": {"en": "Download Report", "ar": "تحميل تقرير المختبر"}, "habibCallCenter": {"en": "Please contact AlHabib call center to update your insurance manually.", "ar": "يرجى الاتصال بمركز اتصال الحبيب لتحديث التأمين الخاص بك يدوياً."}, - "cashAmountUpdateInsurance": {"en": "Please note that this is the cash amount, If you want to update your insurance, Please tap below:", "ar": "يرجى ملاحظة أن هذا هو المبلغ النقدي، إذا كنت ترغب في تحديث التأمين الخاص بك، يرجى النقر أدناه:"}, + "cashAmountUpdateInsurance": { + "en": "Please note that this is the cash amount, If you want to update your insurance, Please tap below:", + "ar": "يرجى ملاحظة أن هذا هو المبلغ النقدي، إذا كنت ترغب في تحديث التأمين الخاص بك، يرجى النقر أدناه:" + }, "validInsurance": {"en": "Do you have a valid insurance?", "ar": "هل لديك تأمين صالح؟"}, "contactRRT": {"en": "Contact RRT", "ar": "تواصل مع فريق الاستجابة السريعة"}, "checkInViaLocation": {"en": "Check-In Via Location", "ar": "تسجيل الوصول عبر الموقع"}, - "locationCheckInError": {"en": "Please make sure that you're within the hospital location to perform online check-in.", "ar": "يرجى التأكد من تواجدك داخل موقع المستشفى لإجراء تسجيل الوصول عبر الإنترنت."}, + "locationCheckInError": { + "en": "Please make sure that you're within the hospital location to perform online check-in.", + "ar": "يرجى التأكد من تواجدك داخل موقع المستشفى لإجراء تسجيل الوصول عبر الإنترنت." + }, "upcoming": {"en": "Upcoming", "ar": "المواعيد القادمة"}, "noUpcomingAppointment": {"en": "No upcoming appointments", "ar": "لا توجد مواعيد القادمة"}, "locationTimeoutError": {"en": "Unable to fetch your location, Please try again.", "ar": "غير قادر على جلب موقعك، يرجى المحاولة مرة أخرى."}, -}; \ No newline at end of file + "queueDetails": {"en": "Your queue no. details are as below: ", "ar": "إن تفاصيل رقم الانتظار الخاص بك كالتالي: "}, + "approxWaitTime": {"en": "Approximate waiting time: ", "ar": "وقت الانتظار المتوقع: "}, + "yourQueue": {"en": "Your Queue Number", "ar": "رقم الانتظار"}, + "currentQueue": {"en": "Current Queue Number", "ar": "الرقم الحالي"}, +}; diff --git a/lib/core/viewModels/project_view_model.dart b/lib/core/viewModels/project_view_model.dart index aff0faff..23b74408 100644 --- a/lib/core/viewModels/project_view_model.dart +++ b/lib/core/viewModels/project_view_model.dart @@ -12,6 +12,7 @@ import 'package:diplomaticquarterapp/core/viewModels/base_view_model.dart'; import 'package:diplomaticquarterapp/locator.dart'; import 'package:diplomaticquarterapp/models/Appointments/laser_body_parts.dart'; import 'package:diplomaticquarterapp/models/Authentication/register_info_response.dart'; +import 'package:diplomaticquarterapp/models/patient_queue_no_response_model.dart'; import 'package:diplomaticquarterapp/uitl/PlatformBridge.dart'; import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; import 'package:flutter/cupertino.dart'; @@ -77,6 +78,20 @@ class ProjectViewModel extends BaseViewModel { StreamSubscription subscription; + GetPatientQueueNoModel getPatientQueueNoModel; + + bool isShowQueueWidget = false; + + void setIsShowQueueWidget(bool value) { + isShowQueueWidget = value; + notifyListeners(); + } + + void setPatientQueueModel(GetPatientQueueNoModel getPatientQueueNoModel) { + this.getPatientQueueNoModel = getPatientQueueNoModel; + notifyListeners(); + } + ProjectViewModel() { loadSharedPrefLanguage(); subscription = Connectivity().onConnectivityChanged.listen((ConnectivityResult result) { diff --git a/lib/models/patient_appointment_journey_model.dart b/lib/models/patient_appointment_journey_model.dart new file mode 100644 index 00000000..9c3bda4e --- /dev/null +++ b/lib/models/patient_appointment_journey_model.dart @@ -0,0 +1,77 @@ +class PatientAppointmentJourneyModel { + int totalItemsCount; + List data; + int messageStatus; + String message; + + PatientAppointmentJourneyModel( + {this.totalItemsCount, this.data, this.messageStatus, this.message}); + + PatientAppointmentJourneyModel.fromJson(Map json) { + totalItemsCount = json['totalItemsCount']; + if (json['data'] != null) { + data = []; + json['data'].forEach((v) { + data.add(new Data.fromJson(v)); + }); + } + messageStatus = json['messageStatus']; + message = json['message']; + } + + Map toJson() { + final Map data = new Map(); + data['totalItemsCount'] = this.totalItemsCount; + if (this.data != null) { + data['data'] = this.data.map((v) => v.toJson()).toList(); + } + data['messageStatus'] = this.messageStatus; + data['message'] = this.message; + return data; + } +} + +class Data { + int id; + int callType; + String calledOn; + dynamic servedStartOn; + dynamic servedEndOn; + bool isAppeared; + bool isServed; + dynamic roomNo; + + Data( + {this.id, + this.callType, + this.calledOn, + this.servedStartOn, + this.servedEndOn, + this.isAppeared, + this.isServed, + this.roomNo}); + + Data.fromJson(Map json) { + id = json['id']; + callType = json['callType']; + calledOn = json['calledOn']; + servedStartOn = json['servedStartOn']; + servedEndOn = json['servedEndOn']; + isAppeared = json['isAppeared']; + isServed = json['isServed']; + roomNo = json['roomNo']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['callType'] = this.callType; + data['calledOn'] = this.calledOn; + data['servedStartOn'] = this.servedStartOn; + data['servedEndOn'] = this.servedEndOn; + data['isAppeared'] = this.isAppeared; + data['isServed'] = this.isServed; + data['roomNo'] = this.roomNo; + return data; + } +} diff --git a/lib/models/patient_queue_no_response_model.dart b/lib/models/patient_queue_no_response_model.dart new file mode 100644 index 00000000..7774c417 --- /dev/null +++ b/lib/models/patient_queue_no_response_model.dart @@ -0,0 +1,56 @@ +class GetPatientQueueNoModel { + int totalItemsCount; + Data data; + int messageStatus; + String message; + + GetPatientQueueNoModel( + {this.totalItemsCount, this.data, this.messageStatus, this.message}); + + GetPatientQueueNoModel.fromJson(Map json) { + totalItemsCount = json['totalItemsCount']; + data = json['data'] != null ? new Data.fromJson(json['data']) : null; + messageStatus = json['messageStatus']; + message = json['message']; + } + + Map toJson() { + final Map data = new Map(); + data['totalItemsCount'] = this.totalItemsCount; + if (this.data != null) { + data['data'] = this.data.toJson(); + } + data['messageStatus'] = this.messageStatus; + data['message'] = this.message; + return data; + } +} + +class Data { + bool hasQueue; + String queueNo; + String queueNoCurServing; + String approxWaitingTimeMin; + + Data( + {this.hasQueue, + this.queueNo, + this.queueNoCurServing, + this.approxWaitingTimeMin}); + + Data.fromJson(Map json) { + hasQueue = json['hasQueue']; + queueNo = json['queueNo']; + queueNoCurServing = json['queueNoCurServing']; + approxWaitingTimeMin = json['approxWaitingTimeMin']; + } + + Map toJson() { + final Map data = new Map(); + data['hasQueue'] = this.hasQueue; + data['queueNo'] = this.queueNo; + data['queueNoCurServing'] = this.queueNoCurServing; + data['approxWaitingTimeMin'] = this.approxWaitingTimeMin; + return data; + } +} diff --git a/lib/pages/BookAppointment/QRCode.dart b/lib/pages/BookAppointment/QRCode.dart index cc700e97..5e2dfff1 100644 --- a/lib/pages/BookAppointment/QRCode.dart +++ b/lib/pages/BookAppointment/QRCode.dart @@ -3,6 +3,7 @@ import 'dart:typed_data'; 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/config/size_config.dart'; import 'package:diplomaticquarterapp/core/model/privilege/ProjectDetailListModel.dart'; import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/locator.dart'; @@ -11,9 +12,11 @@ import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart import 'package:diplomaticquarterapp/models/Appointments/PatientShareResposne.dart'; import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; import 'package:diplomaticquarterapp/models/header_model.dart'; +import 'package:diplomaticquarterapp/models/patient_queue_no_response_model.dart'; import 'package:diplomaticquarterapp/pages/landing/landing_page.dart'; import 'package:diplomaticquarterapp/routes.dart'; import 'package:diplomaticquarterapp/services/appointment_services/GetDoctorsList.dart'; +import 'package:diplomaticquarterapp/services/authentication/auth_provider.dart'; import 'package:diplomaticquarterapp/theme/colors.dart'; import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; import 'package:diplomaticquarterapp/uitl/app_toast.dart'; @@ -24,6 +27,7 @@ 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/buttons/custom_text_button.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart'; import 'package:diplomaticquarterapp/widgets/data_display/medical/medical_profile_item.dart'; import 'package:diplomaticquarterapp/widgets/dialogs/confirm_dialog.dart'; import 'package:diplomaticquarterapp/widgets/new_design/doctor_header.dart'; @@ -55,6 +59,8 @@ class _QRCodeState extends State { ProjectViewModel projectViewModel; LocationUtils locationUtils; ProjectDetailListModel projectDetailListModel; + final authService = new AuthProvider(); + GetPatientQueueNoModel getPatientQueueNoModel; @override void initState() { @@ -275,6 +281,158 @@ class _QRCodeState extends State { return optionsList; } + showCheckInSuccessBottomModalSheet(String successMessage) { + showModalBottomSheet( + isDismissible: false, + backgroundColor: Colors.white, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: Radius.circular(16.0)), + ), + clipBehavior: Clip.hardEdge, + context: context, + builder: (context) { + return Padding( + padding: const EdgeInsets.all(16.0), + child: Wrap( + children: [ + SizedBox( + height: 80, + ), + Center( + child: SvgPicture.asset( + "assets/images/new-design/ionic-ios-checkmark-circle.svg", + width: 80, + height: 80, + ), + ), + SizedBox( + height: 100, + ), + Text( + successMessage, + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xff2E303A), letterSpacing: -0.64, height: 25 / 16), + ), + SizedBox( + height: 80, + ), + projectViewModel.getPatientQueueNoModel.data.hasQueue + ? Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationBase.of(context).queueDetails, + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xff2E303A), letterSpacing: -0.64, height: 25 / 16), + ), + SizedBox( + height: 40, + ), + SizedBox( + width: MediaQuery.of(context).size.width, + height: 110, + child: Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text( + TranslationBase.of(context).approxWaitTime, + maxLines: 1, + style: TextStyle( + fontSize: SizeConfig.textMultiplier * 1.5, + // fontWeight: FontWeight.w600, + letterSpacing: -0.3, + height: 13 / 10, + ), + ), + Text( + "${projectViewModel.getPatientQueueNoModel.data.approxWaitingTimeMin} ${TranslationBase.of(context).minute}", + // "5 minutes", + maxLines: 1, + style: TextStyle(fontSize: SizeConfig.textMultiplier * 1.5, fontWeight: FontWeight.bold, letterSpacing: -0.3, height: 13 / 10, color: Color(0xFFFBF2E31)), + ), + ], + ), + SizedBox(height: 5), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationBase.of(context).yourQueue, + maxLines: 1, + style: TextStyle( + fontSize: SizeConfig.textMultiplier * 1.4, + fontWeight: FontWeight.w600, + letterSpacing: -0.3, + height: 13 / 10, + ), + ), + Text( + projectViewModel.getPatientQueueNoModel.data.queueNo, + // "IMD A-11", + maxLines: 1, + style: TextStyle(fontSize: SizeConfig.textMultiplier * 3.0, fontWeight: FontWeight.bold, letterSpacing: -0.3, height: 13 / 10, color: Color(0xFFFBF2E31)), + ), + ], + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationBase.of(context).currentQueue, + maxLines: 1, + style: TextStyle( + fontSize: SizeConfig.textMultiplier * 1.4, + fontWeight: FontWeight.w600, + letterSpacing: -0.3, + height: 13 / 10, + ), + ), + Text( + projectViewModel.getPatientQueueNoModel.data.queueNoCurServing.isNotEmpty ? projectViewModel.getPatientQueueNoModel.data.queueNoCurServing : "-", + // "IMD A-07", + maxLines: 1, + style: TextStyle( + fontSize: SizeConfig.textMultiplier * 3.0, + fontWeight: FontWeight.bold, + letterSpacing: -0.3, + height: 13 / 10, + ), + ), + ], + ), + ], + ) + ], + ), + ), + ), + ], + ) + : Container(), + DefaultButton( + TranslationBase.of(context).confirm, + () { + Navigator.pop(context, null); + Navigator.pushAndRemoveUntil( + context, + MaterialPageRoute(builder: (context) => LandingPage()), + (Route route) => false, + ); + }, + color: Color(0xff359846), + textColor: Colors.white, + ), + ], + ), + ); + }, + ); + } + sendEmail() async { DoctorsListService service = new DoctorsListService(); @@ -348,6 +506,25 @@ class _QRCodeState extends State { return docSpeciality; } + void checkIfPatientHasQueueNumber(String successMessage) { + GifLoaderDialogUtils.showMyDialog(context); + authService + .getPatientQueueNo(projectViewModel.user.patientID, widget.patientShareResponse.projectID, widget.patientShareResponse.clinicID, widget.patientShareResponse.appointmentNo) + .then((value) async { + GifLoaderDialogUtils.hideDialog(context); + setState(() { + if (value != null) { + getPatientQueueNoModel = GetPatientQueueNoModel.fromJson(value); + projectViewModel.setPatientQueueModel(getPatientQueueNoModel); + showCheckInSuccessBottomModalSheet(successMessage); + } + }); + }).catchError((err) { + GifLoaderDialogUtils.hideDialog(context); + AppToast.showErrorToast(message: err); + }); + } + sendNfcCheckInRequest(String nfcId, int checkInBy) { GifLoaderDialogUtils.showMyDialog(context); @@ -355,9 +532,9 @@ class _QRCodeState extends State { service.sendCheckinNfcRequest(widget.patientShareResponse.appointmentNo, nfcId, widget.patientShareResponse.projectID, checkInBy, context).then((res) { print(res); - GifLoaderDialogUtils.hideDialog(context); - _showMyDialog(res["SuccessMsg"], this.context); + // _showMyDialog(res["SuccessMsg"], this.context); + checkIfPatientHasQueueNumber(res["SuccessMsg"]); }).catchError((err) { GifLoaderDialogUtils.hideDialog(context); print(err); diff --git a/lib/pages/landing/fragments/home_page_fragment2.dart b/lib/pages/landing/fragments/home_page_fragment2.dart index 6d013e8b..c114e2d8 100644 --- a/lib/pages/landing/fragments/home_page_fragment2.dart +++ b/lib/pages/landing/fragments/home_page_fragment2.dart @@ -417,8 +417,7 @@ class _HomePageFragment2State extends State { flex: 1, child: InkWell( onTap: () { - if (projectViewModel.havePrivilege(100)) - widget.onPharmacyClick(); + if (projectViewModel.havePrivilege(100)) widget.onPharmacyClick(); }, child: Stack(children: [ Container( diff --git a/lib/pages/landing/home_page_2.dart b/lib/pages/landing/home_page_2.dart index a8b3a531..cfd1945a 100644 --- a/lib/pages/landing/home_page_2.dart +++ b/lib/pages/landing/home_page_2.dart @@ -1,13 +1,18 @@ import 'package:diplomaticquarterapp/config/config.dart'; +import 'package:diplomaticquarterapp/config/size_config.dart'; import 'package:diplomaticquarterapp/core/viewModels/dashboard_view_model.dart'; import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/pharmacy_module_view_model.dart'; import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/locator.dart'; +import 'package:diplomaticquarterapp/models/patient_appointment_journey_model.dart'; import 'package:diplomaticquarterapp/pages/Covid-DriveThru/covid-drivethru-location.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/pages/landing/patient_appointment_arrival_journey.dart'; +import 'package:diplomaticquarterapp/services/authentication/auth_provider.dart'; import 'package:diplomaticquarterapp/theme/colors.dart'; import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; +import 'package:diplomaticquarterapp/uitl/utils_new.dart'; import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -31,41 +36,163 @@ class HomePage2 extends StatefulWidget { class _HomePageState2 extends State { PharmacyModuleViewModel pharmacyModuleViewModel = locator(); ProjectViewModel projectViewModel; + final authService = new AuthProvider(); @override Widget build(BuildContext context) { projectViewModel = Provider.of(context); - return BaseView( onModelReady: (model) => model.getPatientRadOrders(), builder: (_, model, wi) => Container( color: CustomColors.backgroudGreyColor, // color: Colors.yellow, - child: SingleChildScrollView( - physics: BouncingScrollPhysics(), - child: Column( - children: [ - HomePageFragment2( - model, - onLoginClick: () { - widget.onLoginClick(); - }, - onPharmacyClick: () { - // getPharmacyToken(model); - Uri uri = Uri.parse(PHARMACY_REDIRECT_URL); - launchUrl(uri, mode: LaunchMode.externalApplication); - }, - onMedicalFileClick: () { - widget.onMedicalFileClick(); - }, - ) - ], - ), + child: Stack( + children: [ + SingleChildScrollView( + physics: BouncingScrollPhysics(), + child: Column( + children: [ + HomePageFragment2( + model, + onLoginClick: () { + widget.onLoginClick(); + }, + onPharmacyClick: () { + // getPharmacyToken(model); + Uri uri = Uri.parse(PHARMACY_REDIRECT_URL); + launchUrl(uri, mode: LaunchMode.externalApplication); + }, + onMedicalFileClick: () { + widget.onMedicalFileClick(); + }, + ) + ], + ), + ), + projectViewModel.isShowQueueWidget + ? Positioned( + bottom: 10, + child: InkWell( + onTap: () { + getPatientAppointmentJourneyDetails(); + }, + child: SizedBox( + width: MediaQuery.of(context).size.width, + height: 110, + child: Container( + margin: EdgeInsets.only(left: 16.0, right: 16.0), + decoration: cardRadius(12), + padding: EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text( + "Approximate waiting time: ", + maxLines: 1, + style: TextStyle( + fontSize: SizeConfig.textMultiplier * 1.5, + // fontWeight: FontWeight.w600, + letterSpacing: -0.3, + height: 13 / 10, + ), + ), + Text( + "${projectViewModel.getPatientQueueNoModel.data.approxWaitingTimeMin} minutes", + maxLines: 1, + style: TextStyle(fontSize: SizeConfig.textMultiplier * 1.5, fontWeight: FontWeight.bold, letterSpacing: -0.3, height: 13 / 10, color: Color(0xFFFBF2E31)), + ), + ], + ), + SizedBox(height: 5), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Your Queue Number", + maxLines: 1, + style: TextStyle( + fontSize: SizeConfig.textMultiplier * 1.4, + fontWeight: FontWeight.w600, + letterSpacing: -0.3, + height: 13 / 10, + ), + ), + Text( + projectViewModel.getPatientQueueNoModel.data.queueNo, + maxLines: 1, + style: TextStyle(fontSize: SizeConfig.textMultiplier * 3.0, fontWeight: FontWeight.bold, letterSpacing: -0.3, height: 13 / 10, color: Color(0xFFFBF2E31)), + ), + ], + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Current Queue Number", + maxLines: 1, + style: TextStyle( + fontSize: SizeConfig.textMultiplier * 1.4, + fontWeight: FontWeight.w600, + letterSpacing: -0.3, + height: 13 / 10, + ), + ), + Text( + projectViewModel.getPatientQueueNoModel.data.queueNoCurServing.isNotEmpty ? projectViewModel.getPatientQueueNoModel.data.queueNoCurServing : "-", + maxLines: 1, + style: TextStyle( + fontSize: SizeConfig.textMultiplier * 3.0, + fontWeight: FontWeight.bold, + letterSpacing: -0.3, + height: 13 / 10, + ), + ), + ], + ), + ], + ) + ], + ), + ), + ), + ), + ) + : Container(), + ], ), ), ); } + void getPatientAppointmentJourneyDetails() { + PatientAppointmentJourneyModel patientAppointmentJourneyModel; + authService.getPatientAppointmentJourneyDetails(2016066248).then((value) async { + if (value != null) { + patientAppointmentJourneyModel = PatientAppointmentJourneyModel.fromJson(value); + Navigator.push( + context, + FadePage( + page: PatientAppointmentArrivalJourney( + patientAppointmentJourneyModel: patientAppointmentJourneyModel, + ), + ), + ); + // getPatientQueueNoModel = GetPatientQueueNoModel.fromJson(value); + // if(getPatientQueueNoModel.data.hasQueue) { + // projectViewModel.setPatientQueueModel(getPatientQueueNoModel); + // projectViewModel.setIsShowQueueWidget(true); + // } else { + // projectViewModel.setIsShowQueueWidget(false); + // } + } + }); + } + getPharmacyToken(DashboardViewModel model) async { if (!model.isLogin) { Navigator.push(context, FadePage(page: LandingPagePharmacy())); diff --git a/lib/pages/landing/landing_page.dart b/lib/pages/landing/landing_page.dart index 683ddc6d..5e86cc67 100644 --- a/lib/pages/landing/landing_page.dart +++ b/lib/pages/landing/landing_page.dart @@ -13,6 +13,7 @@ import 'package:diplomaticquarterapp/models/Appointments/toDoCountProviderModel. import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; import 'package:diplomaticquarterapp/models/Authentication/select_device_imei_res.dart'; import 'package:diplomaticquarterapp/models/LiveCare/IncomingCallData.dart'; +import 'package:diplomaticquarterapp/models/patient_queue_no_response_model.dart'; import 'package:diplomaticquarterapp/pages/BookAppointment/Search.dart'; import 'package:diplomaticquarterapp/pages/DrawerPages/family/my-family.dart'; import 'package:diplomaticquarterapp/pages/ToDoList/ToDo.dart'; @@ -94,6 +95,8 @@ class _LandingPageState extends State with WidgetsBindingObserver { ///inject the user data AuthenticatedUserObject authenticatedUserObject = locator(); + GetPatientQueueNoModel getPatientQueueNoModel; + final FirebaseMessaging _firebaseMessaging = FirebaseMessaging?.instance; final authService = new AuthProvider(); @@ -302,6 +305,7 @@ class _LandingPageState extends State with WidgetsBindingObserver { if (projectViewModel.isLogin && !projectViewModel.isLoginChild) { int languageID = Provider.of(context, listen: false).isArabic ? 1 : 2; familyFileProvider.getSharedRecordByStatus(languageID); + // checkIfPatientHasQueueNumber(); } // Future.delayed(Duration(seconds: 3)).then((result) async { // LocalNotification.getInstance().showNow(title: "Payload Update", subtitle: "Payload Update", payload: "Payload Update"); @@ -657,28 +661,12 @@ class _LandingPageState extends State with WidgetsBindingObserver { authService.getDashboard().then((value) async { setState(() { if (value != null) { - notificationCount = value ['List_PatientDashboard'][0]['UnreadPatientNotificationCount'] > 99 ? '99+' : value['List_PatientDashboard'][0]['UnreadPatientNotificationCount'].toString(); + notificationCount = value['List_PatientDashboard'][0]['UnreadPatientNotificationCount'] > 99 ? '99+' : value['List_PatientDashboard'][0]['UnreadPatientNotificationCount'].toString(); model.setState(model.count, 0, true, notificationCount); sharedPref.setString(NOTIFICATION_COUNT, notificationCount); FlutterAppIconBadge.updateBadge(num.parse(notificationCount)); } }); - // if (await AppSharedPreferences().getBool(IS_LAST_APPOINTMENT_RATE_SHOWN) == null || !await AppSharedPreferences().getBool(IS_LAST_APPOINTMENT_RATE_SHOWN)) { - // int languageID = Provider.of(context, listen: false).isArabic ? 1 : 2; - // appointmentRateViewModel.getIsLastAppointmentRatedList(languageID).then((value) async { - // if (appointmentRateViewModel.isHaveAppointmentNotRate) { - // await AppSharedPreferences().setBool(IS_LAST_APPOINTMENT_RATE_SHOWN, true); - // Navigator.push( - // context, - // FadePage( - // page: RateAppointmentDoctor(), - // ), - // ); - // } - // }).catchError((err) { - // print(err); - // }); - // } }); } projectViewModel.analytics.setUser(data); diff --git a/lib/pages/landing/patient_appointment_arrival_journey.dart b/lib/pages/landing/patient_appointment_arrival_journey.dart new file mode 100644 index 00000000..5d5a5253 --- /dev/null +++ b/lib/pages/landing/patient_appointment_arrival_journey.dart @@ -0,0 +1,140 @@ +import 'package:diplomaticquarterapp/config/size_config.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/models/patient_appointment_journey_model.dart'; +import 'package:diplomaticquarterapp/models/patient_queue_no_response_model.dart'; +import 'package:diplomaticquarterapp/theme/colors.dart'; +import 'package:diplomaticquarterapp/uitl/utils_new.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class PatientAppointmentArrivalJourney extends StatelessWidget { + ProjectViewModel projectViewModel; + PatientAppointmentJourneyModel patientAppointmentJourneyModel; + + PatientAppointmentArrivalJourney({this.patientAppointmentJourneyModel}); + + @override + Widget build(BuildContext context) { + projectViewModel = Provider.of(context); + return AppScaffold( + appBarTitle: "Appointment Journey", + isShowAppBar: true, + isShowDecPage: false, + showNewAppBarTitle: true, + showNewAppBar: true, + backgroundColor: CustomColors.appBackgroudGrey2Color, + body: Column( + children: [ + Expanded( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + width: MediaQuery.of(context).size.width, + height: 110, + child: Container( + decoration: cardRadius(12), + padding: EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text( + "Approximate waiting time: ", + maxLines: 1, + style: TextStyle( + fontSize: SizeConfig.textMultiplier * 1.5, + // fontWeight: FontWeight.w600, + letterSpacing: -0.3, + height: 13 / 10, + ), + ), + Text( + "${projectViewModel.getPatientQueueNoModel.data.approxWaitingTimeMin} minutes", + maxLines: 1, + style: TextStyle(fontSize: SizeConfig.textMultiplier * 1.5, fontWeight: FontWeight.bold, letterSpacing: -0.3, height: 13 / 10, color: Color(0xFFFBF2E31)), + ), + ], + ), + SizedBox(height: 5), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Your Queue Number", + maxLines: 1, + style: TextStyle( + fontSize: SizeConfig.textMultiplier * 1.4, + fontWeight: FontWeight.w600, + letterSpacing: -0.3, + height: 13 / 10, + ), + ), + Text( + projectViewModel.getPatientQueueNoModel.data.queueNo, + maxLines: 1, + style: TextStyle(fontSize: SizeConfig.textMultiplier * 3.0, fontWeight: FontWeight.bold, letterSpacing: -0.3, height: 13 / 10, color: Color(0xFFFBF2E31)), + ), + ], + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Current Queue Number", + maxLines: 1, + style: TextStyle( + fontSize: SizeConfig.textMultiplier * 1.4, + fontWeight: FontWeight.w600, + letterSpacing: -0.3, + height: 13 / 10, + ), + ), + Text( + projectViewModel.getPatientQueueNoModel.data.queueNoCurServing.isNotEmpty ? projectViewModel.getPatientQueueNoModel.data.queueNoCurServing : "-", + maxLines: 1, + style: TextStyle( + fontSize: SizeConfig.textMultiplier * 3.0, + fontWeight: FontWeight.bold, + letterSpacing: -0.3, + height: 13 / 10, + ), + ), + ], + ), + ], + ) + ], + ), + ), + ), + SizedBox( + height: 16, + ), + Container( + width: double.infinity, + height: 150, + color: Colors.red, + child: ListView.builder( + shrinkWrap: true, + physics: const ScrollPhysics(), + itemBuilder: (BuildContext context, int index) {}), + ), + ], + ), + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/services/authentication/auth_provider.dart b/lib/services/authentication/auth_provider.dart index 9b1f1e3b..cc608454 100644 --- a/lib/services/authentication/auth_provider.dart +++ b/lib/services/authentication/auth_provider.dart @@ -497,6 +497,44 @@ class AuthProvider with ChangeNotifier { } } + Future getPatientQueueNo(int patientID, int projectID, int clinicID, int appoNo) async { + Map request = {"projectID": projectID, "clinicID": clinicID, "appointmentNo": appoNo, "patientID": patientID, "apiKey": "EE17D21C7943485D9780223CCE55DCE5"}; + + dynamic localRes; + try { + await new BaseAppClient().post(QUEUEING_SYSTEM_URL, onSuccess: (dynamic response, int statusCode) { + localRes = response; + }, onFailure: (String error, int statusCode) { + localRes = error; + return Future.value(error); + // throw error; + }, body: request, isExternal: true, isAllowAny: true); + return Future.value(localRes); + } catch (error) { + throw error; + //return Future.value(error); + } + } + + Future getPatientAppointmentJourneyDetails(int appoNo) async { + Map request = {"appointmentNo": appoNo, "apiKey": "EE17D21C7943485D9780223CCE55DCE5"}; + + dynamic localRes; + try { + await new BaseAppClient().post(GET_PATIENT_JOURNEY_URL, onSuccess: (dynamic response, int statusCode) { + localRes = response; + }, onFailure: (String error, int statusCode) { + localRes = error; + return Future.value(error); + // throw error; + }, body: request, isExternal: true, isAllowAny: true); + return Future.value(localRes); + } catch (error) { + throw error; + //return Future.value(error); + } + } + getSettings() async { dynamic localRes; try { diff --git a/lib/uitl/translations_delegate_base.dart b/lib/uitl/translations_delegate_base.dart index 0dd0c97d..68b1a3e1 100644 --- a/lib/uitl/translations_delegate_base.dart +++ b/lib/uitl/translations_delegate_base.dart @@ -2916,6 +2916,10 @@ class TranslationBase { String get upcoming => localizedValues["upcoming"][locale.languageCode]; String get noUpcomingAppointment => localizedValues["noUpcomingAppointment"][locale.languageCode]; String get locationTimeoutError => localizedValues["locationTimeoutError"][locale.languageCode]; + String get queueDetails => localizedValues["queueDetails"][locale.languageCode]; + String get approxWaitTime => localizedValues["approxWaitTime"][locale.languageCode]; + String get yourQueue => localizedValues["yourQueue"][locale.languageCode]; + String get currentQueue => localizedValues["currentQueue"][locale.languageCode]; }