From 1cb7eb2afb56510f159d2022c82fa8df414618bb Mon Sep 17 00:00:00 2001 From: Haroon Amjad Date: Mon, 24 Jan 2022 10:47:56 +0300 Subject: [PATCH 1/7] CS branch changes --- assets/images/new/CS/Family_Files.svg | 3 +++ assets/images/new/CS/Help.svg | 3 +++ assets/images/new/CS/My_File.svg | 7 +++++ assets/images/new/CS/Todo.svg | 3 +++ assets/images/new/CS/emergency_request_CS.svg | 24 ++++++++++++++++++ assets/images/new/CS/home_health_care_CS.svg | 14 ++++++++++ assets/images/new/CS/livecare_CS.svg | 10 ++++++++ assets/images/new/CS/loader.gif | Bin 0 -> 92203 bytes assets/images/new/CS/pharmacy_CS.svg | 16 ++++++++++++ assets/images/new/CoronaIcon.svg | 1 + lib/config/config.dart | 4 +-- 11 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 assets/images/new/CS/Family_Files.svg create mode 100644 assets/images/new/CS/Help.svg create mode 100644 assets/images/new/CS/My_File.svg create mode 100644 assets/images/new/CS/Todo.svg create mode 100644 assets/images/new/CS/emergency_request_CS.svg create mode 100644 assets/images/new/CS/home_health_care_CS.svg create mode 100644 assets/images/new/CS/livecare_CS.svg create mode 100644 assets/images/new/CS/loader.gif create mode 100644 assets/images/new/CS/pharmacy_CS.svg create mode 100644 assets/images/new/CoronaIcon.svg diff --git a/assets/images/new/CS/Family_Files.svg b/assets/images/new/CS/Family_Files.svg new file mode 100644 index 00000000..ce47d959 --- /dev/null +++ b/assets/images/new/CS/Family_Files.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/new/CS/Help.svg b/assets/images/new/CS/Help.svg new file mode 100644 index 00000000..31d49e71 --- /dev/null +++ b/assets/images/new/CS/Help.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/new/CS/My_File.svg b/assets/images/new/CS/My_File.svg new file mode 100644 index 00000000..fc5c0096 --- /dev/null +++ b/assets/images/new/CS/My_File.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/images/new/CS/Todo.svg b/assets/images/new/CS/Todo.svg new file mode 100644 index 00000000..98232af9 --- /dev/null +++ b/assets/images/new/CS/Todo.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/new/CS/emergency_request_CS.svg b/assets/images/new/CS/emergency_request_CS.svg new file mode 100644 index 00000000..1796a80c --- /dev/null +++ b/assets/images/new/CS/emergency_request_CS.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/new/CS/home_health_care_CS.svg b/assets/images/new/CS/home_health_care_CS.svg new file mode 100644 index 00000000..8cf044b1 --- /dev/null +++ b/assets/images/new/CS/home_health_care_CS.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/assets/images/new/CS/livecare_CS.svg b/assets/images/new/CS/livecare_CS.svg new file mode 100644 index 00000000..8af91e8a --- /dev/null +++ b/assets/images/new/CS/livecare_CS.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/images/new/CS/loader.gif b/assets/images/new/CS/loader.gif new file mode 100644 index 0000000000000000000000000000000000000000..3e343727313c29eb4279f945da7a0eb3cec10963 GIT binary patch literal 92203 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 Wat>Rt)SwmF8JNAC>kov{8UG7LOmdt6 literal 0 HcmV?d00001 diff --git a/assets/images/new/CS/pharmacy_CS.svg b/assets/images/new/CS/pharmacy_CS.svg new file mode 100644 index 00000000..a3ad2b0c --- /dev/null +++ b/assets/images/new/CS/pharmacy_CS.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/assets/images/new/CoronaIcon.svg b/assets/images/new/CoronaIcon.svg new file mode 100644 index 00000000..c02f907b --- /dev/null +++ b/assets/images/new/CoronaIcon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/config/config.dart b/lib/config/config.dart index d71b0620..bdf1dffb 100644 --- a/lib/config/config.dart +++ b/lib/config/config.dart @@ -17,8 +17,8 @@ const PACKAGES_ORDERS = '/api/orders'; const PACKAGES_ORDER_HISTORY = '/api/orders/items'; const PACKAGES_TAMARA_OPT = '/api/orders/paymentoptions/tamara'; // const BASE_URL = 'http://10.50.100.198:3334/'; - const BASE_URL = 'https://uat.hmgwebservices.com/'; -// const BASE_URL = 'https://hmgwebservices.com/'; +// const BASE_URL = 'https://uat.hmgwebservices.com/'; +const BASE_URL = 'https://hmgwebservices.com/'; // Pharmacy UAT URLs // const BASE_PHARMACY_URL = 'https://uat.hmgwebservices.com/epharmacy/api/'; From d974a7430c76e21b97a2810fdc27d4f18247996a Mon Sep 17 00:00:00 2001 From: Zohaib Iqbal Kambrani <> Date: Mon, 31 Jan 2022 15:00:18 +0300 Subject: [PATCH 2/7] Google Analytics as per e-Cense document --- lib/analytics/flows/advance_payments.dart | 82 +++++++ lib/analytics/flows/app_nav.dart | 13 + lib/analytics/flows/appointments.dart | 222 ++++++++++++++++++ lib/analytics/flows/error_tracking.dart | 8 + lib/analytics/flows/hamburger_menu.dart | 15 ++ lib/analytics/flows/hmg_services.dart | 13 + lib/analytics/flows/live_care.dart | 101 ++++++++ lib/analytics/flows/login_registration.dart | 103 ++++++++ lib/analytics/flows/offers_promotions.dart | 9 + lib/analytics/flows/todo_list.dart | 119 ++++++++++ lib/analytics/google-analytics.dart | 57 ++++- lib/core/viewModels/project_view_model.dart | 5 + lib/locator.dart | 7 + lib/models/Clinics/ClinicListResponse.dart | 2 +- lib/pages/BookAppointment/BookConfirm.dart | 12 + lib/pages/BookAppointment/BookSuccess.dart | 8 + lib/pages/BookAppointment/DoctorProfile.dart | 8 + lib/pages/BookAppointment/QRCode.dart | 5 + lib/pages/BookAppointment/Search.dart | 7 +- lib/pages/BookAppointment/SearchResults.dart | 12 +- .../BookAppointment/book_reminder_page.dart | 6 + .../components/DocAvailableAppointments.dart | 9 + .../components/SearchByClinic.dart | 2 + .../components/SearchByDoctor.dart | 5 + .../BookAppointment/widgets/DoctorView.dart | 4 +- .../widgets/reminder_dialog.dart | 9 + .../MyAppointments/AppointmentDetails.dart | 3 + lib/pages/MyAppointments/SchedulePage.dart | 2 + lib/pages/ToDoList/ToDo.dart | 8 + lib/pages/ToDoList/widgets/paymentDialog.dart | 2 + .../fragments/home_page_fragment2.dart | 1 + lib/pages/landing/landing_page.dart | 17 +- lib/pages/landing/widgets/services_view.dart | 24 ++ .../livecare/live_care_payment_page.dart | 1 + lib/pages/livecare/livecare_type_select.dart | 7 + lib/pages/livecare/widgets/clinic_card.dart | 11 +- lib/pages/livecare/widgets/clinic_list.dart | 10 + lib/pages/login/register-info.dart | 19 +- lib/pages/login/register.dart | 12 +- lib/pages/login/welcome.dart | 4 + .../medical/balance/advance_payment_page.dart | 10 + .../medical/balance/confirm_payment_page.dart | 8 + .../medical/balance/my_balance_page.dart | 7 + lib/pages/paymentService/payment_service.dart | 3 + lib/widgets/drawer/app_drawer_widget.dart | 26 +- lib/widgets/nfc/nfc_reader_sheet.dart | 7 +- 46 files changed, 997 insertions(+), 28 deletions(-) create mode 100644 lib/analytics/flows/advance_payments.dart create mode 100644 lib/analytics/flows/app_nav.dart create mode 100644 lib/analytics/flows/appointments.dart create mode 100644 lib/analytics/flows/error_tracking.dart create mode 100644 lib/analytics/flows/hamburger_menu.dart create mode 100644 lib/analytics/flows/hmg_services.dart create mode 100644 lib/analytics/flows/live_care.dart create mode 100644 lib/analytics/flows/login_registration.dart create mode 100644 lib/analytics/flows/offers_promotions.dart create mode 100644 lib/analytics/flows/todo_list.dart diff --git a/lib/analytics/flows/advance_payments.dart b/lib/analytics/flows/advance_payments.dart new file mode 100644 index 00000000..db52eb59 --- /dev/null +++ b/lib/analytics/flows/advance_payments.dart @@ -0,0 +1,82 @@ +import 'package:flutter/cupertino.dart'; + +import '../google-analytics.dart'; + +class AdvancePayments{ + + final GALogger logger; + AdvancePayments(this.logger); + + // R038 + payment_services({@required String service_type}){ + logger('payment_services', parameters: { + 'service_type' : service_type + }); + } + + // R039 + wallet_recharge({@required String service_type}){ + logger('wallet_recharge', parameters: { + 'service_type' : service_type + }); + } + + // R040 + wallet_payment_details(){ + logger('wallet_payment_details'); + } + + // R041 + payment_method({@required String method,type}){ + logger('payment_method', parameters: { + 'payment_method' : method, + 'payment_type' : type + }); + } + + // R042 + payment_confirm({@required String method,type}){ + logger('payment_confirm', parameters: { + 'payment_method' : method, + 'payment_type' : type + }); + } + + // R043 + payment_otp_confirmation({@required String method,type}){ + logger('payment_otp_confirmation', parameters: { + 'payment_method' : method, + 'payment_type' : type + }); + } + + // R044 + payment_confirm_card_details({@required String method,type}){ + logger('payment_confirm_card_details', parameters: { + 'payment_method' : method, + 'payment_type' : type + }); + } + + // R045 + payment_pay({@required String method,type}){ + logger('payment_pay', parameters: { + 'payment_method' : method, + 'payment_type' : type + }); + } + + // R046 + payment_success({@required String appointment_type, clinic, hospital, payment_method, payment_type, txn_number, txn_amount, txn_currency}){ + logger('payment_success', parameters: { + 'appointment_type' : appointment_type, + 'clinic_type_online' : clinic, + 'payment_method' : payment_method, + 'payment_type' : payment_type, + 'hospital_name' : hospital, + 'transaction_number' : txn_number, + 'transaction_amount' : txn_amount, + 'transaction_currency' : txn_currency + }); + } +} \ No newline at end of file diff --git a/lib/analytics/flows/app_nav.dart b/lib/analytics/flows/app_nav.dart new file mode 100644 index 00000000..12601fcd --- /dev/null +++ b/lib/analytics/flows/app_nav.dart @@ -0,0 +1,13 @@ +import 'package:diplomaticquarterapp/analytics/google-analytics.dart'; + +class AppNav{ + final name = 'app_nav'; + final GALogger logger; + AppNav(this.logger); + + logNavName(String value){ + logger(name, parameters: { + 'nav_name' : value + }); + } +} \ No newline at end of file diff --git a/lib/analytics/flows/appointments.dart b/lib/analytics/flows/appointments.dart new file mode 100644 index 00000000..bd69769d --- /dev/null +++ b/lib/analytics/flows/appointments.dart @@ -0,0 +1,222 @@ +import 'package:diplomaticquarterapp/models/Appointments/AppoimentAllHistoryResultList.dart'; +import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart'; +import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +import '../google-analytics.dart'; + +class Appointment{ + + final GALogger logger; + Appointment(this.logger); + + // R015 + book_appointment(){ + logger('book_appointment'); + } + + // R016.1, R017.2 + book_appointment_by_clinic(){ + logger('book_appointment_by_clinic'); + } + + // R016.2, R018.2 + book_appointment_by_doctor(){ + logger('book_appointment_by_doctor'); + } + + // R017.1 + book_appointment_doctor_search({@required String query}){ + // doctor_search_query : value + logger('book_appointment_doctor_search', parameters: { + 'doctor_search_query' : query + }); + } + + // R018.1 + book_appointment_select_clinic({@required String appointment_type, clinic}){ + // appointment_type: regular | livecare + // clinic_type : $clinic_type + logger('book_appointment_select_clinic', parameters: { + 'appointment_type' : appointment_type, + 'clinic_type' : clinic + }); + } + + // R019.1 + book_appointment_livecare_accept(){ + logger('book_appointment_livecare_accept'); + } + + // R019.2 + book_appointment_livecare_decline(){ + logger('book_appointment_livecare_decline'); + } + + // R020 + book_appointment_chief_complaints({@required String appointment_type, clinic, hospital, treatment}){ + logger('book_appointment_chief_complaints', parameters: { + 'appointment_type' : appointment_type, + 'clinic_type' : clinic, + 'hospital_name' : hospital, + 'treatment_type' : treatment, + }); + } + + // R021 + book_appointment_select_doctor({@required String appointment_type, @required DoctorList doctor}){ + // appointment_type, clinic_type, hospital_name, treatment_type, doctor_name, doctor_nationality, doctor_gender + logger('book_appointment_select_doctor', parameters: { + 'appointment_type' : appointment_type, + 'clinic_type' : doctor.clinicName, + 'hospital_name' : doctor.projectName, + 'treatment_type' : doctor.clinicName, + 'doctor_name' : doctor.name, + 'doctor_nationality' : doctor.nationalityName, + 'doctor_gender' : doctor.gender, + }); + } + + // R022 + book_appointment_schedule({@required String appointment_type, @required DoctorList doctor}){ + // appointment_type, clinic_type, hospital_name, treatment_type, doctor_name, doctor_nationality, doctor_gender + logger('book_appointment_schedule', parameters: { + 'appointment_type' : appointment_type, + 'clinic_type' : doctor.clinicName, + 'hospital_name' : doctor.projectName, + 'treatment_type' : doctor.clinicName, + 'doctor_name' : doctor.name, + 'doctor_nationality' : doctor.nationalityName, + 'doctor_gender' : doctor.gender, + }); + } + + // R023 + book_appointment_date_selection({@required String appointment_type, @required day, @required DoctorList doctor}){ + logger('book_appointment_date_selection', parameters: { + 'appointment_type' : appointment_type, + 'clinic_type' : doctor.clinicName, + 'hospital_name' : doctor.projectName, + 'treatment_type' : doctor.clinicName, + 'doctor_name' : doctor.name, + 'doctor_nationality' : doctor.nationalityName, + 'doctor_gender' : doctor.gender, + 'appointment_day' : day + }); + } + + // R024.1 + book_appointment_time_selection({@required String appointment_type, @required DateTime dateTime, @required DoctorList doctor}){ + final day = DateUtil.getWeekDay(dateTime.weekday); + final time = DateUtil.formatDateToTime(dateTime); + logger('book_appointment_time_selection', parameters: { + 'appointment_type' : appointment_type, + 'clinic_type' : doctor.clinicName, + 'hospital_name' : doctor.projectName, + 'treatment_type' : doctor.clinicName, + 'doctor_name' : doctor.name, + 'doctor_nationality' : doctor.nationalityName, + 'doctor_gender' : doctor.gender, + 'appointment_day' : day, + 'appointment_hour' : time + }); + } + + // R024.2 + book_appointment_review({@required String appointment_type, @required DateTime dateTime, @required DoctorList doctor}){ + final day = DateUtil.getWeekDay(dateTime.weekday); + final time = DateUtil.formatDateToTime(dateTime); + logger('book_appointment_review', parameters: { + 'appointment_type' : appointment_type, + 'clinic_type' : doctor.clinicName, + 'hospital_name' : doctor.projectName, + 'treatment_type' : doctor.clinicName, + 'doctor_name' : doctor.name, + 'doctor_nationality' : doctor.nationalityName, + 'doctor_gender' : doctor.gender, + 'appointment_day' : day, + 'appointment_hour' : time + }); + } + + // R025 + book_appointment_click_confirm({@required String appointment_type, @required DateTime dateTime, @required DoctorList doctor}){ + final day = DateUtil.getWeekDay(dateTime.weekday); + final time = DateUtil.formatDateToTime(dateTime); + logger('book_appointment_click_confirm', parameters: { + 'appointment_type' : appointment_type, + 'clinic_type' : doctor.clinicName, + 'hospital_name' : doctor.projectName, + 'treatment_type' : doctor.clinicName, + 'doctor_name' : doctor.name, + 'doctor_nationality' : doctor.nationalityName, + 'doctor_gender' : doctor.gender, + 'appointment_day' : day, + 'appointment_hour' : time + }); + } + + // R026 + book_appointment_confirmation_success({@required String appointment_type, @required DateTime dateTime, @required DoctorList doctor}){ + final day = DateUtil.getWeekDay(dateTime.weekday); + final time = DateUtil.formatDateToTime(dateTime); + logger('book_appointment_confirmation_success', parameters: { + 'appointment_type' : appointment_type, + 'clinic_type' : doctor.clinicName, + 'hospital_name' : doctor.projectName, + 'treatment_type' : doctor.clinicName, + 'doctor_name' : doctor.name, + 'doctor_nationality' : doctor.nationalityName, + 'doctor_gender' : doctor.gender, + 'appointment_day' : day, + 'appointment_hour' : time + }); + } + + // R027 + appointment_reminder(bool value){ + logger('appointment_reminder', parameters: { + 'reminder' : value ? 'yes' : 'no' + }); + } + + // R028 + appointment_reminder_time({@required String reminde_before}){ + logger('appointment_reminder_time', parameters: { + 'reminder_before' : reminde_before + }); + } + + // R053 + // Note : - Payment flow beyond this step are same as listed under ‘Advance Payment’ section of this document + pay_now_for_appointment({@required String appointment_type, @required DoctorList doctorDetail, bool payNow = true}){ + logger('pay_now_for_appointment', parameters: { + 'appointment_type' : appointment_type, + 'clinic_type' : doctorDetail.clinicName, + 'hospital_name' : doctorDetail.projectName, + 'doctor_name' : doctorDetail.name, + 'payment_type' : 'appointment' + }); + } + + // Note : - Payment flow beyond this step are same as listed under ‘Advance Payment’ section of this document + appointment_detail_action({@required AppoitmentAllHistoryResultList appointment, @required String action}){ + logger('appointment_detail_action', parameters: { + }); + } + + // Note : - Payment flow beyond this step are same as listed under ‘Advance Payment’ section of this document + appointment_details_confirm({@required AppoitmentAllHistoryResultList appointment}){ + logger('appointment_details_confirm', parameters: { + }); + } + + // R053 + // Note : - Payment flow beyond this step are same as listed under ‘Advance Payment’ section of this document + appointment_details_cancel({@required AppoitmentAllHistoryResultList appointment}){ + logger('appointment_details_cancel', parameters: { + }); + } + +} \ No newline at end of file diff --git a/lib/analytics/flows/error_tracking.dart b/lib/analytics/flows/error_tracking.dart new file mode 100644 index 00000000..1ceb2ab9 --- /dev/null +++ b/lib/analytics/flows/error_tracking.dart @@ -0,0 +1,8 @@ +import '../google-analytics.dart'; + +class ErrorTracking{ + + final GALogger logger; + ErrorTracking(this.logger); + +} \ No newline at end of file diff --git a/lib/analytics/flows/hamburger_menu.dart b/lib/analytics/flows/hamburger_menu.dart new file mode 100644 index 00000000..404cdbcf --- /dev/null +++ b/lib/analytics/flows/hamburger_menu.dart @@ -0,0 +1,15 @@ +import 'package:diplomaticquarterapp/analytics/google-analytics.dart'; + +class HamburgerMenu{ + final hamburger_menu = 'hamburger_menu'; + + final GALogger logger; + HamburgerMenu(this.logger); + + logMenuItemClick(String value){ + logger(hamburger_menu, parameters: { + 'menu_item' : value + }); + } + +} \ No newline at end of file diff --git a/lib/analytics/flows/hmg_services.dart b/lib/analytics/flows/hmg_services.dart new file mode 100644 index 00000000..357f81ab --- /dev/null +++ b/lib/analytics/flows/hmg_services.dart @@ -0,0 +1,13 @@ +import '../google-analytics.dart'; + +class HMGServices{ + final hmg_services = 'hmg_services'; + + final GALogger logger; + HMGServices(this.logger); + logServiceName(String value){ + logger('hmg_services', parameters: { + 'services_name' : value + }); + } +} \ No newline at end of file diff --git a/lib/analytics/flows/live_care.dart b/lib/analytics/flows/live_care.dart new file mode 100644 index 00000000..fd7d03d4 --- /dev/null +++ b/lib/analytics/flows/live_care.dart @@ -0,0 +1,101 @@ +import 'package:flutter/cupertino.dart'; + +import '../google-analytics.dart'; + +class LiveCare{ + + final GALogger logger; + LiveCare(this.logger); + + // R030.1 + livecare_immediate_consultation(){ + logger('livecare_immediate_consultation'); + } + + // R030.2 + livecare_schedule_video_call(){ + logger('livecare_schedule_video_call'); + } + + // R031.1 + livecare_clinic_schedule({@required String clinic}){ + logger('livecare_clinic_schedule', parameters: { + 'clinic_type_online' : clinic + }); + } + + // R031.2 + livecare_immediate_consultation_clinic({@required String clinic}){ + logger('livecare_immediate_consultation_clinic', parameters: { + 'clinic_type_online' : clinic + }); + } + + // R031.2 + livecare_schedule_video_call_clinic({@required String clinic}){ + logger('livecare_schedule_video_call_clinic', parameters: { + 'clinic_type_online' : clinic + }); + } + + // R032 + livecare_immediate_consultation_TnC({@required String clinic}){ + logger('livecare_immediate_consultation_TnC', parameters: { + 'clinic_type_online' : clinic + }); + } + + // R033 + payment_method({@required String appointment_type, clinic, payment_method, payment_type}){ + logger('payment_method', parameters: { + 'appointment_type' : appointment_type, + 'clinic_type_online' : clinic, + 'payment_method' : payment_method, + 'payment_type' : payment_type + }); + } + + // R034 + payment_confirm({@required String appointment_type, clinic, payment_method, payment_type}){ + logger('payment_confirm', parameters: { + 'appointment_type' : appointment_type, + 'clinic_type_online' : clinic, + 'payment_method' : payment_method, + 'payment_type' : payment_type + }); + } + + // R035 + payment_pay({@required String appointment_type, clinic, hospital, payment_method, payment_type}){ + // logger('payment_pay', parameters: { + // 'appointment_type' : appointment_type, + // 'clinic_type_online' : clinic, + // 'payment_method' : payment_method, + // 'payment_type' : payment_type, + // 'hospital_name' : hospital + // }); + } + + // R036 + payment_success({@required String appointment_type, clinic, hospital, payment_method, payment_type, txn_number, txn_amount, txn_currency}){ + // appointment_type + // clinic_type_online + // payment_method + // payment_type + // hospital_name + // transaction_number + // transaction_amount + // transaction_currency + } + + // R037 + livecare_immediate_consultation_payment_failed({@required String appointment_type, clinic, hospital, payment_method, payment_type, error_code, error_message}){ + // appointment_type + // clinic_type_online + // payment_method + // payment_type + // hospital_name + // error_code + // error_message + } +} \ No newline at end of file diff --git a/lib/analytics/flows/login_registration.dart b/lib/analytics/flows/login_registration.dart new file mode 100644 index 00000000..cf123b62 --- /dev/null +++ b/lib/analytics/flows/login_registration.dart @@ -0,0 +1,103 @@ +import 'package:flutter/cupertino.dart'; + +import '../google-analytics.dart'; + +class LoginRegistration{ + + final GALogger logger; + LoginRegistration(this.logger); + // R004.1 + login_register_initiate(){ + logger('login_register_initiate'); + } + + // R005.1 + visited_alhabib_group(bool value){ + // selection_type: yes/no + logger('visited_alhabib_group', parameters: { + 'selection_type' : value ? 'yes' : 'no' + }); + } + + // R006.1, R007.1, R008.1, R009.1 + registration_cancel({@required String step}){ + // registration_step : enter details + // registration_step : personal info + // registration_step : patient info + // fourth (verification) + logger('registration_cancel', parameters: { + 'registration_step' : step + }); + } + + // R006.2 + registration_enter_details(){ + logger('registration_enter_details'); + } + + // R007.2 + registration_personal_info(){ + logger('registration_personal_info'); + } + + // R008.2 + registration_patient_info(){ + logger('registration_patient_info'); + } + + // R009.2 + registration_verification_option(){ + logger('registration_verification_option'); + } + + // R010 + registration_confirmation({@required String by}){ + // verification_method: by + logger('registration_confirmation', parameters: { + 'verification_method' : by + }); + } + + // R011.1 + login_start({@required String method}){ + logger('login_start', parameters: { + 'login_method' : method + }); + } + + // R011.2 + forget_file_number(){ + logger('forget_file_number'); + } + + // R011.3 + register_now({@required String method}){ + logger('register_now', parameters: { + 'login_method' : method + }); + } + + // R012.1, R014.1 + login_successful({@required String method}){ + logger('login_successful', parameters: { + 'login_method' : method + }); + } + + // R012.4 + login_unsuccessful({@required String method, error}){ + logger('login_unsuccessful', parameters: { + 'login_method' : method + }); + } + + // R013 + recover_file_number(){ + logger('recover_file_number'); + } + + // R014.2 + login_with_other_account(){ + logger('login_with_other_account'); + } +} \ No newline at end of file diff --git a/lib/analytics/flows/offers_promotions.dart b/lib/analytics/flows/offers_promotions.dart new file mode 100644 index 00000000..eea90b15 --- /dev/null +++ b/lib/analytics/flows/offers_promotions.dart @@ -0,0 +1,9 @@ +import '../google-analytics.dart'; + +class OfferAndPromotion{ + + final GALogger logger; + OfferAndPromotion(this.logger); + + final offers_and_promotion = 'offers_&_promotion'; +} \ No newline at end of file diff --git a/lib/analytics/flows/todo_list.dart b/lib/analytics/flows/todo_list.dart new file mode 100644 index 00000000..bfcde052 --- /dev/null +++ b/lib/analytics/flows/todo_list.dart @@ -0,0 +1,119 @@ +import 'package:diplomaticquarterapp/models/Appointments/AppoimentAllHistoryResultList.dart'; + +import '../google-analytics.dart'; + +class TodoList{ + + final GALogger logger; + TodoList(this.logger); + + // R047.1 + to_do_list_pay_now(AppoitmentAllHistoryResultList appointment){ + logger('to_do_list_pay_now', parameters: { + 'appointment_type' : appointment.appointmentType, + 'clinic_type_online' : appointment.clinicName, + 'hospital_name' : appointment.projectName, + 'doctor_name' : appointment.doctorName, + 'payment_type' : appointment.patientType, + }); + } + + // R047.2 + to_do_list_more_details(AppoitmentAllHistoryResultList appointment){ + logger('to_do_list_more_details', parameters: { + 'appointment_type' : appointment.appointmentType, + 'clinic_type_online' : appointment.clinicName, + 'hospital_name' : appointment.projectName, + 'doctor_name' : appointment.doctorName, + 'payment_type' : appointment.patientType, + }); + } + + // R048 + to_do_list_confirm_payment_details(AppoitmentAllHistoryResultList appointment){ + logger('to_do_list_confirm_payment_details', parameters: { + 'appointment_type' : appointment.appointmentType, + 'clinic_type_online' : appointment.clinicName, + 'hospital_name' : appointment.projectName, + 'doctor_name' : appointment.doctorName, + 'payment_type' : appointment.patientType, + }); + } + + // R048 + to_do_list_cancel_payment_details(AppoitmentAllHistoryResultList appointment){ + logger('to_do_list_cancel_payment_details', parameters: { + 'appointment_type' : appointment.appointmentType, + 'clinic_type_online' : appointment.clinicName, + 'hospital_name' : appointment.projectName, + 'doctor_name' : appointment.doctorName, + 'payment_type' : appointment.patientType, + }); + } + + // R049.1 // should be for appointment flow + // to_do_list_appointment_actions(AppoitmentAllHistoryResultList appointment, action){ + // logger('to_do_list_pay_now', parameters: { + // 'appointment_type' : appointment.appointmentType, + // 'clinic_type_online' : appointment.clinicName, + // 'hospital_name' : appointment.projectName, + // 'doctor_name' : appointment.doctorName, + // 'payment_type' : appointment.patientType, + // }); + // } + + // R049.2 + to_do_list_cancel_appointment(AppoitmentAllHistoryResultList appointment){ + logger('to_do_list_cancel_appointment', parameters: { + 'appointment_type' : appointment.appointmentType, + 'clinic_type_online' : appointment.clinicName, + 'hospital_name' : appointment.projectName, + 'doctor_name' : appointment.doctorName, + 'payment_type' : appointment.patientType, + }); + } + + // R049.3 + to_do_list_confirm_appointment(AppoitmentAllHistoryResultList appointment){ + logger('to_do_list_confirm_appointment', parameters: { + 'appointment_type' : appointment.appointmentType, + 'clinic_type_online' : appointment.clinicName, + 'hospital_name' : appointment.projectName, + 'doctor_name' : appointment.doctorName, + 'payment_type' : appointment.patientType, + }); + } + + // R050 + to_do_list_check_in(AppoitmentAllHistoryResultList appointment){ + logger('to_do_list_check_in', parameters: { + 'appointment_type' : appointment.appointmentType, + 'clinic_type_online' : appointment.clinicName, + 'hospital_name' : appointment.projectName, + 'doctor_name' : appointment.doctorName, + 'payment_type' : appointment.patientType, + }); + } + + // R051 + to_do_list_nfc(AppoitmentAllHistoryResultList appointment){ + logger('to_do_list_nfc', parameters: { + 'appointment_type' : appointment.appointmentType, + 'clinic_type_online' : appointment.clinicName, + 'hospital_name' : appointment.projectName, + 'doctor_name' : appointment.doctorName, + 'payment_type' : appointment.patientType, + }); + } + + // R052 + to_do_list_nfc_cancel(AppoitmentAllHistoryResultList appointment){ + logger('to_do_list_nfc_cancel', parameters: { + 'appointment_type' : appointment.appointmentType, + 'clinic_type_online' : appointment.clinicName, + 'hospital_name' : appointment.projectName, + 'doctor_name' : appointment.doctorName, + 'payment_type' : appointment.patientType, + }); + } +} \ No newline at end of file diff --git a/lib/analytics/google-analytics.dart b/lib/analytics/google-analytics.dart index 0ded8cc6..c88055a6 100644 --- a/lib/analytics/google-analytics.dart +++ b/lib/analytics/google-analytics.dart @@ -1,4 +1,13 @@ import 'package:diplomaticquarterapp/analytics/analytic-events.dart'; +import 'package:diplomaticquarterapp/analytics/flows/advance_payments.dart'; +import 'package:diplomaticquarterapp/analytics/flows/appointments.dart'; +import 'package:diplomaticquarterapp/analytics/flows/error_tracking.dart'; +import 'package:diplomaticquarterapp/analytics/flows/hamburger_menu.dart'; +import 'package:diplomaticquarterapp/analytics/flows/live_care.dart'; +import 'package:diplomaticquarterapp/analytics/flows/login_registration.dart'; +import 'package:diplomaticquarterapp/analytics/flows/offers_promotions.dart'; +import 'package:diplomaticquarterapp/analytics/flows/todo_list.dart'; +import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; import 'package:diplomaticquarterapp/routes.dart'; import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:firebase_analytics/firebase_analytics.dart'; @@ -6,29 +15,61 @@ import 'package:firebase_analytics/observer.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -class Singleton { - const Singleton(); //Constant constructor +import 'flows/app_nav.dart'; +import 'flows/hmg_services.dart'; - void hello() { - print('Hello world'); + +typedef GALogger = Function(String name, {Map parameters}); + +var _analytics = FirebaseAnalytics(); +_logger(String name, {Map parameters}) async { + if (name != null && name.isNotEmpty) { + if(name.contains(' ')) + name = name.replaceAll(' ','_'); + + _analytics + .logEvent(name: name.trim(), parameters: parameters) + .then((value) { + debugPrint('SUCCESS: Google analytics event "$name" sent'); + }).catchError((error) { + debugPrint('ERROR: Google analytics event "$name" sent failed'); + }); } } -var analytics = FirebaseAnalytics(); class GAnalytics { - const GAnalytics(); - static GAnalytics shared = const GAnalytics(); + setUser(AuthenticatedUser user){ + if(user != null){ + _analytics.setUserProperty(name: 'user_country', value: user.iSOCountryID); + _analytics.setUserProperty(name: 'user_language', value: user.preferredLanguage); + _analytics.setUserProperty(name: 'userid', value: user.patientID.toString() ); + _analytics.setUserProperty(name: 'login_status', value: 'yes'); + } + } + NavObserver navObserver() => NavObserver(); + final hamburgerMenu = HamburgerMenu(_logger); + final bottomTabNavigation = AppNav(_logger); + final hmgServices = HMGServices(_logger); + final loginRegistration = LoginRegistration(_logger); + final appointment = Appointment(_logger); + final liveCare = LiveCare(_logger); + final todoList = TodoList(_logger); + final advancePayments = AdvancePayments(_logger); + final offerPackages = OfferAndPromotion(_logger); + final errorTracking = ErrorTracking(_logger); } + + // adb shell setprop debug.firebase.analytics.app com.ejada.hmg -> Android class NavObserver extends RouteObserver> { _sendScreenView(PageRoute route) async { log(String className) { var event = AnalyticEvents.get(className); if (event.active != null) { - analytics + _analytics .setCurrentScreen( screenName: event.flutterName(), screenClassOverride: className) .catchError( diff --git a/lib/core/viewModels/project_view_model.dart b/lib/core/viewModels/project_view_model.dart index ab2f931b..78ed83b4 100644 --- a/lib/core/viewModels/project_view_model.dart +++ b/lib/core/viewModels/project_view_model.dart @@ -1,9 +1,11 @@ import 'dart:async'; import 'package:connectivity/connectivity.dart'; +import 'package:diplomaticquarterapp/analytics/google-analytics.dart'; import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/core/model/privilege/PrivilegeModel.dart'; import 'package:diplomaticquarterapp/core/viewModels/base_view_model.dart'; +import 'package:diplomaticquarterapp/locator.dart'; import 'package:diplomaticquarterapp/uitl/PlatformBridge.dart'; import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; import 'package:flutter/cupertino.dart'; @@ -11,6 +13,9 @@ import 'package:flutter_datetime_picker/flutter_datetime_picker.dart'; var isAppArabic = false; class ProjectViewModel extends BaseViewModel { + + GAnalytics get analytics => locator(); + // Platform Bridge PlatformBridge platformBridge() { return PlatformBridge.shared(); diff --git a/lib/locator.dart b/lib/locator.dart index c0a8bd51..df0561fd 100644 --- a/lib/locator.dart +++ b/lib/locator.dart @@ -24,6 +24,7 @@ import 'package:diplomaticquarterapp/uitl/navigation_service.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:get_it/get_it.dart'; +import 'analytics/google-analytics.dart'; import 'core/service/AlHabibMedicalService/cmc_service.dart'; import 'core/service/AlHabibMedicalService/customer_addresses_service.dart'; import 'core/service/AlHabibMedicalService/e_referral_service.dart'; @@ -325,4 +326,10 @@ void setupLocator() { () => GeofencingServices()); // Geofencing Services locator.registerFactory(() => TermsConditionsViewModel()); locator.registerFactory(() => AnciallryOrdersViewModel()); + + + // Google/Firebase Analytics + // --------------------------- + locator.registerFactory(() => GAnalytics()); + } diff --git a/lib/models/Clinics/ClinicListResponse.dart b/lib/models/Clinics/ClinicListResponse.dart index 1aa4065e..6aadabc0 100644 --- a/lib/models/Clinics/ClinicListResponse.dart +++ b/lib/models/Clinics/ClinicListResponse.dart @@ -1,7 +1,7 @@ class ListClinicCentralized { int clinicID; String clinicDescription; - Null clinicDescriptionN; + String clinicDescriptionN; int age; int gender; bool isLiveCareClinicAndOnline; diff --git a/lib/pages/BookAppointment/BookConfirm.dart b/lib/pages/BookAppointment/BookConfirm.dart index 63e711e5..793ac4bf 100644 --- a/lib/pages/BookAppointment/BookConfirm.dart +++ b/lib/pages/BookAppointment/BookConfirm.dart @@ -1,4 +1,5 @@ import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/models/Appointments/AppoimentAllHistoryResultList.dart'; import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart'; import 'package:diplomaticquarterapp/models/Appointments/PatientShareResposne.dart'; @@ -26,6 +27,7 @@ import 'package:permission_handler/permission_handler.dart'; import 'package:provider/provider.dart'; import 'book_reminder_page.dart'; +import 'components/DocAvailableAppointments.dart'; class BookConfirm extends StatefulWidget { DoctorList doctor; @@ -47,6 +49,7 @@ class BookConfirm extends StatefulWidget { } class _BookConfirmState extends State { + ProjectViewModel projectViewModel; ToDoCountProviderModel toDoProvider; AppSharedPreferences sharedPref = new AppSharedPreferences(); @@ -63,6 +66,7 @@ class _BookConfirmState extends State { @override Widget build(BuildContext context) { toDoProvider = Provider.of(context); + projectViewModel = Provider.of(context); return AppScaffold( appBarTitle: widget.doctor.doctorTitle + " " + widget.doctor.name, isShowDecPage: false, @@ -265,10 +269,14 @@ class _BookConfirmState extends State { } insertAppointment(context, DoctorList docObject) { + final timeSlot = DocAvailableAppointments.selectedAppoDateTime; + projectViewModel.analytics.appointment.book_appointment_click_confirm(appointment_type: 'regular', dateTime: timeSlot, doctor: widget.doctor); + GifLoaderDialogUtils.showMyDialog(context); AppoitmentAllHistoryResultList appo; widget.service.insertAppointment(docObject.doctorID, docObject.clinicID, docObject.projectID, widget.selectedTime, widget.selectedDate, context).then((res) { if (res['MessageStatus'] == 1) { + projectViewModel.analytics.appointment.book_appointment_confirmation_success(appointment_type: 'regular', dateTime: timeSlot, doctor: widget.doctor); AppToast.showSuccessToast(message: TranslationBase.of(context).bookedSuccess); print(res['AppointmentNo']); @@ -307,10 +315,14 @@ class _BookConfirmState extends State { } insertLiveCareScheduledAppointment(context, DoctorList docObject) { + final timeSlot = DocAvailableAppointments.selectedAppoDateTime; + projectViewModel.analytics.appointment.book_appointment_click_confirm(appointment_type: 'livecare', dateTime: timeSlot, doctor: widget.doctor); + GifLoaderDialogUtils.showMyDialog(context); AppoitmentAllHistoryResultList appo; widget.service.insertLiveCareScheduleAppointment(docObject.doctorID, docObject.clinicID, docObject.projectID, docObject.serviceID, widget.selectedTime, widget.selectedDate, context).then((res) { if (res['MessageStatus'] == 1) { + projectViewModel.analytics.appointment.book_appointment_confirmation_success(appointment_type: 'livecare', dateTime: timeSlot, doctor: widget.doctor); AppToast.showSuccessToast(message: TranslationBase.of(context).bookedSuccess); print(res['AppointmentNo']); diff --git a/lib/pages/BookAppointment/BookSuccess.dart b/lib/pages/BookAppointment/BookSuccess.dart index 04086ee3..15906851 100644 --- a/lib/pages/BookAppointment/BookSuccess.dart +++ b/lib/pages/BookAppointment/BookSuccess.dart @@ -1,4 +1,5 @@ import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/models/Appointments/AppoimentAllHistoryResultList.dart'; import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart'; import 'package:diplomaticquarterapp/models/Appointments/PatientShareResposne.dart'; @@ -20,6 +21,7 @@ import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart'; +import 'package:provider/provider.dart'; import 'QRCode.dart'; @@ -43,8 +45,11 @@ class _BookSuccessState extends State { AppSharedPreferences sharedPref = AppSharedPreferences(); AuthenticatedUser authUser; + ProjectViewModel projectViewModel; + @override Widget build(BuildContext context) { + projectViewModel = Provider.of(context); return AppScaffold( appBarTitle: widget.docObject.doctorTitle + " " + widget.docObject.name, isShowDecPage: false, @@ -182,6 +187,7 @@ class _BookSuccessState extends State { disabledTextColor: Colors.white, disabledColor: new Color(0xFFbcc2c4), onPressed: () { + projectViewModel.analytics.appointment.pay_now_for_appointment(appointment_type: 'regular', doctorDetail: widget.docObject, payNow: true); startPaymentProcess(); }, child: Text(TranslationBase.of(context).payNow.toUpperCase(), style: TextStyle(fontSize: 18.0)), @@ -203,6 +209,7 @@ class _BookSuccessState extends State { disabledTextColor: Colors.white, disabledColor: new Color(0xFFbcc2c4), onPressed: () { + projectViewModel.analytics.appointment.pay_now_for_appointment(appointment_type: 'regular', doctorDetail: widget.docObject, payNow: false); navigateToHome(context); }, child: Text(TranslationBase.of(context).payLater.toUpperCase(), style: TextStyle(fontSize: 18.0)), @@ -388,6 +395,7 @@ class _BookSuccessState extends State { } confirmAppointment(AppoitmentAllHistoryResultList appo) { + DoctorsListService service = new DoctorsListService(); GifLoaderDialogUtils.showMyDialog(context); service.confirmAppointment(appo.appointmentNo, appo.clinicID, appo.projectID, appo.isLiveCareAppointment, context).then((res) { diff --git a/lib/pages/BookAppointment/DoctorProfile.dart b/lib/pages/BookAppointment/DoctorProfile.dart index 87941ed5..033d360b 100644 --- a/lib/pages/BookAppointment/DoctorProfile.dart +++ b/lib/pages/BookAppointment/DoctorProfile.dart @@ -1,4 +1,5 @@ import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart'; import 'package:diplomaticquarterapp/models/Appointments/DoctorProfile.dart'; import 'package:diplomaticquarterapp/models/Appointments/DoctorRateDetails.dart'; @@ -20,6 +21,7 @@ import 'package:diplomaticquarterapp/widgets/new_design/doctor_header.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import 'package:rating_bar/rating_bar.dart'; import 'BookConfirm.dart'; @@ -59,8 +61,11 @@ class _DoctorProfileState extends State with TickerProviderStateM super.initState(); } + ProjectViewModel projectViewModel; + @override Widget build(BuildContext context) { + projectViewModel = Provider.of(context); return AppScaffold( appBarTitle: widget.doctor.doctorTitle + " " + widget.doctor.name, isShowAppBar: true, @@ -122,6 +127,7 @@ class _DoctorProfileState extends State with TickerProviderStateM showConfirmMessageDialog: false, isNeedToShowButton: !widget.isLiveCareAppointment, onTap: () { + projectViewModel.analytics.appointment.book_appointment_schedule(appointment_type: 'regular', doctor: widget.doctor); Navigator.push( context, FadePage( @@ -490,6 +496,8 @@ class _DoctorProfileState extends State with TickerProviderStateM void goToBookConfirm() async { if (DocAvailableAppointments.areSlotsAvailable) { if (await sharedPref.getObject(USER_PROFILE) != null) { + final timeSlot = DocAvailableAppointments.selectedAppoDateTime; + projectViewModel.analytics.appointment.book_appointment_review(appointment_type: 'regular', dateTime: timeSlot, doctor: widget.doctor); navigateToBookConfirm(context); } else { ConfirmDialog dialog = new ConfirmDialog( diff --git a/lib/pages/BookAppointment/QRCode.dart b/lib/pages/BookAppointment/QRCode.dart index 5bf0a9f0..2f8b0875 100644 --- a/lib/pages/BookAppointment/QRCode.dart +++ b/lib/pages/BookAppointment/QRCode.dart @@ -2,6 +2,8 @@ import 'dart:convert'; import 'dart:typed_data'; import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/locator.dart'; import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart'; import 'package:diplomaticquarterapp/models/Appointments/PatientShareResposne.dart'; import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; @@ -88,10 +90,13 @@ class _QRCodeState extends State { child: Image.asset("assets/images/nfc/ic_nfc.png"), ), onTap: () { + locator().analytics.todoList.to_do_list_nfc(); showNfcReader(context, onNcfScan: (String nfcId) { Future.delayed(const Duration(milliseconds: 100), () { sendNfcCheckInRequest(nfcId); }); + }, onCancel: (){ + locator().analytics.todoList.to_do_list_nfc_cancel(); }); }, ), diff --git a/lib/pages/BookAppointment/Search.dart b/lib/pages/BookAppointment/Search.dart index d4942ccf..e10e3258 100644 --- a/lib/pages/BookAppointment/Search.dart +++ b/lib/pages/BookAppointment/Search.dart @@ -26,7 +26,6 @@ class _SearchState extends State with TickerProviderStateMixin { @override void initState() { _tabController = new TabController(length: 2, vsync: this, initialIndex: widget.type); - super.initState(); } @@ -64,6 +63,12 @@ class _SearchState extends State with TickerProviderStateMixin { letterSpacing: -0.48, ), tabs: [Text(TranslationBase.of(context).clinicName), Text(TranslationBase.of(context).doctorName)], + onTap: (idx){ + if(idx == 0) + projectViewModel.analytics.appointment.book_appointment_by_clinic(); + else + projectViewModel.analytics.appointment.book_appointment_by_doctor(); + }, ), Expanded( child: TabBarView( diff --git a/lib/pages/BookAppointment/SearchResults.dart b/lib/pages/BookAppointment/SearchResults.dart index 0a654e22..ba35a0f3 100644 --- a/lib/pages/BookAppointment/SearchResults.dart +++ b/lib/pages/BookAppointment/SearchResults.dart @@ -1,3 +1,4 @@ +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart'; import 'package:diplomaticquarterapp/pages/BookAppointment/widgets/DoctorView.dart'; import 'package:diplomaticquarterapp/theme/colors.dart'; @@ -6,6 +7,7 @@ import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/others/app_expandable_notifier.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; class SearchResults extends StatefulWidget { List doctorsList = []; @@ -21,9 +23,11 @@ class SearchResults extends StatefulWidget { class _SearchResultsState extends State { // var event = RobotProvider(); List tempList = []; + ProjectViewModel projectViewModel; @override Widget build(BuildContext context) { + projectViewModel = Provider.of(context); return AppScaffold( appBarTitle: TranslationBase.of(context).bookAppo, isShowDecPage: false, @@ -50,9 +54,13 @@ class _SearchResultsState extends State { padding: EdgeInsets.only(bottom: 10, top: 10, left: 21, right: 21), itemBuilder: (context, _index) { //widget.patientDoctorAppointmentListHospital[index].patientDoctorAppointmentList[_index].speciality = null; + final doctor = widget.patientDoctorAppointmentListHospital[index].patientDoctorAppointmentList[_index]; return DoctorView( - doctor: widget.patientDoctorAppointmentListHospital[index].patientDoctorAppointmentList[_index], - isLiveCareAppointment: widget.isLiveCareAppointment, + doctor: doctor, + isLiveCareAppointment: widget.isLiveCareAppointment, + onTap: (){ + projectViewModel.analytics.appointment.book_appointment_select_doctor(appointment_type: 'regular', doctor: doctor); + } ); }, separatorBuilder: (context, index) => SizedBox(height: 14), diff --git a/lib/pages/BookAppointment/book_reminder_page.dart b/lib/pages/BookAppointment/book_reminder_page.dart index 39f1648f..ddf741f1 100644 --- a/lib/pages/BookAppointment/book_reminder_page.dart +++ b/lib/pages/BookAppointment/book_reminder_page.dart @@ -1,4 +1,5 @@ import 'package:auto_size_text/auto_size_text.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart'; import 'package:diplomaticquarterapp/models/Appointments/PatientShareResposne.dart'; import 'package:diplomaticquarterapp/models/header_model.dart'; @@ -14,6 +15,7 @@ import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart'; import 'package:permission_handler/permission_handler.dart'; +import 'package:provider/provider.dart'; import 'BookSuccess.dart'; @@ -52,8 +54,10 @@ class _BookReminderPageState extends State { }); } + ProjectViewModel projectViewModel; @override Widget build(BuildContext context) { + projectViewModel = Provider.of(context); // print("selectedTime "+selectedTime??""); print("appointmentNo1 " + widget.patientShareResponse.appointmentNo.toString() ?? ""); return AppScaffold( @@ -173,6 +177,7 @@ class _BookReminderPageState extends State { disabledTextColor: Colors.white, disabledColor: new Color(0xFFEAEAEA), onPressed: () { + projectViewModel.analytics.appointment.appointment_reminder(false); navigateToBookSuccess(context); }, child: Text(TranslationBase.of(context).no, style: TextStyle(fontSize: 16.0, letterSpacing: -0.48)), @@ -194,6 +199,7 @@ class _BookReminderPageState extends State { disabledTextColor: Colors.white, disabledColor: CustomColors.green, onPressed: () async { + projectViewModel.analytics.appointment.appointment_reminder(true); print(widget.patientShareResponse.appointmentNo); showReminderDialog( context, diff --git a/lib/pages/BookAppointment/components/DocAvailableAppointments.dart b/lib/pages/BookAppointment/components/DocAvailableAppointments.dart index 3a6d9185..d37ef5a9 100644 --- a/lib/pages/BookAppointment/components/DocAvailableAppointments.dart +++ b/lib/pages/BookAppointment/components/DocAvailableAppointments.dart @@ -1,4 +1,5 @@ import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart'; import 'package:diplomaticquarterapp/models/Appointments/FreeSlot.dart'; import 'package:diplomaticquarterapp/models/Appointments/timeSlot.dart'; @@ -12,6 +13,7 @@ import 'package:diplomaticquarterapp/uitl/utils_new.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; +import 'package:provider/provider.dart'; import 'package:syncfusion_flutter_calendar/calendar.dart'; import '../../../uitl/date_uitl.dart'; @@ -112,8 +114,11 @@ class _DocAvailableAppointmentsState extends State wit }); } + ProjectViewModel projectViewModel; + @override Widget build(BuildContext context) { + projectViewModel = Provider.of(context); return SingleChildScrollView( child: Container( child: Column( @@ -247,6 +252,10 @@ class _DocAvailableAppointmentsState extends State wit elevation: 0, textColor: new Color(0xFF60686b), onPressed: () { + final timeslot = dayEvents[index]; + DocAvailableAppointments.selectedAppoDateTime = timeslot.end; + projectViewModel.analytics.appointment.book_appointment_time_selection(appointment_type: 'regular', dateTime: timeslot.end, doctor: widget.doctor); + setState(() { selectedButtonIndex = index; DocAvailableAppointments.selectedTime = dayEvents[index].isoTime; diff --git a/lib/pages/BookAppointment/components/SearchByClinic.dart b/lib/pages/BookAppointment/components/SearchByClinic.dart index 7fb724b8..bd1d8b91 100644 --- a/lib/pages/BookAppointment/components/SearchByClinic.dart +++ b/lib/pages/BookAppointment/components/SearchByClinic.dart @@ -229,6 +229,7 @@ class _SearchByClinicState extends State { : InkWell( onTap: () { showClickListDialog(context, clinicsList, onSelection: (ListClinicCentralized clincs) { + projectViewModel.analytics.appointment.book_appointment_select_clinic(appointment_type: 'regular', clinic: clincs.clinicDescription); Navigator.pop(context); setState(() { print(clincs.clinicID.toString() + "-" + clincs.isLiveCareClinicAndOnline.toString() + "-" + clincs.liveCareClinicID.toString() + "-" + clincs.liveCareServiceID.toString()); @@ -506,6 +507,7 @@ class _SearchByClinicState extends State { } else { isProjectLoaded = false; } + }).catchError((err) { }).catchError((err) { print(err); }); diff --git a/lib/pages/BookAppointment/components/SearchByDoctor.dart b/lib/pages/BookAppointment/components/SearchByDoctor.dart index 6bfac9a7..836bae7d 100644 --- a/lib/pages/BookAppointment/components/SearchByDoctor.dart +++ b/lib/pages/BookAppointment/components/SearchByDoctor.dart @@ -1,3 +1,4 @@ +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart'; import 'package:diplomaticquarterapp/services/appointment_services/GetDoctorsList.dart'; import 'package:diplomaticquarterapp/theme/colors.dart'; @@ -6,6 +7,7 @@ import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import '../SearchResults.dart'; @@ -17,6 +19,7 @@ class SearchByDoctor extends StatefulWidget { class _SearchByDoctorState extends State { TextEditingController doctorNameController = new TextEditingController(); bool _isButtonDisabled; + ProjectViewModel projectViewModel; @override void initState() { @@ -26,6 +29,7 @@ class _SearchByDoctorState extends State { @override Widget build(BuildContext context) { + projectViewModel = Provider.of(context); return Column( children: [ Expanded( @@ -143,6 +147,7 @@ class _SearchByDoctorState extends State { } _searchDoctor(BuildContext context) { + projectViewModel.analytics.appointment.book_appointment_doctor_search(query: doctorNameController.text); getDoctorsList(context); } diff --git a/lib/pages/BookAppointment/widgets/DoctorView.dart b/lib/pages/BookAppointment/widgets/DoctorView.dart index 7ebc26ca..2d113545 100644 --- a/lib/pages/BookAppointment/widgets/DoctorView.dart +++ b/lib/pages/BookAppointment/widgets/DoctorView.dart @@ -29,9 +29,9 @@ class DoctorView extends StatelessWidget { Widget build(BuildContext context) { projectViewModel = Provider.of(context); return InkWell( - onTap: onTap ?? - () { + onTap: () { if (isShowFlag) getDoctorsProfile(context, doctor, isAppo: true); + (onTap ?? (){})(); // For log analytics of doctor click from book appointment }, child: Container( decoration: BoxDecoration( diff --git a/lib/pages/BookAppointment/widgets/reminder_dialog.dart b/lib/pages/BookAppointment/widgets/reminder_dialog.dart index 6fcab59a..eece4d9f 100644 --- a/lib/pages/BookAppointment/widgets/reminder_dialog.dart +++ b/lib/pages/BookAppointment/widgets/reminder_dialog.dart @@ -1,3 +1,5 @@ +import 'package:diplomaticquarterapp/analytics/google-analytics.dart'; +import 'package:diplomaticquarterapp/locator.dart'; import 'package:diplomaticquarterapp/theme/colors.dart'; import 'package:diplomaticquarterapp/uitl/CalendarUtils.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; @@ -41,23 +43,30 @@ Future _showReminderDialog(BuildContext context, DateTime dateTime, String insetPadding: EdgeInsets.all(21), child: ReminderDialog( onClick: (int i) async { + String text = ""; if (i == 0) { // Before 30 mints dateTime = Jiffy(dateTime).subtract(minutes: 30).dateTime; + text = "30 minutes"; // dateTime.add(new Duration(minutes: -30)); } else if (i == 1) { // Before 1 hour // dateTime.add(new Duration(minutes: -60)); dateTime = Jiffy(dateTime).subtract(hours: 1).dateTime; + text = "1 hours"; } else if (i == 2) { // Before 1 hour and 30 mints // dateTime.add(new Duration(minutes: -90)); dateTime = Jiffy(dateTime).subtract(hours: 1, minutes: 30).dateTime; + text = "1 hours 30 minutes"; } else if (i == 3) { // Before 2 hours // dateTime.add(new Duration(minutes: -120)); dateTime = Jiffy(dateTime).subtract(hours: 2).dateTime; + text = "2 hours"; } + + locator().appointment.appointment_reminder_time(reminde_before: text); if (onMultiDateSuccess == null) { CalendarUtils calendarUtils = await CalendarUtils.getInstance(); calendarUtils diff --git a/lib/pages/MyAppointments/AppointmentDetails.dart b/lib/pages/MyAppointments/AppointmentDetails.dart index 06710183..901e6c6c 100644 --- a/lib/pages/MyAppointments/AppointmentDetails.dart +++ b/lib/pages/MyAppointments/AppointmentDetails.dart @@ -551,6 +551,7 @@ class _AppointmentDetailsState extends State with SingleTick service.confirmAppointment(widget.appo.appointmentNo, widget.appo.clinicID, widget.appo.projectID, widget.appo.isLiveCareAppointment, context).then((res) { GifLoaderDialogUtils.hideDialog(context); if (res['MessageStatus'] == 1) { + projectViewModel.analytics.appointment.appointment_details_confirm(appointment: widget.appo); AppToast.showSuccessToast(message: res['ErrorEndUserMessage']); Navigator.of(context).pop(); } else { @@ -567,6 +568,8 @@ class _AppointmentDetailsState extends State with SingleTick GifLoaderDialogUtils.showMyDialog(context); DoctorsListService service = new DoctorsListService(); service.cancelAppointment(widget.appo, context).then((res) { + + projectViewModel.analytics.appointment.appointment_details_cancel(appointment: widget.appo); GifLoaderDialogUtils.hideDialog(context); if (res['MessageStatus'] == 1) { getToDoCount(); diff --git a/lib/pages/MyAppointments/SchedulePage.dart b/lib/pages/MyAppointments/SchedulePage.dart index 92fbeedf..17cae84e 100644 --- a/lib/pages/MyAppointments/SchedulePage.dart +++ b/lib/pages/MyAppointments/SchedulePage.dart @@ -97,6 +97,8 @@ class _SchedulePageState extends State { itemCount: weeks[index].length, itemBuilder: (context, index2) => InkWell( onTap: () { + final weekDay = weeks[index][index2]['DayName']; + projectViewModel.analytics.appointment.book_appointment_date_selection(appointment_type: 'regular', day: weekDay, doctor: doctorList); openBookAppointment(weeks[index][index2]); }, child: Row( diff --git a/lib/pages/ToDoList/ToDo.dart b/lib/pages/ToDoList/ToDo.dart index b46e1958..f3a98df6 100644 --- a/lib/pages/ToDoList/ToDo.dart +++ b/lib/pages/ToDoList/ToDo.dart @@ -683,6 +683,7 @@ class _ToDoState extends State { } Future navigateToAppointmentDetails(context, AppoitmentAllHistoryResultList appo) async { + projectViewModel.analytics.todoList.to_do_list_more_details(appo); Navigator.push(context, FadePage(page: AppointmentDetails(appo: appo, parentIndex: appo.patientStatusType == 42 ? 1 : 0))).then((value) { getPatientAppointmentHistory(); }); @@ -763,6 +764,7 @@ class _ToDoState extends State { DoctorsListService service = new DoctorsListService(); service.generateAppointmentQR(patientShareResponse, context).then((res) { GifLoaderDialogUtils.hideDialog(context); + projectViewModel.analytics.todoList.to_do_list_check_in(appo); navigateToQR(context, res['AppointmentQR'], patientShareResponse); }).catchError((err) { GifLoaderDialogUtils.hideDialog(context); @@ -783,6 +785,7 @@ class _ToDoState extends State { } openPaymentDialog(AppoitmentAllHistoryResultList appo, PatientShareResponse patientShareResponse) { + projectViewModel.analytics.todoList.to_do_list_pay_now(appo); showGeneralDialog( barrierColor: Colors.black.withOpacity(0.5), transitionBuilder: (context, a1, a2, widget) { @@ -804,7 +807,10 @@ class _ToDoState extends State { print(value); if (value != null) { + projectViewModel.analytics.todoList.to_do_list_confirm_payment_details(appo); navigateToPaymentMethod(context, value, appo); + }else{ + projectViewModel.analytics.todoList.to_do_list_cancel_payment_details(appo); } }); } @@ -950,11 +956,13 @@ class _ToDoState extends State { } confirmAppointment(AppoitmentAllHistoryResultList appo) { + GifLoaderDialogUtils.showMyDialog(context); DoctorsListService service = new DoctorsListService(); service.confirmAppointment(appo.appointmentNo, appo.clinicID, appo.projectID, appo.isLiveCareAppointment, context).then((res) { GifLoaderDialogUtils.hideDialog(context); if (res['MessageStatus'] == 1) { + projectViewModel.analytics.todoList.to_do_list_confirm_appointment(); AppToast.showSuccessToast(message: res['ErrorEndUserMessage']); if (appo.isLiveCareAppointment) { insertLiveCareVIDARequest(appo); diff --git a/lib/pages/ToDoList/widgets/paymentDialog.dart b/lib/pages/ToDoList/widgets/paymentDialog.dart index 3e22494e..b145e173 100644 --- a/lib/pages/ToDoList/widgets/paymentDialog.dart +++ b/lib/pages/ToDoList/widgets/paymentDialog.dart @@ -1,3 +1,5 @@ +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/locator.dart'; import 'package:diplomaticquarterapp/models/Appointments/AppoimentAllHistoryResultList.dart'; import 'package:diplomaticquarterapp/models/Appointments/PatientShareResposne.dart'; import 'package:diplomaticquarterapp/theme/colors.dart'; diff --git a/lib/pages/landing/fragments/home_page_fragment2.dart b/lib/pages/landing/fragments/home_page_fragment2.dart index 2b8aa394..2cf7345f 100644 --- a/lib/pages/landing/fragments/home_page_fragment2.dart +++ b/lib/pages/landing/fragments/home_page_fragment2.dart @@ -101,6 +101,7 @@ class _HomePageFragment2State extends State { child: SliderView( onLoginClick: () { widget.onLoginClick(); + projectViewModel.analytics.loginRegistration.login_register_initiate(); // navigateTo(context, CallHomePage()); }, ), diff --git a/lib/pages/landing/landing_page.dart b/lib/pages/landing/landing_page.dart index 915c8e96..40ff61f9 100644 --- a/lib/pages/landing/landing_page.dart +++ b/lib/pages/landing/landing_page.dart @@ -135,6 +135,8 @@ class _LandingPageState extends State with WidgetsBindingObserver { imageEn: 'https://hmgwebservices.com/Images/MobileApp/images-info-home/family-file/en/1.png', imageAr: 'https://hmgwebservices.com/Images/MobileApp/images-info-home/family-file/ar/1.png'), ); + + projectViewModel.analytics.bottomTabNavigation.logNavName('my family'); Navigator.push( context, MaterialPageRoute( @@ -154,6 +156,7 @@ class _LandingPageState extends State with WidgetsBindingObserver { imagesInfo.add( ImagesInfo(imageEn: 'https://hmgwebservices.com/Images/MobileApp/images-info-home/todo/en/0.png', imageAr: 'https://hmgwebservices.com/Images/MobileApp/images-info-home/todo/ar/0.png')); + projectViewModel.analytics.bottomTabNavigation.logNavName('todo list'); Navigator.push( context, MaterialPageRoute( @@ -174,6 +177,7 @@ class _LandingPageState extends State with WidgetsBindingObserver { if (tab == 5) { IS_VOICE_COMMAND_CLOSED = false; triggerRobot(); + projectViewModel.analytics.bottomTabNavigation.logNavName('help robot'); // pageController.jumpToPage(tab); } else { @@ -234,10 +238,10 @@ class _LandingPageState extends State with WidgetsBindingObserver { }); // HMG (Guest/Internet) Wifi Access [Zohaib Kambrani] //for now commented to reduce this call will enable it when needed - HMGNetworkConnectivity(context, () { - GifLoaderDialogUtils.showMyDialog(context); - PlatformBridge.shared().connectHMGGuestWifi().then((value) => {GifLoaderDialogUtils.hideDialog(context)}); - }).checkAndConnectIfNoInternet(); + // HMGNetworkConnectivity(context, () { + // GifLoaderDialogUtils.showMyDialog(context); + // PlatformBridge.shared().connectHMGGuestWifi().then((value) => {GifLoaderDialogUtils.hideDialog(context)}); + // }).checkAndConnectIfNoInternet(); requestPermissions().then((results) { locationUtils.getCurrentLocation(); @@ -463,6 +467,9 @@ class _LandingPageState extends State with WidgetsBindingObserver { PageView( physics: NeverScrollableScrollPhysics(), controller: pageController, + onPageChanged: (idx){ + projectViewModel.analytics.bottomTabNavigation.logNavName(''); + }, children: [ HomePage2( goToMyProfile: () { @@ -472,6 +479,7 @@ class _LandingPageState extends State with WidgetsBindingObserver { login(); }, onMedicalFileClick: () { + projectViewModel.analytics.bottomTabNavigation.logNavName('medical file'); changeCurrentTab(1); }, ), @@ -510,6 +518,7 @@ class _LandingPageState extends State with WidgetsBindingObserver { ? FloatingButton( elevation: true, onTap: () { + projectViewModel.analytics.appointment.book_appointment(); changeCurrentTab(2); }, ) diff --git a/lib/pages/landing/widgets/services_view.dart b/lib/pages/landing/widgets/services_view.dart index b233c6a7..ef5ad06b 100644 --- a/lib/pages/landing/widgets/services_view.dart +++ b/lib/pages/landing/widgets/services_view.dart @@ -1,4 +1,5 @@ import 'package:auto_size_text/auto_size_text.dart'; +import 'package:diplomaticquarterapp/analytics/google-analytics.dart'; import 'package:diplomaticquarterapp/config/size_config.dart'; import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/pharmacy_module_view_model.dart'; import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; @@ -52,26 +53,36 @@ class ServicesView extends StatelessWidget { return InkWell( onTap: () { if (index == 0) { + locator().hmgServices.logServiceName('live care service'); Navigator.push(context, FadePage(page: LiveCareHome())).then((value) { LiveCareHome.isLiveCareTypeSelected = false; }); } else if (index == 1) { + locator().hmgServices.logServiceName('covid-test drive-thru'); Navigator.push(context, FadePage(page: CovidDrivethruLocation())); } else if (index == 2) { + locator().hmgServices.logServiceName('online payments'); Navigator.push(context, FadePage(page: PaymentService())); } else if (index == 3) { + locator().hmgServices.logServiceName('home health care'); Navigator.push(context, FadePage(page: HomeHealthCarePage())); } else if (index == 4) { + locator().hmgServices.logServiceName('comprehensive medical checkup'); Navigator.push(context, FadePage(page: CMCPage())); } else if (index == 5) { + locator().hmgServices.logServiceName('emergency service'); Navigator.push(context, FadePage(page: ErOptions(isAppbar: true))); } else if (index == 6) { + locator().hmgServices.logServiceName('e-referral service'); Navigator.push(context, FadePage(page: EReferralPage())); } else if (index == 7) { + locator().hmgServices.logServiceName('water consumption'); Navigator.push(context, FadePage(page: H2OPage())); } else if (index == 8) { + locator().hmgServices.logServiceName('find us reach us'); Navigator.push(context, FadePage(page: ContactUsPage())); } else if (index == 9) { + locator().hmgServices.logServiceName('my medical details'); Navigator.push( context, FadePage( @@ -79,6 +90,7 @@ class ServicesView extends StatelessWidget { ), ); } else if (index == 10) { + locator().hmgServices.logServiceName('book appointment'); Navigator.push( context, FadePage( @@ -86,8 +98,10 @@ class ServicesView extends StatelessWidget { ), ); } else if (index == 11) { + locator().hmgServices.logServiceName('al habib pharmacy'); getPharmacyToken(context); } else if (index == 12) { + locator().hmgServices.logServiceName('update insurance'); Navigator.push( context, FadePage( @@ -95,6 +109,7 @@ class ServicesView extends StatelessWidget { ), ); } else if (index == 13) { + locator().hmgServices.logServiceName('my family files'); Navigator.push( context, FadePage( @@ -102,19 +117,23 @@ class ServicesView extends StatelessWidget { ), ); } else if (index == 14) { + locator().hmgServices.logServiceName('my child vaccines'); Navigator.push( context, FadePage(page: ChildInitialPage()), ); } else if (index == 15) { // Navigator.pop(context); + locator().hmgServices.logServiceName('todo list'); LandingPage.shared.switchToDoFromHMGServices(); } else if (index == 16) { + locator().hmgServices.logServiceName('blood donation'); Navigator.push( context, FadePage(page: BloodDonationPage()), ); } else if (index == 17) { + locator().hmgServices.logServiceName('health calculator'); Navigator.push( context, FadePage( @@ -122,6 +141,7 @@ class ServicesView extends StatelessWidget { ), ); } else if (index == 18) { + locator().hmgServices.logServiceName('heath converters'); Navigator.push( context, FadePage( @@ -129,11 +149,13 @@ class ServicesView extends StatelessWidget { ), ); } else if (index == 19) { + locator().hmgServices.logServiceName('smart watches'); Navigator.push( context, FadePage(page: SmartWatchInstructions()), ); } else if (index == 20) { + locator().hmgServices.logServiceName('car parcking service'); Navigator.push( context, FadePage( @@ -141,8 +163,10 @@ class ServicesView extends StatelessWidget { ), ); } else if (index == 21) { + locator().hmgServices.logServiceName('virtual tour'); launch("https://hmgwebservices.com/vt_mobile/html/index.html"); } else if (index == 22) { + locator().hmgServices.logServiceName('latest news'); Navigator.of(context).push(MaterialPageRoute( builder: (BuildContext context) => MyWebView( title: "HMG News", diff --git a/lib/pages/livecare/live_care_payment_page.dart b/lib/pages/livecare/live_care_payment_page.dart index 3980c5a7..54aeffbf 100644 --- a/lib/pages/livecare/live_care_payment_page.dart +++ b/lib/pages/livecare/live_care_payment_page.dart @@ -279,6 +279,7 @@ class _LiveCarePatmentPageState extends State { if (_selected == 0) { AppToast.showErrorToast(message: TranslationBase.of(context).pleaseAcceptTerms); } else { + projectViewModel.analytics.liveCare.livecare_immediate_consultation_TnC(clinic: widget.clinicName); Navigator.pop(context, true); } }, diff --git a/lib/pages/livecare/livecare_type_select.dart b/lib/pages/livecare/livecare_type_select.dart index e07c5615..fb5f1e0f 100644 --- a/lib/pages/livecare/livecare_type_select.dart +++ b/lib/pages/livecare/livecare_type_select.dart @@ -1,10 +1,12 @@ import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/theme/colors.dart'; import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:provider/provider.dart'; class LiveCareTypeSelect extends StatefulWidget { @override @@ -15,6 +17,8 @@ class _LiveCareTypeSelectState extends State { var languageID; AppSharedPreferences sharedPref = AppSharedPreferences(); + ProjectViewModel projectViewModel; + @override void initState() { getLanguageID(); @@ -23,6 +27,7 @@ class _LiveCareTypeSelectState extends State { @override Widget build(BuildContext context) { + projectViewModel = Provider.of(context); return AppScaffold( isShowDecPage: true, isShowAppBar: true, @@ -109,8 +114,10 @@ class _LiveCareTypeSelectState extends State { return InkWell( onTap: () { if (_loginIndex == 1) { + projectViewModel.analytics.liveCare.livecare_immediate_consultation(); Navigator.pop(context, "immediate"); } else { + projectViewModel.analytics.liveCare.livecare_schedule_video_call(); Navigator.pop(context, "schedule"); } }, diff --git a/lib/pages/livecare/widgets/clinic_card.dart b/lib/pages/livecare/widgets/clinic_card.dart index 0f534d98..99fa8610 100644 --- a/lib/pages/livecare/widgets/clinic_card.dart +++ b/lib/pages/livecare/widgets/clinic_card.dart @@ -1,4 +1,6 @@ +import 'package:diplomaticquarterapp/analytics/google-analytics.dart'; import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/locator.dart'; import 'package:diplomaticquarterapp/models/LiveCare/ClinicsServiceTimingsResponse.dart'; import 'package:diplomaticquarterapp/models/LiveCare/LiveCareClinicsListResponse.dart'; import 'package:diplomaticquarterapp/services/livecare_services/livecare_provider.dart'; @@ -21,7 +23,9 @@ class ClinicCard extends StatefulWidget { var languageID; int isOnline; - ClinicCard({this.isSelected, this.languageID, this.isOnline, @required this.patientERGetClinicsList}); + ClinicCard({this.isSelected, this.languageID, this.isOnline, @required this.patientERGetClinicsList}){ + + } @override _State createState() => _State(); @@ -126,7 +130,7 @@ class _State extends State { ), ), InkWell( - onTap: (){ getClinicTimings(widget.patientERGetClinicsList);}, + onTap: () => getClinicTimings(widget.patientERGetClinicsList), child: Container( padding: EdgeInsets.only(left: 8,right: 8,top: 4,bottom: 4), decoration: containerRadius(CustomColors.devider, 100), @@ -159,6 +163,9 @@ class _State extends State { } getClinicTimings(PatientERGetClinicsList patientERGetClinicsList) { + + locator().liveCare.livecare_clinic_schedule(clinic: patientERGetClinicsList.serviceName); + LiveCareService service = new LiveCareService(); GifLoaderDialogUtils.showMyDialog(context); service.getLivecareClinicTiming(patientERGetClinicsList.serviceID, context).then((res) { diff --git a/lib/pages/livecare/widgets/clinic_list.dart b/lib/pages/livecare/widgets/clinic_list.dart index 232f62de..49ef4c1c 100644 --- a/lib/pages/livecare/widgets/clinic_list.dart +++ b/lib/pages/livecare/widgets/clinic_list.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/models/Appointments/AppoimentAllHistoryResultList.dart'; import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart'; import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; @@ -32,6 +33,7 @@ import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:permission_handler/permission_handler.dart'; +import 'package:provider/provider.dart'; import '../live_care_payment_page.dart'; @@ -69,6 +71,8 @@ class _clinic_listState extends State { String liveCareClinicIDs; + ProjectViewModel projectViewModel; + @override void initState() { liveCareClinicsListResponse = new LiveCareClinicsListResponse(); @@ -95,12 +99,15 @@ class _clinic_listState extends State { @override Widget build(BuildContext context) { + projectViewModel = Provider.of(context); return Container( child: currentSelectedLiveCareType == "immediate" ? getLiveCareImmediateClinicList() : getLiveCareScheduleClinicList(), ); } void startLiveCare() { + projectViewModel.analytics.liveCare.livecare_immediate_consultation_clinic(clinic: selectedClinicName); + bool isError = false; LiveCareService service = new LiveCareService(); GifLoaderDialogUtils.showMyDialog(context); @@ -277,6 +284,7 @@ class _clinic_listState extends State { }))).then((value) { print(value); if (value != null) { + projectViewModel.analytics.liveCare.payment_method(appointment_type: 'livecare', clinic: selectedClinicName, payment_method: value, payment_type: 'appointment'); openPayment(value, authUser, double.parse(getERAppointmentFeesList.total), appo); } }); @@ -588,6 +596,8 @@ class _clinic_listState extends State { } void startScheduleLiveCare() { + projectViewModel.analytics.liveCare.livecare_schedule_video_call_clinic(clinic: selectedClinicName); + List doctorsList = []; LiveCareService service = new LiveCareService(); GifLoaderDialogUtils.showMyDialog(context); diff --git a/lib/pages/login/register-info.dart b/lib/pages/login/register-info.dart index 341f6098..c275ec38 100644 --- a/lib/pages/login/register-info.dart +++ b/lib/pages/login/register-info.dart @@ -1,3 +1,4 @@ +import 'package:diplomaticquarterapp/analytics/google-analytics.dart'; import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/locator.dart'; import 'package:diplomaticquarterapp/models/Appointments/toDoCountProviderModel.dart'; @@ -373,13 +374,25 @@ class _RegisterInfo extends State { children: [ Expanded( child: Padding( - padding: EdgeInsets.all(10), child: DefaultButton(TranslationBase.of(context).cancel, () => {Navigator.of(context).pop()}, textColor: Colors.white, color: Color(0xffD02127))), + padding: EdgeInsets.all(10), child: DefaultButton(TranslationBase.of(context).cancel, () { + Navigator.of(context).pop(); + locator().loginRegistration.registration_cancel(step: page == 1 ? 'personal info' : 'patient info'); + }, textColor: Colors.white, color: Color(0xffD02127))), ), Expanded( child: Padding( padding: EdgeInsets.all(10), - child: DefaultButton(page == 1 ? TranslationBase.of(context).next : TranslationBase.of(context).register, () => {nextPage()}, - textColor: Colors.white, color: isValid() == true && page == 2 || page == 1 ? Color(0xff359846) : Colors.grey)), + child: DefaultButton( + page == 1 ? TranslationBase.of(context).next : TranslationBase.of(context).register, + (){ + nextPage(); + page == 1 + ? locator().loginRegistration.registration_personal_info() + : locator().loginRegistration.registration_patient_info(); + + }, + textColor: Colors.white, color: isValid() == true && page == 2 || page == 1 ? Color(0xff359846) : Colors.grey) + ), ), ], ))); diff --git a/lib/pages/login/register.dart b/lib/pages/login/register.dart index ea8ef803..74d7c48e 100644 --- a/lib/pages/login/register.dart +++ b/lib/pages/login/register.dart @@ -1,5 +1,7 @@ +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/locator.dart'; import 'package:diplomaticquarterapp/models/Authentication/check_user_status_reponse.dart'; import 'package:diplomaticquarterapp/models/Authentication/check_user_status_req.dart'; import 'package:diplomaticquarterapp/models/Authentication/checkpatient_for_registration.dart'; @@ -159,12 +161,18 @@ class _Register extends State { children: [ Expanded( child: Padding( - padding: EdgeInsets.all(10), child: DefaultButton(TranslationBase.of(context).cancel, () => {Navigator.of(context).pop()}, textColor: Colors.white, color: Color(0xffD02127))), + padding: EdgeInsets.all(10), child: DefaultButton(TranslationBase.of(context).cancel, () { + Navigator.of(context).pop(); + locator().loginRegistration.registration_cancel(step: 'enter details'); + }, textColor: Colors.white, color: Color(0xffD02127))), ), Expanded( child: Padding( padding: EdgeInsets.all(10), - child: DefaultButton(TranslationBase.of(context).next, () => {startRegistration()}, textColor: Colors.white, color: isButtonDisabled == true ? Colors.grey : Color(0xff359846))), + child: DefaultButton(TranslationBase.of(context).next, (){ + startRegistration(); + locator().loginRegistration.registration_enter_details(); + }, textColor: Colors.white, color: isButtonDisabled == true ? Colors.grey : Color(0xff359846))), ), ], ))); diff --git a/lib/pages/login/welcome.dart b/lib/pages/login/welcome.dart index 8688fec3..ea6d18cf 100644 --- a/lib/pages/login/welcome.dart +++ b/lib/pages/login/welcome.dart @@ -1,3 +1,5 @@ +import 'package:diplomaticquarterapp/analytics/google-analytics.dart'; +import 'package:diplomaticquarterapp/locator.dart'; import 'package:diplomaticquarterapp/pages/login/login-type.dart'; import 'package:diplomaticquarterapp/pages/login/register.dart'; import 'package:diplomaticquarterapp/pages/login/register_new.dart'; @@ -79,6 +81,7 @@ class _WelcomeLogin extends State { child: DefaultButton( TranslationBase.of(context).no, () => { + locator().loginRegistration.visited_alhabib_group(false), Navigator.of(context).push(FadePage(page: RegisterNew())), }, color: CustomColors.accentColor, @@ -90,6 +93,7 @@ class _WelcomeLogin extends State { child: DefaultButton( TranslationBase.of(context).yes, () => { + locator().loginRegistration.visited_alhabib_group(true), Navigator.of(context).push(FadePage(page: LoginType())), }, color: CustomColors.green, diff --git a/lib/pages/medical/balance/advance_payment_page.dart b/lib/pages/medical/balance/advance_payment_page.dart index 2fdb93ce..5f397548 100644 --- a/lib/pages/medical/balance/advance_payment_page.dart +++ b/lib/pages/medical/balance/advance_payment_page.dart @@ -4,6 +4,7 @@ import 'package:diplomaticquarterapp/core/model/ImagesInfo.dart'; import 'package:diplomaticquarterapp/core/model/hospitals/hospitals_model.dart'; import 'package:diplomaticquarterapp/core/model/my_balance/patient_info.dart'; import 'package:diplomaticquarterapp/core/viewModels/medical/my_balance_view_model.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; import 'package:diplomaticquarterapp/models/FamilyFiles/GetAllSharedRecordByStatusResponse.dart'; import 'package:diplomaticquarterapp/pages/ToDoList/payment_method_select.dart'; @@ -20,6 +21,7 @@ import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import '../../../core/model/my_balance/AdvanceModel.dart'; import 'confirm_payment_page.dart'; @@ -49,6 +51,8 @@ class _AdvancePaymentPageState extends State { List imagesInfo = List(); + ProjectViewModel projectViewModel; + @override void initState() { super.initState(); @@ -60,6 +64,7 @@ class _AdvancePaymentPageState extends State { @override Widget build(BuildContext context) { + projectViewModel = Provider.of(context); return BaseView( onModelReady: (model) { model.getHospitals(); @@ -309,6 +314,9 @@ class _AdvancePaymentPageState extends State { advanceModel.mobileNumber = mobileNum; advanceModel.patientName = patientName; GifLoaderDialogUtils.showMyDialog(context); + + + projectViewModel.analytics.advancePayments.wallet_payment_details(); model.getPatientInfoByPatientIDAndMobileNumber(advanceModel).then((value) { GifLoaderDialogUtils.hideDialog(context); if (model.state != ViewState.Error && model.state != ViewState.ErrorLocal) { @@ -324,6 +332,8 @@ class _AdvancePaymentPageState extends State { ), ).then( (value) { + projectViewModel.analytics.advancePayments.payment_method(method: value.toString().toLowerCase(), type: 'wallet'); + Navigator.push( context, FadePage( diff --git a/lib/pages/medical/balance/confirm_payment_page.dart b/lib/pages/medical/balance/confirm_payment_page.dart index 2d79219d..09bd4ade 100644 --- a/lib/pages/medical/balance/confirm_payment_page.dart +++ b/lib/pages/medical/balance/confirm_payment_page.dart @@ -3,6 +3,7 @@ import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; import 'package:diplomaticquarterapp/core/model/my_balance/AdvanceModel.dart'; import 'package:diplomaticquarterapp/core/model/my_balance/patient_info_and_mobile_number.dart'; import 'package:diplomaticquarterapp/core/viewModels/medical/my_balance_view_model.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/models/Appointments/AppoimentAllHistoryResultList.dart'; import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; @@ -22,6 +23,7 @@ import 'package:diplomaticquarterapp/widgets/otp/sms-popup.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:provider/provider.dart'; import 'new_text_Field.dart'; @@ -47,6 +49,7 @@ class _ConfirmPaymentPageState extends State { AppSharedPreferences sharedPref = AppSharedPreferences(); String transID = ""; + ProjectViewModel projectViewModel; void submit(MyBalanceViewModel model, code) { final activationCode = code; @@ -59,6 +62,8 @@ class _ConfirmPaymentPageState extends State { AppoitmentAllHistoryResultList appo = new AppoitmentAllHistoryResultList(); appo.projectID = widget.patientInfoAndMobileNumber.projectID; + + projectViewModel.analytics.advancePayments.payment_otp_confirmation(method: widget.selectedPaymentMethod.toLowerCase(), type: 'wallet'); openPayment(widget.selectedPaymentMethod, widget.authenticatedUser, double.parse(widget.advanceModel.amount), null); }); @@ -80,6 +85,7 @@ class _ConfirmPaymentPageState extends State { ).displayDialog(context); } + projectViewModel = Provider.of(context); return BaseView( builder: (_, model, w) => AppScaffold( isShowAppBar: true, @@ -196,6 +202,8 @@ class _ConfirmPaymentPageState extends State { child: DefaultButton( TranslationBase.of(context).confirm.toUpperCase(), () { + projectViewModel.analytics.advancePayments.payment_confirm(method: widget.selectedPaymentMethod.toLowerCase(), type: 'wallet'); + GifLoaderDialogUtils.showMyDialog(context); model .sendActivationCodeForAdvancePayment( diff --git a/lib/pages/medical/balance/my_balance_page.dart b/lib/pages/medical/balance/my_balance_page.dart index e4ff9581..70b81b02 100644 --- a/lib/pages/medical/balance/my_balance_page.dart +++ b/lib/pages/medical/balance/my_balance_page.dart @@ -1,6 +1,7 @@ import 'package:diplomaticquarterapp/core/model/ImagesInfo.dart'; import 'package:diplomaticquarterapp/core/model/my_balance/patient_advance_balance_amount.dart'; import 'package:diplomaticquarterapp/core/viewModels/medical/my_balance_view_model.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; import 'package:diplomaticquarterapp/theme/colors.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; @@ -11,14 +12,19 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:provider/provider.dart'; import 'advance_payment_page.dart'; class MyBalancePage extends StatelessWidget { List imagesInfo = List(); + ProjectViewModel projectViewModel; + @override Widget build(BuildContext context) { + projectViewModel = Provider.of(context); + imagesInfo.add(ImagesInfo( imageEn: 'https://hmgwebservices.com/Images/MobileApp/images-info-home/my-balance/en/0.png', imageAr: 'https://hmgwebservices.com/Images/MobileApp/images-info-home/my-balance/ar/0.png')); return BaseView( @@ -172,6 +178,7 @@ class MyBalancePage extends StatelessWidget { DefaultButton( TranslationBase.of(context).createAdvancedPayment, () { + projectViewModel.analytics.advancePayments.wallet_recharge(service_type: 'alhabib wallet'); Navigator.push(context, FadePage(page: AdvancePaymentPage())); }, ).insideContainer, diff --git a/lib/pages/paymentService/payment_service.dart b/lib/pages/paymentService/payment_service.dart index 13a97866..83dc69bc 100644 --- a/lib/pages/paymentService/payment_service.dart +++ b/lib/pages/paymentService/payment_service.dart @@ -59,6 +59,7 @@ class PaymentService extends StatelessWidget { medical.add( InkWell( onTap: () { + projectViewModel.analytics.advancePayments.payment_services(service_type: 'payment service'); Navigator.push(context, FadePage(page: AdvancePaymentPage())); }, child: MedicalProfileItem( @@ -75,6 +76,7 @@ class PaymentService extends StatelessWidget { medical.add( InkWell( onTap: () { + projectViewModel.analytics.advancePayments.payment_services(service_type: 'online check-in appointment'); navigateToToDoPage(context); }, child: MedicalProfileItem( @@ -91,6 +93,7 @@ class PaymentService extends StatelessWidget { medical.add( InkWell( onTap: () { + projectViewModel.analytics.advancePayments.payment_services(service_type: 'alhabib wallet'); Navigator.push(context, FadePage(page: MyBalancePage())); }, child: MedicalProfileItem( diff --git a/lib/widgets/drawer/app_drawer_widget.dart b/lib/widgets/drawer/app_drawer_widget.dart index b7e00d54..e8572670 100644 --- a/lib/widgets/drawer/app_drawer_widget.dart +++ b/lib/widgets/drawer/app_drawer_widget.dart @@ -1,3 +1,4 @@ +import 'package:diplomaticquarterapp/analytics/google-analytics.dart'; import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/core/service/AuthenticatedUserObject.dart'; @@ -165,8 +166,10 @@ class _AppDrawerState extends State { sharedPref.remove(CLINICS_LIST); if (projectProvider.isArabic) { projectProvider.changeLanguage('en'); + locator().hamburgerMenu.logMenuItemClick('change language to english'); } else { projectProvider.changeLanguage('ar'); + locator().hamburgerMenu.logMenuItemClick('change language to arabic'); } var themeNotifier = Provider.of(context, listen: false); themeNotifier.setTheme(defaultTheme(fontName: projectProvider.isArabic ? 'Cairo' : 'Poppins')); @@ -191,6 +194,8 @@ class _AppDrawerState extends State { Navigator.of(context).pushNamed( MY_FAMILIY, ); + + locator().hamburgerMenu.logMenuItemClick('my family'); }, ) : SizedBox(), @@ -317,8 +322,10 @@ class _AppDrawerState extends State { sharedPref.setBool(IS_ROBOT_INIT, null); if (projectProvider.isArabic) { projectProvider.changeLanguage('en'); + locator().hamburgerMenu.logMenuItemClick('change language to english'); } else { projectProvider.changeLanguage('ar'); + locator().hamburgerMenu.logMenuItemClick('change language to arabic'); } }, ), @@ -363,6 +370,7 @@ class _AppDrawerState extends State { //NotificationsPage // Navigator.of(context).pop(); if (!projectProvider.isLoginChild) Navigator.push(context, FadePage(page: NotificationsPage())); + locator().hamburgerMenu.logMenuItemClick('notifications'); }, ), if (projectProvider.havePrivilege(3)) @@ -373,11 +381,13 @@ class _AppDrawerState extends State { Navigator.of(context).pushNamed( SETTINGS, ); + locator().hamburgerMenu.logMenuItemClick('app settings'); }, ), InkWell( child: DrawerItem(TranslationBase.of(context).rateApp, Icons.star, bottomLine: false, letterSpacing: -0.84, fontSize: 14, projectProvider: projectProvider), onTap: () { + locator().hamburgerMenu.logMenuItemClick('rate our app'); openAppReviewDialog(); // if (Platform.isIOS) { // launch("https://apps.apple.com/sa/app/dr-suliaman-alhabib/id733503978"); @@ -390,6 +400,7 @@ class _AppDrawerState extends State { child: DrawerItem(TranslationBase.of(context).logout, SvgPicture.asset("assets/images/new/logout.svg"), isImageIcon: true, bottomLine: false, letterSpacing: -0.84, fontSize: 14, projectProvider: projectProvider), onTap: () { + locator().hamburgerMenu.logMenuItemClick('logout'); logout(); }, ) @@ -420,7 +431,17 @@ class _AppDrawerState extends State { mHeight(12), InkWell( onTap: () { - Navigator.push(context, FadePage(page: CallPage())); + // Navigator.push(context, FadePage(page: CallPage())); + locator().hamburgerMenu.logMenuItemClick('cloud solution logo tap'); + String patientID = '2001273'; + GifLoaderDialogUtils.showMyDialog(context); + projectProvider + .platformBridge() + .connectHMGInternetWifi(patientID) + .then((value) => {GifLoaderDialogUtils.hideDialog(context)}) + .catchError((err) { + print(err.toString()); + }); }, child: Row( crossAxisAlignment: CrossAxisAlignment.center, @@ -504,6 +525,8 @@ class _AppDrawerState extends State { login() async { var data = await sharedPref.getObject(IMEI_USER_DATA); sharedPref.remove(REGISTER_DATA_FOR_LOGIIN); + + locator().loginRegistration.login_register_initiate(); if (data != null) { Navigator.of(context).pushNamed(CONFIRM_LOGIN); } else { @@ -544,6 +567,7 @@ class _AppDrawerState extends State { // GifLoaderDialogUtils.hideDialog(context); // Navigator.of(context).pop(); loginAfter(value, context, user is AuthenticatedUser); + locator().hamburgerMenu.logMenuItemClick('switch to my family account'); }).catchError((err) { GifLoaderDialogUtils.hideDialog(context); print(err); diff --git a/lib/widgets/nfc/nfc_reader_sheet.dart b/lib/widgets/nfc/nfc_reader_sheet.dart index 00be462a..43f1f05e 100644 --- a/lib/widgets/nfc/nfc_reader_sheet.dart +++ b/lib/widgets/nfc/nfc_reader_sheet.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_nfc_kit/flutter_nfc_kit.dart'; -void showNfcReader(BuildContext context, {Function onNcfScan}) { +void showNfcReader(BuildContext context, {Function onNcfScan, VoidCallback onCancel}) { showModalBottomSheet( context: context, enableDrag: false, @@ -13,14 +13,16 @@ void showNfcReader(BuildContext context, {Function onNcfScan}) { builder: (context) { return NfcLayout( onNcfScan: onNcfScan, + onCancel: onCancel, ); }); } class NfcLayout extends StatefulWidget { Function onNcfScan; + VoidCallback onCancel; - NfcLayout({this.onNcfScan}); + NfcLayout({this.onNcfScan, this.onCancel}); @override _NfcLayoutState createState() => _NfcLayoutState(); @@ -103,6 +105,7 @@ class _NfcLayoutState extends State { child: RaisedButton( onPressed: () { // _stream?.cancel(); + widget.onCancel(); Navigator.pop(context); }, elevation: 0, From 81a3d1ce8716d0f619c200e15e07a7c79e9a7c26 Mon Sep 17 00:00:00 2001 From: Zohaib Iqbal Kambrani <> Date: Mon, 31 Jan 2022 15:36:47 +0300 Subject: [PATCH 3/7] no message --- lib/pages/BookAppointment/QRCode.dart.orig | 355 ++++++++++++++++++ .../SearchResults_BACKUP_53339.dart | 74 ++++ .../SearchResults_BASE_53339.dart | 66 ++++ .../SearchResults_LOCAL_53339.dart | 74 ++++ .../SearchResults_REMOTE_53339.dart | 66 ++++ 5 files changed, 635 insertions(+) create mode 100644 lib/pages/BookAppointment/QRCode.dart.orig create mode 100644 lib/pages/BookAppointment/SearchResults_BACKUP_53339.dart create mode 100644 lib/pages/BookAppointment/SearchResults_BASE_53339.dart create mode 100644 lib/pages/BookAppointment/SearchResults_LOCAL_53339.dart create mode 100644 lib/pages/BookAppointment/SearchResults_REMOTE_53339.dart diff --git a/lib/pages/BookAppointment/QRCode.dart.orig b/lib/pages/BookAppointment/QRCode.dart.orig new file mode 100644 index 00000000..83249dee --- /dev/null +++ b/lib/pages/BookAppointment/QRCode.dart.orig @@ -0,0 +1,355 @@ +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/locator.dart'; +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/routes.dart'; +import 'package:diplomaticquarterapp/services/appointment_services/GetDoctorsList.dart'; +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/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart'; +import 'package:diplomaticquarterapp/widgets/dialogs/confirm_dialog.dart'; +import 'package:diplomaticquarterapp/widgets/nfc/nfc_reader_sheet.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_nfc_kit/flutter_nfc_kit.dart'; + +class QRCode extends StatefulWidget { + PatientShareResponse patientShareResponse; + String appoQR; + AuthenticatedUser authUser; + AppSharedPreferences sharedPref = AppSharedPreferences(); + + QRCode({@required this.patientShareResponse, @required this.appoQR}); + + @override + _QRCodeState createState() => _QRCodeState(); +} + +class _QRCodeState extends State { + Uint8List _bytes; + bool _supportsNFC = false; + BuildContext _context; + + @override + void initState() { + // TODO: implement initState + + _bytes = base64.decode(widget.appoQR.split(',').last); + widget.authUser = new AuthenticatedUser(); + + WidgetsBinding.instance.addPostFrameCallback((timeStamp) { + FlutterNfcKit.nfcAvailability.then((value) { + setState(() { + _supportsNFC = (value == NFCAvailability.available); + }); + }); + }); + + super.initState(); + } + + @override + Widget build(BuildContext context) { + _context = context; + return AppScaffold( + appBarTitle: TranslationBase.of(context).attendRegisterCode, + isShowAppBar: true, + showNewAppBar: true, + showNewAppBarTitle: true, + body: SingleChildScrollView( + child: Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: [ + Container( + width: double.infinity, + height: MediaQuery.of(context).size.width / 3, + child: Row( + children: [ +<<<<<<< HEAD + _supportsNFC + ? Expanded( + flex: 1, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + InkWell( + child: Container( + margin: EdgeInsets.only(top: 30.0), + alignment: Alignment.center, + padding: EdgeInsets.all(8), + decoration: BoxDecoration( + border: Border.all(color: Colors.black), + borderRadius: BorderRadius.circular(10), + ), + child: Image.asset("assets/images/nfc/ic_nfc.png"), + ), + onTap: () { + locator().analytics.todoList.to_do_list_nfc(); + showNfcReader(context, onNcfScan: (String nfcId) { + Future.delayed(const Duration(milliseconds: 100), () { + sendNfcCheckInRequest(nfcId); + }); + }, onCancel: (){ + locator().analytics.todoList.to_do_list_nfc_cancel(); + }); + }, + ), + ], +======= + // _supportsNFC + // ? + Expanded( + flex: 1, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + InkWell( + child: Container( + margin: EdgeInsets.only(top: 30.0), + alignment: Alignment.center, + padding: EdgeInsets.all(8), + decoration: BoxDecoration( + border: Border.all(color: Colors.black), + borderRadius: BorderRadius.circular(10), + ), + child: Image.asset("assets/images/nfc/ic_nfc.png"), +>>>>>>> 259e27d4a7e8d7ddf751de88de36fe901df0e2da + ), + onTap: () { + showNfcReader(context, onNcfScan: (String nfcId) { + Future.delayed(const Duration(milliseconds: 100), () { + sendNfcCheckInRequest(nfcId); + }); + }); + }, + ), + ], + ), + ), + // : Container(), + Expanded( + flex: 1, + child: Container( + margin: EdgeInsets.only(top: 30.0), + alignment: Alignment.center, + child: Image.memory( + _bytes, + ), + ), + ), + ], + ), + ), + Container( + margin: EdgeInsets.only(top: 20.0, left: 20.0, right: 20.0), + child: Divider( + color: Colors.red[700], + thickness: 0.8, + ), + ), + Container( + child: Row( + children: [ + Container( + margin: EdgeInsets.only(top: 10.0, left: 40.0, bottom: 10.0), + child: Image.asset("assets/images/new-design/device_icon.png", width: MediaQuery.of(context).size.width / 3.4, height: MediaQuery.of(context).size.width / 3.4), + ), + Expanded( + child: Container( + width: double.infinity, + margin: EdgeInsets.only(top: 15.0, bottom: 10.0, left: 20.0, right: 20.0), + child: Text(TranslationBase.of(context).scanQRHospital, style: TextStyle(color: Colors.red[700], fontSize: 18.0, fontWeight: FontWeight.bold)), + ), + ), + ], + ), + ), + Container( + margin: EdgeInsets.only(top: 10.0, left: 20.0, right: 20.0), + child: Divider( + color: Colors.red[700], + thickness: 0.8, + ), + ), + Container( + margin: EdgeInsets.only(top: 15.0, bottom: 10.0, left: 20.0, right: 20.0), + child: Text(TranslationBase.of(context).appoInfo, style: TextStyle(fontSize: 18.0, color: Colors.grey[700], fontWeight: FontWeight.bold)), + ), + Container( + margin: EdgeInsets.only(left: 20.0, bottom: 20.0, right: 20.0), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: Colors.grey[200], + boxShadow: [ + BoxShadow(color: Colors.grey, spreadRadius: 2), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + margin: EdgeInsets.only(top: 15.0, bottom: 10.0, left: 20.0, right: 20.0), + child: Text(widget.patientShareResponse.doctorNameObj, style: TextStyle(fontSize: 18.0, color: Colors.grey[700], fontWeight: FontWeight.bold)), + ), + if (getDoctorSpeciality(widget.patientShareResponse.doctorSpeciality) != "null\n") + Container( + margin: EdgeInsets.only(bottom: 10.0, left: 20.0, right: 20.0), + child: Text(getDoctorSpeciality(widget.patientShareResponse.doctorSpeciality), style: TextStyle(fontSize: 18.0, color: Colors.grey[700])), + ), + Container( + margin: EdgeInsets.only(top: 0.0, bottom: 10.0, left: 20.0, right: 20.0), + child: Text(widget.patientShareResponse.projectName, style: TextStyle(fontSize: 18.0, color: Colors.grey[700])), + ), + Container( + margin: EdgeInsets.only(top: 0.0, bottom: 10.0, left: 20.0, right: 20.0), + child: Text(getDate(widget.patientShareResponse.appointmentDate), style: TextStyle(fontSize: 18.0, color: Colors.grey[700])), + ), + ], + ), + ), + Container( + margin: EdgeInsets.only(left: 20.0, right: 20.0, top: 15.0), + alignment: Alignment.bottomCenter, + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + DefaultButton(TranslationBase.of(context).sendEmail.toUpperCase(), () => {sendEmail()}) + ], + ), + ), + ], + ), + ), + ), + ); + } + + sendEmail() async { + DoctorsListService service = new DoctorsListService(); + + if (await widget.sharedPref.getObject(USER_PROFILE) != null) { + var data = AuthenticatedUser.fromJson(await widget.sharedPref.getObject(USER_PROFILE)); + setState(() { + widget.authUser = data; + }); + } + + ConfirmDialog dialog = new ConfirmDialog( + context: context, + confirmMessage: "Send a copy of this QR to the email " + widget.authUser.emailAddress + "?", + okText: TranslationBase.of(context).confirm, + cancelText: TranslationBase.of(context).cancel_nocaps, + okFunction: () { + GifLoaderDialogUtils.showMyDialog(context); + service + .sendAppointmentQREmail(widget.authUser.emailAddress, widget.patientShareResponse.appointmentDate, widget.patientShareResponse.appointmentNo.toString(), + widget.patientShareResponse.doctorNameObj, widget.patientShareResponse.projectName, widget.appoQR, getDoctorSpeciality(widget.patientShareResponse.doctorSpeciality), context) + .then((res) { + GifLoaderDialogUtils.hideDialog(context); + ConfirmDialog.closeAlertDialog(context); + }).catchError((err) { + ConfirmDialog.closeAlertDialog(context); + GifLoaderDialogUtils.hideDialog(context); + AppToast.showErrorToast(message: err); + print(err); + }); + }, + cancelFunction: () => {}); + dialog.showAlertDialog(context); + } + + Future navigateToHome(context) async { + Navigator.of(context).pushNamed(HOME); + } + + getPatientShare(context, String appointmentNo, int clinicID, int projectID, DoctorList docObject) {} + + String getDate(String appoDate) { + var appoDateFormatted = ""; + + var dateObj = DateUtil.convertStringToDate(appoDate); + + setState(() { + appoDateFormatted = DateUtil.getWeekDay(dateObj.weekday) + + ", " + + dateObj.day.toString() + + " " + + DateUtil.getMonth(dateObj.month) + + " " + + dateObj.year.toString() + + ", " + + dateObj.hour.toString() + + ":" + + dateObj.minute.toString() + + ":00"; + }); + + return appoDateFormatted; + } + + String getDoctorSpeciality(List docSpecial) { + String docSpeciality = ""; + if (docSpecial != null && docSpecial.length != 0) { + docSpecial.forEach((v) { + docSpeciality = docSpeciality + v + "\n"; + }); + } + return docSpeciality; + } + + sendNfcCheckInRequest(String nfcId) { + GifLoaderDialogUtils.showMyDialog(context); + + DoctorsListService service = new DoctorsListService(); + + service.sendCheckinNfcRequest(widget.patientShareResponse.appointmentNo, nfcId, widget.patientShareResponse.projectID, context).then((res) { + print(res); + + GifLoaderDialogUtils.hideDialog(context); + _showMyDialog(res["SuccessMsg"], this.context); + }).catchError((err) { + GifLoaderDialogUtils.hideDialog(context); + print(err); + _showMyDialog(err, this.context); + }); + } + + Future _showMyDialog(String message, BuildContext context) async { + return showDialog( + context: context, + barrierDismissible: true, // user must tap button! + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Alert'), + content: SingleChildScrollView( + child: ListBody( + children: [ + Text(message), + ], + ), + ), + actions: [ + TextButton( + child: const Text('OK'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }, + ); + } +} diff --git a/lib/pages/BookAppointment/SearchResults_BACKUP_53339.dart b/lib/pages/BookAppointment/SearchResults_BACKUP_53339.dart new file mode 100644 index 00000000..ba35a0f3 --- /dev/null +++ b/lib/pages/BookAppointment/SearchResults_BACKUP_53339.dart @@ -0,0 +1,74 @@ +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart'; +import 'package:diplomaticquarterapp/pages/BookAppointment/widgets/DoctorView.dart'; +import 'package:diplomaticquarterapp/theme/colors.dart'; +// import 'package:diplomaticquarterapp/services/robo_search/event_provider.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_expandable_notifier.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class SearchResults extends StatefulWidget { + List doctorsList = []; + List patientDoctorAppointmentListHospital; + bool isLiveCareAppointment; + + SearchResults({@required this.doctorsList, this.patientDoctorAppointmentListHospital, @required this.isLiveCareAppointment}); + + @override + _SearchResultsState createState() => _SearchResultsState(); +} + +class _SearchResultsState extends State { + // var event = RobotProvider(); + List tempList = []; + ProjectViewModel projectViewModel; + + @override + Widget build(BuildContext context) { + projectViewModel = Provider.of(context); + return AppScaffold( + appBarTitle: TranslationBase.of(context).bookAppo, + isShowDecPage: false, + isShowAppBar: true, + showNewAppBarTitle: true, + showNewAppBar: true, + backgroundColor: CustomColors.appBackgroudGrey2Color, + body: ListView.separated( + physics: BouncingScrollPhysics(), + separatorBuilder: (context, index) { + return Container( + height: 12, + margin: EdgeInsets.only(left: 21, right: 21), + // color: Color(0xffD9D9D9), + ); + }, + itemBuilder: (context, index) { + return AppExpandableNotifier( + title: (widget.patientDoctorAppointmentListHospital[index].distanceInKMs != "0") ? widget.patientDoctorAppointmentListHospital[index].filterName + " - " + widget.patientDoctorAppointmentListHospital[index].distanceInKMs + " " + TranslationBase.of(context).km : widget.patientDoctorAppointmentListHospital[index].filterName, + isTitleSingleLine: false, + bodyWidget: ListView.separated( + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + padding: EdgeInsets.only(bottom: 10, top: 10, left: 21, right: 21), + itemBuilder: (context, _index) { + //widget.patientDoctorAppointmentListHospital[index].patientDoctorAppointmentList[_index].speciality = null; + final doctor = widget.patientDoctorAppointmentListHospital[index].patientDoctorAppointmentList[_index]; + return DoctorView( + doctor: doctor, + isLiveCareAppointment: widget.isLiveCareAppointment, + onTap: (){ + projectViewModel.analytics.appointment.book_appointment_select_doctor(appointment_type: 'regular', doctor: doctor); + } + ); + }, + separatorBuilder: (context, index) => SizedBox(height: 14), + itemCount: widget.patientDoctorAppointmentListHospital[index].patientDoctorAppointmentList.length), + ); + }, + itemCount: widget.patientDoctorAppointmentListHospital.length, + ), + ); + } +} diff --git a/lib/pages/BookAppointment/SearchResults_BASE_53339.dart b/lib/pages/BookAppointment/SearchResults_BASE_53339.dart new file mode 100644 index 00000000..0a654e22 --- /dev/null +++ b/lib/pages/BookAppointment/SearchResults_BASE_53339.dart @@ -0,0 +1,66 @@ +import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart'; +import 'package:diplomaticquarterapp/pages/BookAppointment/widgets/DoctorView.dart'; +import 'package:diplomaticquarterapp/theme/colors.dart'; +// import 'package:diplomaticquarterapp/services/robo_search/event_provider.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_expandable_notifier.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:flutter/material.dart'; + +class SearchResults extends StatefulWidget { + List doctorsList = []; + List patientDoctorAppointmentListHospital; + bool isLiveCareAppointment; + + SearchResults({@required this.doctorsList, this.patientDoctorAppointmentListHospital, @required this.isLiveCareAppointment}); + + @override + _SearchResultsState createState() => _SearchResultsState(); +} + +class _SearchResultsState extends State { + // var event = RobotProvider(); + List tempList = []; + + @override + Widget build(BuildContext context) { + return AppScaffold( + appBarTitle: TranslationBase.of(context).bookAppo, + isShowDecPage: false, + isShowAppBar: true, + showNewAppBarTitle: true, + showNewAppBar: true, + backgroundColor: CustomColors.appBackgroudGrey2Color, + body: ListView.separated( + physics: BouncingScrollPhysics(), + separatorBuilder: (context, index) { + return Container( + height: 12, + margin: EdgeInsets.only(left: 21, right: 21), + // color: Color(0xffD9D9D9), + ); + }, + itemBuilder: (context, index) { + return AppExpandableNotifier( + title: (widget.patientDoctorAppointmentListHospital[index].distanceInKMs != "0") ? widget.patientDoctorAppointmentListHospital[index].filterName + " - " + widget.patientDoctorAppointmentListHospital[index].distanceInKMs + " " + TranslationBase.of(context).km : widget.patientDoctorAppointmentListHospital[index].filterName, + isTitleSingleLine: false, + bodyWidget: ListView.separated( + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + padding: EdgeInsets.only(bottom: 10, top: 10, left: 21, right: 21), + itemBuilder: (context, _index) { + //widget.patientDoctorAppointmentListHospital[index].patientDoctorAppointmentList[_index].speciality = null; + return DoctorView( + doctor: widget.patientDoctorAppointmentListHospital[index].patientDoctorAppointmentList[_index], + isLiveCareAppointment: widget.isLiveCareAppointment, + ); + }, + separatorBuilder: (context, index) => SizedBox(height: 14), + itemCount: widget.patientDoctorAppointmentListHospital[index].patientDoctorAppointmentList.length), + ); + }, + itemCount: widget.patientDoctorAppointmentListHospital.length, + ), + ); + } +} diff --git a/lib/pages/BookAppointment/SearchResults_LOCAL_53339.dart b/lib/pages/BookAppointment/SearchResults_LOCAL_53339.dart new file mode 100644 index 00000000..ba35a0f3 --- /dev/null +++ b/lib/pages/BookAppointment/SearchResults_LOCAL_53339.dart @@ -0,0 +1,74 @@ +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart'; +import 'package:diplomaticquarterapp/pages/BookAppointment/widgets/DoctorView.dart'; +import 'package:diplomaticquarterapp/theme/colors.dart'; +// import 'package:diplomaticquarterapp/services/robo_search/event_provider.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_expandable_notifier.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class SearchResults extends StatefulWidget { + List doctorsList = []; + List patientDoctorAppointmentListHospital; + bool isLiveCareAppointment; + + SearchResults({@required this.doctorsList, this.patientDoctorAppointmentListHospital, @required this.isLiveCareAppointment}); + + @override + _SearchResultsState createState() => _SearchResultsState(); +} + +class _SearchResultsState extends State { + // var event = RobotProvider(); + List tempList = []; + ProjectViewModel projectViewModel; + + @override + Widget build(BuildContext context) { + projectViewModel = Provider.of(context); + return AppScaffold( + appBarTitle: TranslationBase.of(context).bookAppo, + isShowDecPage: false, + isShowAppBar: true, + showNewAppBarTitle: true, + showNewAppBar: true, + backgroundColor: CustomColors.appBackgroudGrey2Color, + body: ListView.separated( + physics: BouncingScrollPhysics(), + separatorBuilder: (context, index) { + return Container( + height: 12, + margin: EdgeInsets.only(left: 21, right: 21), + // color: Color(0xffD9D9D9), + ); + }, + itemBuilder: (context, index) { + return AppExpandableNotifier( + title: (widget.patientDoctorAppointmentListHospital[index].distanceInKMs != "0") ? widget.patientDoctorAppointmentListHospital[index].filterName + " - " + widget.patientDoctorAppointmentListHospital[index].distanceInKMs + " " + TranslationBase.of(context).km : widget.patientDoctorAppointmentListHospital[index].filterName, + isTitleSingleLine: false, + bodyWidget: ListView.separated( + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + padding: EdgeInsets.only(bottom: 10, top: 10, left: 21, right: 21), + itemBuilder: (context, _index) { + //widget.patientDoctorAppointmentListHospital[index].patientDoctorAppointmentList[_index].speciality = null; + final doctor = widget.patientDoctorAppointmentListHospital[index].patientDoctorAppointmentList[_index]; + return DoctorView( + doctor: doctor, + isLiveCareAppointment: widget.isLiveCareAppointment, + onTap: (){ + projectViewModel.analytics.appointment.book_appointment_select_doctor(appointment_type: 'regular', doctor: doctor); + } + ); + }, + separatorBuilder: (context, index) => SizedBox(height: 14), + itemCount: widget.patientDoctorAppointmentListHospital[index].patientDoctorAppointmentList.length), + ); + }, + itemCount: widget.patientDoctorAppointmentListHospital.length, + ), + ); + } +} diff --git a/lib/pages/BookAppointment/SearchResults_REMOTE_53339.dart b/lib/pages/BookAppointment/SearchResults_REMOTE_53339.dart new file mode 100644 index 00000000..e4744c4e --- /dev/null +++ b/lib/pages/BookAppointment/SearchResults_REMOTE_53339.dart @@ -0,0 +1,66 @@ +import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart'; +import 'package:diplomaticquarterapp/pages/BookAppointment/widgets/DoctorView.dart'; +import 'package:diplomaticquarterapp/theme/colors.dart'; +// import 'package:diplomaticquarterapp/services/robo_search/event_provider.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_expandable_notifier.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:flutter/material.dart'; + +class SearchResults extends StatefulWidget { + List doctorsList = []; + List patientDoctorAppointmentListHospital; + bool isLiveCareAppointment; + + SearchResults({@required this.doctorsList, this.patientDoctorAppointmentListHospital, @required this.isLiveCareAppointment}); + + @override + _SearchResultsState createState() => _SearchResultsState(); +} + +class _SearchResultsState extends State { + // var event = RobotProvider(); + List tempList = []; + + @override + Widget build(BuildContext context) { + return AppScaffold( + appBarTitle: TranslationBase.of(context).bookAppo, + isShowDecPage: false, + isShowAppBar: true, + showNewAppBarTitle: true, + showNewAppBar: true, + backgroundColor: CustomColors.appBackgroudGrey2Color, + body: ListView.separated( + physics: BouncingScrollPhysics(), + separatorBuilder: (context, index) { + return Container( + height: 12, + margin: EdgeInsets.only(left: 21, right: 21), + // color: Color(0xffD9D9D9), + ); + }, + itemBuilder: (context, index) { + return AppExpandableNotifier( + title: (widget.patientDoctorAppointmentListHospital[index].distanceInKMs != "0") ? widget.patientDoctorAppointmentListHospital[index].filterName + " - " + widget.patientDoctorAppointmentListHospital[index].distanceInKMs + " " + TranslationBase.of(context).km : widget.patientDoctorAppointmentListHospital[index].filterName, + isTitleSingleLine: false, + bodyWidget: ListView.separated( + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + padding: EdgeInsets.only(bottom: 10, top: 10, left: 21, right: 21), + itemBuilder: (context, _index) { + //widget.patientDoctorAppointmentListHospital[index].patientDoctorAppointmentList[_index].speciality = null; + return DoctorView( + doctor: widget.patientDoctorAppointmentListHospital[index].patientDoctorAppointmentList[_index], + isLiveCareAppointment: widget.isLiveCareAppointment ?? widget.patientDoctorAppointmentListHospital[index].patientDoctorAppointmentList[_index].isLiveCare, + ); + }, + separatorBuilder: (context, index) => SizedBox(height: 14), + itemCount: widget.patientDoctorAppointmentListHospital[index].patientDoctorAppointmentList.length), + ); + }, + itemCount: widget.patientDoctorAppointmentListHospital.length, + ), + ); + } +} From a2efbf64940fbb8a1f53e2821b0f1f5f64d6546c Mon Sep 17 00:00:00 2001 From: Zohaib Iqbal Kambrani <> Date: Mon, 31 Jan 2022 15:38:05 +0300 Subject: [PATCH 4/7] no message --- lib/pages/ToDoList/ToDo.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pages/ToDoList/ToDo.dart b/lib/pages/ToDoList/ToDo.dart index a293867d..c3351862 100644 --- a/lib/pages/ToDoList/ToDo.dart +++ b/lib/pages/ToDoList/ToDo.dart @@ -743,7 +743,7 @@ class _ToDoState extends State { service.confirmAppointment(appo.appointmentNo, appo.clinicID, appo.projectID, appo.isLiveCareAppointment, context).then((res) { GifLoaderDialogUtils.hideDialog(context); if (res['MessageStatus'] == 1) { - projectViewModel.analytics.todoList.to_do_list_confirm_appointment(); + projectViewModel.analytics.todoList.to_do_list_confirm_appointment(appo); AppToast.showSuccessToast(message: res['ErrorEndUserMessage']); if (appo.isLiveCareAppointment) { insertLiveCareVIDARequest(appo); From aa361547643d1487d6f36d0f8dd22bdeca2dbafb Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Tue, 1 Feb 2022 15:18:47 +0300 Subject: [PATCH 5/7] Updates & fixes --- .../service/parmacyModule/lacum-service.dart | 8 +- .../pharmacyModule/lacum-viewmodel.dart | 22 +-- lib/models/apple_pay_request.dart | 4 +- .../fragments/home_page_fragment2.dart | 4 - .../medical/balance/confirm_payment_page.dart | 128 +++++++++++++----- .../screens/lacum-activitaion-vida-page.dart | 8 +- .../screens/lacum-setting-page.dart | 9 +- .../pharmacies/screens/lakum-main-page.dart | 31 +++-- .../screens/lakum-terms-conditions-page.dart | 21 ++- 9 files changed, 147 insertions(+), 88 deletions(-) diff --git a/lib/core/service/parmacyModule/lacum-service.dart b/lib/core/service/parmacyModule/lacum-service.dart index c7117303..d94632c2 100644 --- a/lib/core/service/parmacyModule/lacum-service.dart +++ b/lib/core/service/parmacyModule/lacum-service.dart @@ -12,12 +12,12 @@ class LacumService extends BaseService{ LacumAccountInformation lacumInformation; LacumAccountInformation lacumGroupInformation; - Future getLacumAccountInformation() async { + Future getLacumAccountInformation(String identificationNo) async { hasError = false; super.error = ""; Map body = Map(); - body['IdentificationNo'] = user.patientIdentificationNo; + body['IdentificationNo'] = identificationNo; try { await baseAppClient.post(GET_LACUM_ACCOUNT_INFORMATION, @@ -32,12 +32,12 @@ class LacumService extends BaseService{ } } - Future getLacumGroupInformation() async { + Future getLacumGroupInformation(String identificationNo) async { hasError = false; super.error = ""; Map body = Map(); - body['IdentificationNo'] = user.patientIdentificationNo; + body['IdentificationNo'] = identificationNo; body['AccountNumber'] = "${lacumInformation.yahalaAccountNo}"; body['IsDetailsRequired'] = true; diff --git a/lib/core/viewModels/pharmacyModule/lacum-viewmodel.dart b/lib/core/viewModels/pharmacyModule/lacum-viewmodel.dart index 1bd0d542..9f624ae5 100644 --- a/lib/core/viewModels/pharmacyModule/lacum-viewmodel.dart +++ b/lib/core/viewModels/pharmacyModule/lacum-viewmodel.dart @@ -22,14 +22,14 @@ class LacumViewModel extends BaseViewModel { String get successMsg => _lacumService.successMsg; - Future getLacumData() async { - await getLacumAccountData(); - getLacumGroupData(); + Future getLacumData(String identificationNo) async { + await getLacumAccountData(identificationNo); + getLacumGroupData(identificationNo); } - Future getLacumAccountData() async { + Future getLacumAccountData(String identificationNo) async { setState(ViewState.Busy); - await _lacumService.getLacumAccountInformation(); + await _lacumService.getLacumAccountInformation(identificationNo); if (_lacumService.hasError) { error = _lacumService.error; setState(ViewState.Error); @@ -38,9 +38,9 @@ class LacumViewModel extends BaseViewModel { } } - Future getLacumGroupData() async { + Future getLacumGroupData(String identificationNo) async { setState(ViewState.Busy); - await _lacumService.getLacumGroupInformation(); + await _lacumService.getLacumGroupInformation(identificationNo); if (_lacumService.hasError) { error = _lacumService.error; setState(ViewState.Error); @@ -49,7 +49,7 @@ class LacumViewModel extends BaseViewModel { } } - Future makeAccountActivate() async { + Future makeAccountActivate(String identificationNo) async { setState(ViewState.Busy); await _lacumService.makeAccountActivate(); if (_lacumService.hasError) { @@ -57,11 +57,11 @@ class LacumViewModel extends BaseViewModel { setState(ViewState.Error); } else { lacumGroupInformation.lakumInquiryInformationObjVersion.accountStatus = "Active"; - getLacumAccountData(); + getLacumAccountData(identificationNo); } } - Future makeAccountDeactivate() async { + Future makeAccountDeactivate(String identificationNo) async { setState(ViewState.Busy); await _lacumService.makeAccountDeactivate(); if (_lacumService.hasError) { @@ -69,7 +69,7 @@ class LacumViewModel extends BaseViewModel { setState(ViewState.Error); } else { lacumGroupInformation.lakumInquiryInformationObjVersion.accountStatus = "Cancelled"; - getLacumAccountData(); + getLacumAccountData(identificationNo); } } diff --git a/lib/models/apple_pay_request.dart b/lib/models/apple_pay_request.dart index 88e16316..4cb6a9e8 100644 --- a/lib/models/apple_pay_request.dart +++ b/lib/models/apple_pay_request.dart @@ -5,8 +5,8 @@ class ApplePayRequest { dynamic customerEmail; String orderdescription; String liveServiceid; - String longitude; - String latitude; + dynamic longitude; + dynamic latitude; String devicetoken; String clientrequestid; String projectid; diff --git a/lib/pages/landing/fragments/home_page_fragment2.dart b/lib/pages/landing/fragments/home_page_fragment2.dart index 87722fac..9b5637c3 100644 --- a/lib/pages/landing/fragments/home_page_fragment2.dart +++ b/lib/pages/landing/fragments/home_page_fragment2.dart @@ -566,10 +566,6 @@ class _HomePageFragment2State extends State { ); } - callPayfortApplePayAPI(ApplePayResponse applePayResponse) { - - } - Widget showFloating(String icon) { return Container( width: MediaQuery.of(context).size.width * 0.06, diff --git a/lib/pages/medical/balance/confirm_payment_page.dart b/lib/pages/medical/balance/confirm_payment_page.dart index 57548633..5f072e57 100644 --- a/lib/pages/medical/balance/confirm_payment_page.dart +++ b/lib/pages/medical/balance/confirm_payment_page.dart @@ -1,10 +1,13 @@ import 'package:diplomaticquarterapp/config/config.dart'; -import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/core/model/my_balance/AdvanceModel.dart'; import 'package:diplomaticquarterapp/core/model/my_balance/patient_info_and_mobile_number.dart'; import 'package:diplomaticquarterapp/core/viewModels/medical/my_balance_view_model.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/models/Appointments/AppoimentAllHistoryResultList.dart'; import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; +import 'package:diplomaticquarterapp/models/apple_pay_request.dart'; +import 'package:diplomaticquarterapp/models/apple_pay_response.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; import 'package:diplomaticquarterapp/routes.dart'; import 'package:diplomaticquarterapp/services/appointment_services/GetDoctorsList.dart'; @@ -21,6 +24,7 @@ import 'package:diplomaticquarterapp/widgets/otp/sms-popup.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:pay/pay.dart'; +import 'package:provider/provider.dart'; import 'new_text_Field.dart'; @@ -38,6 +42,7 @@ class ConfirmPaymentPage extends StatefulWidget { class _ConfirmPaymentPageState extends State { MyInAppBrowser browser; + ProjectViewModel projectViewModel; AppSharedPreferences sharedPref = AppSharedPreferences(); @@ -47,14 +52,6 @@ class _ConfirmPaymentPageState extends State { 'applepay.json', ]); - var _paymentItems = [ - PaymentItem( - label: 'Total', - amount: '99.99', - status: PaymentItemStatus.final_price, - ) - ]; - void submit(MyBalanceViewModel model, code) { final activationCode = code; GifLoaderDialogUtils.showMyDialog(AppGlobal.context); @@ -64,26 +61,7 @@ class _ConfirmPaymentPageState extends State { AppoitmentAllHistoryResultList appo = new AppoitmentAllHistoryResultList(); appo.projectID = widget.patientInfoAndMobileNumber.projectID; if (widget.selectedPaymentMethod == "ApplePay") { - - // _payClient.userCanPay(PayProvider.apple_pay).then((value) { - // print(value); - // }); - - // return FutureBuilder( - // builder: (context, snapshot) { - // if (snapshot.connectionState == ConnectionState.done) { - // if (snapshot.data == true) { - // return RawGooglePayButton( - // style: GooglePayButtonStyle.black, - // type: GooglePayButtonType.pay, - // onPressed: onGooglePayPressed); - // } else { - // // userCanPay returned false - // // Consider showing an alternative payment method - // } - // } - // }, - // ); + startApplePay(); } else { openPayment(widget.selectedPaymentMethod, widget.authenticatedUser, double.parse(widget.advanceModel.amount), null); } @@ -92,6 +70,7 @@ class _ConfirmPaymentPageState extends State { @override Widget build(BuildContext context) { + projectViewModel = Provider.of(context); void showSMSDialog(MyBalanceViewModel model) { new SMSOTP( context, @@ -215,14 +194,8 @@ class _ConfirmPaymentPageState extends State { child: DefaultButton( TranslationBase.of(context).confirm.toUpperCase(), () { - _payClient.userCanPay(PayProvider.apple_pay).then((value) async { - print(value); - final result = await _payClient.showPaymentSelector( - provider: PayProvider.apple_pay, - paymentItems: _paymentItems, - ); - print(result); - }); + // if() + startApplePay(); // GifLoaderDialogUtils.showMyDialog(context); // model.sendActivationCodeForAdvancePayment(patientID: int.parse(widget.advanceModel.fileNumber), projectID: widget.advanceModel.hospitalsModel.iD).then((value) { // GifLoaderDialogUtils.hideDialog(context); @@ -236,6 +209,87 @@ class _ConfirmPaymentPageState extends State { ); } + startApplePay() { + GifLoaderDialogUtils.showMyDialog(context); + ApplePayResponse applePayResponse; + var _paymentItems = [ + PaymentItem( + label: 'Total', + amount: widget.advanceModel.amount, + status: PaymentItemStatus.final_price, + ) + ]; + + _payClient.userCanPay(PayProvider.apple_pay).then((value) async { + print(value); + final result = await _payClient.showPaymentSelector( + provider: PayProvider.apple_pay, + paymentItems: _paymentItems, + ); + print(result); + applePayResponse = ApplePayResponse.fromJson(result); + callPayfortApplePayAPI(applePayResponse); + }); + } + + callPayfortApplePayAPI(ApplePayResponse applePayResponse) async { + DoctorsListService service = new DoctorsListService(); + ApplePayRequest applePayRequest = new ApplePayRequest(); + AppleHeader appleHeader = new AppleHeader(); + ApplePaymentMethod applePaymentMethod = new ApplePaymentMethod(); + + applePayRequest.amount = widget.advanceModel.amount; + applePayRequest.currency = "SAR"; + applePayRequest.language = projectViewModel.isArabic ? "ar" : "en"; + applePayRequest.customername = projectViewModel.user.firstName; + applePayRequest.customerEmail = projectViewModel.user.emailAddress; + applePayRequest.orderdescription = "Advance Payment"; + applePayRequest.liveServiceid = ""; + applePayRequest.latitude = await this.sharedPref.getDouble(USER_LAT); + applePayRequest.longitude = await this.sharedPref.getDouble(USER_LONG); + applePayRequest.devicetoken = await sharedPref.getString(PUSH_TOKEN); + applePayRequest.clientrequestid = Utils.getAdvancePaymentTransID(widget.advanceModel.hospitalsModel.iD, int.parse(widget.advanceModel.fileNumber)); + applePayRequest.projectid = widget.advanceModel.hospitalsModel.iD.toString(); + applePayRequest.serviceid = "3"; + applePayRequest.patientid = projectViewModel.user.patientID.toString(); + applePayRequest.appleData = applePayResponse.token.data; + applePayRequest.appleSignature = applePayResponse.token.signature; + + appleHeader.appleEphemeralPublicKey = applePayResponse.token.header.ephemeralPublicKey; + appleHeader.appleTransactionId = applePayResponse.token.header.transactionId; + appleHeader.applePublicKeyHash = applePayResponse.token.header.publicKeyHash; + applePaymentMethod.appleType = getApplePayPaymentType(applePayResponse.paymentMethod.type); + applePaymentMethod.appleNetwork = applePayResponse.paymentMethod.network; + applePaymentMethod.appleDisplayName = applePayResponse.paymentMethod.displayName; + + applePayRequest.appleHeader = appleHeader; + applePayRequest.applePaymentMethod = applePaymentMethod; + + service.callPayfortApplePayAPI(applePayRequest, context).then((res) { + print(res); + GifLoaderDialogUtils.hideDialog(context); + }).catchError((err) { + GifLoaderDialogUtils.hideDialog(context); + print(err); + // _showMyDialog(err, this.context); + }); + } + + String getApplePayPaymentType(dynamic paymentMethod) { + switch (paymentMethod) { + case 1: + return 'debit'; + break; + case 2: + return 'credit'; + break; + case 3: + return 'prepaid'; + break; + } + return 'debit'; + } + String getImagePath(String paymentMethod) { switch (paymentMethod) { case "MADA": diff --git a/lib/pages/pharmacies/screens/lacum-activitaion-vida-page.dart b/lib/pages/pharmacies/screens/lacum-activitaion-vida-page.dart index 4d2c5fbd..bcd367ff 100644 --- a/lib/pages/pharmacies/screens/lacum-activitaion-vida-page.dart +++ b/lib/pages/pharmacies/screens/lacum-activitaion-vida-page.dart @@ -1,5 +1,6 @@ import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/lacum-registration-viewModel.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/buttons/borderedButton.dart'; @@ -7,16 +8,19 @@ import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import 'lacum-registration-page.dart'; class LakumActivationVidaPage extends StatelessWidget { + ProjectViewModel projectViewModel; TextEditingController _identificationNumberController = new TextEditingController(); @override Widget build(BuildContext context) { final mediaQuery = MediaQuery.of(context); + projectViewModel = Provider.of(context); return BaseView( builder: (_, model, wi) => AppScaffold( @@ -72,7 +76,7 @@ class LakumActivationVidaPage extends StatelessWidget { fontSize: 16, hPadding: 8, vPadding: 12, - handler: _identificationNumberController.text != null && + handler: _identificationNumberController.text != null || _identificationNumberController.text != "" ? () { model @@ -89,7 +93,7 @@ class LakumActivationVidaPage extends StatelessWidget { .text))) .then((status) => { if (status == 200) - {Navigator.pop(context, "")} + {model.makeAccountActivate(projectViewModel.user.patientIdentificationNo)} // back to previous page }) } diff --git a/lib/pages/pharmacies/screens/lacum-setting-page.dart b/lib/pages/pharmacies/screens/lacum-setting-page.dart index 7c402402..46dd93f8 100644 --- a/lib/pages/pharmacies/screens/lacum-setting-page.dart +++ b/lib/pages/pharmacies/screens/lacum-setting-page.dart @@ -1,6 +1,7 @@ import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; import 'package:diplomaticquarterapp/core/model/pharmacies/LacumAccountInformation.dart'; import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/lacum-viewmodel.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; import 'package:diplomaticquarterapp/pages/pharmacies/widgets/lacum-banner-widget.dart'; import 'package:diplomaticquarterapp/uitl/app_toast.dart'; @@ -10,6 +11,7 @@ import 'package:diplomaticquarterapp/widgets/buttons/borderedButton.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; class LakumSettingPage extends StatefulWidget { final LacumAccountInformation lacumInformation; @@ -26,6 +28,8 @@ class _LakumSettingPageState extends State { TextEditingController _nameController = new TextEditingController(); TextEditingController _phoneController = new TextEditingController(); + ProjectViewModel projectViewModel; + @override void initState() { _lakumAccountActivated = widget.lacumGroupInformation @@ -39,6 +43,7 @@ class _LakumSettingPageState extends State { @override Widget build(BuildContext context) { final mediaQuery = MediaQuery.of(context); + projectViewModel = Provider.of(context); return BaseView( onModelReady: (model) => model.setLakumData( @@ -126,9 +131,9 @@ class _LakumSettingPageState extends State { value: _lakumAccountActivated, onChanged: (val) { if (_lakumAccountActivated) { - model.makeAccountDeactivate(); + model.makeAccountDeactivate(projectViewModel.user.patientIdentificationNo); } else { - model.makeAccountActivate(); + model.makeAccountActivate(projectViewModel.user.patientIdentificationNo); } setState(() { _lakumAccountActivated = val; diff --git a/lib/pages/pharmacies/screens/lakum-main-page.dart b/lib/pages/pharmacies/screens/lakum-main-page.dart index a6d8aec5..5dc60fda 100644 --- a/lib/pages/pharmacies/screens/lakum-main-page.dart +++ b/lib/pages/pharmacies/screens/lakum-main-page.dart @@ -27,7 +27,7 @@ class LakumMainPage extends StatelessWidget { return BaseView( onModelReady: (model) async { - await model.getLacumData(); + await model.getLacumData(projectViewModel.user.patientIdentificationNo); if (model.lacumInformation.yahalaAccountNo == 0 || model.lacumInformation.yahalaAccountNo == null) { navigateToLakumRegister(context); } else { @@ -73,7 +73,7 @@ class LakumMainPage extends StatelessWidget { SizedBox( height: 12, ), - LakumHomeButtons(mediaQuery, model), + LakumHomeButtons(mediaQuery, model, projectViewModel), SizedBox( height: 12, ), @@ -253,25 +253,26 @@ class LakumMainPage extends StatelessWidget { navigateToLakumRegister(BuildContext context) { Navigator.pushReplacement(context, FadePage(page: LakumRegistrationPage(projectViewModel.user.patientIdentificationNo))); } -} -List _buildAppBarICons(BuildContext context, LacumViewModel model) { - return [ - IconButton( - icon: Icon(Icons.settings), - color: Colors.white, - onPressed: () { - Navigator.push(context, FadePage(page: LakumSettingPage(model.lacumInformation, model.lacumGroupInformation))).then((result) => {model.getLacumGroupData()}); - }, - ), - ]; + List _buildAppBarICons(BuildContext context, LacumViewModel model) { + return [ + IconButton( + icon: Icon(Icons.settings), + color: Colors.white, + onPressed: () { + Navigator.push(context, FadePage(page: LakumSettingPage(model.lacumInformation, model.lacumGroupInformation))).then((result) => {model.getLacumGroupData(projectViewModel.user.patientIdentificationNo)}); + }, + ), + ]; + } } class LakumHomeButtons extends StatelessWidget { final MediaQueryData mediaQuery; final LacumViewModel model; + ProjectViewModel projectViewModel; - LakumHomeButtons(this.mediaQuery, this.model); + LakumHomeButtons(this.mediaQuery, this.model, this.projectViewModel); @override Widget build(BuildContext context) { @@ -328,7 +329,7 @@ class LakumHomeButtons extends StatelessWidget { child: InkWell( onTap: () { Navigator.push(context, FadePage(page: LacumTransferPage(model.lacumInformation, model.lacumGroupInformation))).then((result) { - model.getLacumGroupData(); + model.getLacumGroupData(projectViewModel.user.patientIdentificationNo); }); }, child: Container( diff --git a/lib/pages/pharmacies/screens/lakum-terms-conditions-page.dart b/lib/pages/pharmacies/screens/lakum-terms-conditions-page.dart index 228b0874..ab1a902e 100644 --- a/lib/pages/pharmacies/screens/lakum-terms-conditions-page.dart +++ b/lib/pages/pharmacies/screens/lakum-terms-conditions-page.dart @@ -1,6 +1,7 @@ import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/lacum-registration-viewModel.dart'; import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/uitl/app_toast.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/buttons/borderedButton.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; @@ -12,8 +13,7 @@ class LakumTermsConditions extends StatelessWidget { final String firstName, lastName, mobileNo, identificationNo; final int languageId; - LakumTermsConditions(this.identificationNo, this.firstName, this.lastName, - this.mobileNo, this.languageId); + LakumTermsConditions(this.identificationNo, this.firstName, this.lastName, this.mobileNo, this.languageId); @override Widget build(BuildContext context) { @@ -37,13 +37,9 @@ class LakumTermsConditions extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ - if (model.listUserAgreement != null && - model.listUserAgreement.userAgreementLAKUM != - null) + if (model.listUserAgreement != null && model.listUserAgreement.userAgreementLAKUM != null) Html( - data: projectProvider.isArabic - ? model.listUserAgreement.userAgreementLAKUMn - : model.listUserAgreement.userAgreementLAKUM, + data: projectProvider.isArabic ? model.listUserAgreement.userAgreementLAKUMn : model.listUserAgreement.userAgreementLAKUM, ), ], ), @@ -62,9 +58,12 @@ class LakumTermsConditions extends StatelessWidget { vPadding: 12, handler: () { model.createNewLakumAccount("$firstName $lastName", mobileNo, identificationNo, languageId).then((status) => { - if (status == 200) {Navigator.pop(context, "")} - // back to previous page - }); + if (status == 200) {Navigator.pop(context, "")} else { + Navigator.pop(context, ""), + AppToast.showErrorToast(message: model.error) + } + // back to previous page + }); }, ), ), From 3eb7a4325b448f67a8a4aaa911c741c40a09f148 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Thu, 3 Feb 2022 14:50:14 +0300 Subject: [PATCH 6/7] updates & fixes --- lib/config/config.dart | 5 +- lib/core/service/client/base_app_client.dart | 16 ++-- .../SearchResults_BACKUP_53339.dart | 74 ------------------- .../SearchResults_BASE_53339.dart | 66 ----------------- .../SearchResults_LOCAL_53339.dart | 74 ------------------- .../SearchResults_REMOTE_53339.dart | 66 ----------------- lib/pages/ToDoList/ToDo.dart | 29 ++++++++ .../appointment_services/GetDoctorsList.dart | 37 ++++++++++ lib/widgets/in_app_browser/InAppBrowser.dart | 8 +- 9 files changed, 82 insertions(+), 293 deletions(-) delete mode 100644 lib/pages/BookAppointment/SearchResults_BACKUP_53339.dart delete mode 100644 lib/pages/BookAppointment/SearchResults_BASE_53339.dart delete mode 100644 lib/pages/BookAppointment/SearchResults_LOCAL_53339.dart delete mode 100644 lib/pages/BookAppointment/SearchResults_REMOTE_53339.dart diff --git a/lib/config/config.dart b/lib/config/config.dart index bdf1dffb..78bd9baf 100644 --- a/lib/config/config.dart +++ b/lib/config/config.dart @@ -259,7 +259,10 @@ const GET_PATIENT_SHARE = //URL to get patient appointment history const GET_PATIENT_APPOINTMENT_HISTORY = - "Services/Doctors.svc/REST/PateintHasAppoimentHistory_Async"; + "Services/Doctors.svc/REST/PateintHasAppoimentHistory"; + +const GET_OBGYNE_ORDERS_LIST = + "services/Patients.svc/REST/HIS_OBGYNEProcedureGet"; const DOCTOR_SCHEDULE_URL = 'Services/Doctors.svc/REST/GetDoctorWorkingHoursTable'; diff --git a/lib/core/service/client/base_app_client.dart b/lib/core/service/client/base_app_client.dart index 01050271..7ffe9d9d 100644 --- a/lib/core/service/client/base_app_client.dart +++ b/lib/core/service/client/base_app_client.dart @@ -122,14 +122,14 @@ class BaseAppClient { } } - // body['IdentificationNo'] = 2076117163; - // body['MobileNo'] = "966503109207"; - // body['PatientID'] = 3648586; //3844083 - // body['TokenID'] = "@dm!n"; - - // Patient ID: 2478442 - // Mobile no.: 0503109207 - // ID: 2076117163 + // body['IdentificationNo'] = 119116817; + // body['MobileNo'] = "9665023032857"; + body['PatientID'] = 1018977; //3844083 + body['TokenID'] = "@dm!n"; + + // Patient ID: 3027574 + // Mobile no.: 0502303285 + // ID: 119116817 body.removeWhere((key, value) => key == null || value == null); diff --git a/lib/pages/BookAppointment/SearchResults_BACKUP_53339.dart b/lib/pages/BookAppointment/SearchResults_BACKUP_53339.dart deleted file mode 100644 index ba35a0f3..00000000 --- a/lib/pages/BookAppointment/SearchResults_BACKUP_53339.dart +++ /dev/null @@ -1,74 +0,0 @@ -import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; -import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart'; -import 'package:diplomaticquarterapp/pages/BookAppointment/widgets/DoctorView.dart'; -import 'package:diplomaticquarterapp/theme/colors.dart'; -// import 'package:diplomaticquarterapp/services/robo_search/event_provider.dart'; -import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; -import 'package:diplomaticquarterapp/widgets/others/app_expandable_notifier.dart'; -import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; - -class SearchResults extends StatefulWidget { - List doctorsList = []; - List patientDoctorAppointmentListHospital; - bool isLiveCareAppointment; - - SearchResults({@required this.doctorsList, this.patientDoctorAppointmentListHospital, @required this.isLiveCareAppointment}); - - @override - _SearchResultsState createState() => _SearchResultsState(); -} - -class _SearchResultsState extends State { - // var event = RobotProvider(); - List tempList = []; - ProjectViewModel projectViewModel; - - @override - Widget build(BuildContext context) { - projectViewModel = Provider.of(context); - return AppScaffold( - appBarTitle: TranslationBase.of(context).bookAppo, - isShowDecPage: false, - isShowAppBar: true, - showNewAppBarTitle: true, - showNewAppBar: true, - backgroundColor: CustomColors.appBackgroudGrey2Color, - body: ListView.separated( - physics: BouncingScrollPhysics(), - separatorBuilder: (context, index) { - return Container( - height: 12, - margin: EdgeInsets.only(left: 21, right: 21), - // color: Color(0xffD9D9D9), - ); - }, - itemBuilder: (context, index) { - return AppExpandableNotifier( - title: (widget.patientDoctorAppointmentListHospital[index].distanceInKMs != "0") ? widget.patientDoctorAppointmentListHospital[index].filterName + " - " + widget.patientDoctorAppointmentListHospital[index].distanceInKMs + " " + TranslationBase.of(context).km : widget.patientDoctorAppointmentListHospital[index].filterName, - isTitleSingleLine: false, - bodyWidget: ListView.separated( - shrinkWrap: true, - physics: NeverScrollableScrollPhysics(), - padding: EdgeInsets.only(bottom: 10, top: 10, left: 21, right: 21), - itemBuilder: (context, _index) { - //widget.patientDoctorAppointmentListHospital[index].patientDoctorAppointmentList[_index].speciality = null; - final doctor = widget.patientDoctorAppointmentListHospital[index].patientDoctorAppointmentList[_index]; - return DoctorView( - doctor: doctor, - isLiveCareAppointment: widget.isLiveCareAppointment, - onTap: (){ - projectViewModel.analytics.appointment.book_appointment_select_doctor(appointment_type: 'regular', doctor: doctor); - } - ); - }, - separatorBuilder: (context, index) => SizedBox(height: 14), - itemCount: widget.patientDoctorAppointmentListHospital[index].patientDoctorAppointmentList.length), - ); - }, - itemCount: widget.patientDoctorAppointmentListHospital.length, - ), - ); - } -} diff --git a/lib/pages/BookAppointment/SearchResults_BASE_53339.dart b/lib/pages/BookAppointment/SearchResults_BASE_53339.dart deleted file mode 100644 index 0a654e22..00000000 --- a/lib/pages/BookAppointment/SearchResults_BASE_53339.dart +++ /dev/null @@ -1,66 +0,0 @@ -import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart'; -import 'package:diplomaticquarterapp/pages/BookAppointment/widgets/DoctorView.dart'; -import 'package:diplomaticquarterapp/theme/colors.dart'; -// import 'package:diplomaticquarterapp/services/robo_search/event_provider.dart'; -import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; -import 'package:diplomaticquarterapp/widgets/others/app_expandable_notifier.dart'; -import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; -import 'package:flutter/material.dart'; - -class SearchResults extends StatefulWidget { - List doctorsList = []; - List patientDoctorAppointmentListHospital; - bool isLiveCareAppointment; - - SearchResults({@required this.doctorsList, this.patientDoctorAppointmentListHospital, @required this.isLiveCareAppointment}); - - @override - _SearchResultsState createState() => _SearchResultsState(); -} - -class _SearchResultsState extends State { - // var event = RobotProvider(); - List tempList = []; - - @override - Widget build(BuildContext context) { - return AppScaffold( - appBarTitle: TranslationBase.of(context).bookAppo, - isShowDecPage: false, - isShowAppBar: true, - showNewAppBarTitle: true, - showNewAppBar: true, - backgroundColor: CustomColors.appBackgroudGrey2Color, - body: ListView.separated( - physics: BouncingScrollPhysics(), - separatorBuilder: (context, index) { - return Container( - height: 12, - margin: EdgeInsets.only(left: 21, right: 21), - // color: Color(0xffD9D9D9), - ); - }, - itemBuilder: (context, index) { - return AppExpandableNotifier( - title: (widget.patientDoctorAppointmentListHospital[index].distanceInKMs != "0") ? widget.patientDoctorAppointmentListHospital[index].filterName + " - " + widget.patientDoctorAppointmentListHospital[index].distanceInKMs + " " + TranslationBase.of(context).km : widget.patientDoctorAppointmentListHospital[index].filterName, - isTitleSingleLine: false, - bodyWidget: ListView.separated( - shrinkWrap: true, - physics: NeverScrollableScrollPhysics(), - padding: EdgeInsets.only(bottom: 10, top: 10, left: 21, right: 21), - itemBuilder: (context, _index) { - //widget.patientDoctorAppointmentListHospital[index].patientDoctorAppointmentList[_index].speciality = null; - return DoctorView( - doctor: widget.patientDoctorAppointmentListHospital[index].patientDoctorAppointmentList[_index], - isLiveCareAppointment: widget.isLiveCareAppointment, - ); - }, - separatorBuilder: (context, index) => SizedBox(height: 14), - itemCount: widget.patientDoctorAppointmentListHospital[index].patientDoctorAppointmentList.length), - ); - }, - itemCount: widget.patientDoctorAppointmentListHospital.length, - ), - ); - } -} diff --git a/lib/pages/BookAppointment/SearchResults_LOCAL_53339.dart b/lib/pages/BookAppointment/SearchResults_LOCAL_53339.dart deleted file mode 100644 index ba35a0f3..00000000 --- a/lib/pages/BookAppointment/SearchResults_LOCAL_53339.dart +++ /dev/null @@ -1,74 +0,0 @@ -import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; -import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart'; -import 'package:diplomaticquarterapp/pages/BookAppointment/widgets/DoctorView.dart'; -import 'package:diplomaticquarterapp/theme/colors.dart'; -// import 'package:diplomaticquarterapp/services/robo_search/event_provider.dart'; -import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; -import 'package:diplomaticquarterapp/widgets/others/app_expandable_notifier.dart'; -import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; - -class SearchResults extends StatefulWidget { - List doctorsList = []; - List patientDoctorAppointmentListHospital; - bool isLiveCareAppointment; - - SearchResults({@required this.doctorsList, this.patientDoctorAppointmentListHospital, @required this.isLiveCareAppointment}); - - @override - _SearchResultsState createState() => _SearchResultsState(); -} - -class _SearchResultsState extends State { - // var event = RobotProvider(); - List tempList = []; - ProjectViewModel projectViewModel; - - @override - Widget build(BuildContext context) { - projectViewModel = Provider.of(context); - return AppScaffold( - appBarTitle: TranslationBase.of(context).bookAppo, - isShowDecPage: false, - isShowAppBar: true, - showNewAppBarTitle: true, - showNewAppBar: true, - backgroundColor: CustomColors.appBackgroudGrey2Color, - body: ListView.separated( - physics: BouncingScrollPhysics(), - separatorBuilder: (context, index) { - return Container( - height: 12, - margin: EdgeInsets.only(left: 21, right: 21), - // color: Color(0xffD9D9D9), - ); - }, - itemBuilder: (context, index) { - return AppExpandableNotifier( - title: (widget.patientDoctorAppointmentListHospital[index].distanceInKMs != "0") ? widget.patientDoctorAppointmentListHospital[index].filterName + " - " + widget.patientDoctorAppointmentListHospital[index].distanceInKMs + " " + TranslationBase.of(context).km : widget.patientDoctorAppointmentListHospital[index].filterName, - isTitleSingleLine: false, - bodyWidget: ListView.separated( - shrinkWrap: true, - physics: NeverScrollableScrollPhysics(), - padding: EdgeInsets.only(bottom: 10, top: 10, left: 21, right: 21), - itemBuilder: (context, _index) { - //widget.patientDoctorAppointmentListHospital[index].patientDoctorAppointmentList[_index].speciality = null; - final doctor = widget.patientDoctorAppointmentListHospital[index].patientDoctorAppointmentList[_index]; - return DoctorView( - doctor: doctor, - isLiveCareAppointment: widget.isLiveCareAppointment, - onTap: (){ - projectViewModel.analytics.appointment.book_appointment_select_doctor(appointment_type: 'regular', doctor: doctor); - } - ); - }, - separatorBuilder: (context, index) => SizedBox(height: 14), - itemCount: widget.patientDoctorAppointmentListHospital[index].patientDoctorAppointmentList.length), - ); - }, - itemCount: widget.patientDoctorAppointmentListHospital.length, - ), - ); - } -} diff --git a/lib/pages/BookAppointment/SearchResults_REMOTE_53339.dart b/lib/pages/BookAppointment/SearchResults_REMOTE_53339.dart deleted file mode 100644 index e4744c4e..00000000 --- a/lib/pages/BookAppointment/SearchResults_REMOTE_53339.dart +++ /dev/null @@ -1,66 +0,0 @@ -import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart'; -import 'package:diplomaticquarterapp/pages/BookAppointment/widgets/DoctorView.dart'; -import 'package:diplomaticquarterapp/theme/colors.dart'; -// import 'package:diplomaticquarterapp/services/robo_search/event_provider.dart'; -import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; -import 'package:diplomaticquarterapp/widgets/others/app_expandable_notifier.dart'; -import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; -import 'package:flutter/material.dart'; - -class SearchResults extends StatefulWidget { - List doctorsList = []; - List patientDoctorAppointmentListHospital; - bool isLiveCareAppointment; - - SearchResults({@required this.doctorsList, this.patientDoctorAppointmentListHospital, @required this.isLiveCareAppointment}); - - @override - _SearchResultsState createState() => _SearchResultsState(); -} - -class _SearchResultsState extends State { - // var event = RobotProvider(); - List tempList = []; - - @override - Widget build(BuildContext context) { - return AppScaffold( - appBarTitle: TranslationBase.of(context).bookAppo, - isShowDecPage: false, - isShowAppBar: true, - showNewAppBarTitle: true, - showNewAppBar: true, - backgroundColor: CustomColors.appBackgroudGrey2Color, - body: ListView.separated( - physics: BouncingScrollPhysics(), - separatorBuilder: (context, index) { - return Container( - height: 12, - margin: EdgeInsets.only(left: 21, right: 21), - // color: Color(0xffD9D9D9), - ); - }, - itemBuilder: (context, index) { - return AppExpandableNotifier( - title: (widget.patientDoctorAppointmentListHospital[index].distanceInKMs != "0") ? widget.patientDoctorAppointmentListHospital[index].filterName + " - " + widget.patientDoctorAppointmentListHospital[index].distanceInKMs + " " + TranslationBase.of(context).km : widget.patientDoctorAppointmentListHospital[index].filterName, - isTitleSingleLine: false, - bodyWidget: ListView.separated( - shrinkWrap: true, - physics: NeverScrollableScrollPhysics(), - padding: EdgeInsets.only(bottom: 10, top: 10, left: 21, right: 21), - itemBuilder: (context, _index) { - //widget.patientDoctorAppointmentListHospital[index].patientDoctorAppointmentList[_index].speciality = null; - return DoctorView( - doctor: widget.patientDoctorAppointmentListHospital[index].patientDoctorAppointmentList[_index], - isLiveCareAppointment: widget.isLiveCareAppointment ?? widget.patientDoctorAppointmentListHospital[index].patientDoctorAppointmentList[_index].isLiveCare, - ); - }, - separatorBuilder: (context, index) => SizedBox(height: 14), - itemCount: widget.patientDoctorAppointmentListHospital[index].patientDoctorAppointmentList.length), - ); - }, - itemCount: widget.patientDoctorAppointmentListHospital.length, - ), - ); - } -} diff --git a/lib/pages/ToDoList/ToDo.dart b/lib/pages/ToDoList/ToDo.dart index 2a9b8e1b..8ba1139a 100644 --- a/lib/pages/ToDoList/ToDo.dart +++ b/lib/pages/ToDoList/ToDo.dart @@ -491,6 +491,34 @@ class _ToDoState extends State { }); } + getOBGyneOrdersList() { + DoctorsListService service = new DoctorsListService(); + + service.getOBGyneOrdersList(context).then((res) { + print(res['HIS_OBGYNEProcedureGet_List']); + // widget.appoList.clear(); + // GifLoaderDialogUtils.hideDialog(context); + // if (res['MessageStatus'] == 1) { + // setState(() { + // if (res['AppoimentAllHistoryResultList'].length != 0) { + // widget.appoList.clear(); + // res['AppoimentAllHistoryResultList'].forEach((v) { + // widget.appoList.add(new AppoitmentAllHistoryResultList.fromJson(v)); + // }); + // } else { + // Navigator.of(context).popAndPushNamed(HOME); + // } + // }); + // } else { + // AppToast.showErrorToast(message: res['ErrorEndUserMessage']); + // } + }).catchError((err) { + print(err); + // GifLoaderDialogUtils.hideDialog(context); + // err != null ?? AppToast.showErrorToast(message: err); + }); + } + getPatientAppointmentHistory() { GifLoaderDialogUtils.showMyDialog(context); DoctorsListService service = new DoctorsListService(); @@ -508,6 +536,7 @@ class _ToDoState extends State { Navigator.of(context).popAndPushNamed(HOME); } }); + getOBGyneOrdersList(); } else { AppToast.showErrorToast(message: res['ErrorEndUserMessage']); } diff --git a/lib/services/appointment_services/GetDoctorsList.dart b/lib/services/appointment_services/GetDoctorsList.dart index 139d847c..d42fbe3a 100644 --- a/lib/services/appointment_services/GetDoctorsList.dart +++ b/lib/services/appointment_services/GetDoctorsList.dart @@ -502,6 +502,43 @@ class DoctorsListService extends BaseService { return Future.value(localRes); } + Future getOBGyneOrdersList(BuildContext context) async { + Map request; + + if (await this.sharedPref.getObject(USER_PROFILE) != null) { + var data = AuthenticatedUser.fromJson(await this.sharedPref.getObject(USER_PROFILE)); + authUser = data; + } + + var languageID = await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar'); + Request req = appGlobal.getPublicRequest(); + + request = { + "VersionID": req.VersionID, + "Channel": req.Channel, + "LanguageID": languageID == 'ar' ? 1 : 2, + "IPAdress": req.IPAdress, + "ProjectID": 15, + "generalid": req.generalid, + "PatientOutSA": 0, + "SessionID": "YckwoXhUmWBsnHKEKig", + "isDentalAllowedBackend": false, + "DeviceTypeID": req.DeviceTypeID, + "PatientID": authUser.patientID, + "PatientTypeID": authUser.patientType, + "PatientType": authUser.patientType + }; + + dynamic localRes; + + await baseAppClient.post(GET_OBGYNE_ORDERS_LIST, onSuccess: (response, statusCode) async { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request); + return Future.value(localRes); + } + Future getPatientAppointmentHistory(bool isActiveAppointment, BuildContext context, {bool isForCOC = false}) async { Map request; diff --git a/lib/widgets/in_app_browser/InAppBrowser.dart b/lib/widgets/in_app_browser/InAppBrowser.dart index 960b6224..66b9a342 100644 --- a/lib/widgets/in_app_browser/InAppBrowser.dart +++ b/lib/widgets/in_app_browser/InAppBrowser.dart @@ -31,13 +31,13 @@ class MyInAppBrowser extends InAppBrowser { // static String APPLE_PAY_PAYFORT_URL = 'https://hmgwebservices.com/PayFortWebLive/PayFortApi/MakeApplePayRequest'; // Payfort Payment Gateway URL LIVE static String APPLE_PAY_PAYFORT_URL = 'https://hmgwebservices.com/PayFortWeb/PayFortApi/MakeApplePayRequest'; // Payfort Payment Gateway URL UAT - static String SERVICE_URL = 'https://hmgwebservices.com/PayFortWeb/pages/SendPayFortRequest.aspx'; // Payfort Payment Gateway URL UAT + // static String SERVICE_URL = 'https://hmgwebservices.com/PayFortWeb/pages/SendPayFortRequest.aspx'; // Payfort Payment Gateway URL UAT - // static String SERVICE_URL = 'https://hmgwebservices.com/PayFortWebLive/pages/SendPayFortRequest.aspx'; //Payfort Payment Gateway URL LIVE + static String SERVICE_URL = 'https://hmgwebservices.com/PayFortWebLive/pages/SendPayFortRequest.aspx'; //Payfort Payment Gateway URL LIVE - static String PREAUTH_SERVICE_URL = 'https://hmgwebservices.com/PayFortWeb/pages/SendPayFortRequest.aspx'; // Payfort PreAuth Payment Gateway URL UAT + // static String PREAUTH_SERVICE_URL = 'https://hmgwebservices.com/PayFortWeb/pages/SendPayFortRequest.aspx'; // Payfort PreAuth Payment Gateway URL UAT - // static String PREAUTH_SERVICE_URL = 'https://hmgwebservices.com/PayFortWebLive/pages/SendPayFortRequest.aspx'; //Payfort PreAuth Payment Gateway URL Live Store + static String PREAUTH_SERVICE_URL = 'https://hmgwebservices.com/PayFortWebLive/pages/SendPayFortRequest.aspx'; //Payfort PreAuth Payment Gateway URL Live Store // static String PRESCRIPTION_PAYMENT_WITH_ORDERID = // 'https://uat.hmgwebservices.com/epharmacy/checkout/OpcCompleteRedirectionPaymentClientbyOrder?orderID='; From 4b4ac4819f110a034ccb5b4301831390f616dff0 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Wed, 23 Feb 2022 14:54:11 +0300 Subject: [PATCH 7/7] no message --- lib/config/config.dart | 7 +- lib/config/localized_values.dart | 3 +- .../LakumInquiryInformationObjVersion.dart | 4 + lib/core/service/client/base_app_client.dart | 6 +- lib/main.dart | 8 +- .../Appointments/DoctorListResponse.dart | 24 +- .../OBGyneProcedureListResponse.dart | 136 +++++ lib/pages/BookAppointment/SearchResults.dart | 20 +- .../components/DocAvailableAppointments.dart | 2 - .../widgets/DentalComplaintCard.dart | 2 +- .../BookAppointment/widgets/DoctorView.dart | 22 +- .../ToDoList/ObGyne/ObGyne-TimeSlots.dart | 543 ++++++++++++++++++ lib/pages/ToDoList/ToDo.dart | 526 +++++++++++------ lib/pages/landing/landing_page.dart | 16 + .../pharmacies/screens/lakum-main-page.dart | 2 +- .../appointment_services/GetDoctorsList.dart | 63 +- .../livecare_services/livecare_provider.dart | 37 +- lib/uitl/translations_delegate_base.dart | 2 + lib/widgets/drawer/app_drawer_widget.dart | 39 +- 19 files changed, 1214 insertions(+), 248 deletions(-) create mode 100644 lib/models/Appointments/OBGyneProcedureListResponse.dart create mode 100644 lib/pages/ToDoList/ObGyne/ObGyne-TimeSlots.dart diff --git a/lib/config/config.dart b/lib/config/config.dart index 78bd9baf..e1177a58 100644 --- a/lib/config/config.dart +++ b/lib/config/config.dart @@ -17,8 +17,8 @@ const PACKAGES_ORDERS = '/api/orders'; const PACKAGES_ORDER_HISTORY = '/api/orders/items'; const PACKAGES_TAMARA_OPT = '/api/orders/paymentoptions/tamara'; // const BASE_URL = 'http://10.50.100.198:3334/'; -// const BASE_URL = 'https://uat.hmgwebservices.com/'; -const BASE_URL = 'https://hmgwebservices.com/'; + const BASE_URL = 'https://uat.hmgwebservices.com/'; +// const BASE_URL = 'https://hmgwebservices.com/'; // Pharmacy UAT URLs // const BASE_PHARMACY_URL = 'https://uat.hmgwebservices.com/epharmacy/api/'; @@ -264,6 +264,9 @@ const GET_PATIENT_APPOINTMENT_HISTORY = const GET_OBGYNE_ORDERS_LIST = "services/Patients.svc/REST/HIS_OBGYNEProcedureGet"; +const GET_OBGYNE_DOCTORS_LIST = + "services/Doctors.svc/REST/HIS_ObgyneUltrasoundDoctors"; + const DOCTOR_SCHEDULE_URL = 'Services/Doctors.svc/REST/GetDoctorWorkingHoursTable'; diff --git a/lib/config/localized_values.dart b/lib/config/localized_values.dart index 706bec87..69c2b10d 100644 --- a/lib/config/localized_values.dart +++ b/lib/config/localized_values.dart @@ -53,7 +53,7 @@ const Map localizedValues = { 'noResultFound': {'en': 'No Result Found', 'ar': 'لم يتم العثور على نتائج '}, 'noSearchResultFound': {'en': 'No Result Found', 'ar': 'لم يتم العثور على نتائج الرجاء تغيير لغة البحث'}, 'pleaseEnterProductName': {'en': 'Please Enter Product Name', 'ar': 'ادخل اسم المنتج'}, - 'bookNow': {'en': 'BOOK NOW', 'ar': 'احجز الآن'}, + 'bookNow': {'en': 'Book Now', 'ar': 'احجز الآن'}, 'docInfo': {'en': 'Doctor Information', 'ar': 'معلومات الطبيب'}, 'appoInfo': {'en': 'Appointment Information', 'ar': 'معلومات الموعد'}, 'availableAppo': {'en': 'Available Appointments', 'ar': 'المواعيد المتاحة'}, @@ -1751,4 +1751,5 @@ const Map localizedValues = { "covidTestTodo": {"en": "Covid-19 Test", "ar": "فحص كورونا"}, "ancillaryOrdersPaymentConfirm": {"en": "Are you sure you want to make payment for selected orders?", "ar": "هل أنت متأكد أنك تريد سداد قيمة الطلبات المختارة؟"}, "successRegister": {"en": "Your account has been created.", "ar": "لقد تم إنشاء حسابك."}, + "pharmacyLiveCare": {"en": "Pharmacy LiveCare", "ar": "لايف كير صيدلية"}, }; diff --git a/lib/core/model/pharmacies/LakumInquiryInformationObjVersion.dart b/lib/core/model/pharmacies/LakumInquiryInformationObjVersion.dart index e7948d7d..f1b64b1e 100644 --- a/lib/core/model/pharmacies/LakumInquiryInformationObjVersion.dart +++ b/lib/core/model/pharmacies/LakumInquiryInformationObjVersion.dart @@ -13,6 +13,7 @@ class LakumInquiryInformationObjVersion { num expiredPoints; String expiryDate; num gainedPoints; + num gainedPointsAmount; List gainedPointsAmountPerYear; List gainedPointsDetails; String lakumMessageStatus; @@ -44,6 +45,7 @@ class LakumInquiryInformationObjVersion { this.expiredPoints, this.expiryDate, this.gainedPoints, + this.gainedPointsAmount, this.gainedPointsAmountPerYear, this.gainedPointsDetails, this.lakumMessageStatus, @@ -85,6 +87,7 @@ class LakumInquiryInformationObjVersion { expiredPoints = json['ExpiredPoints']; expiryDate = json['ExpiryDate']; gainedPoints = json['GainedPoints']; + gainedPointsAmount = json['GainedPointsAmount']; if (json['GainedPointsAmountPerYear'] != null) { gainedPointsAmountPerYear = new List(); json['GainedPointsAmountPerYear'].forEach((v) { @@ -144,6 +147,7 @@ class LakumInquiryInformationObjVersion { data['ExpiredPoints'] = this.expiredPoints; data['ExpiryDate'] = this.expiryDate; data['GainedPoints'] = this.gainedPoints; + data['GainedPointsAmount'] = this.gainedPointsAmount; if (this.gainedPointsAmountPerYear != null) { data['GainedPointsAmountPerYear'] = this.gainedPointsAmountPerYear.map((v) => v).toList(); diff --git a/lib/core/service/client/base_app_client.dart b/lib/core/service/client/base_app_client.dart index 7ffe9d9d..967e03c4 100644 --- a/lib/core/service/client/base_app_client.dart +++ b/lib/core/service/client/base_app_client.dart @@ -122,9 +122,9 @@ class BaseAppClient { } } - // body['IdentificationNo'] = 119116817; - // body['MobileNo'] = "9665023032857"; - body['PatientID'] = 1018977; //3844083 + // body['IdentificationNo'] = 2076117163; + // body['MobileNo'] = "966503109207"; + body['PatientID'] = 2380476; //3844083 body['TokenID'] = "@dm!n"; // Patient ID: 3027574 diff --git a/lib/main.dart b/lib/main.dart index a3175350..12789f28 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -77,10 +77,10 @@ class _MyApp extends State { LocalNotification.getInstance().showNow(title: "Payload", subtitle: payload, payload: payload); }); - SystemChrome.setPreferredOrientations([ - DeviceOrientation.portraitUp, - DeviceOrientation.portraitDown, - ]); + // SystemChrome.setPreferredOrientations([ + // DeviceOrientation.portraitUp, + // DeviceOrientation.portraitDown, + // ]); // final themeNotifier = Provider.of(context); precacheImage(AssetImage('assets/images/powerd-by.jpg'), context); return LayoutBuilder( diff --git a/lib/models/Appointments/DoctorListResponse.dart b/lib/models/Appointments/DoctorListResponse.dart index d43dceb3..122f560f 100644 --- a/lib/models/Appointments/DoctorListResponse.dart +++ b/lib/models/Appointments/DoctorListResponse.dart @@ -1,22 +1,22 @@ class DoctorList { - int clinicID; + num clinicID; String clinicName; String doctorTitle; - int iD; + num iD; String name; - int projectID; + num projectID; String projectName; - int actualDoctorRate; - int clinicRoomNo; + num actualDoctorRate; + num clinicRoomNo; dynamic date; dynamic appointmentDate; dynamic dayName; - int doctorID; + num doctorID; String doctorImageURL; dynamic doctorProfile; dynamic doctorProfileInfo; - int doctorRate; - int gender; + num doctorRate; + num gender; String genderDescription; bool isAppointmentAllowed; bool isDoctorAllowVedioCall; @@ -30,13 +30,13 @@ class DoctorList { String nationalityID; String nationalityName; dynamic nearestFreeSlot; - int noOfPatientsRate; - int originalClinicID; - int personRate; + num noOfPatientsRate; + num originalClinicID; + num personRate; dynamic projectDistanceInKiloMeters; String qR; dynamic qRString; - int rateNumber; + num rateNumber; dynamic serviceID; String setupID; List speciality; diff --git a/lib/models/Appointments/OBGyneProcedureListResponse.dart b/lib/models/Appointments/OBGyneProcedureListResponse.dart new file mode 100644 index 00000000..ca45583a --- /dev/null +++ b/lib/models/Appointments/OBGyneProcedureListResponse.dart @@ -0,0 +1,136 @@ +class OBGyneProcedureListResponse { + String setupID; + int projectID; + int episodeID; + int appointmentNo; + int orderNo; + String procedureId; + int lineItemNo; + String orderDate; + int orderType; + int patientType; + int patientID; + int price; + int orderStatus; + bool isApprovalRequired; + bool isApprovalCreated; + bool isInvoiced; + bool isReferralInvoiced; + bool isEROrder; + bool isCash; + int uniqueRowID; + int status; + int clinicID; + int doctorID; + String procedureName; + String procedureNameN; + String clinicDescription; + String clinicDescriptionN; + String doctorName; + String doctorNameN; + String projectDescription; + String projectDescriptionN; + + OBGyneProcedureListResponse( + {this.setupID, + this.projectID, + this.episodeID, + this.appointmentNo, + this.orderNo, + this.procedureId, + this.lineItemNo, + this.orderDate, + this.orderType, + this.patientType, + this.patientID, + this.price, + this.orderStatus, + this.isApprovalRequired, + this.isApprovalCreated, + this.isInvoiced, + this.isReferralInvoiced, + this.isEROrder, + this.isCash, + this.uniqueRowID, + this.status, + this.clinicID, + this.doctorID, + this.procedureName, + this.procedureNameN, + this.clinicDescription, + this.clinicDescriptionN, + this.doctorName, + this.doctorNameN, + this.projectDescription, + this.projectDescriptionN}); + + OBGyneProcedureListResponse.fromJson(Map json) { + setupID = json['SetupID']; + projectID = json['ProjectID']; + episodeID = json['EpisodeID']; + appointmentNo = json['AppointmentNo']; + orderNo = json['OrderNo']; + procedureId = json['ProcedureId']; + lineItemNo = json['LineItemNo']; + orderDate = json['OrderDate']; + orderType = json['OrderType']; + patientType = json['PatientType']; + patientID = json['PatientID']; + price = json['Price']; + orderStatus = json['OrderStatus']; + isApprovalRequired = json['IsApprovalRequired']; + isApprovalCreated = json['IsApprovalCreated']; + isInvoiced = json['IsInvoiced']; + isReferralInvoiced = json['IsReferralInvoiced']; + isEROrder = json['IsEROrder']; + isCash = json['IsCash']; + uniqueRowID = json['UniqueRowID']; + status = json['Status']; + clinicID = json['ClinicID']; + doctorID = json['DoctorID']; + procedureName = json['ProcedureName']; + procedureNameN = json['ProcedureNameN']; + clinicDescription = json['ClinicDescription']; + clinicDescriptionN = json['ClinicDescriptionN']; + doctorName = json['DoctorName']; + doctorNameN = json['DoctorNameN']; + projectDescription = json['ProjectDescription']; + projectDescriptionN = json['ProjectDescriptionN']; + } + + Map toJson() { + final Map data = new Map(); + data['SetupID'] = this.setupID; + data['ProjectID'] = this.projectID; + data['EpisodeID'] = this.episodeID; + data['AppointmentNo'] = this.appointmentNo; + data['OrderNo'] = this.orderNo; + data['ProcedureId'] = this.procedureId; + data['LineItemNo'] = this.lineItemNo; + data['OrderDate'] = this.orderDate; + data['OrderType'] = this.orderType; + data['PatientType'] = this.patientType; + data['PatientID'] = this.patientID; + data['Price'] = this.price; + data['OrderStatus'] = this.orderStatus; + data['IsApprovalRequired'] = this.isApprovalRequired; + data['IsApprovalCreated'] = this.isApprovalCreated; + data['IsInvoiced'] = this.isInvoiced; + data['IsReferralInvoiced'] = this.isReferralInvoiced; + data['IsEROrder'] = this.isEROrder; + data['IsCash'] = this.isCash; + data['UniqueRowID'] = this.uniqueRowID; + data['Status'] = this.status; + data['ClinicID'] = this.clinicID; + data['DoctorID'] = this.doctorID; + data['ProcedureName'] = this.procedureName; + data['ProcedureNameN'] = this.procedureNameN; + data['ClinicDescription'] = this.clinicDescription; + data['ClinicDescriptionN'] = this.clinicDescriptionN; + data['DoctorName'] = this.doctorName; + data['DoctorNameN'] = this.doctorNameN; + data['ProjectDescription'] = this.projectDescription; + data['ProjectDescriptionN'] = this.projectDescriptionN; + return data; + } +} diff --git a/lib/pages/BookAppointment/SearchResults.dart b/lib/pages/BookAppointment/SearchResults.dart index ba35a0f3..b29fa825 100644 --- a/lib/pages/BookAppointment/SearchResults.dart +++ b/lib/pages/BookAppointment/SearchResults.dart @@ -1,8 +1,8 @@ import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart'; +import 'package:diplomaticquarterapp/models/Appointments/OBGyneProcedureListResponse.dart'; import 'package:diplomaticquarterapp/pages/BookAppointment/widgets/DoctorView.dart'; import 'package:diplomaticquarterapp/theme/colors.dart'; -// import 'package:diplomaticquarterapp/services/robo_search/event_provider.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/others/app_expandable_notifier.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; @@ -13,15 +13,16 @@ class SearchResults extends StatefulWidget { List doctorsList = []; List patientDoctorAppointmentListHospital; bool isLiveCareAppointment; + bool isObGyneAppointment; + OBGyneProcedureListResponse obGyneProcedureListResponse; - SearchResults({@required this.doctorsList, this.patientDoctorAppointmentListHospital, @required this.isLiveCareAppointment}); + SearchResults({@required this.doctorsList, this.patientDoctorAppointmentListHospital, this.isObGyneAppointment = false, @required this.isLiveCareAppointment, this.obGyneProcedureListResponse}); @override _SearchResultsState createState() => _SearchResultsState(); } class _SearchResultsState extends State { - // var event = RobotProvider(); List tempList = []; ProjectViewModel projectViewModel; @@ -41,27 +42,28 @@ class _SearchResultsState extends State { return Container( height: 12, margin: EdgeInsets.only(left: 21, right: 21), - // color: Color(0xffD9D9D9), ); }, itemBuilder: (context, index) { return AppExpandableNotifier( - title: (widget.patientDoctorAppointmentListHospital[index].distanceInKMs != "0") ? widget.patientDoctorAppointmentListHospital[index].filterName + " - " + widget.patientDoctorAppointmentListHospital[index].distanceInKMs + " " + TranslationBase.of(context).km : widget.patientDoctorAppointmentListHospital[index].filterName, + title: (widget.patientDoctorAppointmentListHospital[index].distanceInKMs != "0") + ? widget.patientDoctorAppointmentListHospital[index].filterName + " - " + widget.patientDoctorAppointmentListHospital[index].distanceInKMs + " " + TranslationBase.of(context).km + : widget.patientDoctorAppointmentListHospital[index].filterName, isTitleSingleLine: false, bodyWidget: ListView.separated( shrinkWrap: true, physics: NeverScrollableScrollPhysics(), padding: EdgeInsets.only(bottom: 10, top: 10, left: 21, right: 21), itemBuilder: (context, _index) { - //widget.patientDoctorAppointmentListHospital[index].patientDoctorAppointmentList[_index].speciality = null; final doctor = widget.patientDoctorAppointmentListHospital[index].patientDoctorAppointmentList[_index]; return DoctorView( doctor: doctor, isLiveCareAppointment: widget.isLiveCareAppointment, - onTap: (){ + isObGyneAppointment: widget.isObGyneAppointment, + obGyneProcedureListResponse: widget.obGyneProcedureListResponse, + onTap: () { projectViewModel.analytics.appointment.book_appointment_select_doctor(appointment_type: 'regular', doctor: doctor); - } - ); + }); }, separatorBuilder: (context, index) => SizedBox(height: 14), itemCount: widget.patientDoctorAppointmentListHospital[index].patientDoctorAppointmentList.length), diff --git a/lib/pages/BookAppointment/components/DocAvailableAppointments.dart b/lib/pages/BookAppointment/components/DocAvailableAppointments.dart index 2e81b7bc..0e7a3dc6 100644 --- a/lib/pages/BookAppointment/components/DocAvailableAppointments.dart +++ b/lib/pages/BookAppointment/components/DocAvailableAppointments.dart @@ -293,8 +293,6 @@ class _DocAvailableAppointmentsState extends State wit if (res['FreeTimeSlots'].length != 0) { DocAvailableAppointments.areAppointmentsAvailable = true; freeSlotsResponse = res['FreeTimeSlots']; - print("res['FreeTimeSlots']"); - print(res['FreeTimeSlots'].length); _getJSONSlots().then((value) { setState(() => { diff --git a/lib/pages/BookAppointment/widgets/DentalComplaintCard.dart b/lib/pages/BookAppointment/widgets/DentalComplaintCard.dart index 3c56aa24..e5935ff3 100644 --- a/lib/pages/BookAppointment/widgets/DentalComplaintCard.dart +++ b/lib/pages/BookAppointment/widgets/DentalComplaintCard.dart @@ -93,6 +93,6 @@ class _DentalComplaintCardState extends State { } Future navigateToSearchResults(context, List docList, List patientDoctorAppointmentListHospital) async { - Navigator.push(context, FadePage(page: SearchResults(doctorsList: docList, patientDoctorAppointmentListHospital: patientDoctorAppointmentListHospital))); + Navigator.push(context, FadePage(page: SearchResults(doctorsList: docList, patientDoctorAppointmentListHospital: patientDoctorAppointmentListHospital, isLiveCareAppointment: false))); } } diff --git a/lib/pages/BookAppointment/widgets/DoctorView.dart b/lib/pages/BookAppointment/widgets/DoctorView.dart index 2d113545..ae781cb3 100644 --- a/lib/pages/BookAppointment/widgets/DoctorView.dart +++ b/lib/pages/BookAppointment/widgets/DoctorView.dart @@ -1,6 +1,8 @@ import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart'; import 'package:diplomaticquarterapp/models/Appointments/DoctorProfile.dart'; +import 'package:diplomaticquarterapp/models/Appointments/OBGyneProcedureListResponse.dart'; +import 'package:diplomaticquarterapp/pages/ToDoList/ObGyne/ObGyne-TimeSlots.dart'; import 'package:diplomaticquarterapp/services/appointment_services/GetDoctorsList.dart'; import 'package:diplomaticquarterapp/uitl/app_toast.dart'; import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; @@ -18,10 +20,12 @@ import '../DoctorProfile.dart'; class DoctorView extends StatelessWidget { final DoctorList doctor; bool isLiveCareAppointment; + bool isObGyneAppointment; bool isShowFlag; + OBGyneProcedureListResponse obGyneProcedureListResponse; final VoidCallback onTap; - DoctorView({@required this.doctor, @required this.isLiveCareAppointment, this.isShowFlag = true, this.onTap}); + DoctorView({@required this.doctor, @required this.isLiveCareAppointment, this.isObGyneAppointment = false, this.isShowFlag = true, this.onTap, this.obGyneProcedureListResponse}); ProjectViewModel projectViewModel; @@ -30,9 +34,13 @@ class DoctorView extends StatelessWidget { projectViewModel = Provider.of(context); return InkWell( onTap: () { - if (isShowFlag) getDoctorsProfile(context, doctor, isAppo: true); - (onTap ?? (){})(); // For log analytics of doctor click from book appointment - }, + if (isObGyneAppointment) { + next(context); + } else { + if (isShowFlag) getDoctorsProfile(context, doctor, isAppo: true); + (onTap ?? () {})(); // For log analytics of doctor click from book appointment + } + }, child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.all( @@ -85,7 +93,7 @@ class DoctorView extends StatelessWidget { children: [ if (doctor.clinicName != null) MyRichText(TranslationBase.of(context).clinic + ":", doctor.clinicName, projectViewModel.isArabic), if (doctor.projectName != null) MyRichText(TranslationBase.of(context).branch, doctor.projectName, projectViewModel.isArabic), - if (doctor.speciality != null) + if (doctor.speciality != null && doctor.speciality.length > 0) Text( this.doctor.speciality[0].trim(), // getDoctorSpeciality(this.doctor.speciality).trim(), @@ -184,6 +192,10 @@ class DoctorView extends StatelessWidget { } } + void next(BuildContext context) { + Navigator.push(context, FadePage(page: ObGyneTimeSlots(projectID: doctor.projectID, selectedClinicID: doctor.clinicID, selectedDoctorID: doctor.doctorID, obGyneProcedureListResponse: obGyneProcedureListResponse))); + } + Future navigateToDoctorProfile(context, docObject, docProfile, {isAppo}) async { Navigator.push( context, diff --git a/lib/pages/ToDoList/ObGyne/ObGyne-TimeSlots.dart b/lib/pages/ToDoList/ObGyne/ObGyne-TimeSlots.dart new file mode 100644 index 00000000..2a5339bb --- /dev/null +++ b/lib/pages/ToDoList/ObGyne/ObGyne-TimeSlots.dart @@ -0,0 +1,543 @@ +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/models/Appointments/AppoimentAllHistoryResultList.dart'; +import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart'; +import 'package:diplomaticquarterapp/models/Appointments/FreeSlot.dart'; +import 'package:diplomaticquarterapp/models/Appointments/OBGyneProcedureListResponse.dart'; +import 'package:diplomaticquarterapp/models/Appointments/timeSlot.dart'; +import 'package:diplomaticquarterapp/models/Appointments/toDoCountProviderModel.dart'; +import 'package:diplomaticquarterapp/services/appointment_services/GetDoctorsList.dart'; +import 'package:diplomaticquarterapp/services/clinic_services/get_clinic_service.dart'; +import 'package:diplomaticquarterapp/theme/colors.dart'; +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/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/uitl/utils_new.dart'; +import 'package:diplomaticquarterapp/widgets/dialogs/confirm_dialog.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; +import 'package:provider/provider.dart'; +import 'package:syncfusion_flutter_calendar/calendar.dart'; + +class ObGyneTimeSlots extends StatefulWidget { + int projectID; + static bool areSlotsAvailable = false; + static DateTime selectedAppoDateTime; + static String selectedDate; + static String selectedTime; + + int selectedClinicID; + int selectedDoctorID; + + OBGyneProcedureListResponse obGyneProcedureListResponse; + + var language; + + ObGyneTimeSlots({@required this.projectID, this.selectedClinicID, this.selectedDoctorID, this.obGyneProcedureListResponse}); + + @override + _CovidTimeSlotsState createState() => _CovidTimeSlotsState(); +} + +class _CovidTimeSlotsState extends State with TickerProviderStateMixin { + Map _events; + AnimationController _animationController; + CalendarController _calendarController; + + AppSharedPreferences sharedPref = new AppSharedPreferences(); + + var selectedDate = ""; + dynamic selectedDateJSON; + dynamic jsonFreeSlots; + + List docFreeSlots = []; + List dayEvents = []; + + int selectedButtonIndex = 0; + + dynamic freeSlotsResponse; + + ScrollController _scrollController; + + ToDoCountProviderModel toDoProvider; + ProjectViewModel projectViewModel; + + @override + void initState() { + final _selectedDay = DateTime.now(); + + _scrollController = new ScrollController(); + + _events = { + _selectedDay: ['Event A0'] + }; + + WidgetsBinding.instance.addPostFrameCallback((_) => getCovidFreeSlots(context, widget.projectID)); + + _calendarController = CalendarController(); + _animationController = AnimationController( + vsync: this, + duration: const Duration(milliseconds: 50), + ); + + _animationController.forward(); + super.initState(); + } + + @override + void dispose() { + _animationController.dispose(); + _calendarController.dispose(); + super.dispose(); + } + + void _onDaySelected(DateTime day, ProjectViewModel projectViewModel) { + final DateFormat formatter = DateFormat('yyyy-MM-dd'); + setState(() { + this.selectedDate = DateUtil.getWeekDayMonthDayYearDateFormatted(day, projectViewModel.isArabic ? "ar" : "en"); + openTimeSlotsPickerForDate(day, docFreeSlots); + ObGyneTimeSlots.selectedDate = formatter.format(day); + _calendarController.selectedDate = day; + print(ObGyneTimeSlots.selectedDate); + }); + } + + @override + Widget build(BuildContext context) { + projectViewModel = Provider.of(context); + toDoProvider = Provider.of(context); + return AppScaffold( + appBarTitle: TranslationBase.of(context).bookAppo, + isShowAppBar: true, + showNewAppBar: true, + showNewAppBarTitle: true, + backgroundColor: CustomColors.appBackgroudGrey2Color, + body: Column( + children: [ + Expanded( + child: SingleChildScrollView( + child: Container( + margin: EdgeInsets.fromLTRB(15.0, 15.0, 15.0, 0.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: [ + Text( + TranslationBase.of(context).selectAppo, + style: TextStyle( + color: Colors.black, + fontSize: 16.0, + letterSpacing: -0.64, + fontWeight: FontWeight.w600, + ), + ), + mHeight(12), + Container( + decoration: cardRadius(12), + child: _buildTableCalendarWithBuilders(projectViewModel), + ), + mHeight(12), + Text( + selectedDate, + style: TextStyle( + fontSize: 16.0, + fontWeight: FontWeight.bold, + letterSpacing: -0.64, + ), + ), + mHeight(8), + ObGyneTimeSlots.areSlotsAvailable + ? Container( + height: 40, + child: ListView.builder( + controller: _scrollController, + scrollDirection: Axis.horizontal, + itemCount: dayEvents.length, + itemBuilder: (context, index) { + return Container( + margin: EdgeInsets.only(right: (index == dayEvents.length - 1) ? 0 : 5.0, left: index == 0 ? 0 : 5), + child: ButtonTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5.0), + side: BorderSide( + color: index == selectedButtonIndex ? CustomColors.green : Colors.black, //Color of the border + style: BorderStyle.solid, //Style of the border + width: 1.5, //width of the border + ), + ), + minWidth: MediaQuery.of(context).size.width * 0.2, + child: index == selectedButtonIndex ? getSelectedButton(index) : getNormalButton(index)), + ); + }, + ), + ) + : Center( + child: Padding( + padding: const EdgeInsets.only(left: 12.0, right: 12.0), + child: Text(TranslationBase.of(context).noSlotsError, style: TextStyle(fontSize: 14.0, fontWeight: FontWeight.w600, letterSpacing: -0.46, color: CustomColors.grey)), + )), + ], + ), + ), + SizedBox( + height: 100.0, + ), + ], + ), + ), + ), + ), + Container( + margin: EdgeInsets.zero, + decoration: cardRadius(0), + child: Container( + width: double.infinity, + padding: EdgeInsets.all(12), + child: ButtonTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10.0), + ), + minWidth: MediaQuery.of(context).size.width * 0.7, + height: 45.0, + child: RaisedButton( + color: CustomColors.green, + textColor: Colors.white, + disabledTextColor: Colors.white, + elevation: 0, + disabledColor: Colors.grey[500], + onPressed: () { + bookCovidTestAppointment(); + }, + child: Text( + TranslationBase.of(context).bookAppo, + style: TextStyle( + fontSize: 16.0, + letterSpacing: -0.64, + ), + ), + ), + ), + ), + ) + ], + ), + ); + } + + Widget _buildTableCalendarWithBuilders(ProjectViewModel projectViewModel) { + return SfCalendar( + controller: _calendarController, + minDate: DateTime.now(), + showNavigationArrow: true, + headerStyle: CalendarHeaderStyle(textAlign: TextAlign.center, textStyle: TextStyle(fontSize: 14.0, fontWeight: FontWeight.w600, letterSpacing: -0.46)), + viewHeaderStyle: ViewHeaderStyle(dayTextStyle: TextStyle(fontSize: 12.0, fontWeight: FontWeight.w600, letterSpacing: -0.46, color: CustomColors.black)), + view: CalendarView.month, + todayHighlightColor: CustomColors.green, + selectionDecoration: containerColorRadiusBorderWidthCircular(Colors.transparent, 4, CustomColors.green, 2.5), + cellBorderColor: Colors.white, + dataSource: MeetingDataSource(_getDataSource()), + monthViewSettings: const MonthViewSettings(appointmentDisplayMode: MonthAppointmentDisplayMode.indicator, showTrailingAndLeadingDates: false, appointmentDisplayCount: 1), + onTap: (CalendarTapDetails details) { + _calendarController.selectedDate = details.date; + _onDaySelected(details.date, projectViewModel); + }, + ); + } + + List _getDataSource() { + final List meetings = []; + _events.forEach((key, value) { + final DateTime startTime = DateTime(key.year, key.month, key.day, 9, 0, 0); + final DateTime endTime = startTime.add(const Duration(minutes: 20)); + meetings.add(Meeting("", startTime, endTime, CustomColors.green, false)); + }); + return meetings; + } + + openTimeSlotsPickerForDate(DateTime dateStart, List freeSlots) { + dayEvents.clear(); + DateTime dateStartObj = new DateTime(dateStart.year, dateStart.month, dateStart.day, 0, 0, 0, 0, 0); + + freeSlots.forEach((v) { + if (v.start == dateStartObj) dayEvents.add(v); + }); + + setState(() { + if (dayEvents.length != 0) { + ObGyneTimeSlots.areSlotsAvailable = true; + selectedButtonIndex = 0; + ObGyneTimeSlots.selectedTime = dayEvents[selectedButtonIndex].isoTime; + } else + ObGyneTimeSlots.areSlotsAvailable = false; + }); + } + + Future> _getJSONSlots() async { + Map _eventsParsed; + List slotsList = []; + DateTime date; + final DateFormat formatter = DateFormat('HH:mm'); + final DateFormat dateFormatter = DateFormat('yyyy-MM-dd'); + for (var i = 0; i < freeSlotsResponse.length; i++) { + date = DateUtil.convertStringToDate(freeSlotsResponse[i]); + slotsList.add(FreeSlot(date, ['slot'])); + docFreeSlots.add(TimeSlot(isoTime: formatter.format(date), start: new DateTime(date.year, date.month, date.day, 0, 0, 0, 0), end: date)); + } + _eventsParsed = Map.fromIterable(slotsList, key: (e) => e.slot, value: (e) => e.event); + setState(() { + ObGyneTimeSlots.selectedDate = dateFormatter.format(DateUtil.convertStringToDate(freeSlotsResponse[0])); + selectedDate = DateUtil.getMonthDayYearDateFormatted(DateUtil.convertStringToDate(freeSlotsResponse[0])); + selectedDateJSON = freeSlotsResponse[0]; + }); + openTimeSlotsPickerForDate(DateUtil.convertStringToDate(selectedDateJSON), docFreeSlots); + _calendarController.selectedDate = DateUtil.convertStringToDate(selectedDateJSON); + return _eventsParsed; + } + + Widget getNormalButton(int index) { + return RaisedButton( + color: Colors.white, + elevation: 0, + textColor: new Color(0xFF60686b), + onPressed: () { + setState(() { + selectedButtonIndex = index; + ObGyneTimeSlots.selectedTime = dayEvents[index].isoTime; + print(ObGyneTimeSlots.selectedTime); + }); + }, + child: Text(dayEvents[index].isoTime, style: TextStyle(fontSize: 12.0, fontWeight: FontWeight.bold)), + ); + } + + Widget getSelectedButton(int index) { + return RaisedButton( + color: CustomColors.green, + //Color of the border + elevation: 0, + textColor: Colors.white, + onPressed: () { + setState(() { + selectedButtonIndex = index; + ObGyneTimeSlots.selectedTime = dayEvents[index].isoTime; + print(ObGyneTimeSlots.selectedTime); + }); + }, + child: Text(dayEvents[index].isoTime, style: TextStyle(fontSize: 12.0, fontWeight: FontWeight.bold)), + ); + } + + bookCovidTestAppointment() { + if (ObGyneTimeSlots.areSlotsAvailable) { + GifLoaderDialogUtils.showMyDialog(context); + DoctorList docObject = new DoctorList(); + docObject.doctorID = widget.selectedDoctorID; + docObject.clinicID = widget.selectedClinicID; + docObject.projectID = widget.projectID; + insertAppointmentCovidTest(context, docObject); + } else { + AppToast.showErrorToast(message: TranslationBase.of(context).selectSlot); + } + } + + // updateCovidQuestionnaire(context, String appoNo) async { + // DoctorsListService service = new DoctorsListService(); + // service.updateCovidQuestionnaire(appoNo, widget.projectID, widget.selectedProject.testTypeEnum, widget.selectedProject.testProcedureEnum).then((res) {}).catchError((err) { + // print(err); + // }); + // } + + insertAppointmentCovidTest(context, DoctorList docObject) { + DoctorsListService service = new DoctorsListService(); + AppoitmentAllHistoryResultList appo; + service + .insertAppointment( + docObject.doctorID, docObject.clinicID, docObject.projectID, ObGyneTimeSlots.selectedTime, ObGyneTimeSlots.selectedDate, context, widget.obGyneProcedureListResponse.procedureId) + .then((res) { + if (res['MessageStatus'] == 1) { + AppToast.showSuccessToast(message: TranslationBase.of(context).bookedSuccess); + updateObGyneAppointment(res['AppointmentNo']); + getToDoCount(); + // getPatientShare(context, res['AppointmentNo'], docObject.clinicID, docObject.projectID, docObject); + } else { + GifLoaderDialogUtils.hideDialog(context); + appo = new AppoitmentAllHistoryResultList(); + appo.appointmentNo = res['SameClinicApptList'][0]['AppointmentNo']; + appo.clinicID = res['SameClinicApptList'][0]['DoctorID']; + appo.projectID = res['SameClinicApptList'][0]['ProjectID']; + appo.endTime = res['SameClinicApptList'][0]['EndTime']; + appo.startTime = res['SameClinicApptList'][0]['StartTime']; + appo.doctorID = res['SameClinicApptList'][0]['DoctorID']; + appo.isLiveCareAppointment = false; + appo.originalClinicID = 0; + appo.originalProjectID = 0; + appo.appointmentDate = res['SameClinicApptList'][0]['AppointmentDate']; + + ConfirmDialog dialog = new ConfirmDialog( + context: context, + confirmMessage: res['ErrorEndUserMessage'], + okText: TranslationBase.of(context).confirm, + cancelText: TranslationBase.of(context).cancel_nocaps, + okFunction: () => {cancelAppointment(docObject, appo, context)}, + cancelFunction: () => {}); + dialog.showAlertDialog(context); + } + }).catchError((err) { + AppToast.showErrorToast(message: err); + GifLoaderDialogUtils.hideDialog(context); + print(err); + }); + } + + updateObGyneAppointment(String appoNo) { + DoctorsListService service = new DoctorsListService(); + service + .updateObGyneAppointment(widget.obGyneProcedureListResponse.episodeID, int.parse(appoNo), widget.obGyneProcedureListResponse.orderNo, widget.obGyneProcedureListResponse.procedureId, + widget.obGyneProcedureListResponse.lineItemNo, widget.obGyneProcedureListResponse.uniqueRowID) + .then((res) {}) + .catchError((err) { + print(err); + }); + } + + getToDoCount() { + toDoProvider.setState(0, true, toDoProvider.notificationsCount); + ClinicListService service = new ClinicListService(); + service.getActiveAppointmentNo(context).then((res) { + GifLoaderDialogUtils.hideDialog(context); + print(res['AppointmentActiveNumber']); + if (res['MessageStatus'] == 1) { + toDoProvider.setState(res['AppointmentActiveNumber'], true, toDoProvider.notificationsCount); + } else {} + }).catchError((err) { + GifLoaderDialogUtils.hideDialog(context); + print(err); + }); + } + + cancelAppointment(DoctorList docObject, AppoitmentAllHistoryResultList appo, BuildContext context) { + ConfirmDialog.closeAlertDialog(context); + GifLoaderDialogUtils.showMyDialog(context); + DoctorsListService service = new DoctorsListService(); + service.cancelAppointment(appo, context).then((res) { + if (res['MessageStatus'] == 1) { + // Future.delayed(new Duration(milliseconds: 1500), () { + insertAppointmentCovidTest(context, docObject); + // }); + } else { + GifLoaderDialogUtils.hideDialog(context); + AppToast.showErrorToast(message: res['ErrorEndUserMessage']); + } + }).catchError((err) { + print(err); + }); + } + + // getPatientShare(context, String appointmentNo, int clinicID, int projectID, DoctorList docObject) { + // DoctorsListService service = new DoctorsListService(); + // service.getPatientShare(appointmentNo, clinicID, projectID, context).then((res) { + // GifLoaderDialogUtils.hideDialog(context); + // print(res); + // widget.patientShareResponse = new PatientShareResponse.fromJson(res); + // // updateCovidQuestionnaire(context, appointmentNo); + // navigateToPaymentAlert(); + // }).catchError((err) { + // GifLoaderDialogUtils.hideDialog(context); + // print(err); + // }); + // } + // + // navigateToPaymentAlert() { + // Navigator.push( + // context, + // FadePage( + // page: CovidPaymentAlert(patientShareResponse: widget.patientShareResponse), + // ), + // ); + // } + + getCovidFreeSlots(BuildContext context, int projectID) { + DoctorsListService service = new DoctorsListService(); + GifLoaderDialogUtils.showMyDialog(context); + service.getDoctorFreeSlots(widget.selectedDoctorID, widget.selectedClinicID, widget.projectID, context).then((res) { + GifLoaderDialogUtils.hideDialog(context); + if (res['MessageStatus'] == 1) { + if (res['FreeTimeSlots'].length != 0) { + print(res['FreeTimeSlots']); + freeSlotsResponse = res['FreeTimeSlots']; + _getJSONSlots().then((value) => { + setState(() => { + _events.clear(), + _events = value, + // if (widget.doctorSchedule != null) + // {_onDaySelected(DateUtil.convertStringToDate(widget.doctorSchedule['Date'])), _calendarController.selectedDate = DateUtil.convertStringToDate(widget.doctorSchedule['Date'])} + }) + }); + } else {} + } else { + GifLoaderDialogUtils.hideDialog(context); + AppToast.showErrorToast(message: res['ErrorEndUserMessage']); + } + }).catchError((err) { + GifLoaderDialogUtils.hideDialog(context); + AppToast.showErrorToast(message: err.toString()); + print(err); + }); + } +} + +class MeetingDataSource extends CalendarDataSource { + MeetingDataSource(List source) { + appointments = source; + } + + @override + DateTime getStartTime(int index) { + return _getMeetingData(index).from; + } + + @override + DateTime getEndTime(int index) { + return _getMeetingData(index).to; + } + + @override + String getSubject(int index) { + return _getMeetingData(index).eventName; + } + + @override + Color getColor(int index) { + return _getMeetingData(index).background; + } + + @override + bool isAllDay(int index) { + return _getMeetingData(index).isAllDay; + } + + Meeting _getMeetingData(int index) { + final dynamic meeting = appointments[index]; + Meeting meetingData; + if (meeting is Meeting) { + meetingData = meeting; + } + return meetingData; + } +} + +class Meeting { + Meeting(this.eventName, this.from, this.to, this.background, this.isAllDay); + + String eventName; + DateTime from; + DateTime to; + Color background; + bool isAllDay; +} diff --git a/lib/pages/ToDoList/ToDo.dart b/lib/pages/ToDoList/ToDo.dart index 8ba1139a..cc3af6f7 100644 --- a/lib/pages/ToDoList/ToDo.dart +++ b/lib/pages/ToDoList/ToDo.dart @@ -2,14 +2,16 @@ import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/core/model/ImagesInfo.dart'; import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/models/Appointments/AppoimentAllHistoryResultList.dart'; +import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart'; +import 'package:diplomaticquarterapp/models/Appointments/OBGyneProcedureListResponse.dart'; import 'package:diplomaticquarterapp/models/Appointments/PatientShareResposne.dart'; import 'package:diplomaticquarterapp/models/Appointments/toDoCountProviderModel.dart'; import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; import 'package:diplomaticquarterapp/pages/BookAppointment/QRCode.dart'; +import 'package:diplomaticquarterapp/pages/BookAppointment/SearchResults.dart'; import 'package:diplomaticquarterapp/pages/MyAppointments/AppointmentDetails.dart'; import 'package:diplomaticquarterapp/pages/ToDoList/payment_method_select.dart'; import 'package:diplomaticquarterapp/pages/ToDoList/widgets/paymentDialog.dart'; -import 'package:diplomaticquarterapp/pages/feedback/appointment_history.dart'; import 'package:diplomaticquarterapp/routes.dart'; import 'package:diplomaticquarterapp/services/appointment_services/GetDoctorsList.dart'; import 'package:diplomaticquarterapp/theme/colors.dart'; @@ -36,6 +38,7 @@ import 'package:rating_bar/rating_bar.dart'; class ToDo extends StatefulWidget { PatientShareResponse patientShareResponse; List appoList = []; + List obGyneAppoList = []; var languageID; MyInAppBrowser browser; @@ -48,7 +51,7 @@ class ToDo extends StatefulWidget { _ToDoState createState() => _ToDoState(); } -class _ToDoState extends State { +class _ToDoState extends State with SingleTickerProviderStateMixin { AppSharedPreferences sharedPref = AppSharedPreferences(); List imagesInfo = List(); @@ -56,10 +59,12 @@ class _ToDoState extends State { CountdownTimerController controller; ProjectViewModel projectViewModel; + TabController _tabController; @override void initState() { widget.patientShareResponse = new PatientShareResponse(); + _tabController = TabController(length: 2, vsync: this); WidgetsBinding.instance.addPostFrameCallback((_) { getPatientAppointmentHistory(); }); @@ -70,6 +75,12 @@ class _ToDoState extends State { controller = CountdownTimerController(endTime: endTime); } + @override + void dispose() { + super.dispose(); + _tabController.dispose(); + } + @override Widget build(BuildContext context) { toDoProvider = Provider.of(context); @@ -85,173 +96,305 @@ class _ToDoState extends State { description: TranslationBase.of(context).infoTodo, onTap: widget.onBackClick, backgroundColor: CustomColors.appBackgroudGrey2Color, - body: SingleChildScrollView( - child: Column( - children: [ - Container( - child: ListView.builder( - scrollDirection: Axis.vertical, - shrinkWrap: true, - physics: ScrollPhysics(), - padding: EdgeInsets.all(0.0), - itemCount: widget.appoList.length, - itemBuilder: (context, index) { - return Container( - width: double.infinity, - margin: EdgeInsets.only(left: 12.0, right: 12.0, top: 12.0), - decoration: cardRadius(12), - padding: EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + body: Column( + children: [ + TabBar( + controller: _tabController, + indicatorWeight: 3.0, + indicatorSize: TabBarIndicatorSize.tab, + labelColor: Color(0xff2B353E), + unselectedLabelColor: Color(0xff575757), + labelPadding: EdgeInsets.only(top: 15, bottom: 13, left: 20, right: 20), + labelStyle: TextStyle( + fontFamily: projectViewModel.isArabic ? 'Cairo' : 'Poppins', + fontSize: 16, + fontWeight: FontWeight.w600, + letterSpacing: -0.48, + ), + unselectedLabelStyle: TextStyle( + fontFamily: projectViewModel.isArabic ? 'Cairo' : 'Poppins', + fontSize: 16, + fontWeight: FontWeight.w600, + letterSpacing: -0.48, + ), + tabs: [Text(TranslationBase.of(context).appointments), Text(TranslationBase.of(context).orders)], + onTap: (index) { + if (index == 1) { + getOBGyneOrdersList(); + } + }, + ), + Expanded( + child: TabBarView( + physics: BouncingScrollPhysics(), + controller: _tabController, + children: [ + Container( + child: ListView.builder( + scrollDirection: Axis.vertical, + shrinkWrap: true, + physics: ScrollPhysics(), + padding: EdgeInsets.all(0.0), + itemCount: widget.appoList.length, + itemBuilder: (context, index) { + return Container( + width: double.infinity, + margin: EdgeInsets.only(left: 12.0, right: 12.0, top: 12.0), + decoration: cardRadius(12), + padding: EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Padding( - padding: const EdgeInsets.only(top: 4.0), - child: widget.appoList[index].clinicID == 265 - ? Container( - margin: EdgeInsets.only(left: 5.0, right: 5.0), - child: SvgPicture.asset("assets/images/new/CoronaIcon.svg", width: 35.0, height: 35.0), - ) - : widget.appoList[index].isLiveCareAppointment - ? SvgPicture.asset("assets/images/new/virtual.svg") - : SvgPicture.asset("assets/images/new/hospital-visit.svg"), - - // SvgPicture.asset("assets/images/new/virtual.svg"), - ), - Column( + Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( - padding: const EdgeInsets.only(left: 8.0, right: 8.0), - child: Text( - widget.appoList[index].clinicID == 265 - ? TranslationBase.of(context).covidTestTodo - : widget.appoList[index].isLiveCareAppointment - ? TranslationBase.of(context).liveCareAppo - : TranslationBase.of(context).walkinAppo, - style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.48)), + padding: const EdgeInsets.only(top: 4.0), + child: widget.appoList[index].clinicID == 265 + ? Container( + margin: EdgeInsets.only(left: 5.0, right: 5.0), + child: SvgPicture.asset("assets/images/new/CoronaIcon.svg", width: 35.0, height: 35.0), + ) + : widget.appoList[index].isLiveCareAppointment + ? SvgPicture.asset("assets/images/new/virtual.svg") + : SvgPicture.asset("assets/images/new/hospital-visit.svg"), + + // SvgPicture.asset("assets/images/new/virtual.svg"), ), - Padding( - padding: const EdgeInsets.only(left: 8.0, right: 8.0), - child: CountdownTimer( - controller: new CountdownTimerController(endTime: DateTime.now().millisecondsSinceEpoch + (widget.appoList[index].remaniningHoursTocanPay * 1000) * 60), - widgetBuilder: (_, CurrentRemainingTime time) { - return time != null - ? Text( - '${time.days != null ? time.days : "0"}:${time.hours != null ? time.hours.toString().length == 1 ? "0" + time.hours.toString() : time.hours : "00"}:${time.min}:${time.sec} ' + - TranslationBase.of(context).upcomingTimeLeft, - style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: CustomColors.accentColor, letterSpacing: -0.48)) - : Container(); - }, - ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(left: 8.0, right: 8.0), + child: Text( + widget.appoList[index].clinicID == 265 + ? TranslationBase.of(context).covidTestTodo + : widget.appoList[index].isLiveCareAppointment + ? TranslationBase.of(context).liveCareAppo + : TranslationBase.of(context).walkinAppo, + style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.48)), + ), + Padding( + padding: const EdgeInsets.only(left: 8.0, right: 8.0), + child: CountdownTimer( + controller: new CountdownTimerController(endTime: DateTime.now().millisecondsSinceEpoch + (widget.appoList[index].remaniningHoursTocanPay * 1000) * 60), + widgetBuilder: (_, CurrentRemainingTime time) { + return time != null + ? Text( + '${time.days != null ? time.days : "0"}:${time.hours != null ? time.hours.toString().length == 1 ? "0" + time.hours.toString() : time.hours : "00"}:${time.min}:${time.sec} ' + + TranslationBase.of(context).upcomingTimeLeft, + style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: CustomColors.accentColor, letterSpacing: -0.48)) + : Container(); + }, + ), + ), + ], ), ], ), + Container( + child: InkWell( + onTap: () { + performNextAction(widget.appoList[index]); + }, + child: Container( + padding: EdgeInsets.symmetric(vertical: 8, horizontal: 14), + decoration: BoxDecoration( + color: getNextActionButtonColor(widget.appoList[index].nextAction), + border: Border.all(color: Colors.white, width: 1), + borderRadius: BorderRadius.circular(6), + ), + child: Text( + getNextActionText(widget.appoList[index].nextAction), + style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Colors.white, letterSpacing: -0.4), + ), + ), + ), + ), ], ), - Container( - child: InkWell( - onTap: () { - performNextAction(widget.appoList[index]); - }, - child: Container( - padding: EdgeInsets.symmetric(vertical: 8, horizontal: 14), - decoration: BoxDecoration( - color: getNextActionButtonColor(widget.appoList[index].nextAction), - border: Border.all(color: Colors.white, width: 1), - borderRadius: BorderRadius.circular(6), - ), - child: Text( - getNextActionText(widget.appoList[index].nextAction), - style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Colors.white, letterSpacing: -0.4), + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Text( + widget.appoList[index].doctorTitle + " " + widget.appoList[index].doctorNameObj, + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xff2E303A), letterSpacing: -0.64, height: 25 / 16), + ), + ), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + LargeAvatar( + name: widget.appoList[index].doctorTitle + " " + widget.appoList[index].doctorNameObj, + url: widget.appoList[index].doctorImageURL, + width: 52, + height: 52, + ), + SizedBox(width: 11), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + MyRichText(TranslationBase.of(context).clinic + ": ", widget.appoList[index].clinicName, projectViewModel.isArabic), + MyRichText(TranslationBase.of(context).appointmentDate + ": ", + DateUtil.getDayMonthYearHourMinuteDateFormatted(DateUtil.convertStringToDate(widget.appoList[index].appointmentDate)), projectViewModel.isArabic), + MyRichText(TranslationBase.of(context).branch, widget.appoList[index].projectName, projectViewModel.isArabic), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisSize: MainAxisSize.max, + children: [ + RatingBar.readOnly( + initialRating: widget.appoList[index].actualDoctorRate.toDouble(), + size: 16.0, + filledColor: Color(0XFFD02127), + emptyColor: Color(0XFFD02127), + isHalfAllowed: true, + halfFilledIcon: Icons.star_half, + filledIcon: Icons.star, + emptyIcon: Icons.star_border, + ), + ], + ), + ], ), ), + ], + ), + Padding( + padding: const EdgeInsets.only(top: 12.0), + child: Text( + getNextActionDescription(widget.appoList[index].nextAction), + style: TextStyle(fontSize: 10, fontWeight: FontWeight.w600, color: Color(0xff2E303A), letterSpacing: -0.48, height: 25 / 16), + ), + ), + InkWell( + onTap: () { + navigateToAppointmentDetails(context, widget.appoList[index]); + }, + child: Padding( + padding: const EdgeInsets.only(top: 0.0), + child: Text( + TranslationBase.of(context).moreDetails, + style: TextStyle( + fontSize: 10, fontWeight: FontWeight.w600, color: CustomColors.accentColor, letterSpacing: -0.48, height: 25 / 16, decoration: TextDecoration.underline), + ), ), ), ], ), - Padding( - padding: const EdgeInsets.only(top: 8.0), - child: Text( - widget.appoList[index].doctorTitle + " " + widget.appoList[index].doctorNameObj, - style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xff2E303A), letterSpacing: -0.64, height: 25 / 16), - ), - ), - Row( - mainAxisSize: MainAxisSize.min, - children: [ - LargeAvatar( - name: widget.appoList[index].doctorTitle + " " + widget.appoList[index].doctorNameObj, - url: widget.appoList[index].doctorImageURL, - width: 52, - height: 52, + ); + }, + ), + ), + Container( + child: ListView.builder( + scrollDirection: Axis.vertical, + shrinkWrap: true, + physics: ScrollPhysics(), + padding: EdgeInsets.all(0.0), + itemCount: widget.obGyneAppoList.length, + itemBuilder: (context, index) { + return Container( + width: double.infinity, + margin: EdgeInsets.only(left: 12.0, right: 12.0, top: 12.0), + decoration: cardRadius(12), + padding: EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 0.0), + child: Container( + margin: EdgeInsets.only(left: 5.0, right: 5.0), + child: SvgPicture.asset("assets/images/new/ultrasound.svg", width: 20.0, height: 20.0), + ), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(left: 8.0, right: 8.0), + child: Text(TranslationBase.of(context).walkinAppo, + style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.48)), + ), + ], + ), + ], + ), + Container( + child: InkWell( + onTap: () { + getOBGyneDoctorsList(widget.obGyneAppoList[index].projectID, widget.obGyneAppoList[index].setupID, widget.obGyneAppoList[index]); + }, + child: Container( + padding: EdgeInsets.symmetric(vertical: 8, horizontal: 14), + decoration: BoxDecoration( + color: CustomColors.green, + border: Border.all(color: Colors.white, width: 1), + borderRadius: BorderRadius.circular(6), + ), + child: Text( + TranslationBase.of(context).bookNow, + style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Colors.white, letterSpacing: -0.4), + ), + ), + ), + ), + ], ), - SizedBox(width: 11), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - MyRichText(TranslationBase.of(context).clinic + ": ", widget.appoList[index].clinicName, projectViewModel.isArabic), - MyRichText(TranslationBase.of(context).appointmentDate + ": ", - DateUtil.getDayMonthYearHourMinuteDateFormatted(DateUtil.convertStringToDate(widget.appoList[index].appointmentDate)), projectViewModel.isArabic), - MyRichText(TranslationBase.of(context).branch, widget.appoList[index].projectName, projectViewModel.isArabic), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - mainAxisSize: MainAxisSize.max, + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Text( + TranslationBase.of(context).dr + " " + widget.obGyneAppoList[index].doctorName, + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xff2E303A), letterSpacing: -0.64, height: 25 / 16), + ), + ), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + LargeAvatar( + name: TranslationBase.of(context).dr + " " + widget.obGyneAppoList[index].doctorName, + url: "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown.png", + width: 52, + height: 52, + ), + SizedBox(width: 11), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, children: [ - RatingBar.readOnly( - initialRating: widget.appoList[index].actualDoctorRate.toDouble(), - size: 16.0, - filledColor: Color(0XFFD02127), - emptyColor: Color(0XFFD02127), - isHalfAllowed: true, - halfFilledIcon: Icons.star_half, - filledIcon: Icons.star, - emptyIcon: Icons.star_border, - ), + MyRichText(TranslationBase.of(context).clinic + ": ", widget.obGyneAppoList[index].clinicDescription, projectViewModel.isArabic), + MyRichText(TranslationBase.of(context).orderDate + ": ", + DateUtil.getDayMonthYearHourMinuteDateFormatted(DateUtil.convertStringToDate(widget.obGyneAppoList[index].orderDate)).split(" ")[0], projectViewModel.isArabic), + MyRichText(TranslationBase.of(context).branch, widget.obGyneAppoList[index].projectDescription, projectViewModel.isArabic), ], ), - ], - ), + ), + ], ), ], ), - Padding( - padding: const EdgeInsets.only(top: 12.0), - child: Text( - getNextActionDescription(widget.appoList[index].nextAction), - style: TextStyle(fontSize: 10, fontWeight: FontWeight.w600, color: Color(0xff2E303A), letterSpacing: -0.48, height: 25 / 16), - ), - ), - InkWell( - onTap: () { - navigateToAppointmentDetails(context, widget.appoList[index]); - }, - child: Padding( - padding: const EdgeInsets.only(top: 0.0), - child: Text( - TranslationBase.of(context).moreDetails, - style: TextStyle(fontSize: 10, fontWeight: FontWeight.w600, color: CustomColors.accentColor, letterSpacing: -0.48, height: 25 / 16, decoration: TextDecoration.underline), - ), - ), - ), - ], - ), - ); - }, - ), - ), - SizedBox( - height: 120.0, + ); + }, + ), + ), + ], ), - ], - ), + ), + SizedBox( + height: 120.0, + ), + ], ), ); } @@ -492,33 +635,74 @@ class _ToDoState extends State { } getOBGyneOrdersList() { + GifLoaderDialogUtils.showMyDialog(context); DoctorsListService service = new DoctorsListService(); - service.getOBGyneOrdersList(context).then((res) { - print(res['HIS_OBGYNEProcedureGet_List']); - // widget.appoList.clear(); - // GifLoaderDialogUtils.hideDialog(context); - // if (res['MessageStatus'] == 1) { - // setState(() { - // if (res['AppoimentAllHistoryResultList'].length != 0) { - // widget.appoList.clear(); - // res['AppoimentAllHistoryResultList'].forEach((v) { - // widget.appoList.add(new AppoitmentAllHistoryResultList.fromJson(v)); - // }); - // } else { - // Navigator.of(context).popAndPushNamed(HOME); - // } - // }); - // } else { - // AppToast.showErrorToast(message: res['ErrorEndUserMessage']); - // } + widget.obGyneAppoList.clear(); + GifLoaderDialogUtils.hideDialog(context); + if (res['MessageStatus'] == 1) { + setState(() { + if (res['HIS_OBGYNEProcedureGet_List'].length != 0) { + widget.obGyneAppoList.clear(); + res['HIS_OBGYNEProcedureGet_List'].forEach((v) { + widget.obGyneAppoList.add(new OBGyneProcedureListResponse.fromJson(v)); + }); + } else { + // Navigator.of(context).popAndPushNamed(HOME); + } + }); + } else { + AppToast.showErrorToast(message: res['ErrorEndUserMessage']); + } }).catchError((err) { + GifLoaderDialogUtils.hideDialog(context); print(err); - // GifLoaderDialogUtils.hideDialog(context); - // err != null ?? AppToast.showErrorToast(message: err); }); } + getOBGyneDoctorsList(int projectID, String setupID, OBGyneProcedureListResponse obGyneProcedureListResponse) { + GifLoaderDialogUtils.showMyDialog(context); + DoctorsListService service = new DoctorsListService(); + List doctorsList = []; + List _patientDoctorAppointmentListHospital = []; + service.getOBGyneDoctorsList(projectID, setupID, context).then((res) { + GifLoaderDialogUtils.hideDialog(context); + print(res['HIS_ObgyneUltrasoundDoctorsList'][0]); + if (res['MessageStatus'] == 1) { + setState(() { + if (res['HIS_ObgyneUltrasoundDoctorsList'].length != 0) { + res['HIS_ObgyneUltrasoundDoctorsList'].forEach((v) { + doctorsList.add(new DoctorList.fromJson(v)); + }); + print(doctorsList.length); + doctorsList.forEach((element) { + List doctorByHospital = _patientDoctorAppointmentListHospital.where((elementClinic) => elementClinic.filterName == element.projectName).toList(); + + if (doctorByHospital.length != 0) { + _patientDoctorAppointmentListHospital[_patientDoctorAppointmentListHospital.indexOf(doctorByHospital[0])].patientDoctorAppointmentList.add(element); + } else { + _patientDoctorAppointmentListHospital + .add(PatientDoctorAppointmentList(filterName: element.projectName, distanceInKMs: element.projectDistanceInKiloMeters.toString(), patientDoctorAppointment: element)); + } + }); + navigateToSearchResults(context, doctorsList, _patientDoctorAppointmentListHospital, obGyneProcedureListResponse); + } else { + // Navigator.of(context).popAndPushNamed(HOME); + } + }); + } else { + AppToast.showErrorToast(message: res['ErrorEndUserMessage']); + } + }).catchError((err) { + GifLoaderDialogUtils.hideDialog(context); + print(err); + }); + } + + navigateToSearchResults(context, List docList, List patientDoctorAppointmentListHospital, OBGyneProcedureListResponse obGyneProcedureListResponse) { + Navigator.push(context, FadePage(page: SearchResults(isLiveCareAppointment: false, isObGyneAppointment: true, doctorsList: docList, patientDoctorAppointmentListHospital: patientDoctorAppointmentListHospital, obGyneProcedureListResponse: obGyneProcedureListResponse))); + } + getPatientAppointmentHistory() { GifLoaderDialogUtils.showMyDialog(context); DoctorsListService service = new DoctorsListService(); @@ -533,10 +717,9 @@ class _ToDoState extends State { widget.appoList.add(new AppoitmentAllHistoryResultList.fromJson(v)); }); } else { - Navigator.of(context).popAndPushNamed(HOME); + // Navigator.of(context).popAndPushNamed(HOME); } }); - getOBGyneOrdersList(); } else { AppToast.showErrorToast(message: res['ErrorEndUserMessage']); } @@ -603,14 +786,7 @@ class _ToDoState extends State { } Future navigateToQR(context, String appoQR, PatientShareResponse patientShareResponse, AppoitmentAllHistoryResultList appintment) async { - Navigator.push( - context, - FadePage( - page: QRCode( - patientShareResponse: patientShareResponse, - appoQR: appoQR, - appointment: appintment - ))).then((value) { + Navigator.push(context, FadePage(page: QRCode(patientShareResponse: patientShareResponse, appoQR: appoQR, appointment: appintment))).then((value) { getPatientAppointmentHistory(); }); } @@ -635,11 +811,10 @@ class _ToDoState extends State { context: context, pageBuilder: (context, animation1, animation2) {}) .then((value) { - if (value != null) { projectViewModel.analytics.todoList.to_do_list_confirm_payment_details(appo); navigateToPaymentMethod(context, value, appo); - }else{ + } else { projectViewModel.analytics.todoList.to_do_list_cancel_payment_details(appo); } }); @@ -766,7 +941,6 @@ class _ToDoState extends State { } confirmAppointment(AppoitmentAllHistoryResultList appo) { - GifLoaderDialogUtils.showMyDialog(context); DoctorsListService service = new DoctorsListService(); service.confirmAppointment(appo.appointmentNo, appo.clinicID, appo.projectID, appo.isLiveCareAppointment, context).then((res) { diff --git a/lib/pages/landing/landing_page.dart b/lib/pages/landing/landing_page.dart index 40ff61f9..3a980884 100644 --- a/lib/pages/landing/landing_page.dart +++ b/lib/pages/landing/landing_page.dart @@ -18,6 +18,7 @@ import 'package:diplomaticquarterapp/pages/landing/home_page_2.dart'; import 'package:diplomaticquarterapp/pages/livecare/incoming_call.dart'; import 'package:diplomaticquarterapp/pages/medical/medical_profile_page_new.dart'; import 'package:diplomaticquarterapp/services/authentication/auth_provider.dart'; +import 'package:diplomaticquarterapp/services/clinic_services/get_clinic_service.dart'; import 'package:diplomaticquarterapp/services/family_files/family_files_provider.dart' as family; import 'package:diplomaticquarterapp/services/robo_search/event_provider.dart'; import 'package:diplomaticquarterapp/theme/colors.dart'; @@ -201,6 +202,21 @@ class _LandingPageState extends State with WidgetsBindingObserver { }); } + getToDoCount() { + toDoProvider.setState(0, true, toDoProvider.notificationsCount); + ClinicListService service = new ClinicListService(); + service.getActiveAppointmentNo(context).then((res) { + GifLoaderDialogUtils.hideDialog(context); + print(res['AppointmentActiveNumber']); + if (res['MessageStatus'] == 1) { + toDoProvider.setState(res['AppointmentActiveNumber'], true, toDoProvider.notificationsCount); + } else {} + }).catchError((err) { + GifLoaderDialogUtils.hideDialog(context); + print(err); + }); + } + @override void didChangeAppLifecycleState(AppLifecycleState state) { super.didChangeAppLifecycleState(state); diff --git a/lib/pages/pharmacies/screens/lakum-main-page.dart b/lib/pages/pharmacies/screens/lakum-main-page.dart index 5dc60fda..c93804fc 100644 --- a/lib/pages/pharmacies/screens/lakum-main-page.dart +++ b/lib/pages/pharmacies/screens/lakum-main-page.dart @@ -88,7 +88,7 @@ class LakumMainPage extends StatelessWidget { SizedBox( width: 8, ), - LacumPointsWidget(mediaQuery, 2, TranslationBase.of(context).gained, model.lacumGroupInformation.lakumInquiryInformationObjVersion.pointsBalanceAmount, + LacumPointsWidget(mediaQuery, 2, TranslationBase.of(context).gained, model.lacumGroupInformation.lakumInquiryInformationObjVersion.gainedPointsAmount, model.lacumGroupInformation.lakumInquiryInformationObjVersion.gainedPoints, model.lacumGroupInformation.lakumInquiryInformationObjVersion.gainedPointsAmountPerYear), SizedBox( width: 8, diff --git a/lib/services/appointment_services/GetDoctorsList.dart b/lib/services/appointment_services/GetDoctorsList.dart index d42fbe3a..15a97515 100644 --- a/lib/services/appointment_services/GetDoctorsList.dart +++ b/lib/services/appointment_services/GetDoctorsList.dart @@ -514,15 +514,8 @@ class DoctorsListService extends BaseService { Request req = appGlobal.getPublicRequest(); request = { - "VersionID": req.VersionID, - "Channel": req.Channel, "LanguageID": languageID == 'ar' ? 1 : 2, - "IPAdress": req.IPAdress, "ProjectID": 15, - "generalid": req.generalid, - "PatientOutSA": 0, - "SessionID": "YckwoXhUmWBsnHKEKig", - "isDentalAllowedBackend": false, "DeviceTypeID": req.DeviceTypeID, "PatientID": authUser.patientID, "PatientTypeID": authUser.patientType, @@ -539,6 +532,38 @@ class DoctorsListService extends BaseService { return Future.value(localRes); } + Future getOBGyneDoctorsList(int projectID, String setupID, BuildContext context) async { + Map request; + + if (await this.sharedPref.getObject(USER_PROFILE) != null) { + var data = AuthenticatedUser.fromJson(await this.sharedPref.getObject(USER_PROFILE)); + authUser = data; + } + + var languageID = await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar'); + Request req = appGlobal.getPublicRequest(); + + request = { + "LanguageID": languageID == 'ar' ? 1 : 2, + "ProjectID": projectID, + "SetupID": setupID, + "isDentalAllowedBackend": false, + "DeviceTypeID": req.DeviceTypeID, + "PatientID": authUser.patientID, + "PatientTypeID": authUser.patientType, + "PatientType": authUser.patientType + }; + + dynamic localRes; + + await baseAppClient.post(GET_OBGYNE_DOCTORS_LIST, onSuccess: (response, statusCode) async { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request); + return Future.value(localRes); + } + Future getPatientAppointmentHistory(bool isActiveAppointment, BuildContext context, {bool isForCOC = false}) async { Map request; @@ -1485,4 +1510,28 @@ class DoctorsListService extends BaseService { return Future.value(localRes); } + + Future updateObGyneAppointment(int episodeID, int appointmentNo, int orderNo, String procedureId, int lineItemNo, int uniqueRowID) async { + Map request; + + request = { + "EpisodeID": episodeID, + "AppointmentNo": appointmentNo, + "OrderNo": orderNo, + "ProcedureId": procedureId, + "ProcedureAppointmentNo": appointmentNo, + "LineItemNo": lineItemNo, + "UniqueRowID": uniqueRowID + }; + + dynamic localRes; + await baseAppClient.post(UPDATE_COVID_QUESTIONNAIRE, onSuccess: (response, statusCode) async { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request); + + return Future.value(localRes); + } + } diff --git a/lib/services/livecare_services/livecare_provider.dart b/lib/services/livecare_services/livecare_provider.dart index 552b7d16..441de08d 100644 --- a/lib/services/livecare_services/livecare_provider.dart +++ b/lib/services/livecare_services/livecare_provider.dart @@ -5,7 +5,6 @@ import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/core/service/base_service.dart'; import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; import 'package:diplomaticquarterapp/models/LiveCare/ApplePayInsertRequest.dart'; -import 'package:diplomaticquarterapp/models/Request.dart'; import 'package:diplomaticquarterapp/services/authentication/auth_provider.dart'; import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; import 'package:flutter/material.dart'; @@ -25,11 +24,7 @@ class LiveCareService extends BaseService { authUser = data; } - request = { - "Age": authUser.age != null ? authUser.age : 0, - "PatientID": authUser.patientID != null ? authUser.patientID : 0, - "Gender": authUser.gender != null ? authUser.gender : 0 - }; + request = {"Age": authUser.age != null ? authUser.age : 0, "PatientID": authUser.patientID != null ? authUser.patientID : 0, "Gender": authUser.gender != null ? authUser.gender : 0}; dynamic localRes; @@ -49,11 +44,7 @@ class LiveCareService extends BaseService { authUser = data; } - request = { - "Age": authUser.age != null ? authUser.age : 0, - "PatientID": authUser.patientID != null ? authUser.patientID : 0, - "Gender": authUser.gender != null ? authUser.gender : 0 - }; + request = {"Age": authUser.age != null ? authUser.age : 0, "PatientID": authUser.patientID != null ? authUser.patientID : 0, "Gender": authUser.gender != null ? authUser.gender : 0}; dynamic localRes; @@ -99,10 +90,6 @@ class LiveCareService extends BaseService { authUser = data; } - // var languageID = await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar'); -// Request req = appGlobal.getPublicRequest(); -// request = {"LanguageID": languageID == 'ar' ? 1 : 2, "TokenID": "", "SessionID": "YckwoXhUmWBsnHKEKig"}; - dynamic localRes; await baseAppClient.post(GET_LIVECARE_HISTORY, onSuccess: (response, statusCode) async { @@ -113,6 +100,26 @@ class LiveCareService extends BaseService { return Future.value(localRes); } + Future getPatientInfoByQR(String clientID, BuildContext context) async { + if (await this.sharedPref.getObject(USER_PROFILE) != null) { + var data = AuthenticatedUser.fromJson(await this.sharedPref.getObject(USER_PROFILE)); + authUser = data; + } + + var languageID = await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar'); + Map request; + request = {"clientid": clientID, "patientid": authUser.patientID, "isOutKsa": authUser.outSA == 1 ? true : false, "appLang": languageID == 'ar' ? "1" : "2"}; + + dynamic localRes; + + await baseAppClient.post("https://vcallapi.hmg.com/api/PharmaLiveCare/getPatientInfoByQR", onSuccess: (response, statusCode) async { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request, isExternal: true); + return Future.value(localRes); + } + Future getLivecareClinicTiming(int serviceID, BuildContext context) async { Map request; diff --git a/lib/uitl/translations_delegate_base.dart b/lib/uitl/translations_delegate_base.dart index a367df0d..9ed7671a 100644 --- a/lib/uitl/translations_delegate_base.dart +++ b/lib/uitl/translations_delegate_base.dart @@ -2827,6 +2827,8 @@ class TranslationBase { String get ancillaryOrdersPaymentConfirm => localizedValues["ancillaryOrdersPaymentConfirm"][locale.languageCode]; String get covidTestTodo => localizedValues["covidTestTodo"][locale.languageCode]; String get successRegister => localizedValues["successRegister"][locale.languageCode]; + String get pharmacyLiveCare => localizedValues["pharmacyLiveCare"][locale.languageCode]; + } class TranslationBaseDelegate extends LocalizationsDelegate { diff --git a/lib/widgets/drawer/app_drawer_widget.dart b/lib/widgets/drawer/app_drawer_widget.dart index e8572670..c74eb3d3 100644 --- a/lib/widgets/drawer/app_drawer_widget.dart +++ b/lib/widgets/drawer/app_drawer_widget.dart @@ -1,3 +1,4 @@ +import 'package:barcode_scan2/barcode_scan2.dart'; import 'package:diplomaticquarterapp/analytics/google-analytics.dart'; import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; @@ -15,12 +16,11 @@ import 'package:diplomaticquarterapp/models/FamilyFiles/GetAllSharedRecordByStat import 'package:diplomaticquarterapp/pages/DrawerPages/notifications/notifications_page.dart'; import 'package:diplomaticquarterapp/pages/landing/landing_page.dart'; import 'package:diplomaticquarterapp/pages/rateAppointment/rate_appointment_doctor.dart'; -import 'package:diplomaticquarterapp/pages/webRTC/call_page.dart'; -import 'package:diplomaticquarterapp/pages/webRTC/call_page_bkp.dart'; import 'package:diplomaticquarterapp/routes.dart'; import 'package:diplomaticquarterapp/services/authentication/auth_provider.dart'; import 'package:diplomaticquarterapp/services/clinic_services/get_clinic_service.dart'; import 'package:diplomaticquarterapp/services/family_files/family_files_provider.dart'; +import 'package:diplomaticquarterapp/services/livecare_services/livecare_provider.dart'; import 'package:diplomaticquarterapp/theme/colors.dart'; import 'package:diplomaticquarterapp/theme/theme_notifier.dart'; import 'package:diplomaticquarterapp/theme/theme_value.dart'; @@ -194,11 +194,23 @@ class _AppDrawerState extends State { Navigator.of(context).pushNamed( MY_FAMILIY, ); - locator().hamburgerMenu.logMenuItemClick('my family'); }, ) : SizedBox(), + InkWell( + child: DrawerItem(TranslationBase.of(context).pharmacyLiveCare, SvgPicture.asset("assets/images/new/Live_Care.svg"), + isImageIcon: true, + bottomLine: false, + textColor: Theme.of(context).textTheme.bodyText1.color, + iconColor: Theme.of(context).textTheme.bodyText1.color, + sideArrow: true, + letterSpacing: -0.84, + projectProvider: projectProvider), + onTap: () { + readQRCode(); + }, + ), FutureBuilder( future: getFamilyFiles(), // async work builder: (BuildContext context, AsyncSnapshot snapshot) { @@ -435,11 +447,7 @@ class _AppDrawerState extends State { locator().hamburgerMenu.logMenuItemClick('cloud solution logo tap'); String patientID = '2001273'; GifLoaderDialogUtils.showMyDialog(context); - projectProvider - .platformBridge() - .connectHMGInternetWifi(patientID) - .then((value) => {GifLoaderDialogUtils.hideDialog(context)}) - .catchError((err) { + projectProvider.platformBridge().connectHMGInternetWifi(patientID).then((value) => {GifLoaderDialogUtils.hideDialog(context)}).catchError((err) { print(err.toString()); }); }, @@ -636,8 +644,19 @@ class _AppDrawerState extends State { }) .catchError((err) { print(err); - //Utils.hideProgressDialog(); - // GifLoaderDialogUtils.hideDialog(context); + }); + } + + readQRCode() async { + String result = (await BarcodeScanner.scan())?.rawContent; + print(result); + GifLoaderDialogUtils.showMyDialog(context); + LiveCareService service = new LiveCareService(); + service.getPatientInfoByQR(result, context).then((res) { + GifLoaderDialogUtils.hideDialog(context); + }).catchError((err) { + GifLoaderDialogUtils.hideDialog(context); + print(err); }); }