From 24b7bca471112a56d4f4277492f4b3a918438b1c Mon Sep 17 00:00:00 2001 From: Sultan Khan Date: Wed, 25 Nov 2020 17:21:33 +0300 Subject: [PATCH 01/71] no message --- lib/config/config.dart | 4 +- lib/config/localized_values.dart | 12 ++ .../all_habib_medical_service_page.dart | 12 +- lib/pages/Blood/blood_donation.dart | 128 ++---------------- lib/pages/login/confirm-login.dart | 2 +- lib/uitl/translations_delegate_base.dart | 3 + 6 files changed, 42 insertions(+), 119 deletions(-) diff --git a/lib/config/config.dart b/lib/config/config.dart index 58ade1bc..2592d1b2 100644 --- a/lib/config/config.dart +++ b/lib/config/config.dart @@ -7,8 +7,8 @@ import 'package:diplomaticquarterapp/widgets/mobile-no/mobile_no.dart'; const MAX_SMALL_SCREEN = 660; -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/'; const GET_PROJECT = 'Services/Lists.svc/REST/GetProject'; ///Doctor diff --git a/lib/config/localized_values.dart b/lib/config/localized_values.dart index b75baf2e..7843bff1 100644 --- a/lib/config/localized_values.dart +++ b/lib/config/localized_values.dart @@ -999,4 +999,16 @@ const Map localizedValues = { "searchItemError": {"en": "Item name should be more than 3 character ", "ar": "يجب أن يكون اسم العنصر أكثر من 3 أحرف"}, "YouCanFind": {"en": "YouCanFind", "ar": "باستطاعتك العثور على "}, "ItemInSearch": {"en": " Item In Search", "ar": " عنصر في البحث "}, + "blood-donation": { + "en": "Blood Donation", + "ar": "التبرع بالدم" + }, + "blood-instruction": { + "en": "Enter the required information, In order to register for Blood Donation Service", + "ar": "ادخل المعلومات المطلوبة للتسجيل بخدمة التبرع بالدم" + }, + "view-terms": { + "en": "To view the terms and conditions", + "ar": "عرض الشروط والأحكام" + } }; diff --git a/lib/pages/AlHabibMedicalService/all_habib_medical_service_page.dart b/lib/pages/AlHabibMedicalService/all_habib_medical_service_page.dart index 7e3d4181..2ecacc9a 100644 --- a/lib/pages/AlHabibMedicalService/all_habib_medical_service_page.dart +++ b/lib/pages/AlHabibMedicalService/all_habib_medical_service_page.dart @@ -187,7 +187,17 @@ class _AllHabibMedicalServiceState extends State { 'assets/images/new-design/upcoming_icon_bottom_bar.png', title: TranslationBase.of(context).todoList, ), - + ServicesContainer( + onTap: () => Navigator.push( + context, + FadePage( + page: BloodDonationPage(), + ), + ), + imageLocation: + 'assets/images/new-design/blood_icon.png', + title: TranslationBase.of(context).bloodDonation, + ), ServicesContainer( onTap: () => Navigator.push( context, diff --git a/lib/pages/Blood/blood_donation.dart b/lib/pages/Blood/blood_donation.dart index 99e5242e..a2e46ff6 100644 --- a/lib/pages/Blood/blood_donation.dart +++ b/lib/pages/Blood/blood_donation.dart @@ -23,6 +23,7 @@ import 'package:diplomaticquarterapp/uitl/utils.dart'; import 'package:diplomaticquarterapp/widgets/buttons/secondary_button.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:diplomaticquarterapp/widgets/text/app_texts_widget.dart'; import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -77,7 +78,7 @@ class _BloodDonationPageState extends State { onModelReady: (model) => model.getCities(),//model.getHospitals(), builder: (_, model, w) => AppScaffold( isShowAppBar: true, - appBarTitle: "Blood Donation",//TranslationBase.of(context).advancePayment, + appBarTitle: TranslationBase.of(context).bloodDonation,//TranslationBase.of(context).advancePayment, body: SingleChildScrollView( physics: ScrollPhysics(), child: Container( @@ -85,9 +86,8 @@ class _BloodDonationPageState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Texts( - // TranslationBase.of(context).advancePaymentLabel, - "Enter the required information, In order to register for Blood Donation Service",//+model.user.firstName, + AppText( + TranslationBase.of(context).bloodInstruction, textAlign: TextAlign.center, ), SizedBox( @@ -188,55 +188,24 @@ class _BloodDonationPageState extends State { ), ), ), - // if (beneficiaryType == BeneficiaryType.MyFamilyFiles) - // SizedBox( - // height: 12, - // ), - // if (beneficiaryType == BeneficiaryType.MyFamilyFiles) - // InkWell( - // onTap: () { - // model.getFamilyFiles().then((value) { - // confirmSelectFamilyDialog(model - // .getAllSharedRecordsByStatusResponse - // .getAllSharedRecordsByStatusList); - // }).showProgressBar( - // text: "Loading", - // backgroundColor: Colors.blue.withOpacity(0.6)); - // }, - // child: Container( - // padding: EdgeInsets.all(12), - // width: double.infinity, - // height: 65, - // decoration: BoxDecoration( - // borderRadius: BorderRadius.circular(12), - // color: Colors.white), - // child: Row( - // mainAxisAlignment: MainAxisAlignment.spaceBetween, - // children: [ - // Texts(getFamilyMembersName()), - // Icon(Icons.arrow_drop_down) - // ], - // ), - // ), - // ), + SizedBox( height: 12, ), Row( children: [ - Container( - child: Text(" To view the terms and conditions "), - ), - SizedBox( - width: MediaQuery.of(context).size.height * 0.10, - ), + AppText(TranslationBase.of(context).bloodTermsNcondition), + + // SizedBox( + // width: MediaQuery.of(context).size.height * 0.10, + // ), InkWell( onTap: () { Navigator.of(context).push(MaterialPageRoute( builder: (BuildContext context) => UserAgreementPage())); }, child: Container( - child: Texts(" Click here ",color: Colors.blue,), + child: Texts(" Click here ", color: Colors.blue,), ), ) ], @@ -269,77 +238,7 @@ class _BloodDonationPageState extends State { ), ], ), - // NewTextFields( - // hintText: TranslationBase.of(context).fileNumber, - // controller: _fileTextController, - // ), - // if (beneficiaryType == BeneficiaryType.OtherAccount) - // SizedBox( - // height: 12, - // ), - // if (beneficiaryType == BeneficiaryType.OtherAccount) - // InkWell( - // onTap: () { - // if (_fileTextController.text.isNotEmpty) - // model - // .getPatientInfoByPatientID( - // id: _fileTextController.text) - // .then((value) { - // confirmSelectPatientDialog(model.patientInfoList); - // }).showProgressBar( - // text: "Loading", - // backgroundColor: - // Colors.blue.withOpacity(0.6)); - // else - // AppToast.showErrorToast( - // message: 'Please Enter The File Number'); - // }, - // child: Container( - // padding: EdgeInsets.all(12), - // width: double.infinity, - // height: 65, - // decoration: BoxDecoration( - // borderRadius: BorderRadius.circular(12), - // color: Colors.white), - // child: Row( - // mainAxisAlignment: MainAxisAlignment.spaceBetween, - // children: [ - // Texts(getPatientName()), - // Icon(Icons.arrow_drop_down) - // ], - // ), - // ), - // ), - // SizedBox( - // height: 12, - // ), - - // NewTextFields( - // hintText: TranslationBase.of(context).amount, - // keyboardType: TextInputType.number, - // onChanged: (value) { - // setState(() { - // amount = value; - // }); - // }, - // ), - // SizedBox( - // height: 12, - // ), - // NewTextFields( - // hintText: TranslationBase.of(context).depositorEmail, - // initialValue: model.user.emailAddress, - // onChanged: (value) { - // email = value; - // }, - // ), - // SizedBox( - // height: 12, - // ), - // NewTextFields( - // hintText: TranslationBase.of(context).notes, - // controller: _notesTextController, - // ), + SizedBox( height: 10, ), @@ -393,9 +292,8 @@ class _BloodDonationPageState extends State { ), ), bottomSheet: Container( - height: MediaQuery.of(context).size.height * 0.12, + height: MediaQuery.of(context).size.height * 0.10, width: double.infinity, - padding: EdgeInsets.all(12), child: SecondaryButton( textColor: Colors.white, diff --git a/lib/pages/login/confirm-login.dart b/lib/pages/login/confirm-login.dart index 229e0a0f..87eaf1ce 100644 --- a/lib/pages/login/confirm-login.dart +++ b/lib/pages/login/confirm-login.dart @@ -370,7 +370,7 @@ class _ConfirmLogin extends State { if (authenticated == true) { - if(user.logInType==2 || user.logInType ==3){ + if(user !=null && (user.logInType==2 || user.logInType ==3)){ this.checkActivationCode(); }else{ var request = this.getCommonRequest(type: type); diff --git a/lib/uitl/translations_delegate_base.dart b/lib/uitl/translations_delegate_base.dart index c5fc8852..9b216940 100644 --- a/lib/uitl/translations_delegate_base.dart +++ b/lib/uitl/translations_delegate_base.dart @@ -855,6 +855,9 @@ String get fileno => localizedValues['fileno'][locale.languageCode]; String get searchItemError => localizedValues['searchItemError'][locale.languageCode]; String get youCanFind => localizedValues['YouCanFind'][locale.languageCode]; String get itemInSearch => localizedValues['ItemInSearch'][locale.languageCode]; + String get bloodDonation => localizedValues['blood-donation'][locale.languageCode]; + String get bloodInstruction => localizedValues['blood-instruction'][locale.languageCode]; + String get bloodTermsNcondition => localizedValues['view-terms'][locale.languageCode]; } From 8612ae91c42ff0683c7ffaca4bbb9e0d10baa9ec Mon Sep 17 00:00:00 2001 From: Sultan Khan Date: Sun, 29 Nov 2020 10:42:55 +0300 Subject: [PATCH 02/71] sultan --- lib/core/service/health-weather/health_weather_indicator.dart | 0 lib/pages/weather-indicator/health-indicator.dart | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 lib/core/service/health-weather/health_weather_indicator.dart create mode 100644 lib/pages/weather-indicator/health-indicator.dart diff --git a/lib/core/service/health-weather/health_weather_indicator.dart b/lib/core/service/health-weather/health_weather_indicator.dart new file mode 100644 index 00000000..e69de29b diff --git a/lib/pages/weather-indicator/health-indicator.dart b/lib/pages/weather-indicator/health-indicator.dart new file mode 100644 index 00000000..e69de29b From 799fca346b767817b5a12a30650533790d15146e Mon Sep 17 00:00:00 2001 From: Sultan Khan Date: Sun, 29 Nov 2020 10:43:11 +0300 Subject: [PATCH 03/71] health weather indicator --- .../health_weather_indicator.dart | 341 ++++++++++++++++++ lib/routes.dart | 4 +- 2 files changed, 344 insertions(+), 1 deletion(-) diff --git a/lib/core/service/health-weather/health_weather_indicator.dart b/lib/core/service/health-weather/health_weather_indicator.dart index e69de29b..24a3d117 100644 --- a/lib/core/service/health-weather/health_weather_indicator.dart +++ b/lib/core/service/health-weather/health_weather_indicator.dart @@ -0,0 +1,341 @@ +import 'package:diplomaticquarterapp/core/viewModels/er/near_hospital_view_model.dart'; +import 'package:diplomaticquarterapp/pages/ErService/widgets/card_position.dart'; +import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/uitl/location_util.dart'; +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/cupertino.dart'; +import 'package:flutter/material.dart'; + + +class HealthWeather extends StatelessWidget { + static const String _url = "assets/images/"; + + @override + Widget build(BuildContext context) { + return BaseView( + onModelReady: (){}, + builder: (_, mode, widget) => AppScaffold( + isShowAppBar: true, + appBarTitle: 'Nearest ER', + baseViewModel: mode, + body: mode.ProjectAvgERWaitingTimeModeList.length > 0 + ? Container( + child: ListView( + children: [ + Text( + "\nThis service Displays nearest branch\n among all the branches of All Habib \n medical Group based on your current Location", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 18.0, + letterSpacing: 1.0, + fontWeight: FontWeight.w900, + color: new Color(0xFF60686b))), + Container( + margin: EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Container( + child: CardPosition( + text: mode + .ProjectAvgERWaitingTimeModeList[0] + .projectName + .toString(), + image: + 'assets/images/new-design/find_us_icon.png', + subText: mode + .ProjectAvgERWaitingTimeModeList[0] + .distanceInKilometers + .toString(), + type: mode + .ProjectAvgERWaitingTimeModeList[0].iD + .toString(), + telephone: mode + .ProjectAvgERWaitingTimeModeList[0] + .phoneNumber + .toString(), + networkImage: mode + .ProjectAvgERWaitingTimeModeList[0] + .projectImageURL + .toString(), + latitude: mode + .ProjectAvgERWaitingTimeModeList[0] + .latitude, + longitude: mode + .ProjectAvgERWaitingTimeModeList[0] + .longitude, + projectname: mode + .ProjectAvgERWaitingTimeModeList[0] + .projectName, + ), + ), + + ), + Expanded( + child: Container( + child: CardPosition( + text: mode + .ProjectAvgERWaitingTimeModeList[1] + .projectName + .toString(), + image: + 'assets/images/new-design/find_us_icon.png', + subText: mode + .ProjectAvgERWaitingTimeModeList[1] + .distanceInKilometers + .toString(), + type: mode + .ProjectAvgERWaitingTimeModeList[1].iD + .toString(), + telephone: mode + .ProjectAvgERWaitingTimeModeList[1] + .phoneNumber + .toString(), + networkImage: mode + .ProjectAvgERWaitingTimeModeList[1] + .projectImageURL + .toString(), + latitude: mode + .ProjectAvgERWaitingTimeModeList[1] + .latitude, + longitude: mode + .ProjectAvgERWaitingTimeModeList[1] + .longitude, + projectname: mode + .ProjectAvgERWaitingTimeModeList[1] + .projectName, + ), + ), + + ) + ], + ), + Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Container( + child: CardPosition( + + text: mode + .ProjectAvgERWaitingTimeModeList[2] + .projectName + .toString(), + image: + 'assets/images/new-design/find_us_icon.png', + + subText: mode + .ProjectAvgERWaitingTimeModeList[2] + .distanceInKilometers + .toString(), + type: mode + .ProjectAvgERWaitingTimeModeList[2].iD + .toString(), + telephone: mode + .ProjectAvgERWaitingTimeModeList[2] + .phoneNumber + .toString(), + networkImage: mode + .ProjectAvgERWaitingTimeModeList[2] + .projectImageURL + .toString(), + latitude: mode + .ProjectAvgERWaitingTimeModeList[2] + .latitude, + longitude: mode + .ProjectAvgERWaitingTimeModeList[2] + .longitude, + projectname: mode + .ProjectAvgERWaitingTimeModeList[2] + .projectName, + ), + ), + + ), + Expanded( + child: Container( + child: CardPosition( + + text: mode + .ProjectAvgERWaitingTimeModeList[3] + .projectName + .toString(), + image: + 'assets/images/new-design/find_us_icon.png', + + subText: mode + .ProjectAvgERWaitingTimeModeList[3] + .distanceInKilometers + .toString(), + type: mode + .ProjectAvgERWaitingTimeModeList[3].iD + .toString(), + telephone: mode + .ProjectAvgERWaitingTimeModeList[3] + .phoneNumber + .toString(), + networkImage: mode + .ProjectAvgERWaitingTimeModeList[3] + .projectImageURL + .toString(), + latitude: mode + .ProjectAvgERWaitingTimeModeList[3] + .latitude, + longitude: mode + .ProjectAvgERWaitingTimeModeList[3] + .longitude, + projectname: mode + .ProjectAvgERWaitingTimeModeList[3] + .projectName, + ), + ), + flex: 0, + ) + ], + ), + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Container( + child: CardPosition( + + text: mode + .ProjectAvgERWaitingTimeModeList[4] + .projectName + .toString(), + image: + 'assets/images/new-design/find_us_icon.png', + + subText: mode + .ProjectAvgERWaitingTimeModeList[4] + .distanceInKilometers + .toString(), + type: mode + .ProjectAvgERWaitingTimeModeList[4].iD + .toString(), + telephone: mode + .ProjectAvgERWaitingTimeModeList[4] + .phoneNumber + .toString(), + networkImage: mode + .ProjectAvgERWaitingTimeModeList[4] + .projectImageURL + .toString(), + latitude: mode + .ProjectAvgERWaitingTimeModeList[4] + .latitude, + longitude: mode + .ProjectAvgERWaitingTimeModeList[4] + .longitude, + projectname: mode + .ProjectAvgERWaitingTimeModeList[4] + .projectName, + ), + ), + + ), + Expanded( + child: Container( + child: CardPosition( + text: mode + .ProjectAvgERWaitingTimeModeList[5] + .projectName + .toString(), + image: + 'assets/images/new-design/find_us_icon.png', + subText: mode + .ProjectAvgERWaitingTimeModeList[5] + .distanceInKilometers + .toString(), + type: mode + .ProjectAvgERWaitingTimeModeList[5].iD + .toString(), + telephone: mode + .ProjectAvgERWaitingTimeModeList[5] + .phoneNumber + .toString(), + networkImage: mode + .ProjectAvgERWaitingTimeModeList[5] + .projectImageURL + .toString(), + latitude: mode + .ProjectAvgERWaitingTimeModeList[5] + .latitude, + longitude: mode + .ProjectAvgERWaitingTimeModeList[5] + .longitude, + projectname: mode + .ProjectAvgERWaitingTimeModeList[5] + .projectName, + ), + ), + + ) + ], + ), + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Container( + child: CardPosition( + text: mode + .ProjectAvgERWaitingTimeModeList[6] + .projectName + .toString(), + image: + 'assets/images/new-design/find_us_icon.png', + subText: mode + .ProjectAvgERWaitingTimeModeList[6] + .distanceInKilometers + .toString(), + type: mode + .ProjectAvgERWaitingTimeModeList[6].iD + .toString(), + telephone: mode + .ProjectAvgERWaitingTimeModeList[6] + .phoneNumber + .toString(), + networkImage: mode + .ProjectAvgERWaitingTimeModeList[6] + .projectImageURL + .toString(), + latitude: mode + .ProjectAvgERWaitingTimeModeList[6] + .latitude, + longitude: mode + .ProjectAvgERWaitingTimeModeList[6] + .longitude, + projectname: mode + .ProjectAvgERWaitingTimeModeList[6] + .projectName, + ), + ), + flex: 0, + ), + ], + ), + ], + )), + ], + ), + ) + : Center( + child: Texts('No Data'), + ), + ), + ); + } +} + diff --git a/lib/routes.dart b/lib/routes.dart index b11025c2..62c26bab 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -35,6 +35,7 @@ const String SYMPTOM_CHECKER = 'symptom-checker'; const String SYMPTOM_CHECKER_INFO = 'symptom-checker-info'; const String SELECT_GENDER = 'select-gender'; const String SETTINGS = 'settings'; +const String HEALTH_WEATHER ='health-weather'; var routes = { SPLASH: (_) => SplashScreen(), HOME: (_) => LandingPage(), @@ -52,5 +53,6 @@ var routes = { SYMPTOM_CHECKER: (_) => SymptomChecker(), SYMPTOM_CHECKER_INFO: (_) => SymptomInfo(), SELECT_GENDER: (_) => SelectGender(), - SETTINGS: (_) => Settings() + SETTINGS: (_) => Settings(), + HEALTH_WEATHER: (_) HealthWeather() }; From 19d6057f66ce3c9da8c0819f6519abe8e9e83eda Mon Sep 17 00:00:00 2001 From: Sultan Khan Date: Mon, 30 Nov 2020 08:13:57 +0300 Subject: [PATCH 04/71] health weather indicator --- .../health-weather/health-weather-indicator.dart | 0 lib/widgets/slider/slider.dart | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 lib/pages/AlHabibMedicalService/health-weather/health-weather-indicator.dart create mode 100644 lib/widgets/slider/slider.dart diff --git a/lib/pages/AlHabibMedicalService/health-weather/health-weather-indicator.dart b/lib/pages/AlHabibMedicalService/health-weather/health-weather-indicator.dart new file mode 100644 index 00000000..e69de29b diff --git a/lib/widgets/slider/slider.dart b/lib/widgets/slider/slider.dart new file mode 100644 index 00000000..e69de29b From a9cb6458332b43a89ce39851e9a72454cc164dd3 Mon Sep 17 00:00:00 2001 From: Sultan Khan Date: Mon, 30 Nov 2020 08:14:07 +0300 Subject: [PATCH 05/71] health weather indicator --- .../health_weather_indicator.dart | 341 ------------------ .../all_habib_medical_service_page.dart | 14 +- .../health-weather-indicator.dart | 106 ++++++ lib/routes.dart | 3 +- lib/widgets/slider/slider.dart | 0 5 files changed, 120 insertions(+), 344 deletions(-) delete mode 100644 lib/widgets/slider/slider.dart diff --git a/lib/core/service/health-weather/health_weather_indicator.dart b/lib/core/service/health-weather/health_weather_indicator.dart index 24a3d117..e69de29b 100644 --- a/lib/core/service/health-weather/health_weather_indicator.dart +++ b/lib/core/service/health-weather/health_weather_indicator.dart @@ -1,341 +0,0 @@ -import 'package:diplomaticquarterapp/core/viewModels/er/near_hospital_view_model.dart'; -import 'package:diplomaticquarterapp/pages/ErService/widgets/card_position.dart'; -import 'package:diplomaticquarterapp/pages/base/base_view.dart'; -import 'package:diplomaticquarterapp/uitl/location_util.dart'; -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/cupertino.dart'; -import 'package:flutter/material.dart'; - - -class HealthWeather extends StatelessWidget { - static const String _url = "assets/images/"; - - @override - Widget build(BuildContext context) { - return BaseView( - onModelReady: (){}, - builder: (_, mode, widget) => AppScaffold( - isShowAppBar: true, - appBarTitle: 'Nearest ER', - baseViewModel: mode, - body: mode.ProjectAvgERWaitingTimeModeList.length > 0 - ? Container( - child: ListView( - children: [ - Text( - "\nThis service Displays nearest branch\n among all the branches of All Habib \n medical Group based on your current Location", - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 18.0, - letterSpacing: 1.0, - fontWeight: FontWeight.w900, - color: new Color(0xFF60686b))), - Container( - margin: EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Row( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded( - child: Container( - child: CardPosition( - text: mode - .ProjectAvgERWaitingTimeModeList[0] - .projectName - .toString(), - image: - 'assets/images/new-design/find_us_icon.png', - subText: mode - .ProjectAvgERWaitingTimeModeList[0] - .distanceInKilometers - .toString(), - type: mode - .ProjectAvgERWaitingTimeModeList[0].iD - .toString(), - telephone: mode - .ProjectAvgERWaitingTimeModeList[0] - .phoneNumber - .toString(), - networkImage: mode - .ProjectAvgERWaitingTimeModeList[0] - .projectImageURL - .toString(), - latitude: mode - .ProjectAvgERWaitingTimeModeList[0] - .latitude, - longitude: mode - .ProjectAvgERWaitingTimeModeList[0] - .longitude, - projectname: mode - .ProjectAvgERWaitingTimeModeList[0] - .projectName, - ), - ), - - ), - Expanded( - child: Container( - child: CardPosition( - text: mode - .ProjectAvgERWaitingTimeModeList[1] - .projectName - .toString(), - image: - 'assets/images/new-design/find_us_icon.png', - subText: mode - .ProjectAvgERWaitingTimeModeList[1] - .distanceInKilometers - .toString(), - type: mode - .ProjectAvgERWaitingTimeModeList[1].iD - .toString(), - telephone: mode - .ProjectAvgERWaitingTimeModeList[1] - .phoneNumber - .toString(), - networkImage: mode - .ProjectAvgERWaitingTimeModeList[1] - .projectImageURL - .toString(), - latitude: mode - .ProjectAvgERWaitingTimeModeList[1] - .latitude, - longitude: mode - .ProjectAvgERWaitingTimeModeList[1] - .longitude, - projectname: mode - .ProjectAvgERWaitingTimeModeList[1] - .projectName, - ), - ), - - ) - ], - ), - Row( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded( - child: Container( - child: CardPosition( - - text: mode - .ProjectAvgERWaitingTimeModeList[2] - .projectName - .toString(), - image: - 'assets/images/new-design/find_us_icon.png', - - subText: mode - .ProjectAvgERWaitingTimeModeList[2] - .distanceInKilometers - .toString(), - type: mode - .ProjectAvgERWaitingTimeModeList[2].iD - .toString(), - telephone: mode - .ProjectAvgERWaitingTimeModeList[2] - .phoneNumber - .toString(), - networkImage: mode - .ProjectAvgERWaitingTimeModeList[2] - .projectImageURL - .toString(), - latitude: mode - .ProjectAvgERWaitingTimeModeList[2] - .latitude, - longitude: mode - .ProjectAvgERWaitingTimeModeList[2] - .longitude, - projectname: mode - .ProjectAvgERWaitingTimeModeList[2] - .projectName, - ), - ), - - ), - Expanded( - child: Container( - child: CardPosition( - - text: mode - .ProjectAvgERWaitingTimeModeList[3] - .projectName - .toString(), - image: - 'assets/images/new-design/find_us_icon.png', - - subText: mode - .ProjectAvgERWaitingTimeModeList[3] - .distanceInKilometers - .toString(), - type: mode - .ProjectAvgERWaitingTimeModeList[3].iD - .toString(), - telephone: mode - .ProjectAvgERWaitingTimeModeList[3] - .phoneNumber - .toString(), - networkImage: mode - .ProjectAvgERWaitingTimeModeList[3] - .projectImageURL - .toString(), - latitude: mode - .ProjectAvgERWaitingTimeModeList[3] - .latitude, - longitude: mode - .ProjectAvgERWaitingTimeModeList[3] - .longitude, - projectname: mode - .ProjectAvgERWaitingTimeModeList[3] - .projectName, - ), - ), - flex: 0, - ) - ], - ), - Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded( - child: Container( - child: CardPosition( - - text: mode - .ProjectAvgERWaitingTimeModeList[4] - .projectName - .toString(), - image: - 'assets/images/new-design/find_us_icon.png', - - subText: mode - .ProjectAvgERWaitingTimeModeList[4] - .distanceInKilometers - .toString(), - type: mode - .ProjectAvgERWaitingTimeModeList[4].iD - .toString(), - telephone: mode - .ProjectAvgERWaitingTimeModeList[4] - .phoneNumber - .toString(), - networkImage: mode - .ProjectAvgERWaitingTimeModeList[4] - .projectImageURL - .toString(), - latitude: mode - .ProjectAvgERWaitingTimeModeList[4] - .latitude, - longitude: mode - .ProjectAvgERWaitingTimeModeList[4] - .longitude, - projectname: mode - .ProjectAvgERWaitingTimeModeList[4] - .projectName, - ), - ), - - ), - Expanded( - child: Container( - child: CardPosition( - text: mode - .ProjectAvgERWaitingTimeModeList[5] - .projectName - .toString(), - image: - 'assets/images/new-design/find_us_icon.png', - subText: mode - .ProjectAvgERWaitingTimeModeList[5] - .distanceInKilometers - .toString(), - type: mode - .ProjectAvgERWaitingTimeModeList[5].iD - .toString(), - telephone: mode - .ProjectAvgERWaitingTimeModeList[5] - .phoneNumber - .toString(), - networkImage: mode - .ProjectAvgERWaitingTimeModeList[5] - .projectImageURL - .toString(), - latitude: mode - .ProjectAvgERWaitingTimeModeList[5] - .latitude, - longitude: mode - .ProjectAvgERWaitingTimeModeList[5] - .longitude, - projectname: mode - .ProjectAvgERWaitingTimeModeList[5] - .projectName, - ), - ), - - ) - ], - ), - Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded( - child: Container( - child: CardPosition( - text: mode - .ProjectAvgERWaitingTimeModeList[6] - .projectName - .toString(), - image: - 'assets/images/new-design/find_us_icon.png', - subText: mode - .ProjectAvgERWaitingTimeModeList[6] - .distanceInKilometers - .toString(), - type: mode - .ProjectAvgERWaitingTimeModeList[6].iD - .toString(), - telephone: mode - .ProjectAvgERWaitingTimeModeList[6] - .phoneNumber - .toString(), - networkImage: mode - .ProjectAvgERWaitingTimeModeList[6] - .projectImageURL - .toString(), - latitude: mode - .ProjectAvgERWaitingTimeModeList[6] - .latitude, - longitude: mode - .ProjectAvgERWaitingTimeModeList[6] - .longitude, - projectname: mode - .ProjectAvgERWaitingTimeModeList[6] - .projectName, - ), - ), - flex: 0, - ), - ], - ), - ], - )), - ], - ), - ) - : Center( - child: Texts('No Data'), - ), - ), - ); - } -} - diff --git a/lib/pages/AlHabibMedicalService/all_habib_medical_service_page.dart b/lib/pages/AlHabibMedicalService/all_habib_medical_service_page.dart index 2ecacc9a..43570229 100644 --- a/lib/pages/AlHabibMedicalService/all_habib_medical_service_page.dart +++ b/lib/pages/AlHabibMedicalService/all_habib_medical_service_page.dart @@ -4,6 +4,7 @@ import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/%E2%80%8B%20hea import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/E-Referral/e_referral_index_page.dart'; import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/E-Referral/e_referral_page.dart'; import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/h2o/h2o_index_page.dart'; +import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/health-weather/health-weather-indicator.dart'; import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/health_converter.dart'; import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/my_web_view.dart'; import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/parking_page.dart'; @@ -98,7 +99,16 @@ class _AllHabibMedicalServiceState extends State { ], ), Expanded( - child: Column( + child:InkWell( + onTap: (){ + Navigator.push( + context, + FadePage( + page: HealthWeatherIndicator(), + ), + ); + }, + child: Column( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Image.asset('assets/images/Weather_ico.png',width: 80,height: 80,), @@ -108,7 +118,7 @@ class _AllHabibMedicalServiceState extends State { decoration: TextDecoration.underline, ), ], - ), + )), ) ], ), diff --git a/lib/pages/AlHabibMedicalService/health-weather/health-weather-indicator.dart b/lib/pages/AlHabibMedicalService/health-weather/health-weather-indicator.dart index e69de29b..aa384a66 100644 --- a/lib/pages/AlHabibMedicalService/health-weather/health-weather-indicator.dart +++ b/lib/pages/AlHabibMedicalService/health-weather/health-weather-indicator.dart @@ -0,0 +1,106 @@ +import 'package:diplomaticquarterapp/core/model/contactus/get_hmg_locations.dart'; +import 'package:diplomaticquarterapp/core/viewModels/contactus/findus_view_model.dart'; +import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/button.dart'; +import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:diplomaticquarterapp/widgets/slider/slider.dart'; +import 'package:diplomaticquarterapp/widgets/text/app_texts_widget.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_xlider/flutter_xlider.dart'; +import 'package:giffy_dialog/giffy_dialog.dart'; +import 'package:url_launcher/url_launcher.dart'; +import 'package:maps_launcher/maps_launcher.dart'; + +class HealthWeatherIndicator extends StatefulWidget { + + + @override + _HospitalsPageState createState() => _HospitalsPageState(); +} + +class _HospitalsPageState extends State { + LinearGradient gradient = LinearGradient( + colors: [ + Colors.red, + Colors.orange, + Colors.yellow, + Colors.green, + Colors.blue, + Colors.blue[900], + Colors.purple + ] + ); + @override + Widget build(BuildContext context) { + return AppScaffold( + isShowDecPage: false, + appBarTitle: TranslationBase.of(context).healthWeatherIndicators, + isShowAppBar: true, + body: SingleChildScrollView( + child: Column(children: [ + WeatherSlider(.4, LinearGradient(colors: [Colors.redAccent[100],Colors.redAccent ])), + WeatherSlider(.6, LinearGradient(colors: [Colors.greenAccent[100],Colors.greenAccent ])), + WeatherSlider(.8, LinearGradient(colors: [Colors.yellowAccent[100],Colors.yellowAccent ])), + ]) + ), + ); + } +} + + +class WeatherSlider extends StatelessWidget{ + final width; + final LinearGradient color; + WeatherSlider(this.width, this.color); + + @override + Widget build(BuildContext context) { + // TODO: implement build + return Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + AppText('Low', fontSize: 24,), + + Padding( + padding: EdgeInsets.all(10), + child: + Stack( + children: [ + Container( + decoration: BoxDecoration(gradient: LinearGradient(colors: [Colors.grey[100],Colors.grey[400] ]), + borderRadius: BorderRadius.circular(10) + ), + height: 15, width: MediaQuery.of(context).size.width, + child:SizedBox(), + ), + Positioned( + top:0, + child: Container( + decoration: BoxDecoration(gradient: color, + borderRadius: BorderRadius.circular(10) + ), + height: 15, + width: MediaQuery.of(context).size.width * width, + padding: EdgeInsets.all(10), + child:SizedBox(), + + )), + + ], + )), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + AppText('Low', fontSize: 12,), + AppText('Moderate', fontSize: 12,), + AppText('High', fontSize: 12,), + AppText('Very High', fontSize: 12,), + AppText('Extreme', fontSize: 12,), + ],) + ],); + + } +} \ No newline at end of file diff --git a/lib/routes.dart b/lib/routes.dart index 62c26bab..0a543185 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -1,3 +1,4 @@ +import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/health-weather/health-weather-indicator.dart'; import 'package:diplomaticquarterapp/pages/DrawerPages/family/add-family-member.dart'; import 'package:diplomaticquarterapp/pages/DrawerPages/family/add-family_type.dart'; import 'package:diplomaticquarterapp/pages/DrawerPages/family/my-family.dart'; @@ -54,5 +55,5 @@ var routes = { SYMPTOM_CHECKER_INFO: (_) => SymptomInfo(), SELECT_GENDER: (_) => SelectGender(), SETTINGS: (_) => Settings(), - HEALTH_WEATHER: (_) HealthWeather() + HEALTH_WEATHER: (_)=> HealthWeatherIndicator() }; diff --git a/lib/widgets/slider/slider.dart b/lib/widgets/slider/slider.dart deleted file mode 100644 index e69de29b..00000000 From 12d5ef69a964c8ba3a03816d2ca17835d3f02d7f Mon Sep 17 00:00:00 2001 From: Sultan Khan Date: Thu, 3 Dec 2020 14:06:03 +0300 Subject: [PATCH 06/71] voice search in progress --- assets/gif/robot-idle.gif | Bin 0 -> 51759 bytes assets/gif/robot-speaking.gif | Bin 0 -> 62449 bytes assets/images/gif/robot-idle.gif | Bin 0 -> 51759 bytes assets/images/gif/robot-speaking.gif | Bin 0 -> 62449 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 assets/gif/robot-idle.gif create mode 100644 assets/gif/robot-speaking.gif create mode 100644 assets/images/gif/robot-idle.gif create mode 100644 assets/images/gif/robot-speaking.gif diff --git a/assets/gif/robot-idle.gif b/assets/gif/robot-idle.gif new file mode 100644 index 0000000000000000000000000000000000000000..89dee325d18e6fcce6db67c049b204e70e00c746 GIT binary patch literal 51759 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

5;RGHiepT0P)0ITLPs$GWF*!fx5%w-dEpNd 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 literal 0 HcmV?d00001 diff --git a/assets/gif/robot-speaking.gif b/assets/gif/robot-speaking.gif new file mode 100644 index 0000000000000000000000000000000000000000..253d786b0a6fd121f652cef40a1147a7f451fcf9 GIT binary patch literal 62449 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 z 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

#BsVcD`5v3o0 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 aal!T3GeXdF33@I;&n4)&{J&RD|NS@dav@y+ literal 0 HcmV?d00001 diff --git a/assets/images/gif/robot-idle.gif b/assets/images/gif/robot-idle.gif new file mode 100644 index 0000000000000000000000000000000000000000..89dee325d18e6fcce6db67c049b204e70e00c746 GIT binary patch literal 51759 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

5;RGHiepT0P)0ITLPs$GWF*!fx5%w-dEpNd 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 literal 0 HcmV?d00001 diff --git a/assets/images/gif/robot-speaking.gif b/assets/images/gif/robot-speaking.gif new file mode 100644 index 0000000000000000000000000000000000000000..253d786b0a6fd121f652cef40a1147a7f451fcf9 GIT binary patch literal 62449 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 z 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

#BsVcD`5v3o0 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 aal!T3GeXdF33@I;&n4)&{J&RD|NS@dav@y+ literal 0 HcmV?d00001 From 98f84c2161ac795389f38ac09f21637d5253bacd Mon Sep 17 00:00:00 2001 From: Sultan Khan Date: Thu, 3 Dec 2020 14:33:55 +0300 Subject: [PATCH 07/71] voice search in progress --- assets/gif/robot-idle.gif | Bin 51759 -> 0 bytes assets/gif/robot-speaking.gif | Bin 62449 -> 0 bytes lib/config/config.dart | 4 +- .../all_habib_medical_service_page.dart | 2 +- .../health-weather-indicator.dart | 71 +++++ lib/widgets/others/app_scaffold_widget.dart | 6 +- lib/widgets/others/bottom_bar.dart | 1 - .../others/floating_button_search.dart | 113 +++----- lib/widgets/robo-search/robosearch.dart | 249 ------------------ lib/widgets/robo-search/search.dart | 233 ---------------- pubspec.yaml | 5 +- 11 files changed, 113 insertions(+), 571 deletions(-) delete mode 100644 assets/gif/robot-idle.gif delete mode 100644 assets/gif/robot-speaking.gif delete mode 100644 lib/widgets/robo-search/robosearch.dart delete mode 100644 lib/widgets/robo-search/search.dart diff --git a/assets/gif/robot-idle.gif b/assets/gif/robot-idle.gif deleted file mode 100644 index 89dee325d18e6fcce6db67c049b204e70e00c746..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 51759 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

5;RGHiepT0P)0ITLPs$GWF*!fx5%w-dEpNd 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 diff --git a/assets/gif/robot-speaking.gif b/assets/gif/robot-speaking.gif deleted file mode 100644 index 253d786b0a6fd121f652cef40a1147a7f451fcf9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 62449 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 z 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

#BsVcD`5v3o0 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 aal!T3GeXdF33@I;&n4)&{J&RD|NS@dav@y+ diff --git a/lib/config/config.dart b/lib/config/config.dart index a911598e..394eecad 100644 --- a/lib/config/config.dart +++ b/lib/config/config.dart @@ -6,8 +6,8 @@ import 'package:diplomaticquarterapp/widgets/mobile-no/mobile_no.dart'; const MAX_SMALL_SCREEN = 660; -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/'; const GET_PROJECT = 'Services/Lists.svc/REST/GetProject'; //weather diff --git a/lib/pages/AlHabibMedicalService/all_habib_medical_service_page.dart b/lib/pages/AlHabibMedicalService/all_habib_medical_service_page.dart index 77d536e1..143b6435 100644 --- a/lib/pages/AlHabibMedicalService/all_habib_medical_service_page.dart +++ b/lib/pages/AlHabibMedicalService/all_habib_medical_service_page.dart @@ -385,6 +385,6 @@ class _AllHabibMedicalServiceState extends State { } var data = await this.sharedPref.getObject(WEATHER); weather = data['Temperature'].toString() + '\u2103' ?? '--'; - print(data); + } } diff --git a/lib/pages/AlHabibMedicalService/health-weather/health-weather-indicator.dart b/lib/pages/AlHabibMedicalService/health-weather/health-weather-indicator.dart index 98aba205..19974e0e 100644 --- a/lib/pages/AlHabibMedicalService/health-weather/health-weather-indicator.dart +++ b/lib/pages/AlHabibMedicalService/health-weather/health-weather-indicator.dart @@ -1,8 +1,11 @@ +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/core/viewModels/weather/weather_view_model.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; import 'package:diplomaticquarterapp/uitl/location_util.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:diplomaticquarterapp/widgets/text/app_texts_widget.dart'; import 'package:diplomaticquarterapp/widgets/weather_slider/weather_slider.dart'; @@ -18,7 +21,9 @@ class HealthWeatherIndicator extends StatefulWidget { class _HospitalsPageState extends State { var data; + AppSharedPreferences sharedPref = AppSharedPreferences(); LocationUtils locationUtils; + var weather = '--'; @override void initState() { locationUtils = @@ -40,6 +45,68 @@ class _HospitalsPageState extends State { baseViewModel: mode, body: mode.weatherIndicatorData.length>0 ? SingleChildScrollView( child: Column(children: [ + Container( + margin: EdgeInsets.all(8), + width: double.infinity, + height: 150, + decoration: BoxDecoration( + image: DecorationImage( + image: ExactAssetImage('assets/images/Weather_img.png'), + fit: BoxFit.cover, + ), + borderRadius: BorderRadius.circular(8.0)), + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 10.0), + child: Row( + children: [ + Expanded( + flex: 3, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Texts( + TranslationBase.of(context) + .healthWeatherIndicators, + color: Colors.white, + fontWeight: FontWeight.w600, + ), + Texts( + TranslationBase.of(context) + .healthTipsBasedOnCurrentWeather, + color: Colors.white, + fontSize: 14, + ), + ], + )), + Expanded( + flex: 2, + child: InkWell( + onTap: () { + + }, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + 'assets/images/Weather_ico.png', + width: 60, + height: 60, + ), + AppText(weather, + fontSize: 22, color: Colors.white) + ], + ), + ], + )), + ) + ], + ), + ), + ), Padding(padding: EdgeInsets.all(15), child:AppText( projectViewModel.isArabic ? mode.weatherIndicatorData[0].cityNameN : mode.weatherIndicatorData[0].cityName, fontSize: 24, fontWeight: FontWeight.bold,)), Padding( padding: EdgeInsets.all(15), @@ -53,4 +120,8 @@ class _HospitalsPageState extends State { ))])) : Container(child:AppText('Loading...'))), ); } + getWeather() async{ + var data = await this.sharedPref.getObject(WEATHER); + weather = data['Temperature'].toString() + '\u2103' ?? '--'; + } } diff --git a/lib/widgets/others/app_scaffold_widget.dart b/lib/widgets/others/app_scaffold_widget.dart index 976b28e1..4691332d 100644 --- a/lib/widgets/others/app_scaffold_widget.dart +++ b/lib/widgets/others/app_scaffold_widget.dart @@ -12,8 +12,6 @@ import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/others/bottom_bar.dart'; import 'package:diplomaticquarterapp/widgets/progress_indicator/app_loader_widget.dart'; import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; -import 'package:diplomaticquarterapp/widgets/robo-search/robosearch.dart'; -import 'package:diplomaticquarterapp/widgets/robo-search/search.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; @@ -137,10 +135,10 @@ class AppScaffold extends StatelessWidget { ) : buildBodyWidget(), bottomSheet: bottomSheet, - //floatingActionButton: floatingActionButton ?? floatingActionButton, + // floatingActionButton: floatingActionButton ?? floatingActionButton, // bottomNavigationBar: // this.isBottomBar == true ? BottomBarSearch() : SizedBox() - // floatingActionButton: FloatingSearchButton(), + floatingActionButton: FloatingSearchButton(), ); } diff --git a/lib/widgets/others/bottom_bar.dart b/lib/widgets/others/bottom_bar.dart index 4de9efdf..0615a7c8 100644 --- a/lib/widgets/others/bottom_bar.dart +++ b/lib/widgets/others/bottom_bar.dart @@ -41,7 +41,6 @@ import 'package:permission_handler/permission_handler.dart'; import 'package:speech_to_text/speech_recognition_error.dart'; import 'package:speech_to_text/speech_recognition_result.dart'; import 'package:speech_to_text/speech_to_text.dart'; -import 'package:diplomaticquarterapp/widgets/robo-search/robosearch.dart'; import 'dart:math'; import 'package:diplomaticquarterapp/services/robo_search/event_provider.dart'; import 'package:diplomaticquarterapp/routes.dart'; diff --git a/lib/widgets/others/floating_button_search.dart b/lib/widgets/others/floating_button_search.dart index 2bfacaea..e8900040 100644 --- a/lib/widgets/others/floating_button_search.dart +++ b/lib/widgets/others/floating_button_search.dart @@ -21,6 +21,7 @@ import 'package:diplomaticquarterapp/pages/MyAppointments/MyAppointments.dart'; import 'package:diplomaticquarterapp/pages/feedback/feedback_home_page.dart'; import 'package:diplomaticquarterapp/pages/insurance/insurance_approval_screen.dart'; import 'package:diplomaticquarterapp/pages/insurance/insurance_update_screen.dart'; +import 'package:diplomaticquarterapp/pages/landing/landing_page.dart'; import 'package:diplomaticquarterapp/pages/livecare/livecare_home.dart'; import 'package:diplomaticquarterapp/pages/login/welcome.dart'; import 'package:diplomaticquarterapp/pages/medical/balance/advance_payment_page.dart'; @@ -41,7 +42,6 @@ import 'package:diplomaticquarterapp/services/robo_search/search_provider.dart'; import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; import 'package:diplomaticquarterapp/uitl/app_toast.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; -import 'package:diplomaticquarterapp/widgets/robo-search/robosearch.dart'; import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; @@ -95,22 +95,19 @@ class _FloatingSearchButton extends State @override void initState() { - event.controller.stream.listen((p) { - if (p['isRobot'] == 'true') { - if (this.mounted) { - setState(() { - position = Offset(250, 400); - activeAnimation = false; - }); - } - } - }); + // event.controller.stream.listen((p) { + // if (p['isRobot'] == 'true') { + // if (this.mounted) { + // setState(() { + // position = Offset(250, 400); + // activeAnimation = false; + // }); + // } + // } + // }); Future.delayed(const Duration(seconds: 2), () { - // _currentLocaleId = - // TranslationBase.of(AppGlobal.context).locale.languageCode == 'en' - // ? 'en-US' - // : 'ar-SA'; + requestPermissions(); getUserData(); @@ -122,81 +119,39 @@ class _FloatingSearchButton extends State @override Widget build(BuildContext context) { projectProvider = Provider.of(context); - return AnimatedPositioned( - onEnd: () { - // setState(() { - // this.isShow = false; - // position = Offset(250, 400); - // }); - }, - left: activeAnimation - ? TranslationBase.of(AppGlobal.context).locale.languageCode == 'en' - ? 300 - : 0 - : position.dx, - top: activeAnimation ? -150 : position.dy, - duration: activeAnimation - ? const Duration(seconds: 1) - : const Duration(seconds: 0), - // curve: Curves.bounceOut, - child: isShow - ? Draggable( - feedback: Container(child: getStack()), - child: getStack(), - childWhenDragging: Container( - color: Colors.transparent, - ), - onDragEnd: (details) { - setState(() { - position = details.offset; - }); - }) - : Container()); - - // Draggable( - // feedback: getStack(), - // childWhenDragging: Container(), - // child: getStack(), - // onDragEnd: (drag) { - // setState(() { - // top = top + drag.offset.dy < 0 ? 0 : top + drag.offset.dy; - // left = left + drag.offset.dx < 0 ? 0 : left + drag.offset.dx; - // }); - // }); + return Container(child: + isShow ? getStack() + : Stack(children: [Container()])); } Widget getStack() { return Container( height: 150, width: 150, + margin: EdgeInsets.only(right: 0.0), child: Stack(children: [ // Column( // mainAxisSize: MainAxisSize.min, // crossAxisAlignment: CrossAxisAlignment.stretch, // children: [ - GestureDetector( + GestureDetector( child: Container( - child: Image.asset('assets/images/robort.png'), + child: Image.asset('assets/images/gif/robot-idle.gif'), ), onTap: () { - showDialog( - context: context, - builder: (_) { - return RoboSearch(); - }); initSpeechState().then((value) => {startVoiceSearch()}); }, ), // ], // ), Positioned( - right: 0.0, + left: 15.0, top: 10, child: GestureDetector( onTap: () { setState(() { if (this.mounted) { - activeAnimation = true; + isShow =false; } }); }, @@ -246,7 +201,7 @@ class _FloatingSearchButton extends State } Future _speak(reconizedWord) async { - Navigator.of(AppGlobal.context).pop(); + // Navigator.of(AppGlobal.context).pop(); //await flutterTts.speak(reconizedWord); //RoboSearch.closeAlertDialog(context); getPages(reconizedWord); @@ -699,8 +654,14 @@ class _FloatingSearchButton extends State break; default: - Navigator.of(AppGlobal.context).pushNamed(HOME); - speak(); + { + // Navigator.pushAndRemoveUntil( + // context, + // MaterialPageRoute( + // builder: (context) => LandingPage()), + // (Route r) => false); + speak(); + } break; } } @@ -803,10 +764,6 @@ class _FloatingSearchButton extends State } Future navigateToSearchResults(context, docList, arr, arrDistance) async { - // Navigator.push( - // context, - // MaterialPageRoute( - // builder: (context) => SearchResults(doctorsList: docList))); var result = LinkedHashSet.from(arr).toList(); var numAll = result.length; Navigator.push( @@ -822,14 +779,15 @@ class _FloatingSearchButton extends State } speak() async { + var voice = await flutterTts.getVoices; + print(voice); if (_currentLocaleId == 'en' && results['ReturnMessage'] != null) { - await flutterTts.setVoice("en-us-x-sfg#male_2-local"); + await flutterTts.setVoice("en-us-x-sfg#male_1-local" ); await flutterTts.setLanguage("en-US"); await flutterTts.speak(results['ReturnMessage']); } else if (results['ReturnMessage_Ar'] != null) { await flutterTts.setLanguage("ar-SA"); - - await flutterTts.setVoice("ar-sa-x-sfg#male_1-local"); + await flutterTts.setVoice("ar-xa-x-arc-local"); await flutterTts.speak(results['ReturnMessage_Ar']); } // Future.delayed(const Duration(seconds: 10), () { @@ -854,12 +812,9 @@ class _FloatingSearchButton extends State getUserData() async { if (await this.sharedPref.getObject(USER_PROFILE) != null) { - //setState(() async { user = AuthenticatedUser.fromJson( await this.sharedPref.getObject(USER_PROFILE)); - // }); } - - print(_currentLocaleId); + await flutterTts.setVoice("en-us-x-sfg#male_1-local" ); } } diff --git a/lib/widgets/robo-search/robosearch.dart b/lib/widgets/robo-search/robosearch.dart deleted file mode 100644 index d471a085..00000000 --- a/lib/widgets/robo-search/robosearch.dart +++ /dev/null @@ -1,249 +0,0 @@ -import 'package:diplomaticquarterapp/config/size_config.dart'; -import 'package:diplomaticquarterapp/services/robo_search/event_provider.dart'; -import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; -import 'package:diplomaticquarterapp/widgets/buttons/button.dart'; -import 'package:diplomaticquarterapp/widgets/others/floating_button_search.dart'; -import 'package:diplomaticquarterapp/widgets/robo-search/search.dart'; -import 'package:diplomaticquarterapp/widgets/text/app_texts_widget.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; - -class RoboSearch extends StatefulWidget { - @override - _RoboSearch createState() => new _RoboSearch(); -} - -class _RoboSearch extends State { - var event = RobotProvider(); - var searchText = ''; - bool isRetry = false; - var tween = Tween(begin: 0.0, end: 1.0).chain(CurveTween(curve: Curves.ease)); - - @override - void initState() { - event.controller.stream.listen((p) { - if (p['searchText'] != null) { - if (p['searchText'] == 'null') { - //Future.delayed(const Duration(seconds: 1), () { - if (mounted) { - setState(() { - isRetry = true; - searchText = ''; - }); - } - //}); - } else { - if (mounted) { - setState(() { - searchText = p['searchText']; - }); - } - } - } - }); - super.initState(); - } - - @override - Widget build(BuildContext context) { - return AlertDialog( - content: Container( - color: Colors.white, - height: SizeConfig.realScreenHeight * 0.5, - width: SizeConfig.realScreenWidth * 0.8, - child: Container( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - isRetry == true - ? Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - margin: EdgeInsets.all(20), - padding: EdgeInsets.all(10), - decoration: BoxDecoration( - borderRadius: - BorderRadius.circular(100), - border: Border.all( - width: 5, color: Colors.red)), - child: Icon( - Icons.mic, - color: Colors.blue, - size: 48, - )), - Center( - child: AppText( - "Didn't catch that, Try speaking again", - fontSize: 14, - )), - RaisedButton( - color: Colors.transparent, - onPressed: () { - setState(() { - isRetry = false; - }); - FloatingSearchButton() - .createState() - .startVoiceSearch(); - }, - child: AppText( - 'Try again', - color: Colors.blue, - )) - ]) - : Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - margin: EdgeInsets.all(20), - padding: EdgeInsets.all(20), - decoration: BoxDecoration( - color: Colors.blue, - borderRadius: BorderRadius.circular(100)), - child: Icon( - Icons.mic, - color: Colors.white, - size: 48, - )), - SizedBox(height: 20), - Center( - child: Text(searchText == '' - ? 'Try saying something' - : searchText)) - ], - ) - ]), - ))); - } -} - -// class RoboSearch { -// final BuildContext context; -// var event = RobotProvider(); -// var searchText = ''; -// bool isRetry = false; -// var tween = Tween(begin: 0.0, end: 1.0).chain(CurveTween(curve: Curves.ease)); -// RoboSearch({ -// @required this.context, -// }); - -// showAlertDialog(BuildContext context) { -// // set up the buttons - -// // set up the AlertDialog -// AlertDialog alert = AlertDialog( -// content: StatefulBuilder( -// builder: (BuildContext context, StateSetter setState) { - -// event.controller.stream.listen((p) { -// if (p['searchText'] != null) { -// if (p['searchText'] == 'null') { -// Future.delayed(const Duration(seconds: 1), () -// { -// setState(() { -// isRetry = true; -// searchText = ''; -// }); -// }); -// } else { -// Future.delayed(const Duration(seconds: 1), () -// { -// setState(() { -// searchText = p['searchText']; -// }); -// }); -// } -// } -// }); -// return Container( -// color: Colors.white, -// height: SizeConfig.realScreenHeight * 0.5, -// width: SizeConfig.realScreenWidth * 0.8, -// child: Container( -// child: Column( -// mainAxisAlignment: MainAxisAlignment.center, -// children: [ -// isRetry == true -// ? Column( -// mainAxisAlignment: MainAxisAlignment.center, -// children: [ -// Container( -// margin: EdgeInsets.all(20), -// padding: EdgeInsets.all(10), -// decoration: BoxDecoration( -// borderRadius: -// BorderRadius.circular(100), -// border: Border.all( -// width: 5, color: Colors.red)), -// child: Icon( -// Icons.mic, -// color: Colors.blue, -// size: 48, -// )), -// Center( -// child: AppText( -// "Didn't catch that, Try speaking again", -// fontSize: 14, -// )), -// RaisedButton( -// color: Colors.transparent, -// onPressed: () { -// setState(() { -// isRetry = false; - -// }); -// startVoiceSearch(); -// }, -// child: AppText( -// 'Try again', -// color: Colors.blue, -// )) -// ]) -// : Column( -// mainAxisAlignment: MainAxisAlignment.center, -// children: [ -// Container( -// margin: EdgeInsets.all(20), -// padding: EdgeInsets.all(20), -// decoration: BoxDecoration( -// color: Colors.blue, -// borderRadius: BorderRadius.circular(100)), -// child: Icon( -// Icons.mic, -// color: Colors.white, -// size: 48, -// )), -// SizedBox(height: 20), -// Center( -// child: Text(searchText == '' -// ? 'Try saying something' -// : searchText)) -// ], -// ) -// ]), -// )); -// }), -// ); - -// // show the dialog -// showDialog( -// context: context, -// builder: (BuildContext context) { -// return alert; -// }, -// ); -// } - -// static closeAlertDialog(BuildContext context) { -// Navigator.of(context).pop(); -// } - -// startVoiceSearch() { - -// // Navigator.of(context).pop(); -// //this.showAlertDialog(context); -// // new RoboSearch(context: context).showAlertDialog(context); -// FloatingSearchButton().createState().startVoiceSearch(); -// } -// } diff --git a/lib/widgets/robo-search/search.dart b/lib/widgets/robo-search/search.dart deleted file mode 100644 index c1ce33d1..00000000 --- a/lib/widgets/robo-search/search.dart +++ /dev/null @@ -1,233 +0,0 @@ -import 'package:diplomaticquarterapp/config/config.dart'; -import 'package:diplomaticquarterapp/config/size_config.dart'; -import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; -import 'package:diplomaticquarterapp/pages/BookAppointment/BookingOptions.dart'; -import 'package:diplomaticquarterapp/pages/BookAppointment/Search.dart'; -import 'package:diplomaticquarterapp/pages/landing/landing_page.dart'; -import 'package:diplomaticquarterapp/pages/medical/medical_profile_page.dart'; -import 'package:diplomaticquarterapp/pages/medical/my_admissions_page.dart'; -import 'package:diplomaticquarterapp/services/robo_search/search_provider.dart'; -import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; -import 'package:diplomaticquarterapp/widgets/bottom_navigation/bottom_nav_bar.dart'; -import 'package:diplomaticquarterapp/widgets/text/app_texts_widget.dart'; -import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_tts/flutter_tts.dart'; -import 'package:hexcolor/hexcolor.dart'; -import 'package:permission_handler/permission_handler.dart'; -import 'package:speech_to_text/speech_recognition_error.dart'; -import 'package:speech_to_text/speech_recognition_result.dart'; -import 'package:speech_to_text/speech_to_text.dart'; -import 'package:diplomaticquarterapp/widgets/robo-search/robosearch.dart'; -import 'dart:math'; -import 'package:diplomaticquarterapp/services/robo_search/event_provider.dart'; - -class SearchBot with ChangeNotifier { - SearchBot() { - requestPermissions(); - initSpeechState(); - } - - SearchProvider searchProvider = new SearchProvider(); - // RobotProvider eventProvider = RobotProvider(); - bool isLoading = false; - bool isError = false; - final SpeechToText speech = SpeechToText(); - String error = ''; - String _currentLocaleId = ""; - String lastError; - double level = 0.0; - - double minSoundLevel = 50000; - double maxSoundLevel = -50000; - String reconizedWord = ''; - FlutterTts flutterTts = FlutterTts(); - var selectedLang; - bool isSearching = false; - - String lastStatus; - - bool _isInit = true; - - // @override - // void didChangeDependencies() { - // super.didChangeDependencies(); - // if (_isInit) { - - // } else { - // startVoiceSearch(); - // } - - // _isInit = false; - // } - - //@override - // Widget build(BuildContext context) { - // return Column( - // children: [ - // Image.asset('assets/images/siri-ianzhao.gif'), - // AppText( - // reconizedWord, - // fontSize: 28, - // ), - // // SizedBox( - // // child: FlatButton( - // // child: Text('Start'), - // // onPressed: () { - // // setState(() { - // // reconizedWord = 'Lisening...'; - // // }); - - // // }, - // // ), - // // height: 40, - // // width: 80) - // ], - // ); - // } - - startVoiceSearch() async { - speech.listen( - onResult: resultListener, - listenFor: Duration(seconds: 10), - localeId: _currentLocaleId, - onSoundLevelChange: soundLevelListener, - cancelOnError: true, - partialResults: true, - onDevice: true, - listenMode: ListenMode.confirmation); - } - - void resultListener(SpeechRecognitionResult result) { - // lastWords = "${result.recognizedWords} - ${result.finalResult}"; - - if (result.finalResult == true) { - // setState(() { - reconizedWord = result.recognizedWords; - //}); - Future.delayed(const Duration(seconds: 1), () { - _speak(reconizedWord); - }); - } - //}); - } - - Future _speak(reconizedWord) async { - await flutterTts.speak(reconizedWord); - - getPages(reconizedWord); - } - - void soundLevelListener(double level) { - minSoundLevel = min(minSoundLevel, level); - maxSoundLevel = max(maxSoundLevel, level); - // print("sound level $level: $minSoundLevel - $maxSoundLevel "); - //setState(() { - this.level = level; - // }); - } - - void requestPermissions() async { - Map statuses = await [ - Permission.microphone, - ].request(); - } - - Future initSpeechState() async { - await speech.initialize(onError: errorListener, onStatus: statusListener); - - _currentLocaleId = - TranslationBase.of(AppGlobal.context).locale.languageCode == 'en' - ? 'en-GB' - : 'ar-SA'; // systemLocale.localeId; - flutterTts.setLanguage(_currentLocaleId); - - await flutterTts.speak("Hello! How May I help you?"); - flutterTts.setCompletionHandler(() { - startVoiceSearch(); - }); - - // if (!mounted) return; - } - - void errorListener(SpeechRecognitionError error) { - //setState(() { - // reconizedWord = "${error.errorMsg} - ${error.permanent}"; - //}); - } - - void statusListener(String status) { - //setState(() { - reconizedWord = status == 'listening' ? 'Lisening...' : 'Sorry....'; - //}); - } - - getPages(text) { - var request = { - 'VoiceMessage': text, - 'Lang': TranslationBase.of(AppGlobal.context).locale.languageCode == 'en' - ? 'En' - : 'Ar' - }; - - searchProvider.getBotPages(request).then((value) => {}); - //getCommands(value['Response'], value['Understand']) - } - - getCommands(result, understand) async { - //RoboSearch.closeAlertDialog(context); - print(result); - switch (result["CommandNumber"]) { - case '100': - Navigator.push( - AppGlobal.context, - FadePage( - page: BookingOptions( - isAppbar: true, - ))); - break; - case '101': - Navigator.push( - AppGlobal.context, - MaterialPageRoute( - builder: (context) => Search( - type: 0, - ))); - break; - case '102': - Navigator.push( - AppGlobal.context, - MaterialPageRoute( - builder: (context) => Search( - type: 1, - ))); - break; - // case '103': - // eventProvider.setValue({"clinic_id": understand}); - // break; - - // case '104': - // eventProvider.setValue({"project_id": understand}); - // break; - // case '105': - // eventProvider.setValue({"doctor_id": understand}); - // break; - default: - { - //eventProvider.setValue({"doctor_id": '40036'}); - //eventProvider.setValue(); - // if (result['CommandNumber'] == '0') { - // searchProvider.setData(understand); - // } - } - break; - } - if (_currentLocaleId == 'en-GB') { - await flutterTts.speak(result['ResponseEn']); - } else { - await flutterTts.speak(result['ResponseAr']); - } - //searchProvider.setLisener(result); - } -} diff --git a/pubspec.yaml b/pubspec.yaml index 66e08f5c..be9bb252 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -151,8 +151,9 @@ dependencies: wakelock: ^0.1.4 after_layout: ^1.0.7 twilio_programmable_video: ^0.5.0+3 - flutter_tts: ^1.2.6 + flutter_tts: ^1.3.0 vibration: ^1.7.2 + fit_kit: ^1.1.2 speech_to_text: path: speech_to_text @@ -182,7 +183,7 @@ flutter: - assets/tracker/ - assets/images/AlHabibMedicalService/ - assets/images/pharmacy_module/ - + - assets/images/gif/ fonts: - family: WorkSans From 36b9d5cf7ce45dc9751bfa10cbd7ee66bc1a6edd Mon Sep 17 00:00:00 2001 From: Sultan Khan Date: Thu, 3 Dec 2020 17:55:56 +0300 Subject: [PATCH 08/71] robot pages added --- assets/images/roboticon.png | Bin 0 -> 198847 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 assets/images/roboticon.png diff --git a/assets/images/roboticon.png b/assets/images/roboticon.png new file mode 100644 index 0000000000000000000000000000000000000000..5b04e287282b85bd3a9e3fae092ff8767ca48e35 GIT binary patch literal 198847 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

!phI<9 zUTM3+^E^YmNtRgZs1N~wTkrX{Z5cs_xMx-H9tU3>y zCKki~q{zez%Q}7+E?yoZ0zF}%2KJ6jqcK`o)tN|DLQV%V7A4ZT=zWgAvcGyIKI2kN`dobP-uGKKvT@2XefzuvwK{t>}qul+WLhl1*%t>3S4 z#$^Ndmap+$w^utUPBM8s6o!nGanytrobDO9bJPrAJd&fii3WwCvrMVaP_;=J<$Lg+ z@XQ+P++uCgXCD_0R70E^syMN-2Gf+^>Jr|-T(Z11@`32!{}+dfmbtmmMEQ+)dCAYt zm~B#*m?)cMjZhi{vipau)|K0p^U#e9zop;fh36~uM>4g~ z_b30PMz`g2&@K{{BhN-7J#BrH8k0j;OG@ zSHeSFQpA&I_K~!Z=PD_CCL?yn0MD8_cY2nq6vYEuRf8dTtE3a`hY(7LinboR^Srhh z`T#Hv^*dmbm|ZA|Ktj9XHNJJ9mDi&+njP7f97y+03kZ*gnpZ>pCl_13utsw1&-XVa z)ySKRg#=QB_7#zpR@f+na9}MIrvp%QFIl1x8q+a~>+g9XCex)SNRM(S2H7U}78Yp^ z+=8^#$Lnp6o}m-6_}_5ilH!19sDN84=&*}Oka79^_ARI5$2L#sR9*(hrvyqXZ5ybT zt{AxhQdwOwX3Kk(2tb;Y!}{YR`{ z0uOJmdAs^KOB@Y7ncRX;SAv56J(bRv;{b(RIkN|W7N$x>=f)SpCn8QC?g*SErty*< zPZs@*S|I;#mV_U!yuk0!NcDUOM=@JYd~h*DvA=K-Zkwa7`96;03z&&YS`_=-qs)0t zg#3|Z`F2gmZ2QY-#V4}XkLiy(WiACE+%t@vI&Cg!a^PE5QUB53{oKcs2n#Q04SwLn`2&(;xPKdav zfW=r*?iW=HrZ5WP1j>t^si|`WA&oh$!E99iJHM6EFR4yn>5>%)YQGcHYc_YeVtQ$H zs+yjtX5D0u9x%38XYh3a^7R>;F*OZ59N8bSpU4T<>JoCds`m6b5`B)5MDBFpq~^(5qg^8}j?CCl}G(mXxQ`|7}w_uM3ciSe**y- zCFY>^o!h9C5uUX*>)+@(8`h1`cKu`qJ8CE?b4wXM5U$LK9HOA@2*q~DrT8*Voz&aQ zJC@M#Romq8KtJ@pp=`-a>8f)&?M^W^3$nVIzd>+ zRP0@1`H@KWf8fKozKTpBQS!)rHD%4ML2N03y$$vBHxG|P&*$>TvQC(-uX-N)x|w$V z^^3@-0=?=67*zOIJFVPT|JIrJ(pOJE*6EEtCl$qB^=Niu4{}S9&QhL)#{KS&( zHIq88T<|>q3uM!;cygZkTMD~=iZ)9`8dlDM#@V@B;7I^L2BI|sm(dkI4kbU!5~vx3 zGhEUj;N1(G+Qudx`MIR|3YVTEed_g|qaA}1zP}zJ!5QdQ7VY4Dx#&*!zc36W)OwPByD)~M)Bj}T z?(^@lyT5AKZD8x704`u=2ylTM6p>)Cip2hEz~A3tR^BrZzkdou@xE3fHN%`8H;T%a zYt6&bt?-zTAF_Ht_R;Y0!H=T7)qWroE~G|r3#XGg)LAuY@08&)5iltg_NpYw=RF`z zpj^>tUea%KDIk#@z0}M&Ger~#DXzb$5*{`EB6)snah=s7*=l>e)@DBYsB!_u=0gO< zgo?GvQM$K&Yfo0Hd5x)6hA`MK2b52p^X&Ma(yw03HHH1{$4q+AfP@Ihfc*Gjckdu) zVrKqQYf=(BUikE&9<%vu7b4_`I+?tmu~wiySq{DZJ9zwIBIYZ54jUP5PDg&YMdkNmh?KQt7lffUd-M~!6TuYy+P}9qHtS{$jz>+rch2Vs`P>NcF zKHA9e-HyKnf)RYzvC&k`LF_6J_=C{$VeuC;1 zArjg9Hlo^E2$C0rM~zrc9|r9bc1**cVtYE-3m(Z1!-p!ElLnkL&xbB*vn5up$ z#hgJ;=>l5=j|zZ7(-;IJN1)OC1z)LNMGvAyx|=Z= zm&RNCOlQ7!M^cejPb+Zyi&i}N6HQ7J5By1+R>|S-D}h5#SHsHjouzLdQc4YAKm)h* z+2wm7<68@*#+>$xG^oR5l^{fYw{g2oNq2ecQB$%KrXRM=g!@b`*L z259g@p~c&-@Zvj zH0w&1ytp653f31LoqadR8?>Uh%fO)xVHG#3F7l?_XqEVy+TeAx(oh6lR0vK6g@-){ zqVxXng1K7=hb8Hec1kYdmOz+?0+G($2iA*AXJYfqV&!Ax<~B}JWr-VNGhQt|*)vbm zm#CQ7S5DD%-9l=#X`bli+kpeE!0v-h>_%%83$_N7KBv~YTM@o-jtsn}IGz~GuQIW= z^E?k2&7qAd@mr4)AOr)W%7{Ak)!rNG@y1$Qbf(mi^Wh6Hzqd+`DIyxOnr7sW~qAi+~L1n`iC=)!xe`wsKp&*=A|u^QlG(}IiDvW z*vY{J!M@ExyJsbB=?fidLm55-r#WgRX=IQ>3r6sZh8)E-Qb3;9x-CUdioDO%d{Rf1 zGZ)<)Xu10=>J0fEic}k~X>i$+L1*?)7DPCafM~*_v1eyqmY}sA`V`b@XECz=>BWFU zc3&OgN1Q}4V{67|Iy1|=kAIE{@>Tkk?h!A4swrw;pc~T3v5X)Plky>y)RK-)m%nhS zMOd=#84*`7zvI|Jg)rHO*-!5)J?{sU?<7eh+y{W}%bc=LA#E=$FWgHPIdN^Tyrk<8 z)MmTIBtQ&$$Oiz`13U6Uo{KY$UKl5FcX>H&wchE^Y#(JKdVt=zU(e8T-J4Iqg_)XPkY!GRcf#3tC>p!sj-D*> z3;X>6;?8e=_D#e3YSQ3~5P&wCCJ&bOSNFR0M7S--LNv|3ei~Qyefcu!{Hea<7tJT1 z?+%+sP}_MYOlq0}I+ZlrbDkT+EiXewO#drDgs+5LJ0%ppdQu`Ejh1&DOzrI;qRYLydV3vs0z6*bhTuWsO%^TjiTooT9!9fC9OT{*CLSA@NXGk748QAMbEuGB|f{{*0b?xsx2sy+#NB-Ox+?ksr3-th0EVl0O`9{2cW~(oNh;#t&0_H=o0iL z6ZF|MzZY}N&z+Oi#4_nor&{8ap2x0iU$s(iz^b8gRwg=wJ+Pdu2JU^IG}g`$iMs!P~5~i+RbO^p2iDnBI#lgcW*m`4Nq6UPbw?1 zFTt*DD*`u`u8)YMJ)6dqCXzpx+_2GA3cmL((Dk1jEDUezZ=`0Vk;JyS&F;TA##9ew zaNZ&JnSus%SH|u`@OMM}ue2pp2&EC})sELINA|>?!WY^hLzVm_@BffcIUtbaFpVq^;zG8|kt;5fm)wpi)GU=G*Sp50CK^ zN`>?CW!wMQo2frtY$HyU2dt(;I}ho^nG7qli}QZ%%+Fhyq`|L@wyp0@DW6~x+@;hIB&;@kgjOs-K{rJV@)U>e@=;;kX6br*LeEoAQ_fW zDF}%k|4vb@Oih{qQLjyxH-!w%8lDObc<)z6_m>d2Sip7)fk8 zSmf#3ZeDJO?Z1m*&NJ8_0D<29V<5JGreI79m6N`FdAk|3folE9i_XjvR{Ola;YwE6 zN$Mm}xmI{&3s@HiXKiMquSF8{A&gYsM3}mP296O*_YN`1hd$MTx)oldKfYOQ%p6{C zc)N6(8}MQcFV>{f1KlsM)Cfw7ttc~fU6Y#vqj34 zZ4c6T@1c64K`C5SULP>T0(aXK{%D?+i4vI!2m+^QI zsuk^#RY$gMIyA2)nIy-ogIue(4gIPRdDJMw(jvSPl@JAsj6^C=(?uSE3ef+X1wc@U zpaDy_$?F)MVEpp8X#O;od|G{hO4?XG{LOA#{^gcn zm;aAcZnM<}xeLPkphTh6se7R3Z%Uc<2_^7omW5|GwVnT*cELg1AK$ajulOD{= zLkYVy4OHwcoXCe4{=JT_+TD#)Hr_aIR|y5^$%vNM^cvvyAGRd zi^>IY@54B@Rj9bwG^HnFAtDn&2eoWIx{dGXETa=oe*C>mTZQ(|Og@ANIauUFD_IGd zP@M|_6h|jHe2n=h>$GtNh4t?rPJRN-&G*TB$UU(djP`PLj>;gNS*P#ajUHMTS55C! zwMy8~RIg!^LzRZj3}tATJKd7oSVK-ttV${!>0)Pin%eracxsiIsQ6g`NWn(396(g| zCvl2gNt&0r9Be$N&FkT=A1gZV)dp(q2()sb6Daky8K|`!dP=rPJ7t_wtIsi+|I>Wx zDC<*dT8fO6G;@pFs0pt^6Dq^Z%P|qhC6?5TP0tLIg<`H>;f-BecYMNwlX0NE6hD7Z3gWFI}Or#Ul|?QI-062b9|O-7)EMA zqSVrUUt)eFV*TPM{(~psC_MRB)$)Skh2>oyN{F_4al4+E4!ob;Kn_0t8qQ%#_f)k} zDgBWDBR_XDgaF9Oo)Y4w3wpH)-0#qRM6i2GUbpmpGV&(p+XwGEoqqC#)m|QC;CqOv z9(6E}Eg___Uc=$nE0Ol|)QQ#og-f|mjaNaYZMJrZb6{YG!q5X0o?YoUgHAp0bFM4y zW}zq8x$n_5V5>e8!C@HE6CT};x>|GT_nOZtRG$>8x3x**Q){_7+q_0_FsO(IO#N;_ z4ZM7plg67eP~iM6Vywh+ObzN9xb}9?RS=3*9Y5tms(w~fdV1KVUpBA#QL9h*;D}Yl z#t@ttH}Ge6YbfGc!=cC8=qqJ$MkHf-fz1uxbL-GvVN*A=6xPf+g4!>CV-k&TzA7e-j(t-qKdfgS%`coDhH z;FtS3xhz|Z!yTrCpW?Q@+iv*$ZnTlbCLUBIy7rz*`XRFz0(%U*QQ}oWAYyDFvZ-SB z@qnklm}A7K8UI<8a{0|_}sx}fgab-8!w9$kiCzU6>ciwYhR>8?iC_1 zy+kDK4TjuAxHd*HsoFkDW5%Y%!&Nk|M=CT0xbLp_?C?r0aPC1Y9SAjbFV=)!H*Z{s z9%~^)oCIQ~9^AcCW7ftAuPac(n6FY&NSg%S?6)EYi?~GfRkW*q4oH^=R*Oe7Aj*Dw zn9_NTXWR!lJpl|qs1_i%Oru6e<&X9b7*Yf@ObwbeU#MRcARcDCNE~lJN0~cEN8$*u zs7;Da2v2hxoHCp;*c^CFd`^Qh3;X7AA*pnK>CQyX1mx6_eR~}nKSiUB3iQZTml3!} z5cn|nCI8!BTXY|HPRoCNwRcp@9RzECrv_C_K8HdeiEJ|@ek;2j#j(Vo|LGQAS(6y7 z778&RN0ChC5Hi$|zQyjBeb4$DNE9DfPEiT@Y#viJ>fB8tWH9*=s*2?#1VvD3tKMtq z0B%5P7rs5wpBsAh<;xbADO^29M~<2&Ra|SSMR<^L7f~&y9qB3v6QFukq1^tdTKT;m zM9&w4iRJ>tA5$pW1VU<;hC|0Xi(<9YRI{l>1kxDQQkBO!J9Zsi@Q$Al7x4JDN@{67 z!RBC@R`lz49dZX6dO(aRI3QQSgFg#K3Tsmil8%!B7|Ve=YBBvr8Bw53c%@*@ypGQwaE-EDJRod1X(tDM*!we)tB1A}G&BGJ$YaL15WUncS* zI%+z^%{u-QjpeQr>kiMN zYc5hd&1p2gD==A)=B}(7e<0%{l{6FYb*c(UIkWw+{y~t$3Ty!5^L5t74eX>A56pu+ zkG-`b=Adsj@LjK;ib>SeWH=DP@5m6Bzj)=?YsJs{YZ=lP%?S2#8K00ea$wa=5eOR3 zz+qraSutPmRDqt`vp+~g&`+U@!BS10+@JzM0G_Vp$a-&8IyWi-6}{bni3h?)DFY(- zvQ4jCOEhMrsLl1Gjo5Mm_N(6vWAA1dWG)Zn!pa9S)72ep=;?ea=n5SuGPL-dmnsDf zsKI>%3Kkrb;8MdI3NI}Izx7jD&hnXiSBRk8hW6MGY(if)li3{Ru-*4Z`>BhQ6>8|C zh``_fSbc!7ykZnT_^c^wI8jKZs7Y-jRyVz|!;2QLanN}BG(?I(3RLj*BQ9z_B^uTx@WLzOjb2p9EAGKYIa~($@2wZwzA5n zSrDWU7k*#CT-{I2)U4qUS-M4H=UiS-SwglTTu?O@!_iczN!9RFamI4vWBA6uA(@lH zu=C^L&r>=QZyYYmELZ@|NU!0(BIH+r@SYKYZRLy29yMmzmDQ>oDWs<6i>Dz>_q>q| z>PL`JZS^ETQ^p5HCD-R5nPur!=VBq2;`ji zG<1z@n9SJM0?&g+AjSa_v=H3>c|SoBrT)hCYqUAbIqgeX;vFvZ@1u@&{X)>0FtVP{xr8M0a;_{&Nk=DNO;#Ju%GKgGF!k<6e`F7j*3F z(6*aujb@42vA^Tzwz*C+xMPrzPjoX63%dXTAluRi)F1|IU4+p;wcf{BmQ%p*7nD!W zvm@mk5ENEIcrDV)P2i&YyMN{>UL-LgWvowHxS!3IrVQF*?!Z$r~}VAMgCQK2L| zNWI~6O~^Ne`14NZG4MufN$-QmUKnCh5qW9hYhVVL+uuiZ7pFc({4547fd7R{DPZJS zK!-P+l=QY+6nQCJQU+{4XrJ67(r(*4t3UMT!bTQbZ%vQAyES^)fJu% z0#+&UZ>oFyyNdw(UtBo5=*@0Ou@l==$t{UpyFHix_yeOFM+hVeTlc*a|3jqFvmKLv zLP*_e#7h1Z?OMAsM~z~M)-q#|VsokQ4K3XQK^u=&Yy&hyG4TYD0^CVLo`4*v0YMNi zTlji4aQ~&m?UwcJn_SX-0lz7W`4{(snj2}U37bswI9RW&6Dr%$BMw52lZUq1n*_(r~qah!UW!7-Ct<*bh+D{>qE(PsEu`)Nos=G2m;P#C5qATKW) z^kRAsYH$wU^t?2EY+|X`nkuBKv_HKKEauKM9v>&%NTK`QD}1*;@T1QWhKsVCK`dGeX8-&i%4CjZvEa zJnR7@#nw)HrRJ{LOn8-XuF`5AHM*8mU12Pa)$p)_x@{;8KuG(qW19zJB3og%WBGX= zKeO_M(Bnx!iUc^9kcpOda|FKyyofMX5nr2zB%?at*KD#Rsag_;Z6is*ZTKQ#}eYahnCh$?@I21@Dg$3HAR)Sp> zaafRioA0UJXksvmJB<>%wOYWS-`^m}NYo%U{RKRc!VBbp-`hF}!h2ikxP{)SQ!1>q zyvqS7tr#+G5G8F?{BSNj&Tl?Qq)7YjG% zkMC~wYdF_qI+Hu8cY~VTPCs%?!8i}3eQ#tkLP<5oa=Qsp>9r7C20BjLNz|5<;Ap;e zn|I0zec^gEQAelZZUB#k!$T>XXnK8LOCN?pjMZQ$-fjoA($DkdRIDEx3lQJ#Tp2V9 zAF_dmWurKk0Z8&#p`fc|`7lSVN*#O>^0Z6KH9SpucxO&GuB_{P4! zs1#<|pZUrUu~MOwqRsDI;q4Nbhe~m@`(gaQ-H`S z*BCR7_jLJYmfuD6P`55REmCp7>#O?4&S{Ee+ouBuYHl(iNA?$b4i#WT+i}W&oEee6 z!s%t1toKP$2&K@<0YDxq07ePN2Sq7Od#GJV7C$^sDV8?hX`Adbp;TEmolPcMo`~i2AB0H z*2qG9xH9APVnsR&0+leVvovKtg1?Crxu+4N0oarUn#Bf0X(atfF=6}ckh4uSY^iql zx0vwkhBHO^01|B;vRkU5^6pj+i*l)p+WvbPMMZ2ScZ!%{lx{xVUjL~QQ9Xo zH#k3zM`lldEUu_P$ox5VZ>7Z2IOhY1Bpnp_n*W*yYyu137O-O2+I~G_GzT`N+Ke1O z;WNQgVh2Ja0pJ_F`YoPN87nDmpBYQ*Ar{3W{fvn|9+}t1)RD)NG0))P>9{xvnv~e! zU^GSwVTSiA!}MZhVD@BEa&&Bfb@TJ$y=&c?@W>DbKX(>z0Ia zfVqOXTQW_^(Oj7=I|G~%=t}<(axV}~!#`$E(N262P9!1fIJ4|^oyKQs(!`gQqsquy zjTmRtyJ_x8oLg7gc%YYp*=EHCeBQ$fj?d8j7Dn*c&Q<7@hUEjzg$aMbp~uX#M)j(-LKlss6=-2$ibhiD zybL}!6&E6K+_w?(T!+yP^X)-2gB^s+RN6?EG-1QQt}txB?%`OX_wT8foH9pTOO?H^ zWAeCnM}Vm)!=1193LtYH&=q;l({!M9? zX-PXx+QI4F0dn4Ot{-&=y-^%(D)*GDbPHUzV@uj9i_E^M=!x~Ld;XVOQwNPDkKdCu zqbAt7p>JbVpC4nqvCz$@zd0bNuF@-5tGoUb@^Yq^(C~0nEM8w%&rj`1 zuF}oXct&Upw;?3le3qyLee~k#)W_nsdI3XWgS3O(iY9I zy%gkrxc1fSMz(lWxHg?AEuqqmAM({G(fwcC@tG9iyix#+bB1)en##^JdieX6r5hc@ z6I6$|X_2n|WmM;Rv&8Yy^|_YRy1i4>*LtSGKHxQGg+d z6MNK*=GlKs)^-xf6jl$FCt2M~;M4AoQ>3tz$igY9Up`#SP^Ej35-dsGkKB!Y>A^bz7b0t1nRsUD{-cD4K+*N34(#B+B3HTf9 zl2Fzb4+QGy80X&dS_HzQapC*>Tga`|w$Z&8!&Y3r!v|gr3B`BE!r1;mL^|)jjIZS3_*8|?laHbe!9QYq7sWAB z;u&P6pAt1|vH-uUtBV*m>a2836h-2Mrmb^ruvFDIlqzzHp=qzl#5NXx=31mON%N6Q zdy6{wofUW9%DT81_ksk(p8$-y;idl5Ief1%e0q~e4sDGBj(rHHlhVXM^}I13HI6FtuTp6Pf2ey8 zx(6f1Y9r-*ive8K4y$UDAyFV@mMu|E#DXZ!baeUg*O07AMaZ_M^*%d*2 z9LuUk5K=RW0y{dG@6`BYiu8Jf6)U1!e~g4bLif9YZ+xHt3xxElSz0ckQb^dH_C=kg z^GI2a-A3ir*HAI!kLRzWt(d`o8w{g8ipMDsK<*X+2>*RWXv^zeH}mB~8KrbH6G%Ia zC_vm}TN~ee+teJQdgrJA-83k#)S1GJ`xOJnK`$#-%_FM{PweLJT>tRLPpk>RDGy$g zlpzzK@lGZ>ELyLhDc#>NZ=0$S>Xy)**dKxsz0|e|!J*EVdkAMkK7QAOe`;FM<`#I< z#<$B|bW$CzM2Rgr)Kv=f6P=X8{I*Nt-924vnc+4|4}ClafIMemW?m|9h@c=1@BtJ8I&6s5{e(oAfOC0U3;kpJUcP@hmeAF86cd z^dWJY1%ipHvk#2tBS)WKzf8^}o*NdFC;*%{DLYH+?jHBXScVm+WnNJ)&&&t#W#B3x z0UGRK2#KOMnn@<-Rh?1}`B>wW_qcd0;wUm*+m~c^ZlY9cB2sNVIvw<_f`Z!_PIIE; zJ`*X6cB2zWBG+H(blrOKbhBlHx9cTFJH>7_w%N*B075AJ2*P|3DQ@@Gh+I37TA>2` zyx+JH8GZa{v}w1Pv6$;%d@fK9)?_FEMKU#L10rK#1cKk^OD&SAu0{!$D^JG3aPq_` z4V*@Q_`J(~^nnag{9b~kA&5bYCk#d?p|yZi9AZFlq}!RlZ$rST z#Dj*0GDT~7;Vs<2x!`FB9Aj~*X)*8Ry(X`!IOpP87uM&@U|fqHBJAh$Uc+-|*3(e%7~F87eJ4M*|mv9%wfkKSZNF$nuIkT0+EXM>`SJl5;XBjkp! zTq?8E_;4#Ks>VzH05Z@iQ?H~|Sc*~E4s6X^OQ1iwRE~RK7Cw|A({V&q;E)w9$e4YE zGCB>Ph%~0Y-|1ta;hqjbuG}3*Lk-0Gq&_@W%h%nX6K$Q`aLzKxb)HD{ac$TqSw~M8 zW4-&0X8X)$i&y0X@9eLYxl5*kzLh6w700a>f+YmI$SDCd&UZpjPg z&7mr|oNNoe+RURu;ig$p67#-jJnpvMBeS}rAT1cjL81A|EFrV#{C6Y)7bSFYX!EEX z@dS*n29H^!Qg780uK7!7|OGf`AgaBM{T`;| z)kyoDh^|IlA!whW)&&C!fXm=ph7q?$V9)3={+vwMZNcO0S-*G-`&cs zM_4A7oonql>-6gxeJ$NE0R5o%0$TpAnyc2zF5{LxbKI>K%a+->YCuwE+XM+c(F3U8 zYGgFMfZtqxwycapYt#@8g2cpoEA9E~xc%JV)vZSYGXen?M-*l#O;x&?YSeqZPp_IQ zM~I~1GhI)v&EoYKC)FvHgGdhhK6(_$&XqocAsY6+Bgqg5No22GPo8K{=Xx|-#c7Cp zn^6LLhm~8~fHOk}DaInCaq9f)Z`H)czJ2WRG5w9exO2(g!i-enG!%$ybL3Zo@Ft+M zFIWYt|LrO|Q~np@*w%gDojMYX9odyog+}ztuB5j0h%qms!-ciQrBS#{<_@ zX8TVZ^#5i7oV`#V1sVijEEBdbZ5Hf%a~xpZ zy22DpL3)keFLGTWq8GKwizrI+u1N+j(?vH7&Ds=DFyy|A}n>o(hwjVoN zxn0;YnYDmHQV$!45O}N!!hXP^-y5+{pz#NQzI4@_*>D~WPnkh{CNOn+J>QP>9Z<;2 z457h(H6B@@^J8~ZWyaH_#Mf@XcBQzrMzNEtWm(0z7w-2c-+cAp2uUhQt@snW3tg(F7e=@<`ks04Rnc1dk@F$f~ z(}5-x@@SpKQ%L*fom`i5ze$ zNd3%0ld*Fx7e82US5O^^Vze_G4$t^iCZL>2z?3`yVXd~Hm?L%ME+>#2OMkhYmS%8- zXu;Wc1%-lqy_#jw>E9Blzz)fCz!8Vw-7ZM!E5DA<_jCwkjaF=p{|{4d8C6Hqw2eZr zK+xcB!9#F&cMSv&?(PJ4*Py{&HX7VDxVyW%+s3}(e%`aznLn`Grn|bTy1TmSns_}z z-LJ+xBE?`SFFeoj9HN#pWlloJRi@)J-hB8{BHc}y410_ZPZLZufhD=~^2MX;uP)4w z47_(y_yK^E?3rXPEh-G|;(W`i);u}uiew-4FXCQKwI3P<%8TclsqGl2@KFDSw~fwF ztyDSPE6dS3!jSo>_I<`3uI3*y2V9Tre`cCyaGHOpI<1PF?WnzI=|oIex6)fb zX&T7{Zjj0d1^bf$VMfUaSR$p0U+Jl6t9g_MihSFE3u5fhc}qPQ2syw7I{VMr;3tl+ zs@%mOp+sZ^wi_YYE)kac6RUiSkccdAZi`)UBCjf|yT6@L<$`8da?RB_ofmQBqkd|- zVR#N^{)zKig6MidbUBdGZ9J#K@w`!oEQ6J)Bug#(Afib^r*)DXE3%d1GcHdK>u`Ls z#pXsbl`tlK1-$Ge6~2^k>0}&GU!}-?+d*qkw4o152~AP^&6AW&p%XIZPjSt$xJYzI znjdi>CW948PM7Bg5kT{0!F!WHg!%$TkecGng{W^a<n_9SYq{2F7YBRV+RKx_#H3N9edO1m51muNnd=hP;5O=oT+`Tg6T6_h>Z94BFP&1>`pCMepcPmxlt4t|7 zEUwqurkci1o8f{zGS%~NQh6($)0yE#CG%eQl0|X*+I$;<|Q}aL^F1RB9(TP@5 z-4(J1MVgZ$mBy+D(`ONiFO6=`7DSIvXM`Ks9iJNxi~lc~p3c7DCx~(!kvi@Nc38_8osmnfg|`G_1W+MQNcGfk-4d3o;Bx;llpu)kmY@<=N7B z1en|8i4>-8IKFwnIdgS?oDII(u!LE#|8QA>Z1H!a-e7N+>pB}xmd9A@{PeZ=bU$E5 zXp77rt45Paq(!hl$`n~|S$D?!7W}PgLfxJI$a61<6I_#Pt)I&07q}%6eoOBc+=WPR{J_RgwruBrV>y$`$%oUaVo1NS!K%sQ>rG`X|6umiH-gg zeDSc3rz-3LXB~Oi_*Eh|;8T{AB-p4zs?N{joFZEzKOak;51)S~*%CgZ;#`sBB|csIhxO%EKg|k zZ!Fn;m-zwejwNfxQk}(Lw8!8Dw(u4kIz=79V`--$yVCPJJMEiEHg+S$FM*IGzu(O? z=`s*ZvU0AnxTn|Zse$HO(<9|7a8PpXy6GGYu5GQ>nnfsUq#2jagjaYPdr?KVNBnX} ztWC=>C7%C`sXWQ4o|d zAODbM6`L9+6_srs6_l{bhsSw0>6iE6(G z6VqSnD*pf=H~+lDC4!=5bRC{U1kyc&I2%1076DwA#p|Qe#2Ds1Lt+{JGGZ1R?Q%5N z*Avsd*;LmAs^_uu6ei*~w{o9ruh$>WaoDS+^T+;;zSnn?Es z?8PCxE5f3xgA#wkrD3wBiB+$9kgsJ^Vl_hZwC=s!deh6`9>sJMh(4mB`zXCT?iagl z-*&g`eM1iP=e1xSr|+`a=rCpN*E9V7{LSLqZpX~)FY~FaVcX|fUDemt$vQ<}Vz5W& z)Z+}(na@)O`Kz`7`E1dby>q3f7Fk^n-Cq>HP>$V(ymdS7*E|^B?reR))03H^yvy$H zbAPu#F@^&7hH?{=Ouv*hb4wUr?v2xdFic-aeGyIl+@bF+LCs@)%#J(EL2Z ztC`xay|UUgAm9~3v&ZnzrD6CZkMEpVCnWUIK}wn8wu#{g#ux1mVS^_6vi}!jI)c2@XKyEDzy>3%ektrch4+Ine zB-}@JoZnD5oF6%T+s{Z>fCOK1VPrjD zy)cB>$w?-S&Aty~@Ib1?1ba0LKsLS}DX3_o56C2ml;<*>#6ZqPRTmCRBE6AcUI+zk z=hJ3izLWVoAlHUrE>m!DUZ)b^#M)|W-n@(bo@i+z(Z7?%<fY z5L}k_Ijo}i3M8ib(duVsq1k0;jBXwQ^|Gakw;;f{kZ?=5gcSfOCuCLZAzng#p{z>) z>Jzxz0(G(nP3-;sUPU_nTzVPsfdtm&gXri%&ogK+JWx@-ne9Zj;=OZVNJzK|g^!#Q z(GL_r+rF>erV80vsCLWsV8_&5dcnx%VHF7ijzjk!`;NemMwmc2K5(G*>-~PV!AWX_TG@;2`LjL$5qn7)9AN^b_Re2& zwF&W`Zis8ja20D;Sak!wjZywmPIjAXp|HeKaC1EOzbgbPR%{DNQn88#Xjcukv=L}LHa|ClnI z>t+q&J$1v&Q62OFn0mqcJD{a5Dd_0v|5hvaPMm2#(}0*vkoJLm2%^l>Lk*5ZbT|S& z!1uHS&hI>i`<_sKz_af@{?C&x~iOr0yKu8#GifdSFWX!q`2x9grpUgOto*u9#bI8}~i)QLuc$=MnGmm^k-3Oq@vaMfc zaIRl&Hs+TrfzBTPl7f&R2IlRjM88oGcFk0I8-|&z`Mu-&*q1Vy`^qNN0P10;^Jl*S zWTh|2=}W(f5PWAkrV@#MX0LZT_x*wSZ|wvUqdb zv1kPV>H`6r(m#U|ZGlXZnUgMqC=QHR_4OX`8wauw6$Q=@A@(V`~w&( zmo{%F3MPTsum1|;e6h*@4Rs*_1E;CE2-reH`TX|Ch#=Z~(|f z_Npv!VVaEx38yKp*=CQc_AaW{q4-{cFaY^~r!{H5SNe`VodFGr0SL1Uu!!&u;;_V* z0)zKu??V#Eh6d`wSR%g*+1WQ4+h@oDp-#Ua@6mgJYU*Le%!Yu3gKY)$+4s7=SUR8@ zgxxj@wJ=bIF`yJ0`1z&Q_yk8DW&#^%2-4UMNa^g@fF+3y@P#VZqg8t!B4^}yzaSuD zh-T)=2b0}4BKv(^u|EDt*!~XYI zQ}&&~wOKYK-#d`GiSRyH2oS2BUiNYy=DUnXUtknL9RNBM3a`Kw_$^3$QvwC_CmWM@ zSoOUCvLPbE&@~z`!{|?AhxPJ_`ilCUa!Zv)Zz2S!C~Xsi-^l?WYN1xcyM}px+muA!ja$5(6BlVsi^|!mX~Zb zwtlk;QlKT+_y9PR=Z9G}j+HYv$;#WiyNYcXUl(8sYs=pCr(!i6FtuHK6FDLb9gll^ zVrVp_VmI5n&o4@ zRzKh&1B|DDW@Vw?+A_mVWX^Hc?;Z_M5+pl7h9KSX>8Y2ZL!DjU;N~gue=FUx8GqpN(4PQ_f;Lw{Xi|DlJ%1Lc| zpeO;7#g}Hs{b(_*`c^_^uS;25+jI7BB=6$41SkTfT*PnOD@ihSW#1c?ER0aAW?cXf# zuK}7s_<&~KJIC^Lf9_+lTu(1>wSZgjaT9g}*gy=t>ysWF7MhpTxX03xua-cCPV=G+ z6L}tMf4~X1Va?;PAo+C@nAf!X^YxCiwtJV#Yb!j>AUh~KVAmKp=mmAU+BnI};Ze`k zSjt^X?6MVRGBw|BBLA%RHgvMwFn+Sy!tr?hehPT}4UmRH*RU^=>)Cl^Z*=edV#E6i z2;|cP9MHq2&bg`_i!=bQmo-E6BA+wILA5^sW}X@QidVxu4wbHV6W4wF6T+MKORkv7 zbwkJL%LDV#R>UZPC6MGj4j{{=l?yxwO>k1S@dNOa$+&FROK3i?XG?WL^KFy=2kTci zo@J}iz5>L530-U--5t&zJpaEaNAP zJ;6vauN^4nrr2oPevqok`Eg|$A)Q((VW}GNW%;-H)x-(_ z5W+J4{tk$8!`fxKUa&9g%OVvVu%vr(?B8`Y(D@}$dYg%BzxHd;QbYGwhr$&BuiM1J zudy7F5M-bJLR)W^N7_85+a_UwnBl(Tqa)_zpYDg1;(YL4Qn0p_C1f!+r1KHcB-J6GMnd2argP* zLuJfCgCTHL=o%@8D7n>{n!URkH1Qo9W@-$7rtZxW>_84&bgFT)W!x zKie_OBmM^&dYc8{VY;u_dl8)iQNgm5o~aLyw4XTgUC-C3D=XnUu6YKp=^cT1I1>Qs zZs!FLh=#ZWW9n48w%@ny@STe6AD>iujUMVArFw0oT3Qgt_i>(gyw0y!W=iz)-i6cs zzCW)*7f)&Uxu}PHx~2oR75CopWVsun%OHB|^n)_lmk(;li_fy`kH$CUzbR4p^J3fK zCF+*9@3mAUkO9q7F}`~HAYO=0)z*M%a^RK2#M(aW>{`&TQiXPW8NOhDf(?rdW8tn- zx8*$eN%i(=v)p(X*(dX(m-Vr$);RGS0K_uCeSUbzv<$#+?YM5Ftv^ODHh8sg*<2Y- z^LV;_HlpsVA`SLVT6n9|MNqn(ZSiRM^%$XB_RLkzs|Rw3&xzC)O0!;eJB zeY2QIr^cRVA)?jQzOcM}{1$;@CL+>w;L8C+Q1}-?n)riLLrq1pZ3o|Dw&L!BVGJ8p zx}E=GyMfq6qQ~v)Q#`zQ96cIk)?ABa1RdRNPT#(~(~nu5p^1LiO@|lIL39eOlEG@u zw_Nx<$_V4_gY#Rj_846(n^4LG?lr|c;9}tl%_-fTpMTrj;hdRt^6yUo>2vUl2Jzi7 z2qa9yO({2^V~&_LpA_wL<^Q<%Eb!#W@^~h|M3vaOE}y|tG-r6eSkwP}mCQHzrI#rA zrw6vcOD&hr;O`wv03M=NI-C~4iS-pg6p@uIfZec6^ zBm&?}DE_eSOu_{N&U&ASdQ62i)MiDw```va1yFyZzoV~$n04jOj^vx80FMXrCZP;? zcXAl43Un7BF0R5e<67O+pq%OEMf24eh}ij3>6NS~w%=)NF1_Z4%?~!KmMscDzDi~W zedF<-`oePgNmtfCnkjiyl9v6ZU_!*Fu%mJ~n7~CNlaF2Nw>K-Q4WhS8m~t7YQJi7j zMeDN}>kp8%_eIx%Aq}eraK|VGQ$o1|o>E4EL2)NS5b!))Z~l5YZEpc@Jg(M}3XKIO zhfNl|Qxg`5bw;gvq%Gu@s$i4f=>&ZNcw7-V^eaM_Y zWqP92N2UDg0rUSuTIxN62px>Jx6*u@$Zsl*%n8Ona~UWe*hU9yZG$?$6;oF-++S{k zVscSLn7UJ6QzBL5!b4z^_M24@%=|&;pK=DPjzt^J+}w4{yHA_Nmx7TsleT++D?Oh) z2x0VB(1p;X7GcunuVd(o+b=KZ4`+&i2^rO$6mnme0}m!Tpb_ zY6}cckGYq9vG8R$vzJZnM6Ph2-qP;3tk7S;D>rd5o?luu7N73&yMoKEJS40NN7YA{kaDCs8+=j3fg3$*ZhC44(Sr-i|$J2EC> zy0#+j4jH_y$*43XGaiSA%o?N6N2K_#T8m7t;Nuweew$Jq1866A#QD9P_8E-YKPqB{ zv3Yrh%GDSsP%`!KWwgjqrUUBY=OXmwRp(+bF7E3y=HE1of$&E!yrI;aZ*AVM2QrC} z;MLqLbLY~~o0_tt{est@U82=0woA1;FUO9a;KyADL(wdHr_-D3y@#6dG3)j}NJJQ- z>bCqhil_SpS@!NfD>kjo^a`^!zg70O9upmj5Q8U5(1=XhXgNNz``SSh_-09suCU+f z<+pGf3sVMHIB~3dGtR&joxoAb3>zK65`^FljcZeefV1(gx(Y$0rBYA6?{J=jA>3J@ z1a4v*Ol7lHZo{CHk2zsAABf6(YzW3(KTiyNlbFyMeFsp8FR6b0+793>EEaHrrvgRL zQRM8LMkA7bJXT}UHK)1j^&{^W@InP86|>@#h6uC-gj2S;cl3E$FM>i&o^(k=){6MM zOeS#_0Ss02>l0)x@GnO<2_*WOGOmiTD9fy`FJp?%A>I3+Ofd~G*P(EKN%m6kECR2y zEc)IE6P4FZo_tK)3*p2=%ip;6@nC|AN+ccKb(3i@7ic4w)~#w(O{DSp38zir%6mMD zkcWMzw~`3|*u%r)9-5B{A_TCmcq1HFiGbnNduaJZgT5)1OgE4O4zFUU^39ZsF3c}m zMvt$UJN!{sXuX}AI;ARYTq~FfR3}!f>vNxmLg9?ruW`;NlyM~==C8uG=F&>8NNhhz zb>^#RyT*zCnI`2dw#RgvI{$C_`RTbu9w zII^T6ly2^;lst0jE}B<7!tuik^FLjy@S!Bz`YN~-Sk@t;~)jYJMnKwe??qRX+c=C6|UENqiM}1dRVPYfnYJH0E<$YW%w_$%(oj-UE zTw26|yko9*11W_ho#<=^FV20$%YxL zH^HB^sMqYC`#wE8w=!b#*KGx0hc9q!Qa~0{O;Nn2;gn#XHoWxZLm0S^A;d z??JS5zcX}++(^t2w8{^g>xo1! zL`krfOx4F&jF?gFfzR30bTF+yjaLIgwHW|HoiWqc2Cvb~|0|~@sbAIx%b#(~F5Hrv zoBcYi8@!w^XTNFdsklCIe-)-B(di4VBOm4wc*yy6iXSoB?r&1W1KeG-%SZ$xGKDyF zv@m3_z`TlK*bumHBRQI_w^R3jHxlXj{Y6(SE8=9XiOI#1u7%5KPQx@q_eudJpC`}h z{j^N60`YFqz4(r2XI6d0Y;Ti)C6UbY2qwzvZ_tMNtP1n+t*OMqU`aCG{T;A>J9g`PHx-J5?dBNw|nE7GC9D!2^<6f)Bq#HSwNv6~f zCol|7ffor$L7%3t@LGRz&#G*nu~w7FP-szg$Z!OOBd+&FI(ye+(#w_P+T8+32N~Yt z$7infgGDGA9Uww)*2UXJ+@UF^!`8$}qqVcwt#^3*&5oHTMXm9^1VV)lY-jqRpIR-* zgv?aP&K*7_v3xDlVfBMZr>b$PcYny|)ZNDqOvK`1@AHmv_FhbmI#O+J!7k0@2!613 z7!v_d#kP^d9TQU!Ud4`WJW8%!wfxVtsFNYf+^&M2v_vO&NnpDJ2UBGkCt=#pcpkiF z1_gvvcf_1}^&NMqxE$uc)$X5ZU0Re0^T6(ks(v_D57|5|J>pUB9bHEMNQ7f5dETN% zDNeuP4cdsKtuZVbBlH)t%~zk6U=FH{WCJD_OCOh=e_kDjY?Z{!Cf%PHz9d2pGPA@$ zI9NteP^V%Td&nG^>d&%Ge_=IZPPFQBU$&O#qww^=E^am$O;qC!YGeYL+<+^O;4mDO zbsl)hR3R|K{_={Un`cn9ja7HRSwrYL=jn&`*w8NirCfCwM)N70Z}k4rTkOV&xtvw1 zpcZ-jvkv3CYP_=z=VN5t2}G^;3p_fNyfzvus;?e!+2QqF=PjtsP!&_~AfQ>H61wF? zh*|R@b#({jE#} zfs6Lt@FpYpwkb>=_o?U#ypsez&zDO5c@}wX)FcyuDlOQ(HWz8G{hUvJuWzR3vYj=c zF|Rih`SuZXsgJRY6u#8i8^@}FiLt;Zi|-a3 z%fBm>hnG8OmTS6KAyexyA?h>6LVh826y9U#@p`3ON8sV{Q1^KF9oyQmzlhhaU)grw z5K{LF>>wHb!KK?C9JFBaFh0!bUM~=T6}Q&6r*#RPYD;zQ6-RYG*jmV+h-qe+#A7E_`ORd}fF zKK$CW>$?JOrjI82k4loO&J!-U%aLQmmW;vtP=p&r+H?$1{;zU76U-NC=m)v9;N0So zQ22t9e{`buIC5nh={;O$1xG1ZrB15aEu3$yuXjJl5Smi#n7hyT13+3Z!$~@VqLnQ+ zf%-VQ8yJ|u_G3|^Hwp2!`g6S}T?mt1V~MLY;uPP;XMQJWMicQ#+qN<>&#-ZE{kgg> znwlvIkYSeinSMFo$VreJ03Cpavtka%=WsU@bHpOwvuV$e;&NOb-5ZjD{qw+#gsj!l zrfoJ(A)0@;!V$t4qRjCHeV-w_72h`hL0D!uSHIIS@1%lC`i-+;#{x#AFxk{(7a$NHlRpSDWRW8lN26RrVsU=7tM?(xS4CojiiLEj zG8C>f9BBbXU9wla6AC@vwZy!QWGlw6xWRuzV333Dqv@Q9px~V@g1bSOvhyj^wG9o^_0|?k zQ^4W#AP75pGB1Yziox-!CZ2uGYud*c8{@l67w^!wuZ4mZdx5;wAEWwnqvkHZA5^Du zVeq32CxvzW#=e$lOAdtg5BYHuyBBj2Y>#*8+m$mENxIfQ!Ym41RG4IAnlDxmfp4pV z#l@=%R=fbnC{rXJjx72wcCr|gdG(+Cju``eLGZlp_qEr0MQB=4A*rC(}9+odl6Y; zA6v0g_>Vi9X{oy|+>zjo!%`tNs&wt??`e(COoSCZ@QOva);zPkkg+H8r}^-OkR=xOl44j@L>K-8L6*{j>6=`w!+C&|QWWm!F5e zrAsi`!|U@o;G7Ii`5kyRUkX-luhfblE0aDK z=Vxo44p^r8OY@kNu+P3gk^L4<{3EcUcQ|Z+z|%l0W_#e*8Ha(U&y_++EWBBlqB?bv zxAl=GU-&`EtNYCJRc}*R;TTS4&8>%dX~=RHV-|4MJ5{Z~WH@asv7){dC@;5ErL(bC4&1PLr13q)?n6nUbU26=Wq!uWCnN@4ek*?p*0&$yx??Z&gdv zW=oS^VLdq?}=xZOmcVHVuw zi1n5|j*drzGw1ogon4HEA3qTwZX-7CVqP%e>%?YWO-lGU&Y0-xuJ_YnjSk9%M*Oh` z=Y)PlD1<4_ge~S*m!ryDmW0PAF8sHHC{0US=+EHw=l6Bn%gWMJs>t%(9Hm1ylT5^C zub(ep(gS}R+QoQUQSH^+Ow&)Gsme86;33CAe&+pjLdL~7aO;m6mPB83^6^PEyjlTU zv!Y+B={p_wS7_wG!ZaiYLxOrJg=jsUQ$<`26&drT`Y27;Qzv>GNjz9s(c6!0of|U; zsxYNOnEwO?2CAfjE~JBnaji5qyXjpH2|j;}zqqo;AI!mv^F5xkc1EQtL9K4a#Zqdb zNZ>Z3630{Zi!%_v9;CG>Damafnm#tOI%UP==!_=hF~2)mB$K1KZ$3__*MZRplR7sI zc(QGjE|ux(k;-3FpSh`Gyo!(D%~EJOUl`t`%Wh3}ZfkkFYe}Ue9Yy$B876 z?(gsCJvXNu=eQr`?-MZoW~+U6u1?@@+s6ur|DpuWb)?z9q7#*lKtC~AK=Y3fdmssP zD9Ug_wJ%#4sUGSI%oyth?4MZruJTFI?AYXFot9Po;x>pZ>&^07k zo^D5&&W?zRbof3y>Xt2)yFo{*n{+Ya94UdITc`6buu5k z6_r22KLm~dSKM1cya1Dxiix)nRyQx_< zT>ziPjwFvLWts$m>gLItX8UT`XD}pKzYi9R6Q>V16B=2A^aF48jSUVX0irR(<| zeeTx>i5q=~54)K)k%d@UrA9wMcopA*kely++JBuiSGyg$AVbU!h#6~8U2uqxpe1y_ z@G9#+dG2gFmZ*bmaq)~OGqXfzsTS`at;B#qbStaSVklwPWK3aCHE%%Y5cKzNN7GfL zo>I>J;D>ge6Zkb!tc8|N+qNUA%=x&Of-0H$2}~{hoeZ6Z&SbAn{%?e*U~{0_UwPvs zynW8IL>rl(pf%kpdUZyU5J{u`FcPJxHJo}K(rbxykJ)j4%O{Ub^_I){&T}{+n5Q7q zKW;XuwG`h;pCze8Ta+&b-u9Od7xvbbpZ-c)9G~Zd|9OL!u0Hi2^O~9p&=Y%J7y|@0InnbA&`;mg+?bf(TyL{T9Du*e8w%2i@)3}wq!2H7 z*?}P3e3M5azRh+lU5$C5kSQ)Ji(Fb-A}lwZ-RiDSIiOx2>bWyQLbi}6Sfa;@P2v#| zb=H#_{lmY-V?#?jU|3?2NjWOB>hIWpL~v6|8#t@C$e`paylm;R@@&-)@)BS~P@6YM z0PkQR3Xhr;+RGO|kg2OGhsl0a?8(b^hz2B&pv$@%!6v=pj@gzuvf#m8A{%$2+hW{fb@C7)VzOx$gX zUf6ydG|JFwMs(uV6k}<-pBp#^apqs9^nMGYskkLQq80e6poaTkXj;m?^xY}_@ zIZnvtG*I>rY3h%x@QGm2s9Y@!Y|oDXBJ+pP17r?WR>t_stQUe5rT}Rf6h&?A^aocT zpAL0JNKi*dOeC!k5+Y)H>vJoa#37B1ped%z;c{j8(AQjAnPTowLEiWcdcH=k&!Pi0 z{TiMvLLJFoioFa<5c@7&IQRhQE2~e!0({obJZQ$)dW4q#+fswyq4J`YgC2);YREED zOdqx+x(HpTCXw)qJ8F7n+exI2mgtM%PEkc-hy~=Q3+3?LQkETMpBrkq2G1iHQYnb)IA!Ibz zC_kQbGF_JDyHvG&=fysvLs8P{6PN+7CFHR^(AF6JKqUvimZC>ic`8{;3t<27E!g_X*2C>lC zJ&Le89G3e52H9fZ7;br>^gN3tFoZ&J?V_rqZv9#Wqca;}-?35ltX419m>uVePWsCV zWjrclS#+YsOn@o{=0^hB&NRchV5ACBm=7d!QA;m3xA@90yY{}JF%b5pko2gq6XQGg$cTzND@`iO1~!a%XlSHYr+ImKH09X%A%da!N9Ufq^y?)ao-Lfo z;^|#4NTr03vq44XXLl?blx@v5)6m7NkfG8?Y|utcZ;Ze<=ufIsKgw8d?;%3B4o(Qn zJ44q|o`THa6Q|O>KSEW1faax)%w@HUe8C_lVKnnGJb{8PwM!AUXjm?1==&ooArrs| zwOY5Ub^|VKF(2+(&pBmy)ec?Gqqk8U23wI3=ZohG7hd|9@F`|A%) zAdC~7M@d0jgyu3&@7v}1WHz0E&R4mG9O6&{hWHE^<$IH0tT=6%RURp@if z57I)-vESOT0hRJ{t_T>WE3&fnIEjEtOH1nOe~8*WBo_LcqKu3v>BG&7ae6!61l>#q zG@c9Y#7<)Ud{!zO(*0C(G~tCz(|{Up|5AKnT3Z;dtoEzPJtPh=N9Y6V5k@h1aXcx@ zb2F#}l~{$R+0B=`w`5?mAF)OHTSwXf65qiHoN(RAD8RlFBWV&(_sQHg$GMNwSY~fg z)X_BNQU*CppLzYwAuTkN1?e^a=21vGRd-!n|A2D&sO7GJ-Jt$T#9vV47RIg!S<^>5 z|A~LQ*Xr|!qSdcFu<@wS<;rMfino%nPyRw>sD$-4s#rWLDGvzvgk+Nss66kn;k}$%UksmQ(t6ieqKT%CTV)5$x&7y-po-K z0d9*klaq98)h==AAK$<81Pqqv;%v5`IL8U-MLVWc--WFZo$sKLI>Jm3B5_$frM`Ey zO&{=+%iwQw`#)^#y8DOf-=4%xVyPSbi;cIGT{q*lrNyo@@IVJx6YkGw-zyg1aSt%c;uwK*;-z`!_&4Gw z{HsqqW-sR8%YvBc!)}aTa===?qLdJ3sZg1>ILrr$k=9=~XD#Pk7UbV3K~yxPbDOTP zFfm+@i%vf$o&Ijvy19u;1mCkSCgVt0i#6RG4soemKlTbg9B49%?6?_HDxq-yXwrQQ zXRsE*slq$S4FGMy7=&c#Q^LC2EO*_fBm3GRlByW^R`{dai+uV=uHxtWcX#S^Sq!H` zH5I=Vw-r&^I043!Xyk5GE=-XnAI;pqLRorj$+^956PuB+w>zC{1K0K8ZdvE?`ywQ9 zR5hVb;VC}H#2kZ9rpu}i6`}h}0gLiVHee0GZE^MaI?`Ya+7ElXf72#Zpdw=hOQU{P zL|zZG4VK=e(4jxq8>hOx28uD+@#!!x5? zt!017VFcO^qtX9B)dF84>~2LCcS%v5@fWH&+E_to!DT>9Vd8ZCOqwG> z0j(>pT8zVgWY5z=*G6F{uUSVoirWUpmb`@QuQ`~Mkod^WDQ}}JF~S%Q?Z>$1+Rl4t z307<8y|KmdDWv(KfNQ-Wp=ZR+jb@JW7#0ajZQk}2PUp$SH}~VTdxQ&i=qDAj9Wni{ z>xOQeo7*VY$u83@RI;IxL-QFXmNf8(vB1mAz_}1|GP2*fxw$ml+~PR4A`6ygX4!jt zLVo8nnS8n3(cgRIIr?=IdR$2qxugi0z&1g07FGC=Vkl&)AbQH?S~BPT$-I*u;8+a- z9IFkXo;lntEJLQ67+IL`2qjwBS9b34^*IbrD4czTyZe4~tf7|BhzHO)Rio}zoH}K@ zOW!;{s%X0F{o6mK&P+P=IMOljEMxr2XK6x|AyDbNCpVr`@~0$EIR|D|ePg0ycijfv z08Y4sMy08<7%zbKK}Q9)1(oVzne+oBlq2GA)lnCwP&K3;Y)qatPsfR}3BQR=wtM1! zh*LbV-UkYs13&73TWPz<=R4^M8AhP9tb4; z>_ZmdK?|Gct(wjVbu2N!-->Eve!=$*c1&DwWrBZOH2mPSA;L81NKfMjPuI)!uFuPo zVgb7O=cSBzGHBzE!=|)u>_U;c-Y%pCR8(QK29hFSVPR;Ay+%^EP;kh~5)yDQ0YdiU zJ%62*HxWBZwDcj?zne?w+AJV(VwdM?wN>cmdag*zybM$WY)bkr+w7e_B5&|c$Ymx4 zd93nFHh;Awj-v_NpPe>c+WI?3t$ah}(YZC;o8e$ZjRx1|Uw0bYS`p7_Fn@?jh$)Lp z3w{l1!tJii`&$>Fxx`a)nP5K)ClFg;`WJet+6=I=r9R!OP5&PLh8_S(mB~PB^2hxG z-$3shIc5Gj6t}yHwV~kY%()Pr#?TO!!Q$VZD#xf|xQ;PhE4sVW3F`)=y4`;&3pDDL zvQqH#Y&d7PGF#JAVoh@_ewmphgaWTLm>46R*GR=!l=l#5W zjs<+vI_6=Dv4>H*3NQw-OTHmdZEPMn7j}*{bfPfU;GcEHs7eURCaV8`z5s&xl)Sey zp^MEMoe;hB>Vm{?w)=^~diCt7B;g`jzp)G?woC4+QWFheKeNQCPdS(>cG2tR)YP2k zHDmv*Wvdm<_a~+xuTy1 z{K@fzgum(?U%0uYPXo505wB3Iv;O?~C2rk7sA(S{O!~xG^ipQ`K_4Bn`$QQ&aPqV$ zD_n)9pE91EUu{94jMzL1l^Z;sDN`rcFN%N=xDf`?nnj`~I3g(*StRILhB{x)>FQEZ z(y63eE%8ijPFuq^?zyRZIU&+RHWYaw<5|^x=Bfr67iO~6mQ0O7&uCH4{nK4ZKwUTH zQ!H>K#1&KD(8Iy6eZ~LGqXe-Pn9Q7+JJvEfl18jVMqA^7gGzofO@FYXIl48B0f`1* z>)+gYpMAg*hEkeS%yPzuSYf!QX7+*UF^9< z)zz$NvDg%m3k507|K_PX?{j5D5Ay+1T2d1At*>qW!7v6%jC|9*i)&;45mq1Kp7TWz zZJ+JTuW{W2jqtC{NZ&D>og{vj#{x>FwH`4^cJU8r|BwFX#VXL#xp*0&Ugh8zs$x2U z4DKRhMcbcvN=AWs^?jd02PEZWQH5clkvI-xer$QmjY^RoiHV6J6_$L};dZLne#3dz zQay9f!jw1IzunEBN-)Ro?M>QG)$Kcx&m(S$Ce+%I=|SwF?)d=Mqn>@gPSX23!GN*e zz0R`dD`M3NckY3wN7QGf!`5L|D5uxe5%27P(%+k3^B}9w+tc_Lo8s4gJrVX>Q}p)# zo<^YE6b;5u$okDrTk)&T|;%tAhWW~)~8M7to1a;_-*sk9{+wnRSM&KU|7%Co{ z+^xWyLFN9qE~277Zs@pmUe&?GbaLu}Jvt|7{Xv%Hom$QBgCuuZBK*mdGZw^bIVTJ9 z-U>r2AQx*o^Ek(>8Ny-xg$8R}>$myhIREW3J=Fbxl$2A1z-bA~8?JO}5+^+z@~G_| z89qZ^46|q}STqSqHL6~j$xrmp=@|`8Hx7nRmN^NxA!F|sp-^0~3VH*He-FZg9f<|J zcuS~nd@jsC#vel4evs56b>32-_^Xe{qD5j1tww5{{_)psfCMk=$fF!(TqiVsKzbEQ0#& zSQq=W*T`7O$CU#HAJ3{IMBaK%RgG(@IyDvVC^|G7Th~)+gqv%#%-^cnWRal1-+)!n z&EA0|x>`A&nt>(p^A@Z~bc=_3iH~0AJpI8rlJa(u#NmO&axwU#e`bANW>Di71|}hT zJzrF01o|hIdcADl113b#_%W`K&nBZ+ULK4ji>|BADo;}~TWjb8S<*^sKM$9|Pu$$a z&#y=`^Ha<>OMD8Z@_#in z#^!vEFuWZ0GgO|oBI?H>TVvLN4?gSnY3;fT2WlUVa?shL-@%;ZEe2S9t*LXMY=wY zabq|_kNU*&oXg)kozM>;(%}>|nzh=&$xSh;38@08kq6SY9&_hU%rxXBQ$+PB1>cl# zfx|gXeQ$}x2aDUDLqgAI`>^fPG@iag8j#?E@AXUivz1aXma4|Z`GMq{?I4-gZq&Y< z%ouatC)oT=kd2=il=X~y6bjd=dn9a27dln(uVwc2B{R3v7>u$~7SGBTK^lO*I_F#M&rJ<-KWkuCO4wV>>qRKY(87$R5MzOd zGjiy=~;eXJyZNdPr70gUFW+$|J@Lk zgjAuwWPy>Rp8Ft)`r}2fi4++wtP&N3y)Ic7(+PT@K{G<%Q z5w?ru^K*!o{FFiEt3-|gHlC+ke`U~4VEn%}ZF*pn;#O27)LX`Hox|54cD86;ys$=X zcRi}PFX(5kbls&%UcRxN2JG zLdGOq2X5#OxBWAVjZltw=3?w_wkUQmukGwk>#gVh=0@AfO2PHRLnnB5!zOj6tZ;t$ zbO57M@JbDkX~X+b;uw_fB~%9Y@L2o|uQaPOPHUFWhVf2LR(!|vEj$*$)Q9nJIYAuc zwr8?j{q0tK&wJeQtQP^@vp6NS`>h#D%UU^3MkD_b=m`N8$`@+(uKmy8E*_Bt{i+iA_U`iNe zj8mckHzb?n5En$8uN*!>FaE%md~2P|Q1+!uOPo>-le~O0Rgy3nkDT3v>}Ke-t0OS^ z#CE|1zH!c$d|Fs^c4nGsT1Iz0zz_nZ;NXyFWJl6Z6)LH6BC0Mqll5MHqXWU}e&V-g zd`u?X@Kt*eaO&2P-4MDvpqka!;cF&UX^Eht?^({q?9}=48PVLpui-Bnwn-9t4~*!6 z@HBMHL>%CD-=Fk?De}H@1j4}dB;BuHuS(fk>{aihfq{Z=kLke94hG6m>-*OjUA$dH zl{_BmZWo`eKDxhVej?IRO;)MgZiv3a+jXB1nV45sGW#!oYFa%nH4ZZ-?xo2?F%@@kxo+AO zka@qLL>f9LY*`(xwb){X>FdSsL4?!N7MTX5iYLrtDFHg3@D$`Gni#qbgge49P#Nny zj{1v5F{Rww;Z@y3fI~p1!>7-t)1tabtkj`=R^)CcqhGDd#6>?O1ha}Tb{~vdA9Wws zBEeRwG@VjvbeE!fT4ev0nkrPNJcrTDaIX&xEKP6kyG$tTP+YE)4HwN>%s%7FPvLBP zBjmDMk*edi&3@<+U*XpE_+2*tfkPER(30^yjEK&B>9H{Dw6r{5?RU32JgV|>m(hRW zIG||932nsbX7s1f@;#Ff+2wE~&5{`VmyGi7_h};Du)hWCm@TT;B4Mz}00QGO16j#z;+aC&L2_x{Fq=3JJBB!_^4s@_=1r(KP_ILL{=P`RZLs=HYL`CLO)DxXLsa5!Nq>M$p zL_zoZ8lO3a_~pNQ`1~oaeRrbjflbiSVHzJlyH2kW-iY}Y`#)KwT4Aw8*2nKPwR_o! zs#|$K+qndqW@njfN1tOUz`$TbAl0Y%IuXRVs||xcQgzGEO8h9q7Ll8i%5zU&E~G!u z?fm|?*G`#!g}#^?lK-5a&}EePvnF=TQQY49N6A$2&6a41wxA1^9c7uLq4aFg)NV8b zK_qktc6`RuNO5Jr!L>|<(7W%JO31Os-;TXmC3)mnV@ngOldov_7C*Xx;WBwr!@wXq zJoOiR8mZv!g#V*Co6n{ODA}^Uz8>MH$^+2MYX8<3xn3>K=swHcq+)8*T2=6MJeNO& z&T&Semp??+cM_Vz00I5LlRw5A1RXh!!ppx5(heDNK5rMNbJaDdn>G&DmvRx6adcke zKP*S)7)`Us#4rVss)rIaZ3jn_QiM)7<0EKekYJ45vaSrk6f~~P>;^ko`ifB~wD#xo z&x(qma&o6=at5kvFNlbG#m}n{n^8C~lF-s_rZ+}5U-y>d!U!=sl1R4@uS)&br*?nC zWSyC!*xihq%ls#eNR#~sOafu#^tUdj!XQos;OUS!Oh`xwZUIj2^ds7|{KRJFp?X_y zUDvQ5!M@qZ4XA`ht-4uTMrwJ z-O)m4=4O#rC|F%VpZ@_s^KgTK0>#S<3rYfBH#9~vQ%81F`wNohBuh9=qNNR)4<1lu`N36iVA z!k8yS4P4d{k$aM;Q~l^w+^miQUFLCYNt-A91I&uMWOnpCed^Db7{`>-Ha6^^UYYyV zaX5^wPNYAE%i=IV$P89$<#e!Ny1zJ(VD_9q5dNF&S|ynME=Vrh8vB*pBwO7^%6U86 zNKmY+&hb8;a3+J#5xB)z4Ip9C(&XZi=2{&yH#5VZKa{Q&KWLNl4=FToubz`r?zGCR zNu)LJABDO?h$Mw?3c@Iv#21J%(XTpUTye=}ytSShD8r1)|H<7b2PGwZBE;JRU?`5q z+MU3O52E{npAdc}{xx2Ea!5bi%Qc7xR0qIBkbD}62*bT>A{$D7%s*z%D~Z9Fy*&$; z6%WBCbM#+y!}gI#q*^7XVuCK}4OA$((-zj4SYIjd_i{S%e7xk=m?jy3?j5LbUNurn!Q4YP^8~0}1tJ@$T%I?VN2!_e=@G#A|D7 zvr9`Q*!>jo1~Sd(5J-52K)(r%uqOt*qupmRrY`u6q=#s>TGQP9|S%E+*DcD5STKDbPEbO>KI5xt|Pn$a`38(FZka7Z$p z>IjvGuroP+9g1QE#W$Fw@y=f++KjH>oQd#0q>hnC;YvptH=%g?S9HlVryEsr1{aJ6w@2oJ(t@Mx%~SnIwDuB%D#oCq-MA zN0-bkJj1U%pz(mMP(6#KaW!2*#ak~-Y$qI%#~ar}Z7t7=t8@p`#hUlO*O};jQC20w z0#hJ1;-uJ}04f{|8KVm`gcyG;8|KvYoqR+)l+LtpImR-02({{s2&+9P(on`l^}!8N z9J{AR+0)C|km07DCXvv5W-@Xvo4?tJUR?CsyHA%5pGV-_@$890a1oVGz?an`f&4f0 zAZP2nD5< z`!6ag;(t40o&^}Tc^@mtd3kS{zISF2#rKwaMwVkMke!K_la6a-OzPQ3`WZ4ct|mBWF4p6HHO;c^+p$8Th~rcdxBwzg}i4E?U8wf z`Uwzbq@G3qncXBMHH85V!NBU=GN<>I_TT~Mn(pZMnC>sfXm|zNh>6jzbixPvgoc|u zl6ofqrlnL6BWu`QV4~^6qS_MM?PAeCk|V+fUUn-Mt;P5&+}M3FL*K4hy*@=C|51G+ z2FKRpSev4xlu|nBDnJe51VNBMJnGRlF(9myYK>LMJbeu$;6aKGRV|KlIY*&>kE=s548XB5_z_*Pm|~j)kWg_aFoF zO{&`dxxr9X(XCF>U7r=i`vnV&8Ceh!MunrbU0`K zZBU|DCTstf_T`x;wg;x=`r#YDe34BK0~NNq5XYmr9jfEhGCL6%jE^e#_BC>WQ#N;UV|A|@HWA21S53Xc5Jzf$t$bzZSeJG-_RbP z9gmd7QZnW`vM|bL0nCMb8>EjNz8)To$l`fM{`)*Q6!~!1A;5>0%svc}B|W!?m7kxH z0e4F*WTM=VlmP!f;1J-0;7jAN7k6D(0#DsI5L8OwD6U?GcyC8vxlLv<>6r}5s?&LOq-eJzFspQ!;1pq_qF;S9rpeW-ITUUf9E~n4Jt_zZ z*!jE9)`Jl^P%PRBqf1wJ+6r&X4BWW-&6H|hiDg?Sma79}?H5H~GbRL0R`a_yui4ZJ zmH+mluQcM_7O+g6kge}qzUn%j_j-AGzCK}O(kqVAt>jcV=Tx|cUaNSr{oRimLVe|1 zoth?BRVKF-%_deFy1~+U4XJ_u)3+u)CQ^92B^rsuP}58lLqnWoT+1J~;dmb#C!m|@@P^*X zyV^HJ4G9HZw?jWYBT=IiBwuz8qyUQ0VmHK%@Zi`5Yc`W z*&I%}jI!{3;VqdI0bTR3$r8_Qn-pR*T(TMXmg4VRcKuVSTuzn^WhVs^2xY3q8kQ2R z{x zB#1@9VftR$jLULzq3_bil^OpurfCWyU@6^mxb7j0f13EW`4m9B0 zS)Q%(VPj$Kv{YPv$Ssk5e>!Tup8HO%kMVh+c|Wu>X*#b;*Jt1NGRiRfxaz(3L4Y7J zz~YalJvz+&`n)E_;ihybw-CcCnpJA7aA+EWwt!PFLJ@{mYgKcP^6td@01r}8m7(FG zXC6VAN)Q!b#`lV{TJi}+!6$P5sh2(ezUiXa2S0YwO@|#!oCx2DAaO@$|E*(QbLRd9 zlV^zhheX=*@q9oqV{tUv7UW2jS1{=$$YiARmT30rS;RB4TJ-BeYlO1qkMYU7h%mnm%JtCV+u8`Y{r#vnGgnzj+&ok zRz!^mV>Tebpb`W4?j%pGd3h4aek+Kc?35a0Tw%|6XA+0M4A1x~U;t^rKb%uxFvy2P z^-TTThGF1PYI6x{OShi`{#B%IU+13!06Bn<<@siePyNpzLCwIy*)JnT7hJu(s71bX zSNn|~jCB}gd|!R1yViv!fGyqFcG-MZ(A>>0R^!I@_tNCtY^Cn?RIw|dzu@uJm zDmhE(i$??<$4Z@DYgs*Vt8>wZItP0{^J$z>YipIy)MER@+hM-~1F^}fhZv-!GHg)5 zZBl}kGh~xX;X}*IlcL>wxUzIi#JG=}coNWk_|pLES1L?R<6ZW^zAU;(=l4A4WR8#2 z&B;NnqVCeOF?OJ)sVS9_p`Y*_#PU%veM3g4Cif~Q9Oc~9Q$gNn)#qHffr1C8fIM3? z-wo+(Uy&wUJ!U4Rt0UJWUB5nKZdc7gZd9`J-x+*)DCuD(9()f}(OsOc(*CKe}Z%zp<8MzJ~oV>JE{zr~56h(I#n@yn-!0H%tMk zHK08c(IrB}NLm~%t^hx^>m&Of;;c;b*CLpt9tR^nA!?a>*e|@cNMD6(Cle$rm99qKpOm>#P zh>ot@OZH~;!??;b}f!kWaLb~n30xT9FLQ*`zA z4w9Io9bnuUH-w?5^GYe{F$`8y9>9CPOGLxsWj*}RNkBzNQrK$}^iic8lJxC+*|z>( zJ*p7HPYM70TUE>V@=QccEbwVTfmMg?$6nU3f6EKSlVZm2f#I6!iup|mZ+JLyO=$QY zzSpku7~!n>s;nF-T3JTN=GzT&MHK=M@={Ypf9~78JLEVt2#NiS)+Uyt!-g?(qr#g@8n;$fVTFzE4phe98g> zSb6hjU^pC&>FH^C_#jiU>eio%#H&K~A*kwNDL;e{%Af*+3H+RAeij!F^Am0#Oyx-g z^ajJkYtz%yhh@15SOq_GwH*85PSLnM+Hmmu3u6ftG+#w5Sx_}q){O^RQ zm-QzIAdYCj|FkFdxKKJ0ZlqxB)}>g-U-LIMWVh?E2jCnI$sBc@*6_RC6_n-uv>T)Oo~86cg=4QEujW;nUIk=rlC9l1+lNk z;uU^tHe2jWOHCbvMMLlTrh;8Wia>6_pl2oaA0&nLr{Tb%<||d=&H7skCEMBbt zioFHpH8f1Pa2mmsSY^m;}6+5!K#Z?a3<>gG$ z=B6=YhFc0D2s}mmm!6p1X7zAHVVNmFr4VFqoUt%a*{nb%HB##`2f*^45s9)?O{Vr) zj|Cph(_{VPwSZ~xAMn-lkye6T9x@Rb`EkyaVl-VhM|G;ZHfFBOPM{r%Z0u|@7Uv+@ z(<}K{fbjM8wRfa9>6ccs0Z&m;x{lF>T5_7$KCS|u6_Wv+1Ta7pb_zdNYY+U4pxhDp z_v(BML#6yd#dHkBrk2N9A_@R==dZgmweq=bQsw^K^GC}`~ zzXyj$@Bgs?l3z&QVvD2MleXbhl^jX3L^?(F7MSd#S=3RR<>b&I@6uq&h@p|n%6O?M z(Ee(WaF}fU53<6&gED{szZ~Ti+LXA_0O(7;4qKF7R;tY+jNTAu3XQm6>jpRo7VE8x znhgm(D=ZS<`vojr`ytKX@vm$SBfOZP*dBm;W8&x4PA}{~h|>V7ES0^qr{}gkB1_c- zIXWf_tGc4=f9LeO-QuX2+%1LEw`M2*8|?~lS+)#)uz?3|u{c($Ta38&Gv8M=Q+wP7 zZq1qcP&{Q<`Sg9%z|F~xB{BU(9Ci1F4B&j6x}i7RtKIg|N}mpu!aEakV@r5B|e`1z8rHgy=BBBJ!l!%O)+lyfqwOQzD4CTR3ZxB{Wlh$S%|4y=D$ z`VF5gGNo#@kr9;wevNhmW1FliwPnK;QE_*i?u-5KUnGXFf^>KhlA4BMEjm01IeAwg zSb%)#E+{K8n(F`gIvIwF;tq-t&9M=5>{hkb|E{DlN2V+-`8{=|wWM;JJfrKlXKsxnsCNSp6GmVVIqO6b! z=DE1I(6h6v3ZA1^7@qSBnb*IJ$T(dMvuv;@{@6MgBmn}TwQ;jf7n^ty5J0HBBmf>= za3uQ!19j@L!PYlnAA3HKIv0;uUKu5Bhhbgw+5Y*#vw_W5i|=WKt1NjUx>!uaAqg%t zGesO95#1Ff;HB!sNC=xj<|^VeUM%iDhh@ePaQZ%{h2+8!ssx|Qzxv>s9n@F(Nh#7A z^QX!|*EjHkV2Jbhj`%{UVK7QXbNuZb%S^h$v9 zl*(E8d-TKcEyAOjl@h}z)?)~%?(+Js*d-O_+4rG-%3b{{bPuV=L9ySYv`iCUZ)s}mfo~H z@wNFY3585#pzV;{U|iq_@!|V&9S+|{w*_W488LpsO6fUACo0G2O`Le&^%m^5BNK*4 zGg_7LA@l*Tw5p;m^P6g@5<&3L zkG?uwhzuGET9m@e_g#l_*(Z&xy!p@>OT#&X+&qQKraz1_5-Gye8Gc+ehyZkqhDeN! zDMaq**^bVCSqfnd6G6Kc%SaMev{6-wN{Z} zoQwfRK|#4tF{a_V4S4ANYkt3a{k7GU^|>2f2o;UajPvV_QU3?{pkOj{m|KY0u#!Lf z>{J+wOb&9+0J?HeW$jgcvD5qOJAbZx21D`Xd#lev?65y;9`eYT_<`f`4Ahva7CBOK zMBH=?*+RSFLZOZih}Q}Ig3{Hkw*yKpppIal8(s%$GLZCJcSC->QIFj;*Hj8^2_1z$sSCF@^i|QT zLy)^uO~SoT29yA0t^Oe~t}}SlfTy3J|JEXj!|hw`4mtq)9tFnGZ|?HVm5Xb#XgtyN zU|0C)9F@V3mXb0EbH}u}Dd3wTF?~VEuB+@weeCYH^MUyH+fGZ-8dRb7Pvf&*57oeu zVFRy1mWiL8Vkw`!fYDi3qR|+SONSZ3v z4)9Pkk#7vX{56*F(fdlF0lUbkI$Zeu(I)IIMzyA-qy(FU=Jne$OqPMBqY*_9wQm6NkaJt_dJM za`&6tTQv`*DhQ@ykmdm-B06UX%T1QVIs{7s{~L0^^3~tiIDSeVv{l!iB@l-0#%2sY zN0Ac0LqL5QeGQy6rd@9Yh)J@yH^kCP=lztQAfiu{(4}bSd6kX0DwhM%BV?}-@6z@} zXO#Jc2pXz6h^H8sHcCvp>`bk;U=b01cX;d095 z%2^Pc%6}we7yf0l3Q7fL8%_(Hl3a{LeDOo4;m8@I1&aK?!M;9a)#>a%I8W%T1mTl8 zlyDzbX{Q#PpwE2pZ<-Pl7Ap;rpRDYkcoy+ah?d9SpB5y^K#4gw;<54+17BZ1QcBMl zzD;MoE&btVX&PjWrcc)!W(7;A`7P@W17(82E(ZQyswCcE`>tRKN}Kc6P{v|;gM11r z2m4MN2~|&5-JIt6_yX;cXtRdmpMSN_ZsD9Av)I*zWH9O!s5%89;PoLgAwK#8N@hEv1-)# zX5<0%BVM*u{rxQYpS0{Z>$sDg#sNZI=W$eQ5*L2&(_M>O1ZcCUUSw(Xml`kk7bt66?=NKeneE_6wHYaBi=6p^xl0h|0L zP`?TKi3!=AgmJ>VN5l6a)QISPJTtGAsWh~ih`<)9r+N#x$Oc7EDdw28_|R^yqs1=` z3oU-K`epE&w;Yvq?7xsK=P|QzIoFmCBq&G)E5*}=X@T_gOFLFX%|S?1fs=tcR!sJc zRVaugE_Id@{ToG_S?i7E-XTju>Ihx7c{t6Qt4Y*-Cv?lztrM$z6+efWY^3F2>;f+L zXZ6(nT4!jYXlf%W>${MgzU^>GP{R9uPEWGsq67xskno|dq1p;M`CtB zO2k_f@T_s3xOJA+f6h0Yv`oq%G3RiH5SxC%N;Red0g%s663qz`XUo^890L2XOmac& z$1^%)8{FEs8|;b}x)FvWSajO#Af#S=iqP1Bd9?W7+x1sSA+bW^=c=1+#HrVOHaR;0 z<%$^C#UMzSGhr{L&E4VfYhtgl2MTWE$u4|jVC9eS2_JQT^58TNG%Igzs%v#sA(wh zsnoHIGxYYr!Ti9SZPyqX87Z!-vq_GVcX6pJ=n~8Mv3!6`o-0lm71la-_tA_R@H%$L z{(Z;{wx~_f2v&lyLmmXJ!Dwb@EjAdG>rWKoo+qx^(P`YiWF&+k)22D!Hz`)c4oa~F zmseK8$0WrhLz^Nk(=&S(108*t?B&Kv5lBGfpbTT~FA+AYc4qyP?!^56EhoE=ehNFM z63>5H`l?^?g^U2YGe-YQrfUOpk?8J_Ok~k~tm4xOSyqnZX!{1d@q?8HDfcHc1n(ET zGfL}v`N!#BD28#7k+}&(9rEK|@#?x?#MC){!{y3|h!G-zg~RAmQ^n3t)Z+TY3GThF z71KVLnn1@B^Hx>Jpi2f(z~vx?1Pzk1nG4?tE-a zoG@X5;SQ~Ki=y%(bQ01Z>n7|&a9WjpbW+5|=r(++ERjhv_oAbXvsQp0ZrU1A(2N?s zhAQUHVR?#|_yOX^Q%=2uUlb)4{PlJmF}+7UsSvB8DL$>}K^L?G8rZd~tQS%B zK<0}F;&}8}P7W;YH6xh$3| zdh@J){J<=!crjhRF6s>7Y8XVo<;G`B&oBPg?sGql*U8(aG&wtK#^}hJNso}S9_P$X z)GIF!XudQYxxbK|pqMwGpgxaG7f8SbP!7(TE>eF?pt@hTc_8hXtU>Kh<8D!;3jDBT zHh>?@VT;~aW;sK%f`Hj%PUrLVTw=Pfc(mM^RU7aiag_0c%Gs~|`yeTCw47Ol4hqs5 z0txH-s)9zsYhq`f*DpN@H4Ai})aWY;OgUsQLLN50-FoX6Z!FWpKb@=OeQA#0EMrny zQpB~VgYR+2CyHKi=4RLDu-M5I@{fiTM>?#jZ#&M~qHW~wu>bxM2R6T@JR)vhOg?9a zW~bte#YOzcBiroY08eJy!ATV02yoIB;Q*F)7_zYW%RI4=QcmF+Ba~mWYmy+>3FuUS z@ROjTW7uUesMo;yO=}HoOc^J0#1*3wabNrykk{;(^EsN`hT&NQcZY>xgnxhuZxr$Y zV?zV+U?>oVNo_41x13#}auDlXZR=U>%b2KA9AvL6yI%olEOM!7SM2uZ?tEqjc5E)m zf&LVKqQUN%p{c12CBMZ^qwl}vWQ$F#h1*|&vV?`azm*MmUQfckU7lW2-75^qyrkJ?;NL>6YNt6PiCxG@ z{0zTyRMJ`@xivE(${;JI7zX;WZ8E;ELPY!Y5x@$g4ce*WyE$o$gP|rEiyp41u=$jmLdxxV3?Q%bH%6#L>$-bR`&jlpa}ed$fH7TZ@Z#8#83dGBgL(OdM}@yRga7z@#-)RLhviD zyt-1UaNMRnSRwJ*#hAkD@!wpJ=^#~IFMk3iByYxmE3EiJJ%A~fpl=5nmSprbG?oYg z?mf;>67jKsX(Y&e}e&14%Um>RW6k$TQ23IoK0EBIPpu!zV;4Zz3r+J-D=9HsZk2ZxWY zFG0RXdH$hF0#sCdVgzZ%y|Da?v=`5+41v|~Z1uSv|HUu7eg_fV>gw+1 zzx^JvBz|?-MsVXP96pOSQ&Uq3YJ_$dPbLToq{p(!cqn%h&XqA-}~G$6Ll7 zawHQ6Rp-Dy2S<>}TT+ju{vEx`%jj*|V4k;gt%`-jP7LWZozZr14zT`AhXe)&4*R1d z4YdeE_0IYf zNxqRD;ir~8xTA;W5M7TmOkfPBr-qcXma*?7%x4II1wb02+dXx3e*H)z=|bVUalT-n z*|hQxT&#_;0ZmaZYh}yBvy#BmQKD95u7lrkTCYJ=R8-#fwn=0(F%w_(^Y}WKP1r4> zSzpS=Aqj}1{H6c9B1+!ZCQ=JBCOyl?4yN$9x8yYL=&_CQX2*>Vgh5nR6b@)y-sIsC z5ukeO!KW%$w0q4X%2$D-4GCQ`PPi2NE+Pf0DlC}u!I8`FPbHQS_)CC@n-wLm2{O__ zT6mo2@<5e-O>&1jwU)YRPn1@U=>%+9$mEoo!RPRWDlJ_2sraz{uwTCJW44qhIsr-t z8HO@$*LA*lJRlX;!J;8(Vh0409}}4dM=^4F+kak!sLgjFS}Sr&e`I>KXCv;z)Qrdp zm*&I^0{s2e{kX|(cg+itx)D^QP*MKjYNKtKZ$Q0f3IQYm zyW+2PTt&yQVjIo6T2!@$fIVeyvwA>i-)`}ErdM@Xs!vK#)1!jBi9Fve?6lF-3L z_zQpnt&@Vt5o90-CJJMU%*3&^ZR>e=sxfteZ`lP?vy5I$XQaZ{gBson@}Nnx^PHJ#`VhPNF4LEX!pS5Oe@ z?ChK%`OzvH@e-2GDdi<^(m$<4y?+Hh6}jzZTMuCWb`Foq+7onbVICAKj`+GYs=BstOB4fWp0{f5MY1AvJiyH-AOH`>t{cK_>^_$hg|ZX zTK4sB#{s9eExd&trI(&zEZ@xOIGpUMcEjC5SNXmdl^@j~R1M=Z zsB?DnP7hmVkKXY7tlypOwU9(>bsVs&rFhFzN>QwNhj& z&GC|ejt+E$jhUI%7#`BQLx*cDhcmE8uOWWb5Ne!6qC4Npv;(CR9Bl^7YoH=xQ z3vH2$Zy~rTd0<&tlKVf)N!egtNp}6ELfe5?m9aVt#3RKK3O%TEei@&HFMa#mI2G7w ze_3z;V4MA)#X?Q{%~>5fqL?LTm$2BPXozg237>wLlbmXh3)^(@w2p@rJ=f`-e+)VF z$Gsfy?^i$$h=NV7KrCSh;8uiu@>PZeKF4YG-gn&Hv3RZnn9J_J1w_jCdZT(YO&S)P z(NqkFDKy-CRIn;b9NmhM0=A`2ae1n!=)X#Bv2eYlow=SjqA}0jsL4Q?D3Nz(m{VYB zII^_5sQ*f7Z922ov&u;UkkfZ$4Nz!R+O=bA?-N5WSZ$ zIh&cAPnY))xW42y^|48Cj$4v5=0)E+nbD99GtUe&Fe-`EJs%yHFsf(jWceS#$(LF( z_C2cXk%FmdRNqi}CTG(e3aNpz(Q=1i&eeI6w}Qr$+tbOfUoLKDDkWnpO$TwkRyo5` zZXBm+IS4NQZsnvl2L3)t=5r+UjtI|-xybZ^TM4vzWUTtG21V<0YrXPkGbaW! zDcQ~HWz;a_xp|2R!YxG2FOas4%aq;D(tcu@7QKmpX3<79&h}-cHH5%QZg9vs%EFSd za*Xf&oJj=P7-ov_!M8aVy_$s;i$v)S1meTo*(q+bVBLnLlvb}!L2J7uO7%I!qZg*1 zyYK-FbV}>Ivjbu8>xFlp+0s0-|KKex3}}38Sxv)M5Mr;cu5vnkI0KGnlr&P@{s<+s zY^x%CQ+z1`Ajd{S#5gQ=6N*zhg@WzvDe(ES>+2;+;ty*~1dt=G;niN6I#9JJ zUaxF5!z|lZOah??2{5lVDb*JUWj^K=^{z_qI(udp2a}pY_2d+m^`Lg4fl?C); zrE=NOm={q`-|YuTtr)&M76TQe;TJ1$Jb{pu^#58Q+jR6x95)`ySmS|TeLJJ_5S*yk zsa!&u#d2I%me7R{4x13iQYC9rQm|9Z)*Zyb;S26EPC;^!#EQ>p|6EVEsVkGf_L#cPPk;o5RW+uwq3w#E)vH!@efxC@f1UP<1oMTS4 zEtWHlwA|^kb;S*j*p5iwl8g z_BABQY$^ZJj**x(&_O8ET1P+|OX}KZgZ9*IJeI=K6_ITHR^hAqH<$h0=>p_&0cjMD z%+HW0j2zkW1f71jW?a}f(p4SYDfg#qu+*g#s;4hZlvKVjI@WO*xQ=C8Wh&@*t1-qjsc zWxp@HoV9XJ&g>LtjExG*weW1%wzB9>!b@}_lajlij{iOvmTiC7R)QQT#d1d*CsXhS z1*h0D&7W083x7Ad`>>A5^+yP(q9DKRt@vQfi9<8GH`R6b_w!*-N{Ima?mC7-(kf-xeF#qe@MR;t2kC10Jp`>$& z+A97hZ*TA7j$CoDy^Iq~+eMFswXN+Fc~Y&{A$VJbcca+J>a$jbwr`!5I5x(?{OyX)tr7-7bACPpX% z8YmniqCyYtKWRLGr4q8+C4rS2o(27pQW9;=od~6XCZrikF;npK+}vERfdtyQ+kzLP zDe^kNsLIOn)>-@_kP2Pz@aH#Jkf$X~5C851YlSmYl&=8UKpez~CypuVId2HufvZ!) z?A44ITt)*-r2hE+z{Mu0Q#Uyc7Ao{_bEQt&f|CWzO14$tm7PHb>FN;==>&t z5O?qXWTK6dLALGGzPhGAE-j;TdvyMDN_VA0xy-E_!!`yE+M!Pw?lUQR)&;gz+Bzjh zP$|MSJvj2=u!SwDzM&z;QvZwG#wW*bU!8(eijBUbs41Z&$2Y332ww4D5k1&tV}6#B zHR>VOAePQw65T~uVB2-Y-jmC_3U2if2YHyVk%V` zUayT`K=pg;VJ9vQQXG2lZN$l65iO^a_Q|(tb$f+hs5%+oCY<0!a#DsvcG3rcooD$r zyftQu5+6lXdT=OZW_lVXv#HCDBp{6MXIC~su7rUFgN8bfvYfP*b|Y!<%{Boa7WdPK zK~{c-kp&3;3pa-g2W#`qSFqO>s$^hLEZl_PLtUR)AO zr&-@Iz)Q_ePmA+CK2rXGMpkvGQ68!rQ^J6zr}WRyNf)c0qU&uAfkm^ZWo1rubp80f z)VVOYZLS@NV&8hWDnB>c^`c0Pj>LMd3vlC^(@@bzT-IBwnJx$&tIHnudUFV?w-(GlHIB>Tf*CkAAG}~vQdK@N7UYk_c<>hRp2T#@`I5i6BHd6dFRvUxJ_a? z#dZR!3n13C0F71za6OIiFu|?}ln-suX36D431m2dw1ChRyJRM_V@!i*keLUMPRj1v zUR4#R`{m1{JQ7)YVGk=aP-SmXo6Y2CG#M-T!ymYXqdq-g7$zXVlkwmXg z`;l}=1T8u6K@wYQ9zNVt4DFXvDy{mkCt6Z6T~0rEkpH08Q-uPNW#J=^=3i|ptUuoz zAF!03>&)Dlh1^H?1uKG$@!@XnZsS0FAPkOA0x=5U6vRIjaqq*4=!4Y1^yEEOFNJ#V zgIYaibbc8s1`=>g9Q49(<+u%^Maq88i5_LXZg^p`qBN-ZHWb*AYyn+Ly$iHeMZ^4) z>|qctpB>6xLz)AjT016wXa1Yio^pz=9P_?UZvEXt+Cb&WXVRC2yP{bJaNJ!uu%OcBoI6>W4w-8i(s_m9EEOa?()|A zw;Q`c2<&tJA5GWbUso3`+ql7vZ8mP~q;b;NY}{BkPGj3>V>^v)qp@u?w*5}N_ufBn zfBT+u_TIB*X3e5Qd4=;vZpa!1YNEwUgYxz0@>eel)*=Oz^jM+w@^Ys(hB)tsfnCSZ zYVM5r9wxwy7@yp6TAJgYp>!5(_AqMeCHv`9VPEImXlfsXA;7+}(@H%@dWo*7chL5J z>`-!_l$Z{OMERhQGKVY#U2v?n1qp?zNeW|5DR(z4DX5r#Up3Gk+iuwB-T27TBcsGc z6rYT!A@{budCMqrYa?ot54VZMRDk>*t$s(**kx`b-@zqj=-0TN8Vod69_~I7;3Z z++VC0#MDTd8~)9AU@cc4<%9=pgpdgCiOkwJw_5B#2g4MhbEXAS=sd-Ycu3V2#%nN7A zOL^G~8O z{T%;JDj`{ zCF*L7Eq~?MTqWgGU1%Ao6P*?{87*#eg#H|x&iZVM4jl@KV1!9AX?4{^PaW|8u~XT_ z594poCCNF_!AdtZ<8Diyn6bGX`GHE~&Zf`Bu&kJmw<<_Vsyo$Hbr*?RRWhoR6LM_GD^%zOH}tFVh*@| z9o^w{Ezi$kO+JtDBJh<37*OE?dLnwt>*;CuNQvJ@_6~=e2!bf+1yYX3i#*_>v!O#a z|7aE8`|!Q+?QJHV*ysx7Q~%nF^x=x0Zpx{AR|wsgoQJf_;Ra*t8Ut8Q&;@40_-uVW zhXoL7=L?)MEGS$kqvq@fzFtEY1LA6i%)&PgCLtm7KyO{TkNtLG0d%}D6Hi^Y>{3Jq zkTGxSuKTG+hAih{z=VoL*|wd#%k1v?vXn%229n57NroG624X@60j*dCl-0au`(>Q<+`abA-v&h_Dpi5a* zRSY*YwBSr+BP5dPZrx9D51@?ejxF`K`YT@J=|^o<%%Ra0ZRk=JsPkQJqrHASaaYjL z7Ga^Mrt+>&O92i3U8n>jqNe$iuk3DrIE1r<$AFl7<_$0{|x^;qni5Wo1;{-C+*QpI{Hu_jhSR@tZMi^RVc6 zSzQYC;-cUzRm{o4y!spA1)gfQL?#);IwF0DmlLm0z-wk$qwim~ig*RzuJ&XDyU4 zjrsoVenOW1{wti{>zS($1MnbK#1$9@5oZ|gk89+A+6!zQY0csx-TARK7}0qErwiCt z#ZiHCBsAin=Y#*l`$a~x)m47W9Y|y&X&jq@D>qbGvg7jVeLDsvQ*t@6_=YbEoCuNiOBs|C%Er*~zC?zZXcS2NQJ!=CHftEy*BZ+G5fp-}8B z8#|S>_8PK82eEQc zcA;@njrLPU=8sEZq88||&X2OI<`YV)wleuop>tejx&JWo1|sxo#247>1WA0GG=KoX_>`0s6}?zy zV|Z%|74H#R5g0H4Dc>IwWS;L*u~R+cwN-c6X_ z1&^Il1v5Q7fz)0L4Y8LQZNG}bqQ{mnkXREJ!1$@@5^-Bt!F#*HxiIi`9~NL&EXbGs z@?dh338f(Pe>!`xk#J;!NNk-9=jZFdJYX@=>JbMzZ-goF61!4UwfCRaIrj*dx6b5O zDR#Nu_e;<9zhqh7{aKfAh7Q(>j&@%;fd>lq;6BFK9m>yl3u1j@{7}%W7wCqS)w{#R zZdWGKS4u0@&Vsy}wMDb|=zAZsg<)_?Jzm^qh4XM=?XsjII6l?s=F9jPc*sooBMS_6 z==Ddh?Bv%i6NFZrszN5hLru&Teefmg0#g%*SJqArv7&PY! z$qJ?h_!#4bEu4(U)pzg_e-i`Sn{*ek(f@znGxp~|@h>lP4b-IUiFoU-{yZh6?)qu@unEZSIDv$he& z(6@62OS-7=<~Q|m&@27@FX)CvoVW;LnGK-T?wFc^cohsqyD?#9ge^1ib#~yax%`~u>63NZ3UC%M-j;`s_V&q^M_HC(8P6u zfmj_EPl$<4qF$*mQZKVVmI(yZrP+^mMiBwb7~r(yQ1ree$)DVN>u>4yRB{RSR&`Y* zHiA1$%x`LBaj88cOacLxU?wl9ZgGY;lX0JPWL#eS$jC^?jn0pw1GX(Eppv2@N4_!d z6|ejg__O~$y`=3#m#~AyQC|8sZERhxSR&VrJ^s@pD~p^*U?jlB7w?01TR|H}S+5r- zyNfYNa^H2Sph-X)!1>yZ)y@=Erpxf1T2uNrkH9arlSpODd8Lg}PMSgnNz5pTO%Sc_ z?zaD!*Au-3v&`}2)5@=THYG7xqv$92%W9`-xCe)0hU4dUfrp)G-8)JXW5qWhrX?YV zti<#6r_{(uokMlU@s*m-R8`FRk*mwd>efU zQxgK99+k+Q`e?uV=h~WE*`U`OpYN)(Z@ppIky4!6nuj0q)l4g!UstkPBT68T=B7oc zT%3K&#wcJGxuWKEB<^7<6brpv>L=QQ5*Q!ab8QeIouZBJX3R|5a=U}?Htu~?BWF)J;%b))VUrasGY(`u}QE>)U=n$l2V+AIC zk1Ie14q4(@GH{5qK`KXRt6Xxrvf(GK2|s-!APIxrc~@$=g{G{mEJw_W3kc3@J}D}D zfdztBxCL6iwLW2^lc;U@!3qc3GgB~zSh$C4ctS&*o`+WvVVh{X$(87L9w1QJ;m3IL zn2k&BuKwu%?YenYn)QGS5wr*f?_X*G2a52V$<^J*vBYMkE_w<@h&d2)gZCihy_KU*|)CF z)S@9LOQSDGY*lsI#n@zWNy{>EVYboXRHga#@**l4-If|#qywjUXDXfqUF~zh!eFia^OBLQu4MTogY^8DsE_2)v$k zpXwKN-n~338)`uv2|Y*La0>|$$V3Lc^2K3(f<}f3^3|b6uGh7nS8gFx;v3H-MP`c> zn=8~bG}-m_th~WRzoPIZWhArqmi$!+9CiKud5e-DKhmt=F5IlVsUn5r#&!0gK_S=D z^aDdi@APv%3bddwCuGu_41Ubi^RQ9O4L-Wk*yfG4s(g02e?02Xfm^}f?vKpP%cGFE z60xdrpQEq3*rr%j3m?3W1(R@LFlcU>$ux>=>}q5u5ptDC6L<@QwjVUK zr-n+Iyzt>StUyB%b60nhK=kt~|FAi2sTx1|A-MK;VrU~tex-t=a_Eoi{mF!U`wmP6 zCPGg5@BtOZXKVl3wXolMa~@68%%fbEH~mBp`?;H`3iEb^prA=05366D!26=lWh{kt zkEIkMAca8@Is73Gf*&y8bR}m zXj!fujf$DgaPGQ`2f^15!;iP)QGlKtjjVDGs*v`Xu)9f6bR11kym(b(f)Pyc*iARI zn;i7ZiG9DJx4_R~b`X-mc}Stcb(s z%7jG7GjqFA%aQ%VijU?vnX^J-m4zXJdDE><_~G$JrQR?wmpkg`t)|$HYe)!@qa#z$ z1v5~1v~Sg%c~)ct&5Kq$GAY*KhoY*5F;1xEux-wUa=l2<fI}nZ%a|X!?+^AFx#K9uv9G3!u9E~!y z!vYh}S?iTmTaU@KjhJjzlY@1gZXZrdfo#onibk_#&p=wOSS`x(Sf4nqIR0r)_dR?F zJ{R!Y3DmHbJ*cO43d|us)?#&1p_e(b#8s!#V0EI7mlQuh=AH$wn#8Y@lf^9i4s6Cfi;i~GdW~KO}kjM zjh9lx2ZT@93@ob3GNFCPwYp{NRXtN_)H5HU%hAdfD&}!`U9^ZqtVdA9qLBNU1gK)Y znYgLj97ni)|9x&n0 zgN>a%RNxjvO4gi)@$@ET{Al-k(txxlWC-54)e>n~^Xk3#n`A}1_Q+NcY}Y9t{i=6; zQp4E&^;vdPq>bJSRX9EoRHkulVc*`*+m{YZGE9N_`}BTvaIMB>r>}nk8#rr|Zb?eI zc*hquU>L)Rjm!v#K>@o*>X9k1PFFQNu@;Q>)gX$Rqy*NGjV^FqR$(w*<$q6wb(B99 znV3Hr#Sy{?XLXVDKVSv+#+x2N*y!((PuVQuqn7ejjU4bO>w$l*Bc5@U8@y@cH~gblOpHo!)fsn!U=yy*HH|Cz?K)z0#+zMK&i znN-dXe^$~17$>WKJq;Ivg)@K{o2sm)F!l{0t#EByO|Zls2V07py5}AR7})3`@>Hz6 zUg^fjLhp}3%M->!5L-+xUed0bAhi^WHLma3matulIV$|YzZt)7{A88shUn#lc>+x#>#LEqUOs6 ztmw|4`uh4XeEK5)UkvE8ljPisdQsA7+!J2STq^b#Z;=c~b{|)`sA>Q95_hN9?V`Vq zJ`s5IZyx#}j8{Z4G*VY#X>XoyvPjXesH5eukDL^%gVA#W=B%-dHr^eEGRPU}+DBuXhq<>prjRKn=LPd`G zFe_)itB<}&kmx6oub?0XF0}df!1M+tUC~=4r;?$G$(=)qF(%H9q8q%06$zXdr<~R3 zh`H!|1lRDQX-LK*J?Ct!9VZG8$@iYRZ3!yPKRs10XSz~~i_Z$VtD-z~EBJCPkpYm| zqN4`BwHSGogD6TTQR)+SqYtPAk%IJAY2s-dU!N`AE zq@Vac-Jxsp9`IUYv23F^IxA%M*lNfs3uPXuB zQA`-y6VaH>WHL+pUf|Cy>Zc7l92_5G5UR{bjtrs6Mg1dQ7w;3|zTteH5P}|yH08Xo zvEf7i(g&A3eSXHT#QHJKN>Uqf-|8jXy2jtv1lY*__+Tc&4-y278OqN>Ho- z85SQeZ?@OxN)>58R^Uy@LM&^O9x}Dd1-Jx_wUob^d=P5ITV<1Gz9CfsGzcmuwaOLb0ZaUvoAk90XUSKzs1${1V36dY?Y?4i8hu%3(Y&%sLJI!z zN{DUanv@4X_WMU^cs=soH}}cW0-{xflI+~38A5(>QIq&L!=W;)5SKr_5?a(^>o-3B zJ?1GaTY`j~Ebp}*Ccs5_2n|o>w*7H4!TR?3kOxb$^j4&X4E8uAe$8vSwh*YFR=#+mU>&CZaz3MYcjy;>U>ja_-eZQh)_kr+jqI01>-QSrx%vqj2YuFXQ%Ly zH`95^*z^!QZPbI{^;OFV3GVK-z zA=2tB*-}IU5u{@Xecx4HTiv@PaAi?CEKebju8Knhq)-VYvT#-u7FxX>!xa`Vt!AB5 zMDE=6oK-3Ze}aV$vQ6HOK9Vi9v^O@!%>VA0U%XckO)P)FdMzzM4bj{6beg+ly-Ys} zeUYqrM`y@PsVn*%Ty;KObWbgc$_p*Z{Kd+CGstd&LHy{M#3m^Owop3*s;BoOu#Yo7 zFU&aV+;hXtE{h+23IO%pOioS+-taoZRY8W!y9&|fa|9`q3frmoqD6$>6}U}PRk>O; zeJ8O21{@!a9q;^&pE9xeyf-fkCKBlBB^H5k?OmT5JY#1#E@`- zV)~0wZ_UUE=@b*eNKp04blfng>Yd2jJFqf8sItyVv^RjJ|1-4ZznyKZ$uz@)xvH77 zTO9(OV_oK3X;|>uA4`78c!m-|6chcvysKYWVH1 zz~NUj6ekt+QUQ>i(F8ydF&?TK~Zh}0w8gou31bD zZ3zUvQ=K5Td1RAJq2dIEO2fnaaIiBd!2gPg7dU8;AHv8}j5veB^^WRlPTPJf2?t6} z1`*-Y0J{L%*Z~G#4y;j>AD30sOn>pwjyTLit@YXd&J%_~+Zs|48VHI2pHFX5;Sms| z=E;W{@VysFdk1f$wi&B$sp~s>c@!}zhBHK1$Ez*sOG&zNiZpxS_*4)Th2NR~H9bE& zh^8t8eSC_ZzyIgid6$Ig3rx95vEOiAs1$nsO3E6q6c$EpK0z{+veu%~TdZ8T|EFfG zny=!V2W!%KURXg93dF@}6@pywNj|w&sZs3Lx60|s$656t`SOYiP7gT;2Lx3W6{%$Gy((6( zEqg4kE%@(Ha)tvSbi>-dtu&kd!zPWB5|{=vW##yzb=a9}@Xr*MORvWkeImqdJYco0 zAOr%QEPTWg2XEKc2LP0xay#^POuETRADh7~^4|!Sm(jNpq5R7$Y}Ut$!1uxb#QP}Y zvH5#0E5gB^<++AP|B7^Z>(QjHMa$Z{tWT2}@BBAPPXKU2Z#(f>j{0|kt!^yrM5_Ln zReDe65J6XCOt=#o!UjY|F$qD|aYiil#QpH?IRb&cs*ITKfamLOm(W?(VCvwx*h5K) z9ihT|5C8jd5)>3@iB*HKs*%pXk|FJ1d+qelsBlf3KVeV`x|1Ax0-!}SnYjVk}uydkY z5eRrJTs&hulb~#DQDtcLMd78)8x<;*7E$?mGJHf>HKk?aneZS`TPO!0Fvv9vyx#Gh zBV$^5D=E|aPN~`RCbj%cyD!S)-i1*hQ-tl1L>4bU-L2-y#|?=JLkDz5e*+L#zqBIV z(wPOM6tiP`rlhhJ9o19W%;OIBjFh3BI;yLyt;U#|_0i#IXvNEJ(tR4yx2aET<9~fA z+;mwns9R+KNGEilSt(*Z_BJ0RA$B3ld1J;KEfY)2T@Lm#T5b{aCWV z@zed75253X{}RzjEe1Q~3Q0l;kr=F3x2SrDzeLZcy>=isD{j8rrRI*yWh<6uF|^@B zgTx$*7V8--AcE1Z0{xTzSoOhA!egh(Q}LF9vlW9rk!P2dhOZ;{#}nu@Rab6qM@v_o zBLZz>1Ld&vCSfrKFfCCCTvQ~~NgsiU#2C~MYAfU@mN9;Y(DximUs@s_U-l(}Dw;dvUk$>@Lmz+*B5;3w4nRDfk-}zr{2=zh_rB_@<0i%lp%WLU z#)>}1IcLL<(fXp-RT@Ub5X3O)A>^{q%@w6yJWLh{eNBETHf)A9G4W)q6-4M1D-Wq6CAVyR=eSX*~=&Lds*k8w973)vriSX6l z07~uza9;af`gqjD6#MdbZcee0&L<>N^0mVtYHaBRhSz(+Knzm&mO2y;E{4ERsHmJb zk0W%N6QiC!#ODBB@(dn%q4Ul?tV})5aH4ww4VUo-{x4{yc7OT5Xu7=~RoGTuKlk>E zl7jOJ3oQi(%pj#2ElkHEmQ1j>T66NH^SQXml$Az&?vZUkkTLkzq1&HWB9H+yPk+rj z?rEC}D2(g8Q9v0=W^0*%mXfmSK*GTy5xQb=r3u*toF={$`d@#2+dCv=g0RY0cN zls1^uUq{PP`eM5eahu>-2kzp?&tV^+${9RAZ=4++<-%{NMMV6N9L)ARQ>S!7%GBnn zJ#R{+)Zp2DJ<~Z{K7)kYQ6u<9N%^#YJOn?K#FvaFo0pMwihby9{)u3rlG%QK&Ssg) zrby4A;TJAPGsqxUty1lo=|1cF3Gn{zC9U?a0+Yf$_NR zntOP)rtzkCo%*%a=HcGresn4vVXvK#h#E%PC+5riV(pE^@}4fDZSzClUOpcd zl^0xJY|}VByGkLf)(-ytn;lE;9_$d3>^z=gtcg;2*f@dCITK}_3s3%B3&zyC;BD3_kk>5^|&I7KNst~0sQ*_EwN^}AY4m{)`P!L689 z?J$Ho>s6dd=Jj=( z8b&P6n55)yxIm`uzw3jxUQlhgSomW?LITlU53_;lN*2=q^vWOcVnVfEBzQUqc+T?0 zS_Am>a2-1lTD{e4m+)|`e{hN$f(XPfKQ#xdH1Fh4*~qflg?&y5U8g`1ELOwZ_5fjY zE({bNeSHy=O)v-nVgMTn4H}fGTSP||JT2^BbnsEg=<#6>+y)Csg5ewPSCa z%w~C28-=SXzg+25A{#Qyob2*w{O{thIfeDF2Gjc`)2A;Ln%*9Yh_7F z&JVpKH@p5fc6Y6_DJ#Zer|KlHfLfG?ONrgySds6Ku+nPAH-QRFR9&<4zy<+k>%{&i zh-KDrJU{@mSL_9OaP}--^p8Onq!V6f=`R2Sak zSjluUjxr^B@qjBwJi|9+%keWr`1XQosfx0)f+S|0_%VG3*w#@z1ZzJhM_f}Amk`c* z>1!y{7NsCY9idG}b;|^a&3!|)dq|e1Ipp7i&%mmyvRhh|l4`bxLu!RRh;x^JPZe354?*MVp+1T6X;AiTTA)uVszPf6!&PQ@u+V^KgS!boGZ5R?XHg_aSy|JI&*b3{<2X*b3_13kFU1B`4>c1`)+t z|2R54Y=#Em7WaT#qjZ{-ZmK}(j?rd5AXhmfp|)}+a300(4ww)`bxI06xr!;b>!L@@ zMtE`S?rVFzQNIM#7SBo9^q!TbW(fGe^g`8Gaz1{_x=IB&f>;7>`v|YsPNS{0mDh(k zdBMPW=Y;T7O-5?R4iXlYufG{_T^?T+mEEeJUgd{JPCQgIEDB1RO)k#5URbC*yn|*Q zj0+1V20gY7%^qG@od$?vGs&a+fWr8mm`mf2W1dj<PMSf-F0DmMYc1c9! z=SJNdo}$4&>IN8@zO8iSDEKzcmUbkd89I|N9Jce_-#`s%hYaY}u8H*}wA0=#kmZeJ zho;5q+x{|)UT!4NeTXRB`Udpc?JL)0C2#~NoG^^q1&?WhS&Ng;#+CDVk`wa|E48^Q zLscY>)P}(_0t@OiFG-tbpA^wmPu0;cV#Or9dXeKUUnvtin<7D?A4Tvt|_p^68lynZK&o|`lmO*P~e99NM zzwrI_M@Z2~eV?GPrf_ zxB*?phb$Lt2hdRj9r)t-@*j%ZaE5JSoymVoQiSZr*n9^xw_p9ZUITN`@#=oe_<^I_}ZqchyD(yEJ@Y2c&N-vD27z^`5P1LCtfL_ z{B${<87UbanepU10lE>qb#w@ka4efgQmB4Xt+t?0$JyIkadV$*l^*;J85S3~3^{N# zgkv``)HD`g*RDsbVj~T@Abn>M$Z_BzSXfP|k4&bOfhIW^ZJ_5O1f@vQx_?p8Ea&Yf zmjV*2|p5WagStLxL$>zNvshYDFU<$*g(qv%M(#@s;=S34&ES50|d*)s2BaT+sdr35jC9BEfEL5LKBvE@gg~ZXvW57nD#L%yjBYp&y$j zsL}5z9K~uwe&95qFEmtacD}u?FS^n4TF7-4lSmWz)EL={x}f4BeCI+@1^~!x+k}B# zk0E~9DLwU$s$q4^ytekMRL9F|P|=9L!81GoG1xT=G)QT5wYUq|oJ}>WP4L^E7E!0C zJI=d99VLW+TYOFw8vdoYp7d?LywvIK?O@BfZ(@LpI4qDF&Ut6bLjW>avh0o>6<6ayPt zi&^vx{yvCB#H2^*8DRC#Su1VmQMfX|3}Dh>%$Es@p|Se1jAo_!HW*u-bJ^ z<1T~s!mptyFUxT9tH7w?G78V(TP7tWyQZVtAE)d=%3?iKr z+fQj;xS)CsyYnw_iAR?-etZu+s;{4$aoAk*2?q@7+=9oAr#WQK&P)XgP@&*1A!$jj zfW2DhbNpoq>cEI)9-adQWBxi9$Ns*b+ip3m3s+}$RjSj433AO3j}>Q)Y;#_xprC3QWIBi;0J6m@RpLG%Zmxfhr+5v7qc0C%{muXdO7hbRqcd@9(y;DJi_NsdPp>SD6KcB!Ejn zAAdi^BM}}rO$Zn05}kkS&rAUdJllCg2fHW1P7ezrx(?X)Y1)anYGTtUM(MJvo%Yea zhy$UA=`ah0$L8SR;2ESDY-CJT{_eNIYk!?kE1*GnMZMj9zRhHH z%k`nc4`^X|)yv7DmhZHZs5jXmcIkt#N0x%vshI{bsTFm3*eSEi3EIm%vq={cXNX_1 z9QNE4CY@U?u}D*mzB+a~U^c@8FIy)RDfQCDJwC!nNy#~}ApUDe$i)Bm_ zNLlBP_T|Cb&$+lQ9B7P!=~>7sFOPyrSqTY+2^l~sm0hZ)v@jx>pR9Atb!UU$A;j zhBnW^kY|GCy=C;qwm+~wl^2)1dhqjrm$N?tpEt#;{<>UuTv|#h$8Nh{Q7Y`=ww}eu z(&!EFo8=|Jz343H!xZw@e5|L-pMH;f1)Z8b{=DF7&#~th>3i z{iPMW`xl6=#Xe1}XcgA6w(dTONu&F`Kaf)o96uIce^w8?+SKN<5@x%sz3@^7Ej2SEqPtt9E}1>;?I!$AA0rEv_N}}qWzd^Y_Fj<= zrp4cSInl?NMkH{>(s4fMYs-j|T}VqKkdl@@YOgRkQWGX9%DY{P?760Xn2dJgqD67Y zaJrc#1I0sc)s)QZPV?g#e$Ol0_->t7)*7fBdsogB;qtC&;_~3(y&3`8ur5VSL<$XL zw*O>WXk9opzzPA=^eE~~1*)8X0kO>e6S9dCl>dzRc~fxB_8*`- zDWO~Vv4@yrl34eRm6wa&kMQo#HO7#fe0J;u{~HGtMmnVvy`w>;l(7!0YMRBICnn=U z$>DWoPcKnzVqmJj9V|7$bECj1~yQq~H00mYyEtRIAr);X0JUpMy-E?wTDt9I)`Kzm90dbR8NtAP z%?dC^>Polw+eSD4jwozV;U54x)~byV2fN!pIS@JgdhOxLIua5diyq~d7!i4&z_Yl6%n4c&S z|0yag_;tH>r_K>FA2^-oKp>6}XBPdXRT9ojX5F_tTi$xDhn)kb|Dzj(goOodBpyeE zz}ucTM;&v3E23~`48Bceni??XtLH)yMK^?o)l`cJQf_m##w1xvF^a%tYS}h5${LwL zyWYFE2l=Rf1aVvay};`kU^RtVE-6799Z^T+$*NE7D{&V=Vuf!Z+!creM6HQ3=$zd( zGa=Q>F}dk&M6LRWUmf+aAR@-XfB+~7hg-?=`hShtQMPCvIB1gzxiiLDrI872xWsAC&M>X;;EZ8Qki zD8U4RLS`iq!{y{na9X1t{^Fx9iJ;{9> zaf^LEO(5a86a1e@@$l%W^uAAne`nCS6k@d_Iq?1dea`fdYI?aM9A6CY%(na6=s{{B zgU_4vg~BK#1^r)K)!Z9sHjOHlhCg-;ts?K=M(c#!FENnyQmR&QUBNfLjI>1YgP;96 zxe-1h2ifXh|6MZ#g?=~}vog0s~cO}s~lLuK=R&_f}$xagUhW(>}XHpBt+VICcvzCn!zwo1;32eZgtCF{VD7y z`1nZ_RJJ0oclF(J;l zjJ*5H`lBC0D2q&l`C5~5FC#dsU`ZxX?AVwBJQxB=%D5j%-qU3%+Ndx+JIPFO2+0zG z@ZTfuDkvcPe5ImQX0dBHWUsn|3&1bDEq_&*eGJxFt-NK~fxErIzPANv6$QllGta7(YUA|B>w{L zhb~$?u1%}yfdEU$Q=}jRLkUZ}Dl=30Y@Gh`PE_j2vtRJo73ijcnuercw!n1Dr%?1k z)1Op_{wxv0??wwK>%_z;C{V5XEFIhIkIMUGF?rxX?3VK~rQpJ5_#C#jWv;ei#;qvZ z6(HJOQ(E$@Er^VrhrmcY8Yqlg+$m(I#U?^GKdr+7HXsN$Ou#V}^n=bsj6~vctyXg6;0WTI9nD~L@!#7bOm5y5w3Kz!4My0mU=f5PYYQN57@}@VT z4k#@cY|4C28N>sk0TGtz`%oxz#K3<`efNaa@XB8^N+75+RPGN-;ZM?;(Dt|a@BEt>CPD5xIM^$_ed&u5IB+U4x1x(^bm8UNQifR>OP_L83O;f3YKe13$d`CNp~3x%5qCAGB__UEv=q0R3y1HuHr{Q>7>q&$M6I}7s;Vp>Ea}F zGs`=1fEZ*4-r$xhu~)XU^Bw@c4p`tLw&VZw?b{OcXGEX4^g`tdVJdNG@v8g96HmG9 z84SSG2$)DFhxu0u%<}oImhLaMOdTA;N0XZozLRuTM~6!X9aw_9^56);+M?SKc-V?x zY`+SA&2Z5D{@Tv#pB^;+O>*jtCu)6o_>3Tii_W1l^5ejGKn@?NMdkEJ%Z5v^b|V~w z1Y8&zxp5?PG;12yVhg#dyQXHvlU8#x^=khGD-r>LoU#PU8?JQ$5D{@b72hMo0l+Rfb$4aB~HhTOKOYzcQn z%SQ;8@oL&dc->w8;KZ4;`T{e?;vrF{!{)EH?p6#=zHm`}{`e71uGA^qbi(1y?a}>% zH+}?%8bR@oZXHYZ`Yz_7F^y_%qRK!R_mCUjV}==w{Tnf#xaDNiwz%=g&q z4S(cI+cZ1&(Bk4@p2MSXyu0HnKG~wfzc8~kLWiBc-E)O-AckOMZ9LQCp~QlI#ZCtY zDme@z!^v)t@YA;&0u?w?xhX5OU{HQPV3KSLBAI3a7cVZPyB;tjy8jliWvBBiDJUT9n_e+u+^_*Bc79YI5d_AsmW~h~dBJ`-|MzgEu-FDxRn1Bg~B@R$HA^4lG)-(*(BToa~9&2-dnIj~= z?N=8Cu*eWAEKN=*;ApCM!+BJZtM)Kzc)Z(*!!t7KP{LCcPxEo5et#(h49ce$GKG7B zIj-}cc$|+lqM!6%M7=B}oa!W{zY*~z#gRey1QR_5QnRG|%8)fba89l1!_sIY)^kPG zV`IvIc6Q=|`{9dVaSR$j*w0eBYO>RbKi>SA;ORUL5!;y6y3Khev75f7B^W_??&;%L zY{nb5(z(Pwev={wm@!qJJjN}rdIO+_q@`Hcjkt(6QrIE4+WhZUO^Zv3R&bOBo+sv7 zf+HCsOflxWZxny9h-pSf1qI#3IoLDSczy`FAUXCoY851<575Z_6GC8eg<0oQ1Hnm8 zUu636BboiCKeR$n<3}ctR&rqU_76p6Go`;qvVf1RPqeOPB9xXkry(2{36O39cCCa= zddDXmQVhvxmLHBx=)Ny$pTdqd>+ySjS%GRo6q!X@e5zb}ooQ5Za+>7c&c5e#I;j>7 z|4K?q6+%05K_nr;&6u%O6u?!`n{kft|uUvCr_bD;j^Q&v(mS3pX%!BGzEs7 z=0~x=wry`UoB)hyFr?Cx5$>rr; zW8m>{1z$d;V-ezM@t9pjDIILTnBD&DZt7x^^VNVu1rcgIhotzEqjAY=hlkT3nfJQi z?l&`}0k3X@ofZ!H4#tqJw3yt2q`pj}BLe`7C`R3F2wh@^5!^l@a({VndKw9VYp((F z=kv`Vcej)VU>~i0 z-ZfOyuPyS=%O?=9f7Yp|23m4~{)SG{(n$I+O>r-AjE2CiYJ~uVicl;YsC8)+o$ab{ zBy^n#yWQf^$u9x;mLotP0FauY!sW^|YqMH%P%gF#Unscmm^LaR1WsHp}6Mz5K7Vrn+{xUP% z4$UuY8xRN@LqZZ?G7JnqeMkSQa~F$IWw28D>Ui5pPpU6CvGFTm5;BUV_JfI?e<;?y zjqCnww7Kn|!7ePozyTRyY$hW(7wA=4aqWnEkl&Hz;A<>DRzZTadw++p=QjPtgg&Lp zF>Pft2(p6!NbluEQBjA7h9A-Xu*gax{x{*dU!M)o%k;dPH;PlCqbv)tLb2R|GAc*& zJ}wqH4c`)be8Z8OiYn`99Jp7{`%%U$#dT zG&Of0T`+wK^(2`tJ_NM7w)$M)-Hq(lVo=?FXW`I;v%I(^^aa^b=Zz)#soGPO1BlO# zHAQbwYHattWv8CX4Hu4mK&=8R@XwD)v+UpQ6tJMi^14!nMNLbn6A_M^`w^?1>}_Y78Or zy4h}g&>*{alAAP%q+b*^srqw9WBd8%uRkf9O#y+;2Pk?* zzZY?EPS#sq{X2c@dHA3xXwt&SMY{n~gfuda!vBm#RCr>@EcYYRiQZo0_#9{K?--7x ztm2_9lzdv&(rjsQext@sQ@XE@D`LZY&)!~OJT)t+F9ai_pa;X539B89R_j;_myFi3 zhBy%?xS3!ZZG+4&)oeOys_{N?W_DK5%j^1oXu1Z!zW%qpWn)=O%l0SR#HB*<|G_!$gZsX(`$D!V8XTGl%<=Kyn+pI95-2tB+*l1}MmRYE zjOPr5G{%xDrybh~J#;Q13l}zHYd~TRCOPbdZ7pZq(e9EJ!;w_5-`E~}SAWJoS-03> z80>LlP%1gsG!j~tAHw=Qs!j}V9awVvq#v#O=h5o>WdMJcI=xK)L`~RfJ@kDHz1!<-G^B*2g<4IWkp$t zXg|WeN;!&)!xxG&Z7<)ZjG=F*a@l^bor47IDexG%1yMp zE068x&Hd7AACN%X7X0Cqj*W&1bO#!~YQ^4Fnxvd7*)e7m3n5vM7sQ-{F+-Sr(tssj znaSkVPpUEI&%y66;q|B}^Bf0sQ2#6MS@BwxA|j@QMM>vq2~S0)&sZ{`%k z9Y@|bZ(>e$SeFB|4i3kBiJv}|kC&wUQWlD3x=i;BgBG|8I4jc9MU8MG)udvg9=}?v zg{hezSt@0)6@_tH0#s@P=IIz{CU}EEOZh?H4a=CR#Ue(oP05*w;RpfB6UH{ewoWz` zXJ=pZKbwh8;P=x=*hz!5Lka*%t8(#`Q%cqSHV(K2^9=#hfcafz9d(3Q&_f2%kD+33 zQ5!;rgq?YdJmtR*ekM;#H`1rll99WKPCib<16&wBo-^BDmF`oFR--m}nA|uyD(qLG z+S{moWMS%wb(__>z?dZX=~%>@HCUnB3<$LD`=uY8pf4CERp$#3OQen`IxE27?jm8l zAt0B!7o38ZaMeI35HWaKnuWCTOC;U0S?PxeBAXQz?wGAt6gC=nU0o<7`oYy;G(%ZQ zi0bdt^^P_8(2kG216&8mJzz+82WER1MwI!83q*jR5N&QdSGvv9oF(CW(z;L2Pizk_ zZpj=ych8ia5HGO&B1m5F_h2+-l`%CE@%=1hP)qQ(#Q?Fz&$1}!5h)fAYb*BX93EnA zvCSNe#dAe4-14+zwMOP@^-ABa+=QIMPBR*gqKX|2W7dbczX**xh%elL&*?)AcS8 zg>a9bS?5fQOccu;N=4z()Y^D?o4h4~&RQuiUeK)Kgbh)AU*c>dmFb$FRIl; zj+L}2ztB9pqtHDE&8#YT>jYiT6kx;+;b-KTY-=ISwQM#k{jtifn_-^;9+>?CAp(C+0aY?cBmn7hXS*pKLsvIs#O2exI{ye`;HIShm6>=1- z?AVW-8Bg$ggjp0|%CU=?AldpLYk`%nba@~H*@rOcsRh#43oT=O!%SP2L5E5-Mf$c8@J zM?ymzLvT2= zh=drH)FDm}ClSSiEdYnAfXz*BFM)zG4vC0*60H93yJNutksu%?x1jD6L+3u?vSrSx zNeqH0Vw6{;*<4duoL*X$&=F)P=?wpIAoPvlH>~!cZ!CkIanwuWoRyM2CGts{^v=|0 zsiN?|GmDbgO73Ca2n(#QUo1Iq1`3oJa-kRFQPrmhD&8?%!qcA@5dP6Zz!IWLu#g-% zgBU(I>{fk{VyNeh0}!4sGF4hWbMl=>POd+j4AcJc>j3v24}`z&NO-{!g3E~k#i#4} z>yw@QZz*LB+(v7xe+Eq>KSv7EcnWWIvljtUiClB{AWBHCHzd2*yT{^z|4wYO%LIoS z0Bp}U`L>@PqhCp44q@7VLCzu*@ z>K%|lS@*~*2`V*LQ6=mBrU;NRNu5J*W*h{aAcQa2Qc;HfSL|bTak;6)i>dXxR%aog zzOLH}6a(;q?HVnn`!hQ)Hnwu3h|HZ$sT_K=BG5p$p5yyHNHrpF?>(D!#(!K;w0M>aO^8 zT^&6%eUlcyADtrrv8IeGfeLOo|MPa7t72{MqMm#srY8hf43-CZF!P_kj6F0Go0!hm zSv%c(7={D7-vJnT3lhV}-*!1U$+@1|+aozVzvpd8U`Qr|&JCN3KCiZi!VoBJMJzdt zVawK+{+UmfN(TRQKUSYfK-+Qq*?iOJLlSm@3lMqii>2%o(9r6bNt*j@N2B!jF((#v zokGFF43di&^l+AEl_ft-oPwYFQ8ay+U z+c$M~xUY9nPEh{rQt=_Y?~k&v7$=LRUd!ZD=1s;dBhRd$rwdC^q;43T`-f zJs7(b+)`BL=OWveBRbInNW`gRRKa9U?EX4noX@+&TDuV+|8m5-ZY+1J{9^H?Yms6jZ)?(3n@>sPdMeW_~o4ZZ1OP*QFMyKPTJh z^p_HUnyKU}Z<~C!Z^cObgkiabg>hg|n~j-tv7KYkbpvg;tbBB!C#5J~nELa;HdL4Q z&bsY%*@m4s9J1MLkhMVlI${ z5&(NShQ1WCR>z8kT_BzSZBtkUlb+8X(Hn{N;?!v)4ucuE1YW!bW-<+o&Y_tzU3Xb# z-e|L;iH;dZ6hhF_ao6onb0^5iNa<|}c=+UGS8ZD<1%Vef78;65GPr1hnf)nV)afJw z!QzG6rRDEG6gXzOtNoJfGki(cSj#lr@ry(TX;7aKNRy*aE-P7wLx{nGm=KDlKVc8|m;UJ*j2=vPS5-x-TQ`n3;(I66t<)9M z(uu%gXzwI9X?%O4<$5uQGXpql55C0{@k$W;-J^Hb85JFj zpI@EnkK*veFtq6|?=Ao1yFGd;jIgA~6@2ZO_UIWjX8(KTKUc}nbmTv=xlE`mCP5U} zandA!0qPUJn6dBO86psG0Ruy`N^LsHpH#?-EL6Y5XY+!(ZxnujVrHEFaq8 z^Tdufk>(cP+i+wZ9k5KC5#KDJ9JN=Vrm0s~lZ|#n|H8ypumW=?w)wsOc);>%>?(HwrQtOwbzTrm^O&DWSah(vn zS7TsTK=d@>;Zi4SZ_oJhxY&)EcjuTqCD<15a!n;`d0I}H2_h3bx{8!EbybO!(8I!nklp2jgKK7mG*!_xO)Q+AIUKfliEXNLLjG+$?%BVw+T`@_eK`D{vSBLULV$?9G@ z(n2ajd!F_uwnLn5f2JdsD_Z&L)6S7|2;I5xgF%M8D9-8n4|#7!lpfv0{yxyvFM0Ub zprQ~YoNydCm|zu7|7Vz}r6N^C2TE4I_ny)2Jgo-0YJLMQ7ewl;rpWhP2mTGvU4J_) zk=p`v%7Ob&E=_uq?jFADOD`P`g)2h z4q9c#i*w5KuS4SvSLRO#oS-mlm!w3? zqDIw&!2_eR&`6oQrPddSlZ~k%B~ZHH8*i#XFj>flP(`NhO+p0^1koYrp%4%@GDhOx zlVgCbaIyOYXE6ZD)Q!=2LE@+l9VF$f?(gN(4|_fLFlWrU=$W7I5A)9roEOOXOJSLQ z7y$&@+yzvD&M&$%pRt`tqW&(PEmNEVaEun_Oq%kOC^}aVsfO%tn_4X7?th%a!)CZG z?}|)H-NiHl2FtOAZj;4QDGaKClvY$MR_8D#OfcbqZWO4#U>JU)Hk#34fNML}^3s@_{q zOO|Vjj5RoZoLY1!3;1;>19MNfVsw8FRHxwhgRl%7M+>aTUD*Sfy#T0YxBKu1`*#6=DRutWD!sP0 zwsJO4ZNvWVq{L5$ZO3~mfJ3nF&M^i(F;+zjvi~caTXKr>Y`$?kC{M3CXZkS^gG027`_*=8 zVhxaSPr35_h?&ogn=%~6lQfi+?21Fx|9>ukckNSq8xIZc{Ofw#skZlDl6e&eCxgfP zi)0TVCL=wC0xAyhMp@?Z1GjVX*+E^TCB-s87nk(38o>-?qlwg2z!db`R{i-_ss4;a z$TNRjUlSKc8mAa!q>F%qXSNz*6sTOjl&~F!uNiaBxAgSgV+qsQD;@eYR;oQ8+w*fa zcDu#Ir`kr5e}~o!rOMevz*0C2IqZfD!v862s{q5XOBoG>>+$gph7sFX9;{@PTHAHh zIfjG-E9zP|n-N?Dz_c`+zGWh+Re|0+V>|V=SxUOLXD$SXca{tg7WiO0+l(0o2i58=(VNp!+{!96 z#mDrbmp+N~0~EH<55^onk;(ucyE&&)2;G4QE1j67$P{TOG3ZQuAErh7aw{IPF{sL`$HAGJ zG9nNuFnIqiyKB&HKaFDI8{QLUkm=RLBWQcDC1#N5CU4wCsbK z8*l%v1n}+#aSR%sGh+$frgz@Z%#{f{z-U8>J69lg z54bmMvZR?`Mgz6&w|;YpUnbH9DZdH>+*CKUufXkJwmt-K3OPf^5i-IZ(mFa#1J{r6 zZ@}+5;hW7fj)9Nx6klV*;tO?5+e;&PqQyRcC80Y7zVdg1JO^DUEvrdZ*Bk`-dZ@ll z??K5YQ``9&t;V5_k-+4i;lzH$i!a@NY@Bv>cqX^Wxyg@=L;|+e)w2JNeuq`GU{X4( z{rmaaV#29j3|IyLq`bv#ZuK>St%&3lz+^2m8hv6ou0o&)Kt;eO+9QBBgd=lJK~aHG z+q&)vn3inj$B!BQxWOiL4iZOPEx2m>`~;yiRChP!%gx@*DJv!h4mWxbC@MJT=YAiU zxVY?^qGkQjgj5$daDUb7hx>7x$F}a~5_tiKiMv-+a;qm%nMk~90Zr<4Gc#N-*=$My z%s}j!-`$g%!Nv;F)kWatl3Z#ew?y+mpA`cmHVw6T;D~aYDSXc337c%0nFl1oX%qlN zbH4-@O#WHs`Fr({L*e}8pp zczW2FLP0TTI5R~CmNr(@j_h3*VgKfaOO?D$ilh#4+pV$wTHB%-C5=^q@}U8&inE4w zRuyebq)M4!SjJ1|2y=_ zpFjOtRm-du#MQfuOXGUB*w0uQ1oMV!eNsQUxX`eiRq4l@u%v9E^^)01tO~`Vkn>u6 zA|%wiR8fSEnT`(HZ{yno*zKKqoCDNOU_Q#c&~l9Oq079|X9x z;*1AH!t{20Y?HK0B|&I%b64qZoGRUF*;tniSpoz&Dw7D4dPTA9WmeOU4#mg>r4OLV ze*g_CBZ}i4S(Z#P!cFS~08)+b$vON|Q?vU`C6z&`3<+O~dyDt>RYg=jQJ9)l2*g3d zFG$e`C@`z~Ln47++-1h+yYr=E5`)RJ6By~Ou@%|x3+1<3Zcf0eRSfVPij5xK?VQA{qFj+!%C{^x$#R4e%C28QmrEx3W z()*kN>nPX zP#V(YI$P*&5+dO%0OGgH=c@tofx{!RDWpi$!>V zLt*lrx&wy%$3fvDei&oD2*TDRs$+rL##Sv}Lo-~|_bmg$qkL9rhReq-;jlJ)i5o`1 zeChULg_f?O=npuS+#PXR&+HPGczQ(gvvPG%HS{V0_uI8%XY*^QM(0vBW zH)m80SZl`^+#hysP0{0wIQAQ)X6c%BWhcc&%8cjVUScOvjuqJPP8;}3CjFRVzOl}N z)@I_7PV>Yw^pqJr^fkqDa&qR&>$NCn)d>N&zjSosp(@=&>QW9in9xYVoyDpdzLr#S z$)*(?)|l}B4%X`-1nu+pd;OT1nHMYGS&x9)59Kb<#2i4O zuak(@7x5D?8_%`-W*@1g)%VM3q4RF`eVA+nd~cowOAI*W3Ak1-FL2Mk|7%R`yjUh% z08;KuySmp1h~yV|L*=NC^yq%ko-mu>TIj~$7K?6JB_Gw5dp$08QTpZbxXD~`FL|cLgeJ6)D$4;_XL!==>lcuW2yd} znUG!i3B2&b!PQLnzmnvCtUG!M-Gm){sE4dUDY|X&Bt%TjRVso7Zi5dLwyqfrWCN3` zgD6Z!F}Dszw3%OA9nr-bz$2DeGNLbZ@?UWzwf`(gpUYCo-1C$kJ(|E4x1;IJQe9 zuXg4gA7KYI{yJgOj+P59J)N}IY%BI5Fx@1z*5gxUYVH-2WTVT zEYoTRkhu5!4s652Rh`%?TZ~_wOxGSPsM~apB|P**3Jtk6ml=^MtGZTelPVlZ$XTCb z*}U#M`VPy3#awT4U3ZURYpN@zxQSigDHLATi?TAv+3XH(%Zkc_nnZ_w%;Cf}p;g2y zn;FVPjDk@WQQGJYjLiugOLZ$-)+TisiaE7tX=wpGWc+wywrhSzKamNKtD{--+F$`w z7KnO>^ygO>_e}vhvZ(b3_yY3X11TwKfZJq(n+AxN=JvmsSr{0)p(qv3xMLwgTp~8> z5=DWH7PZj1DdR#1C521D1^M(f2p}%%=a<@6iAJGRhUFNB#)d}@H-Xr0H^(AMVsDcU&4=_n80|v0Rv+(*s+(j)o-!(TXMjANN0e@Oh>L^GrDLVd z@5(lPwLO0Tt(J_WML0xVBjqU50zIUlul}T<RUf!1AT9*Pm z08{}mX&!IJj^gR)hj+>s4x6&k46~C+hIr+;$J}K>~TMW zig2@yR^JVN38)iU!bwTJ4S`7-4pKr-H9KHOlrJ(2ENnFD1=9ZA{V#FaixRB|1;Jef zMPpt@5C?C;Q?sWvEPy|3*G#oHz_zkH<>_t?=iSRFR}l8cNO^bfA+~^I4|BqMS^Y=@0So-PW?*s@jbm*C zgO|NdU3&)6kpo3xvP-vPYU6410bK9=k_K+OK6rFPHoFxu0vbinw1exb+eG2dK%KdO zE*5LJ&d#Urh~~z5&##lwHf#-kIG3-J{l}GGTtPPQsKS5;^{mR~suBhl=F!m+Jt85d zjCk+FfA$qby1~Itkk5auKOmS$S9gD0_Cla+m{pUIEGXAAiEiwnT5nyYnuP7n4#)cb zx(PH@hIdHtG2PZU&*zgTB3DfULPp)@^xD`0=p*NRtgc+JFe&iy zhY=CRoV{-dAu%3W95XYkb*%1A{xn@}M|-bstgg~Gze-rBVz~J{YsEiFL>L=P>a^{d zUe{>+y@m+ltpGvdz$UEObqp0JK$ERe<_6U5Hw92EZZMk{LIv)ep&WaPB_)VXVLD%v zS)x4EYA9TuJg z1J1RK>EgBzh6X7+7uyv46u*VrHSoy3XE74~275JhVDHqIGItA_{eat#X*v9T%eA@M zYlLl!Tj1!;7qryix3A!21MDpR5*gya?$7~O^N6qLQ_-jOQDYDwiWr($@R zEZ8L6#rEdt^zGLtkal$R;jXHpvWN>C1 z6bu1=4P#+lC!dFRcF7!FThtSij)Z4Sk913YzGAPH|Fbyqs1O;$^(p9jTdNgnj@GO<B%y7*|LrvNWIjLE3;1w+jU(>9P}hZITirk^H_+5Cpk z2gl1_RD<0Yy^2!DIdRUy$%KRtDDE0~+$5blsejg2iz79>+f+3^01r4mhKG<9p-&>| zOqZ<1%!?jZfH|BpcWhEbOKqXGEK7k2HvHh!oWI8UJs*`0D~l__MXtN1en#bpX=!msvPoLC<_!6y7!q|zM3#Nxr$sXJA(r2k{LZ_^MT=}PX~0`~Xk!ach(>g7MzqwT zNDp_@?jE_Ir|FX~RTKve6@Si-$_qDRdbOutI{5q@q&s2*s<{3)Qx|Y7kqO% zUUyvPKLB_;M!3@6No|_+MJVBOL3J}QjBzn)XY5nK8@u%c7Hx)3<;$?(^pQ7HG7#CIRxJ1av&dUcZF|zMZQWe6$&#IN7uYNzb@!AItz3$-J@+#NTP>7Sln=jm~I4Ys>nBbnrjP3_ISf1#sed6q?CLMg^=Moq=3-Hh_kzY^ zw$8oENFJej^`cW+=#DHk!@-7)g=uzd(nT<^;uX{7NU*Tl z=B&w|f|I?8UZF6z; zg<)}WY7F$EpCIn{Mt?)z3@sP?;VvvO_1(tvD4e*ol0r7*>Z{_3P$nRRjec~($G3dj z9&DS0<%5xAS;cyH`O?LmAJHlR76xDylZMUCne2BS%NRghzyU^!xiTRRbwX^V;@IiR zuSVF7D2UC4dFnmfr2Ipc7rlj$Mq-HMf&EC><~EM3e;9t$pPLbym7vF?S&&=#Y;1P{!|=p3*~V9AkdRB zQewNH=Z>)=jmiJer7Race6uY#t*bqnvWaH^bb~wi`BDT}%0OC4|Ang!5;i7VbfDI? zZHPo@$w){~!fkWyp+L=V9tH{xZwArnA9y~Xo{Hw*^1nA;K8VE`ysmt$!Qc)7I}N8) zHtTLf+oP^V zo-IlVPtZO!?Nx@u-(?upMar*RtOSELSB3DS6TTaNaWs|7D0~8IlYDq`5E1nKNRAH? zK9@t>qUL{xVUNL$=_Fc>q1ZtJm>SvBFrL^D6`_2D$9h#@|a`nwW@mK7ZkS{`v0h9r7u|a7N z`bX%fYUMW@GSDlpQ^W(Gr_P#;f7h5PmPlHs6qRWnKYpuNzMUt>`B7a6?TsKwPv674 z2`#*fEsrTBHNu}XCP(>DdnW77lQF*jwC3IIZLYZYP{k4bJ>$<=F52zW>DiNS7i!9y z8_rk0E2O`nk!b1Xx4K>xb<9AbP6I9N2p3?GX9J;Ztypi6mYHUEFF+++RKl}hT*fQ7 zO1nVBoQOOeJRj7$Q<2%ot}K9eC}9TYa&)UiXQy zQu21bLJj1QdwNw!zhaz$+>ZncoFboiukOpd>sR05iFtc0GiEHC1*OB;5|PyrLP5XH zC+@jYX;_(zHm<#K7JdmS3)1hbqnewJ4MhgpxO$sP^~{%Eh(lt~WUxo;GtDHQQ{9?^ z#r7l`q6vyE@7|6Ohh#gVBEx8%sL@B&`W|X|YfAh(_sC?V6V_dn`qGvET$knPD;iXQ z=t_4e$@OWj*!2u>o1*Nr+7~YFtxUqBzG=5>QVHKC7#7K*CNr(T){WaX;}}ZLK>EXy5v3ClCx(~=uYRU z7B_Jx2?p9xzOSZF>7gs7A%*REXt+_EN@b=K+1$Hue%%I8ahZR6v`8Iprx^`FudrA9 zyeQ*TNzFjmDvD{kDWD6cw7WjiOV4Cjk+zbsHw} zGY&2>(SqI(obW4uyEK}&0*o3G_NIFqe?7YveVACW^DC{=Pm+t5Eyq6BpY-LyB099Z zFWYG6ly+DU9;;d*i3p1^PK;I+9+ra6=Ioi0-|d*A#*Ou17|-mw3~O)Q{@#7zdkTPR_BE%)8pqEHe z?V(-aoQGe-fGCg&r5DvM| zY1?W0({y3MH9djIXu2o?>l^LGc98Vo_2uZG$ied^ zcS)bqR){ip#&z{rY19sX-3jrZW^@x;EL#*gm0hI9bleSG}7a34v095q7!6hqX*}H)(k1H%&eS6bO5zeA|GarLH5$thWUedDW?k$ zR^nwKW+8yYh)=qWFktO%zoeQO-KaETlEW{IWv>e1M;&aN6X<3Pbe!^*`f4mAC zZN;lIEZfK-5yK8zB$LLAfm2pbU9>zt9f6g{*Djxg%roOB8SyCywLQ<@UhWGE#ZPvP zIUvF-M4LL}$`4ipyCvwFn;{#x>ab^tes<;zjprPfyU{HKnA@Aek+AAr$1r1Xm3Mz> z^BF{_)NNHcO7A2hI#M$Zi(~^ZZ>J(ATtfCSyp*_rSpo;w)wVG??%@IUhu0@@P!bW# zpsjHu)l!qf{Jxq^O|eN=L{mxdz5EXWopC6&#o%mN+q1s4vCs1 z+$+BaMC8SZm`#Wxh|1@NMT<)7bF4FA-VE?EQhK@Av6bsrY6~IZTwvhD6=cIm_Q-Hs zmyDuqYx5(q@X`34B&f6Eb|5Np-K6ZA1=6lIWplm|Y?ca#!vzM1JRW z8A1N_dl;KHA#v<6J`BNxcj{+QgTtV;eU9O&>;J*czEoj^x(d}jv8KuwTABAZZ^JG3 z$M#nePl?wJ3#b09@^r48)byZ8)(3r}3DGW&yMkvJJQ0bl?H=ta(_f!- zb~I@O1KT0Ah|tuks%*AC)i*2*WMT(J{l1~^|HAtIsL1)I%Y{TdKUj8FMxv@89=JaJzKK<;L5yrv@9w^CTsvB{mQkE)VM!;k9J zOa%3uFgFu0n8$mI|k+<6f&h|h&;&r0o9#Euz?*8hU@#{l1` zp?>d+o`Im%m>oqv7E?Yxs-$is7sr6I93hoW!xZP?;h_f1#k{=Q9HoUYr**Ex zgIKMpERW^#Qy94HS2&flA(SBq+}v~eic^dP&jaq4{SUq$;0J$rTUcu!yla>g$O@iJ zH~I+72&);6$JIYW10CxjlhBTk$b+*;?34c}b=*u-^2-Uu0zR9QbdE`yUr%p@1l^G} zY0Y%{M)Ltg1K++W3K|DM4$A#C*k}5maKj!OxztW-F5h5pgxH;F9RsSL;u?E;2avH) z>Jg1|yhA6_sUgB)IK971E_9h8Hao1x1dNy02CqOugwq!&Ni{`>_7tFZ?ahg7k+(ng zx+yofRy4%da`T?|fS2#of;f(Q+JNBre(+cn+V%Ue@xK+=d1qpVzrxUZB}Vf4icktbuyXW1N^;*|rX~(?D=UM7$m-&aOfq zgj;LB0;c9POb(XZaSJI>s9@r{iZEox2m*JaKGt$;vMu@6a0yR zM#P@hail2{8CGy5+~8s4qLsh>n0oDD0xvGUpIKcg#n2G2R1 zx`t})hN6|Y_$~q4&;qw{5`30?Ma83enDA-%miVjVvy$9pulg6jn-`mlo%t}|lwxK8 z`Dkjx(c?q2ai|_+-X0%QK>t&^n8nLvQJmn%fxfZQN>nKG$$&ftzaa%-8Wry}pGcDa zav||=QI*fgpK7SR_0CO&7hs%uPNE3%+uL=LE56X+P#(itgy8^BDkj{qk#7*iolmwCUk|R2j^dPsekF=Dv2TUy}c^c}p z9^>TO7-@v70l*PPd=P!rx;UW1>ohJAFBW5TEZ)fjg?uuiT%+wkggY2bP?l`z+TIZ& zB{km1Li%=4y5`5l?+A(YqDc#kocbg?mGS(65 z=w&RC?BU&hdGBDO}|liix@jK-ziFR*CtN?s>#zUkv5hbY7*hu3&`Co7K^GJ3^W1ZH%IjZDUkF*Q|c74jINUpG8w6ixS1STmpi3W=d z{|F^YNQI6*hfQ31iCXMWXj-z17WxjY196S&tl#oTr|WewM}j)1VKQGGUhsG2B zbX3oGkpWzpN87UuV=LS~LZ#4YM7cL%ysr0srLh!T0sFRV&OKgUiZSZ@`w<06?EGM6 ziFvpC$AxFEFxrL>{cR>1|U^v=OLSlu>l=pRtOSuzQ$70&aRx$+&uo`LiOs$|r) zqg7DO{K~XUMbTdmpK5xks>0AaZoLpE4+zSH_k%7X!K>bpD1O|nw4bpWtn4W`@)~4B zp~No#q`dPjwzpKy!0VZlNn1z9>iU4~o6*)J0lQ4 z3$eehm7@UXaix0g=cZD-<*uAK!3!w)j;GVw*oPsm*K%9tut>=4-rg_l;QO=IYZb5k z=c~b;;D@V0ae|j$ETk15Xg!L7KorUjRBZZupg*&VSAV)3!)!vc{=3ndWbFVvQL!Y7 z`v<3^<7`mC84q*Q215*7(0M>1dZIl;hELctMk;aDv_Sm*hsqWGP8H{CUig={+A z->wV}d?@HcQTlx|5bIb;?4uN8CaGERw6a0p4I3Bt2q3UYZHG25ewTu;n92sVB`mA< zho!U~sEjCK7d+tluTDE3sd|6ols8MV?UlFb_YPjHROg*5W;;Q4YKwCSK9l~g)u#AN_4bfg;nojRe_JohjEmWO=Ewnr4#5oBJKz|9T!>WY zd7L?C``Hq`Xeb|jQ?-W7C%?*ETHpq*QZb~W!)=K6==K-{g zlwr__AqWm;a&j;Um7VCgh%&sB6QfY`_v_xXwa9=A^HnBCX|1T1Y=t4~W? zxuxZnuYwVPp}WcRHoj_T;iov-q_bl(zAyL!{#gAISmyDVgHtYEUCH`HS7mmC)?29Wqe=G=bM*8egI zXUg@CGxe=iUjPJON6Dq>f&X3jVnu_!X&4^L`vnu}Is(ZIMx;7pmg3EEVwx{s)K0XM zo24p`W_r9?{$#*&$)9z}lEOlShg4>T6G<7?P*e;!*S!#Wh680qT zFNf()yMIyZZ2?1un>>0|r5uG8%?{QZY@I>(+p4KSz+z9TGZkvPhqxbdT?)Nwjx9IO zhFj~mr)K7QjV|A7+Ssp1@MAAnEP3{~DRMGF5?FctA!rcVWY)3R=4i+Y(lhXJ3M_he zt$ZK#aUjYR6=OLWts%_@5UC(wZ|MF>U_emjWV#&_zFCr#rbm7$v)y&j6hK z9q3rmHpv<@E8w45%O6=4dQDGoA;)+0(M0FwxjR8Ofugq;3f(so(qwja%@_ZH5VMe> zdA#gI&L&3&pqCgpUc9`G*Fz~4=&rPm-+zVV&yI%s9k%T|ZbLPH=H5O4@Qqj(4puta z$qvRf{YV+7z~=lJF4WI0d|{QWSSJx=BMC+w5YAj`|0-V%g`wNI_yS~bU`JDP*DCgg zlBM2=vn%k1*yj^I`*Ja$I<6=o!p zd+wTp+H42Unol}ButYKCH)G~D^2LBvJ5y{Tg{o0AH#?UpLx z`tSgjtGx2p%%IHsu`=z|7gJr>!m6kM(}0bX4QCCkAu=@OudWtkh>R>CF6QAeh`XV; zhvmW4DcG^108L7EMHSf1BeZ{M33D3mnqJs$EPL=-#QL| zB%848@}V6Sl}>i^W07uvu)T-19u2Z5gtS%A8Romm0?IQ)*I)Zcan) zqyeCKyGU#?SN%nWk|TGnOy%nVo!mA!FpVC)0gMmT9InUVwHo+9(kk@Uv0;SfZtv zAdw3#!kYt;7M9Qsfsv$|K<;pBJGTf0gm1*+i<_LbhD&UGD=YcM%fXu^aR^rG5b@Rs zaQ}S2diiHFOgQD=)10c^bzPt9w=kCfqv;zQ>iplom#t;nwij2+ZrNIPE!&-HwPkbJ z_Q}?=ZMU%SyZb!P_b)j2x$ifw>vg>#J_qi)PT&~jdnIK`&6m2A!%_9!A5H6w|Jk8s zI`v1&{L@G(GWo=g(JjW~Cx2DO_0iToGW$86;bdVgJI<;|!tqSuxmA3k#SEG8;c0A= z@}N7+d3`>MIhQO>+GDLigO-yp?Qc=AwVW}n*(t_JS2zf(M7SM))9OnAG+5_#6R;n8 zN425m_I}3+TX+g6en!<>m2+Dq+%gIZ+P1U24lHHiY;gnphUl<98pfq?M@IqXD{WXD zyK9cY=etBd{|by|OTZ{~Su;n(JUQU~`U0Cd+}-Fvqe-@klb6PD-fj=u6sqtcK8{1* z`Cb?H8P$md4ihDUP(=H_k^=*q%tKFV-q&uj7wh1XO%k z#>YExgpKNd0*2Uq!LXz5g4!!NVan}I_SivDKMAC?@1?yZA24b3=QsJ$Zk>B%Bt^tmIGh zL-;)_v^+yyBtD`p`VsANW4Heg!Zh-?*mI_^68SFV-R+Sb-?5U{P5r@SG zJK;8l2d>3lGMaW&h4dS}PzlYfR&gxeCWJlpsu=xP-_RJjf@oy&z9pfA^=7mDk1X>QJC@3|Qs)qqc zEzjp|dn^UWJ1W5HGg17*>UTwHCr>UUbQ4n%-C)rad}w5LF-t>I=HB^*3}j^@UC+)A z(vFOUz2oXb z3?+8sS&sDEQ=*jZO$y6-k=q?^Kb z9XBAY@Er(an3Ki&1WJjKPe8I|lp#26R5_x6AN1BsT(bxl)?Yr&z+@Zj&U( zpPVc(Hb+PEds|$H8P}wY%Fh#N`x(pml!4~$XjVz&r=PG_cN5@Smoj%IKlAOMLF03l zBgxVOs@*^3S0Bn2D`y1ZnrE9|8*uCGl58U(N={?QTO4VvA#h?kGO`(b~UM@%|*i1d-^~HK!{&LmEpoL_}@; zrhU6Z{6>EFD$;2@8v8hi9gU*fN1=Yp3U}R)lwHz$+Md9I1Q#;4h{R%)`dHflDe*$rB~*?;2b zIH-jYJFiNXhI~dHptp}8Y(CQR{-^QmeH0*SL(A=F+c}#lm>cgrsfvqCfa<=Y@rwzf zKF{~su&cL=P$rCU8}=?aK*z~}$;&9X!s*rdLInR)*UOjLoYmMbW6&VSYK*y)`)CC+ zUB$05G>REt@}**(&mIztcFrF#mEaGgViv~fYlvcu)qANK@ma;ucGsIPj=mycLox}Hmj6E;u0Fx{XhyCYbAeQ zij4O0u@m&QWFFuzs~=uPzu3+UeNchQ)Lg~l6?Ji`D;tc1J~wK^cScSu2lhW3JM0qS z&}Ia-7k9a4_44Q^g6bv{+96c?RkrG(p2Z$!C#dh7oLG$n=G&u_T`%TaLn;Wsuff3+ z+Sen7VIEF6C?@;)dRun8D>q}H1GX|LRdCO1BsTUpJ0d}txZ&x%$fG1HJ(-Aj600A1>p#d?JUBhh znG|N`Z~;Fg1PJ78Vsy7*oq5Zl|MYfj6$pJ++T>ebwbMz<3tT8{%x?5WwV$5Z_SqRi zF6aFGI*_O&pyMJ120&oG%D>$k_!fM*?t)3iyI-_4nk`-ByN-w)#<-JHEx3+9Q~#mG@S3 zA<2r_7&G>-yEh>>ht;+O;PnJmRjJ(sqFMD~{K=w!{P3_?02bgOiV1gbvLe(4#?yb1 zlS|kTqA%9HFZTR}Y3B9*yeT6lodY!UzHH%&3NDiws=~qWAiv$ll@eBTbhMbyI4fWZ zf2cLJ+g4oeas!1-?|W4TX}CL>;5juzr9jiclAE)p-)BF+me@>^l+pp)$?qm6y=z_NYGc<$lTQE#`XKwX{&}5k-P+PEJsy65~6i zVOsZ%fD7ztQKi?G@72Ftg42=-AxoyW0_@=H#Q5P@iY$+^Xjv+k3C6;%&ij_@4f3-z zjg<6$3Ten-wrLI4R+re^*N@F`uftCk$U0yF48G0HhvU%T1>@|D>)FU(_D80>mc?pE zi_>$-UrqiAt$r{cI4t<_tH?bYFWoZS?-J_x>9kI4V=%35Z=ARP#tPGh*AYv6V7NFN z^rTmv8%Xea@BiEF-oB<%VRTebUQ*B&rH{=i?0p&1;qozDbf&*ULJ@?Xn-piR6cM|1 z8f7KEZ=2~pF@Kuv2=@#eAPUZ&GJxdO$!HLIYv1}O!OT3@;KBO%_LrCZo%vxR zU|~Ib0D?iyk==y94WXkPm&VOD_3sH{8|e6XH@Ew>tqpp;Oo$m8D<<&9>__rO`xAn2 z-AgrNHfh^$_(}7*S?vuAV0xg1K-3Hx%Mkj-)Abg5ZMswRa0V{!TR`_u?Sr7E@ACXk zYPYJtx6E(DJY6wi?!V>|(|GE(pOj%>AfK$5&UWe1%)9F}VcYGvX?a)+H^ z_aMM$;B9R^lzcI~^{;)6*&-ivUYc%Zer*@PobDqC&4_=8`+N zk*B65OhKqzP>qwbFfQ({bm>a$emJprE5YsW($A%Xtbb9rfUo7d6PJnNN~bT9FF${> zP750$M4SFvG%M=&&kvIE{{7gXf$qK!5Yz<99VZ5!VnT_+c4=E7Y5*siQ1MUWw?s#q zp${I?3!T1Le4g>O786{qE(KW+5vora;c2BG`Mv~3Lq&6+Mx8%24`9o&u9BlG7sXB% z_v&$X70Yi25XQA-ugJBb&Nn+xSj|4np73{#GqY1WuJ67${UHbxb8&zGG#VE^0K^CRJW{3m{sPoum zO`E~7;mhehCsSk?(0+r>@2#!y{sFWQcs~7_PsjYMv^Cw2dU4Pl2- z4}r9ZP*@};a1^s2+=P?ps65VQ|Jn&c4G+b^@k>IY}9^^AlNb@hH-+@ws6#~cUWh71tD{mnZSXj%hhHA<9;Ok zpvWMiqZdO!$UxI_=;gQV7mh)x{}Nt}zu0H9*sg86nHovt7%sU2&qcw_$=US~MwoYT z3fP4M4*l}00d3p)pQHOi7gz?fJ;jeRE4=S#deZG{e`3WNO@qMKJZ?Uflpd>Mq=0Y0 zVV#?sn+jV=R~cSOWuuS%9IG>z&~1FR70pMA?(*3sR1AB(>Ik*9PdphL_Aeo?c57{} zrTp~Ez0}+#pEu_d(?_pw%l@vkoH!LsIFvD$i=gKv#lH&VYHSw~gOJ`PGS$1RvHz^Qr=v5Q z1@f6lDkTYV*Q`IU--onmg=P6Q)ewuHovGUBnmMq^bG#?Pe06jJ(ychS$|Q5*MMDr% z-=adb9RmEJ^bFB8Pk(uqZmF*Zc;`3DD1^r!?S0->YUV{<_hN2})0hXhlv)Hd>Brm+EB_+rNyChyg?ljtxtr(iv22cP+=Z=)T# z({oFhZgoYYJ*^0VxfXbqeM5SMt zRgRl~#QCqLot@_)Ury1%k1QXWJ`}wh&;p!$ai}>e1QMw_HwuilulDv34#GBaLJCHM zFsTWKHt=3{NYTF2P@9p|<0`4Q@X<+8z};v-Dl90_~r zTaVHs)oLj>?$V^OA?1QAPSGsrtXNUDuoTm@a<&EXXF4z@Fv8Dcjj+g72lS1@mWtxb z>v)Vdx5*-}(d{tD=ojf?u+%O+7!@tU@LArW?ToB_i!}px;E_{@rd^(qMwl3!eU86T zN=IQGTP-pxL>9OnsUku{ZeyS%{p#j93JKD+&mD`3BA5PhRF9)$EeVoqn=I8M!jeb` zeq!F#>NX)CrNUX9c3)`_173b?Ogo0E#C_jy$_g4ga9d zQ?TPwpOZ8(nT1ZW+M|bW5hpHDa|VLs-rynbdJOD81nvla)l@!@K&F-+G(n60bgJcd ztlBo|Se^6vH(QF{pAnmSN#TvN=ASn#o`C5akdEweuOnwWOzMW9a7#jiDbnjz;DmL9r3iOn-T&qBcbNM8fmCOHdhDexwD~e`(vE6=$(BSTn0k175vW=y{~wGvP_907@B)t=BY9D zFOs_PFl~&3wN@{Y;R(1g`JT2jdN2@zqs@WJ%RIKq&Z~17L~92@I50_~Sb>y41kqM0Tkr2+ zs6zUL%2+E=E3wC>Qf|No_T3#@DM8qcL8Dxob2kVD<~eV{029|rkinJ8++&TJo1PB> z67KN$I4Z3xa4hE8e6-~Ina)Z+K!-d!wuFasSL0PV+s@%Tjj`_L4q{)p5Mr<=sK(nP zTwlaMGY)=o5a<+nlY4eJgHWB>WpI>O6FaJ8toguOkr;KOXQxes5CV#AE9-;m0;3Bq zhVtO)sVRrSv(x>erkhq?vsgsAAL#o5X$~pvB8{dZo%leIYOasEa%>|x%3Oy84I0A! z(Fn`cd*r3bD#7xxJa_bKIl4Y{#nj5QQ)eydM{wVJ=7mxqQgzm4z=g!KC?iwB=M|W! zrqt4N7dpT0&^#djqP2L}z$La?ym5Iofh|2p4f4s<8>N}g@9jAJHb1oPXEr`g2PZcS@^!P(PzUUX!HfpRE^qX3`ZJjzl^#rl@`{>aK94)2Jty%fK z1doE{AmJV~{fCDf421D+X5gMTdZ6$*_~J&3acIxDk(LO6aeux@*FSA}S>o~TE(BRs z_5CN&RmXf6St%)4ZjaKpHMbc8o*%BkAF<0qo>uy;YfJYfd7$jK0hGorj*-z(xob11 zW~{X}B=P&-rE_f${DIH^A*p~aAJ-;=sCt>4Z+PUh4w&gu1_~3xD|{u>^V;I=g{GsS z;m<=uG;VYx&Ud0(?(De@f_W~zdfkd{a(8p<^du6_3|s?|ooza1b&+C|L8Lt>I_=0i zR3dxTdP2AgpS{}OpWA1v;GgxH&IL*8R13bSUzBjvuDzn0C zfR)lyuWt6tZ@=8Va`tu^6YSN9_RD?1Ln2wEAQR4J+k|jIpm0oR@Ou_&ehOCJgx3w> zTs;PU68lIx?^&~f{=dDtqeRScC+6sG?vsv@*>GKqZ^6QTk-Sm6IVQmuNY*(z0GgCbM2gZK{mP`NkxUAPa=sGE1I!=cG zjhgZB3M8XfwIJw@BTM4H>Ig?cy(rTetjiQ@H=wle9E+;{hhEr%3&7-R7+FA$%5t$Y z37)4Qsi4nHvRc)0;rgmH0y@O)xb9yy+}VugFs;rC2I9sY)}3jwRL`~7C)2yfdF^{U zpeuDbN2F(Ww-dG}C5O%e*rIF(rT?JRSCz7#e*8*z4qPMA0O9hlv_5ij{9 z2?rgwZQNK{;kl15N6j!jAmJe%gKceBc=~NN#GBuQ7&UN*VI`PNKI5IC#y<^>S~84l zw`ToMUAfXky%sW5uZXK38J^+rFennv--IIyOSpGX!0j08&)ggz;mxKPdoFkhqqM3x z>C|?lZ3}kxX*vlcbxo|n*e=p!Dk9uv+BIV;wR2K8k^6I_qxa6Kdhs($cyjsBoP+eh zxH!i`m(At|JO~$_(BRQS$9a#x-VF45PKxQT?4{Z?*#6T~Y8{?Ih?RXLT3NtpBYXWO zgsu$EekA&)4o(s+g3Nw3Cmn(v3$-P#l%OxWVLa1`(YP*nWdYC3L8wE+x0x=*Rg+%d zJ)!l3lH&`^=iN3(^1H$;ry3)Lx!c{u#^wGzCOkClYFLQ_oYa{Vz3jM&mOD+|^lu5G z0anY6XEE>?HA{uo3XJdkNO3^+g6WcnK;*uLy(Q`sFoa>C8zCTG9~`Pb#k_gioub^m zwM>VEBwJBlUcdvxYA(obX941jO7kNmajhCBAG{t$w@LNg!235p_I zc3+V`XBv01xbw8DEo9R@v@Or~#^M_{P?s(G2^yPXsgv!v;XD>1$4$PeVb_TM-(`fWeze_Ey6 zr1@YH{@0QMid_QfFF4zvgI_E;iP~ji>qioF-s=m)GWD^$ zjZawrm7>P3CkjHb0=+Riaf{BN{VO z2Gv$~aaXT2pRErKPvnIfzC>N`7_if459kXedr7BRs)qv1u&mZrh^xS-w!9SgOtpZ? zgM61s;baa@OpyTI7_7+*1n`&lg^KoLI~nyqz#JDWw#jFyM_$o(lg>`41jUPL6&ImD zBMI9Ul(w0>)T@G9m3v$yyeh!b8K%+RbuOI1ymPwz#a0KD`Qx~N!)ri0DJ!v=muje3 z4E`HMvIP~TqYYDwv#k6ms)O&f|55OW&I0H{>J^r+iz|Gh?Lie0JG1P0v6TO$yw2+O zaJq(gP9LZcK7zPjX-)AwBEJ3|_yFOJup=eU8fOKg=?WAKSNQ`zrh-W`xfr>`NUEN+b^VHQ1!57@PLOzgen z_7QGWd_?79(Y@jsTGA4*lpWJIzW6%d%3vR`%??vZB7za%?U8~&gq-LId|@`0fYsRZ z^Ye#SD=24XyAITubyH?XDQAOM3`laL!XYz8fXgL)WmCMi8h>s^Z{tJys4G2!(G;_Z6Q;?~CMl z{VHH7101l%dO3gqM&8j~%v0kaOE}M-t1eGmhVB3<-9IYmQTXx-9$piQun&ndAq% zE+^keOAuN{yrX2RjFcAv_U>LQhxq@iWy=n#5N#bFU;IW!ZyKS{jh{Uqq(E4K&#>B_ zk6ub_G4G^We4ZRj&%s=Y?VTJ>B%Q`m*hC1gAEr$5@Lq|KSUznJ9_Ix`#aRTm=k+zF zlM%!RnY?6PDG48)Et@FkfwOM5GWa%=k&(_rQc8X>7FzJ1XY~}jPlPnF5GJ8d>JL;9 zh_CHT??cz5V|K0}#)u|g1XrUdSBH;I4Q(a!Stdk{%qEY03-3paa)>iTA}fSw_i6%r zSE%y#fA*yt_1}i>f#{q9;O6RU#o1}C0a>JI0VoM4Q^28ei}PMi+&0i%wlCHFc0AW( zNa3AyB3vFqfY3MMnnICEN58ZJqRT!^S(lriEt79ZPr3mjin|54x|s9rC@O3 z8YrWDF&go z>#ETrSpepYU6gcNau>$s7e&y1B}`fyPP$@3eSN($5LZ-KRHP%|_viSJ`oGgUiOx8M zw$p0vqQr^d!E7H6ASYVq{u~<(rQD9z=k1><(!petFbTL13UK7=gDUKDRc;dj%yMqs zU|bGVftsjs?sC9x<#34D<4Xt6;(~OhW#(u81w9FVmwhb)+B9!)%-pFhL4)m5e9g?? z4%;KXTA}}c4>Jz(>=d@)s(s59#L=QPO6E!ce@TR4JuBs?$pwyB#MBV`q6gLAo_`Ap z9&iJvu9iD@>fJUFa4fK$rEaq}Tij?hXbyE0x=?)&5SuxqaOxgNK&w9 z03E|^3Z3+Cze};Bo4{_2lG3~nG~n^{-$swuC5Zl9txq1XqHPP5(#LLC7(4x<-J zROfFygtvXyRo~BJ8rW1RE0M8MFTjJ zs}`Yhb8lEvM1daS`qT|(Vo)oBkc?ON)xv;Uico^?BJ?3%MJ4yb{imqXYR)S+-fDwq zy_u!j`9c@VyosaJ5F!yeiCI6&)e|t{KDkP%_G$4PQm*sspmqv2{)qjKnFUANa1pL9 zh9Z6DkNlI?r5T+E2zt>fJJT5E%M)rJx$RbXN=Rm6j8YgGl=T%*x}LDHD-4*qYurhN ztd8nJX4~DF%?-a7;?Wj@g=u>Vempb;N<<6Rx3+mY%dAfHz^@8D8}%ex4QIFRLT>f2Eba!22E__;Do>2F4SxV|D%wLnAFXDpOFHe^5Ma(%mIS8Y zh>^jGV3M})$}H--{c*&nNtf!6I^gR@6j4d|}vF{hI+ozy|`;Rt%8eRvCkizW{4xigb` zv?90iT>6cH(#&h}SrK`a(9I5lU~NsxH`U*;PMi7YPX>-w+#ahg&0W?nw-csp#(8JM z=YL&lDu$##S#->vyvhjO63En`&UXQdnyX>3s*T`z?7FB?QhuUo3g0_&%Wu>I?)L*| zRH<2Mi82tq@N>3vY{#AZeF)^8Lm%nwt)RRJ~9D|~<`ya2yyG6Cq<~67>ru2wC z)#n>g7kjl&mBW8kIBEL}8iq{=1WSa8%3bsGN zE~x~yrvjHPjzR-btEYG`8we+;a9?3~;!meK&7(b&Q-=cGQrFnKd$M0*IBsrGLgA(% zrg{a`&?1PWb{6$n;S@6&JbavyF-_l_c?6cf=%mVxCO{|);RWwUJ_4{n;ZP2(I0SC45B4@Zl%HWNC2aq&A^kPf*@FbVXwbSz8=0gsl)qbxw$2QPP2G@ zUK$GU_ENAJz4rMd)V*wxK**VVuSruD8&S!zRQ>s{4Va^|?6ExKq-bNDAJox5rd2P0iboEmec`pPOj^pzIhpQ3xDY;;!Vx`}2^$F(mwV)cOj5um6V zj}0=DBwjq>^(eCzx;CQ6GPz?7u|$`$Lw0l|@!I@4zj1fo%`?WDy6B^x0gl(N2ZL-R zfQ`#QUCv|^M(vq#EE@q-X)89wXQfp#s6cQ@N2ZNJR#V3N!rgTgUYQ~Cadb8zxkng=7KkI|e zm4^vF6M>R?BpM)SYMuN|K4=->`;CEQkZX|+7$L9iYj;lx?gjh^*cT+t& zT%trSJ#aPSz&{L*4gK+d77vAh(-YD%74UBk)EpdG3yY*Cp=!6WczUhIProMJ0BVr; zd^_5!z5U}TG>x*a(e+l?cna{E)7X5-BWh%_W*X|s$>2;#`8@lk@H>V$`&9*(2@%09 zNa@UvSz8$PXt-^;Yr;@%c|VJnL-d6-ah%2@#Z+v!natR(x|8Ye1uZoPdI5O=^W4s7 zuhxG}n6KyPDqrg!mXFdRsYbm15jCE{ExGI~cOT@7l8I_-pEu5oXYnZ9^K(jbfsx-m zj)Wpr${2;hHER{w+cy8XeyqwjPU=c<`J)kbLEK=A4|Cq8bgR%b3Lh#Si<~HnXd;k> z0Va1;r%pRGu4h~(`Fx7rcxBPDA=b>&8(5MXJIZDdtlQ54CU(V%cB{71J48@c4)hMD z81>4}5tp2v_h)8iZiNhA9CN|5&|&kav`@wf_=xXHQ=hJT-)|cCGt=$gnYG^~GA7i2 z&z4XJIk`8UAya`$3(a{iHBtX6^gDc-upFU& zrg((2#!CU(p`>CX@%KCbNXzRyHX#~UE|Z+5XWQ^qRlY=X7@!+}A^s*yw|Qu38kS5% zL@@lZa)2#{+e{yyh--w3;{J`@uaLf`prtNcRa{JVeAr2-R9@TRmxQJ5{8%cKp@)Zu z8XKOzXupmtK*e7%nCj# zNDXTU5EqPWbioL4kb~tO>$xtZzDWZH9{O`LzpNe!;c-JB$b1z|2c}ZI&vR?;S1FlY zjbc=I*Xe}A7@TX{lRa`_Kpe|C(=yyLK8p--R=kQHx{`~r9$N|_8i&*cGk zoJ6E*q~7x7cEy0x{d}XB(YS8Cr<2c&4gLTPy)SG9GyVX|I{%x`nxTN+lx6$v4`Yu+ z$Egu)VvTa0b26PxV_YiLg-SzK+fX(Ip1;WJkKpqUBZ^}qYBBJcpA_^-{pACL;Xb$3 zW<5QLRfTy%I#D|FQWo+`cD`7PYsEG{CMc*cln*eJMy-}3dwt*AE|J z`RQNW&rLI;1^|jaQ}>97h$Um&Y1PFQ3a;AUmOFjF;3G*!0+xBmb-d*PZgytj;^o6N zsVSUx%OW4AQK_NW<&pmb=cFLvY+WoGLZ(IIE&$b8Ka~+ImV;ikhCCv=*55TR#y_DA zo2umYhoA*Rv?$Y)B`!4qf?6d6-QsTMCDq)x6hDTAl8z%Ge^!+D;-(y~Gh&dt{V z-FZYlzkmDVGvd-c%uUEnmqo?Jv-RI*hYoJEUlt+DdC8s0K6C+%*io!#nd!T54W9DP zDmlMpYu&1}kfq;689_4>?`!eniVa0kav9Y2-Q zPVC7j7|G!)%vO&zaV`_OfViEVD!IHnpYtw!gYPSUVGQ0@TD5Vg7C+zr_?&l6r^>4F zjItVdVa6Xu)Rc=%q|QUcM}(u>*xA?j2f__=0YpUD4U{aOE}Cp8lzF_o#+aHaSQsE> zD3twFJN_2e=&&R{ZnJ>;yvFRoygYB6sb3AtCE%x`f)N}2W9QcgK-MZl_uupNzB*0< z91rs2eqcI*YfG0#Eq4US%=+i9?_mu(Ry-}{VtO+y3gn{`(fcDAL>m=ND z@6mEL>8hP@lx-Nq%Bg=$>sTZiYTPaZXn#^x+GVGQkQqkC9mo5pSMdu}k*X$j+f$?r zyelkua;wR4;GyXl8AqWkO(U*?aQOUtFD_>cf97Q4t#0ViOKirn`HegaE6Z zkYg)1_dKgPlN6ld^hUaIc{*w3^*!MMlLeJm#!iIU*EK1|bJ$q!g#`p10ubSH-|-qE zqqzm2W+=hZg~y!QU$6C}x?;8f#Tkx8&G;k!m^r}W1?_Je9A4Hr>VuEXO%e(a)bMUf){|E9{qL3P;h>}W^33&PM1kLq)VoKBPZKp(o>9`92r#=#y1A>8 zJ`1*o)rkctLxgwkLvW$ur+6)%R{?e4`y;}n863jtt%TT%sYW!B*kLWj7QhAuz^N2g zS&_lWx|?Gq{$0zrJLF~gmqHCLaNtFlLi#u_Atl6g;<%U1G_j3;<++LL6`HyO(KE^Z z&)4dR3a#Sz+*;DPZj5Yh?K;qd_Fl*I$E$4~M)~vyrDaS9K3G^-%GycijKX$y;-2W@ z!4O(IIJZb>?io0E5-#>b@hYm~xNm0;^ooA&KpgM;UWFPHk|j(yQ9xAgWQQn07i5zH z0Hf^_gHx)*h~U6uYebPbmQ6 zZS@9d8Dl3ETDfNQg^loQ8a0HP9IVKoAJ#{{|jUc7j`t(`0w zd~uKVL^9ut&Qu=c#=`SZ-S`vY#5@fD{6BCX;N(yKfd(A|Y^rUj5IDg+s5?PMGa4AW z^}BQ)gdWoi^W;eOiU`K7#PBR{N`e%1_Nz1qr`}R;${)bZPDhQ^)~`&#&lk~F$|gTU zIV(fmKPX2@^GYSVfW=`&h=wcOI{7jZ_O9Tji6ha{74zxN=M~qA@9#1V-(uuuFWe6o z!BRxy6e|>FdJB4T;XMr+=jDqTpRe~^FZBk1A&jhke5DUt#()5r;?EL8ZK)d--VH$J zE09FZz=i&Z!U#xN+Ze~xU(SOk9NM=CBB}cyBfp+Qw6WTDA%m$%0a&LfTRS9yL!L+` zX$A`=zwt^fy7ngso7q%;o*ro$Vmmlyl;Q^o@x2t6a%+%_z~kf_(<*`=}%GiZ8pgP+|qOu1i|^J%1nq^X>bi$aiw}ZOI(>H}Fo@mD_G&lTj1zToR!$ z3XgHS9um%YIpt%38|DhDxmy>5f3q_l!Hh#N41bG4w%g)>oKlx6YqspHK8Th2FZlu{ zio1O~Vlwc#oPVVKVh|{hba57az;jbfPzUa}W|$1ZK}8;#xygm0o`fyAT!csMkpb&- zJR-g(s9`G$vwG@ax`D~llf{%A@KRJCDpjzWyicaLdc7v1}6a-%ttFsn>aAW7kyp) zOBJX9uJE)!g$?LA{&MtWlW*_NxV@e4qgR-o8r_^yCgv$M{?ma0Lg%Nd<@nMY$S9$i z1oBGjHr{WK?@uoFe~J1T0rYzBaoLGEdV525P54=9@VMN+d6UQ|3u0|{@icFExn}Zj zg%*?(x*%pI({gtCG})G0t~jdSUg6$f%*+ps6p0o~>?pVqRkM{Lju^sv51Rc9s-5k3 zy6=O^{v&T~fot~ChZEOD{LrTxL4a+@XWK?3Ksqx3!nQM`6ibcrq&uX6kJ0I`1qOug z#N8|yO@aLG0&6O%a2P;=xnd?RiuW6kGKurRfMOys-Llnwb|vud2vHB#1T9U(CI_PM zB?PSkby3RJ@C9ZyS1406pGIix6BK!#vNE6H*{+EsrRwgKUIRMsROZCDfPX{%(fNKN zScsAK45hNtV?3vLG}^$meZ^%(NmywMZU_`Yp1u*3_pFX)wPp$GGwJe*OqA z*WL&@=e?1_UintSIXda=8}p?o8Mog@{%1GpvtLmCwkhx!VWe%SK8mdESt%{bwJZ~P z3HZIkTUg|d-B-2W>werQjZYM1@Vn5Rw0Ak6=ThxGcy!6p0#3K3A^kBJoR-I(+qcvC z44=Zft-urXJ+sBQt?rItDly+BJOO`+)c$@hlMyTekDKu%e!u4&OwlR_>~FJXCI`Wn zfd}B9Zfy|xso210WgSa z4$eI1I~dRS-DWI(dT#Us*&X<1l-@H`X|J~z-;VR+kXwML8{x-5xTMTl?QSc8N*MgQ zZt9Y8%I^|0xdX&MumoW`cfGnvUo?&0UT-(Yl>GqeNIc!-GTl-OMy$pY#DIUc?L z62}M|&}&eZ<%!2!U0sDu62E@2O(@A!@BRMLeQ*naJ?$>y$Y8dyYFK<_QYw{5DxCpE zqO)?8I*}>dfrf`4zkT*!yurq`f1npoD;XgwNU`X+_1Ti5XTbX=%=lLHuNp-o@NP?^XTL3$bp4Zu4PROwLdM_9-TbAS=Ppvi5vKAz zN=iuvA@glJ+C+j`X}g_*zT-*?e4XT|{8zuz1V+E!tqfi89VU>~!v~n5)?P~-|FxM{ zSd^Ayczl^jV@zN*@MnTOhGtQT!|LP1Zf`SM=w_*r`SP0beQ>O?CEN$h?Fj9-Caw`Gfr`4xZ2Q*!!M3*=i4%D7F}hS<=V4*Q z_eD{^Y8=ZztyfYjg&kVy!|-SyPS|YumheZ*g|wk6OcMG7Q5vGSZGdT?iFD6u%f6|6 zrYzVs6c*C-Nl=6wN&dL*4uS*Qj=%R-po2t zbgDTXQo2H6)0)&l)%P%#XK)>t=^4QYH=W1;e{41S=@JP}R-7Ai9|({g^HfLTq9mnm zax-+N@M)SU!o99%UnEq$8@NDpdS7%T`%lQre_L-jY17xxpq?HWOXZ40JQ&NJdxn%9 zuAZL;NdIafbYg+_8%=RRuy;Qbfslz(q0jkcWzokcC%>zzl;Cmk)ryoS{(MC`q3Bd3 z6?u(mB}I;!vs?U#l+22|L{Qp2NqLeNO?P=U$mP5xKGOBLPhJUH@Hl-qO$3Lh_b>bd z`Lg@ZCr=QhW)>DbwnMyDl6CmyET0*h3=C#30F7Iyx+a(Pq7O|NP^`U@d6@33gopQc zL64}hWLo%|im)=qezG~tGaB-$)K2fJd)dj)CT=}0Eh{ow3q>I-A0%_#Jc+q>-uD%R#`?b z?xTlkKUO65Maf=3C*_glOTYo@H(n%=B)l_yK1%xG#C@M_cYzUkAUFD-KYR>-rh453Nqm;l22#z672u z`XB-*6$+ZLWZ-d6I;-RM$gko<3|SeB%5~+dsSW}196+)ab}C%Q>^*K@W)YRmyX#&JQ&zphVf_^Ud3SV33osq)<@W|>r z5peMoH7UjbdqIXTzO81vEBx!gEEOEY4xL&JrQ=W#3VAb~wci6c(1Q$9VJ{48Ai%WA z<-&m6c5~5+^`vgAw3~)tKFtdf?px-ImX8sh8gRm!fLM8(;N1LxVfYUnkL+QA00O&t z@Cs@Qaz>C094bh1b9bw!aX~1%sy;8S^Qw$H-SBO4#r`3DEQZS_OCG7aKT!4OR>-fx ztNhUGJ$c}OLB>RYc7ZhB~_ zxZhXj&_th$U7?F*L=fbfuvZb*fu+sLYG8vFYs)kXq453f?=n*K@!k z3usqoE67n?T_r^n4GsSVfQFC0Gzk+9Qq zF-|;?{R3EfDiF|DTPbb1xg!ln7K?N|VX9Iwj{QB;C--VQU^KObo?x!6IDd6_y$Tyc zYiowP`UaKRM!R4ENDB}lt@w?G*_biq<TJRJ-|_TtAG9Fpg)HIs^m7T2 z|8d=9So`aZ=w`?L%j-Qw7h1wjm;Vcg{+p6v;SVS4V`&$xC~AYfJE-j0*($#;ysQz+ zdnxbtIW#)2b^6DyJ`FUDN`<5ntUU{5{WcwPctYj7`!(rrrh}?I*L$+OxsIp*N7GkE z)zvi3KEWlx!QDML!QCOaySuwfaQEQuf#5E|-QE4*kRZVw?&kg0{m)v=nLRVzRb5^E zlRA$;6V|w2M$H4uv@4P|g{dn)m~&H%ln}cP$Z!#kCW`>?5xYnf5NAvr%KvmFt-K`e zs+C$MUIby0u>TiT{>fIhmA@B!u$RXx3g20eYb_TV?Qqc$m7(*m!Kv%pDQFT z6*Cs^E-wYxi#lWx@fJTW*Lfo@r_GXi%f56zv%C@M6-z(Sy-}ODJcrc3{3yeJPYhl} zD&s|fhSSF-on*J2(EV|bEjTfBdGEflu=e}2qDH4Z8ow9M;bB-mBqY^a|F`&phZ$@* z#o?WP)%!lg=B3u~u6I9#g$1c@BF6Zx++6k|#JRBIDVxoD;BwP)Kz*kQZO||E)mX!3wL_)=kzB4+APZXPw2NrO}LI6LtNgk z9UPBofLr)AWC!mHUgX$g*W&cm40*PpXYawOf6^X$UIQNTfCOqQ%KL z@^XEZ37D=PkWd6=0c}W%XRL~VANZ4~6FFL?)6P(W-ge)~XQzQLq}}g2ae@T>10NHi z()Y%v1SDRq9Rb@i*Znx&kd;8hYIG8Pp!(>ETr(Sj{PlNxd-%S?gU4yDZ&>;R^J>_U zRr+kRQSgD2a%L86S2a9T`GmfIZG(%yiGo53m9uZ{uosO@Jsbf6&lvEI0D6z-K*6p= z48gQ-Q6ds8w!S&~-_IQu?%J*m$1Qim!kV#M$eh8ivtvo@wI?BR45nqP;qs_&2{FTL}X3P?Lw=+U^O~Z~(I`5NMdU>B+ zYBV@P@!0>pdkbvM^HmCO4$3bCsAH1Gd}MzKyfemGaFfOk9mFOA1bC@k&F zFm=H!sktu2O-*hy+bpC!m_&up;bD*mU5jBpkT)T#WKD6jtog}iJ~n?1+#8z(-XDnH z@9v`gH|%*a<-`qM#2~x~?x{!Z2|r?6&dwGKB^u!IIDiC|<6rxn6nOEdu&6Ra+=-u! z3-_3e%1KkHJ7`TCsb;~T+g^W!5!alE)kx~7_`bFTm)yWS;rKCMI!Oq;(ruaOx*C;) z$dOH+7{!^5Pl(E%>JE7DvZ%c482HZK)rp>141~sQZNczfI3S0v-Fdj48r*g}2zVUz zPdnJy+h5dqe^yIf6f?fgH7PvI{74JrN$h(T)9AUJY}D0q^TRc&N;1(!8@jc-6X;ZM zHTc}K@7OuQDiPqd+oI?}il?@Yqrav53~CO1LY|(=hJTJ2i2-!+So|nZD+X5CU};82 zL&<_bX1CceT(`+sPlRgsJE0d7dh+}g22YY;;j`}YFfp%yzy`jf5tjf6b&o5L$vGogU#MguL(xsKM2 zh}@-Lk(+tGhW;)yI#;U?LJ~c|AA4rPw`}o9`9_E>4*oVg-w3SX<>jTt`HcL+&pzzM z%Lb$gM#o@gZ~3sNFc{kKP_-Ge5=Ox1vV_k6eauIO*z=I`bmW*&Lj1W^ENp!ksHA^3 zP>gEb?M}MKW7?Y=Fdx~?d$sQ;)?ep0tqO?6NuIN}vj2Ww6c<;OSRFUz?%%ULw`S$~ z!V(Hyawphp2rM__DCfvC`=*|C^C(6--)vm9mejIQ-#p#)|HL_LB|u)bIo~iRu@o`k zv9AT6yBx6ORKy>Ls9+R2ns@n9!CjMmO_<=;d^z#sAG<+T<%#HBy6#-`b`g zw8ro|8++C2%EApV-@n`8JioVsiMAMKC;GC!6Rs8T+&X>#{qWn%(QjP4Pou0U*;ezi z1}2C94AXZ2PE~e-_WeYGI1v~99ElvD?l8zAQ~`YGi)i@$TpRCSZqHt+vEQB@-hu`{W3g+WNVBGug#?4S zvABWMD-4!~KZKVlV-P87cTS8JfdK#d`^`wE|KmXeZ!P?;Ys_mN0SnTu=TVM_d>Z<$&RmH>T)*aF-C*<$X&AnlS2 z#Aup)2$;@hBX7B)yAcT3{#D6mqul5WT&hhxGx|iuA~s;cRt?;LA7wduWuFb41b8qoRk_Tsb)jQ2h{>Wa+De?mW_ zTPQ!#Hcr2RM^B&ZgY6ubP8fSkBC^j0N0n!EKa*M*Ns`jS6{RJk&2<8B}fq%Wr?A& zs&}t@!+E!{H#eWn*y|&wHn%&2#DQ1>M0pjt_tB1^m`e?B7`i#^VKgffJ!e0kzbBN2-{o)SzET^p#MHm@F@d8bx%7$~}yl4@mo|f3h zOPxM)+bVDG4IYeOrIh>M?}q{zIwB%yXe3a5lmFeKVTe_%>eE%lpELZnYsd6iYtR84 zr**1sEPrXAE$OYsr!nxiTWA!xwQOQ~*EVa`{SMStW!#z>QG*bHXrp%N&O6eZkfu&@ zGq7R(I{JRk_xF?eQl&!`e8%nMbLabgxA!faQ!xC#1KcN07>-K3f1D&6H_pAWat>CA zKi8hBOlV=!gzX*u&de-qlRA(N2Z%Fsxh6b8 zgkd-0M*tLZ;jz%FRQ137WZQzG*I7yN6wBnE{VkC4FAT(As_&2Zpvq{-zsn7d5}LC< zCg>3C`5@UDYb;JD0$$#lBLDZdQ8x~J?3>wrM_sODS$Co+vAgeh(X`D?s+#m$JXv-| z=X<{#aVlVA=b1Vjw=9@iNoHNH_J4VJoOvspu0)C%%TfuIK#3t&TIQuaqDg`tm+)eO z|GyUCzrw-ZI05%^rk+SV5Ucc{dc5P-sh}4hZrX76lk~XK7%q^6(hWlqD_-)%^r3&P)wZok1Q#-|L54_XFAA zm&fTgZu?uew@N;uJ!@jzMNv3%yyqhSWPNd9Z4w;IH_@o4RK;G8Z<7wgUN12s{DnQ~nbAf3@ z0T(F|hjyt!miVt%rIZIFt>TY(x$J@Geb4&)&E^HesGsh)wy4}WRHBL70kOF9_H)*b z{^;euW^!_JVMHnj$yJ8A+4J65*c&|N)WRSC>+x*6kBpe#~gMv6RYulPEkV$Orn= z-&ifri1yKDArWZt!=t^V|BZc`F-{Oe7C{8Dl2{swst<`>90sJ^ZY;Vbw+WqcdE8+* zdx0`ZokVfSH!~b#ycw_@*mC0B2ls-6OO(yNlq%#QBk(gG?K6)Vjk^t3RGW+9bH;h| z5ue%A!KKMkWr&kS_e&)==1@i$hXUu8L});WpBTfKi~b)qQAPU!R=)!5uo_t=&FHqG zNY@||gQ|9wnlprCQU7e&?E^?DXw)>o!#PGR)}B^`47LD+i_P8FGaCvCvuCi6TZ`4p zrvvOX+6VLGM~)%98^#5c`V-JFP5sQ$`l)cDktop!Uq?-kPCPq;vH6O}RC(lcF`6ue z_S3I!<|~g1!ZqpXxN^rObehI$=TMX3P3T*>Nq!1#%*@NHM|tv10c_ayqpugYfN%`8 z6qp2I@HwWgq0O*}Ofj+`N|cberj-F}b$1l6Lam|alQ|CoVuOsDVuehOY6xj!Fen(E z4LNW3tvEILX$Lw!&(1HN4mG#|(s;N85uc_b83#HNe@?Yzo>6!`1i^U_$^CFVqI1sL zZeVHOvDT7@kc%*$_<;hAdu4TTo|eLKVR1>y+@+@=kTtoh$)=6bRU)|r?o&&c-=QoP zuQwahRIKgHNlg!gq&O)oHC#zTk1$45pt1K+{|<9$T)YMh8vLlhZEckL9}KQaswDE~ z?S*gRcxc>ksV8%_ul;-3`NE8`FG2Tr)5Jta&62FRM8~#Jy^uR40|Q|LNM2JeD@^@M zX;O_IlxSzt*PWg}*UxT6gb&-eWT_N_H@AZ9j`xDYwdRjcBIk|L)M&gCA+>NHoz-h) z;e0cMt3kA2unxB-NnBxZ>b)TUT{3e~$d)T+{NS}^$1=a8*};k9 zD^4#;p2jV25xwT5_Zr-gbm_Tf+>p_j>mx82TStKv?S$xTAFM|M#j-^b7)-+4i)ux! zWBG%hztVs6w~`3Y3y(P^E*=MAJ>}5P@m?V#uwWAlYg&+xN?) zp9r6@CF=s(GL_nhoIfKY|L740u>zk+*0XRHsGA{CSPZYNrDOJq+EkQJQAzI%A_e4E z0_0cU3qB|7MHFU~28DADW}7b9y`}I?ZQ9G(eKC6!$xT@a85j$W4HeRN*JZNp^hJ;s zwSF*en$Z>^iuoQ-Zt#cC>VlLiSthjZy+fG&ec9 zuujbXc{|%4659{xQ8F;dOEW222S>X7Z58~)gQ9NW-)Xdo1aDjk>>7>-#mjehK;d90 z+V1X@7KUPJ`w-whnI~8-PQQU)W~JKS6NW_p?`qsae|Bl;mGI1n)OiIDzfJy&cl$3x z@c?Yj`fsitE|Ht9zl=Y}Sd?SDEAyqx-bL_xBrdO)bNWD@91(|zI2;Pd=cq39MiXqe zy+J&&s_lZK(Kqnkn~GwCL}UmA8umsf+gB)~@m99|n=`~loc@c%|1-*{G%7yIXZ$0s zP2$)!4ZNqPr}xUv&Yl#Ki+Hg$xjP(J=jp?HO>bcD8P2=!ZOF*+a$&dLTK(nmKNIK{ zTikQFuWWXB6`i{X)z>74EfO=GUSD~Eh(aFUXo2$g`=z+L-=>@G(4WPk!)Yj`%8&aM zvS+i*k<8AHgoq+B=e}-7?@CgkZ9JWeD(NwqHB39V^3SNMnGd?JzqU0IIt12sr}8p; za&iLR=-`KpDz(S3sWW@)WwV2Y?X$bN9Y!8!cGRGljOvDYgDFBATAX;1&!F~J6)NIFDXHCfrD zLG8pTipsb3?aO~$kqwO0Rve0+Q$tfA%~`$Oyc!#A;u&!*w@BX zEGz5TS#C*w!Py^zKbkOkB_yPOeYwu2QS$g(WxH0c_In5wgR?%*|56-lqdSkC|4K^9 zRe%DHTlT~?bBn@w;?eS8O#XeVQ{};l@b)&l9l{uvql!4+nRsqhlaEN7H*9%uPrNP2{r@ggqM>^Gz=HQD{9FH0l=<$uIDPYoJdMNG2jpBr=ZzQ5VZpXOJ_ z&Hc9vlkKd^_%qi9W^j`cusprqu&*YM%Dt?Z%IyD1FJSSo&F}Y`vt0R5?==*I+w@}6 zRvl%_{9dlvraVpSDCElJHcUuQ`NJiglC7aIb@Z7H=xrTpiBeFogHRtV-KeR`VYhTtl0VFmHQ;n%ZVE zTBpQb?|!ML=jt2Oeqakh^v=LTBX4W=d82n zCe#W7O$IQ89d2KBc-t7_d4|l+3J!_eh5poCk>`{1U4uQ~DtXLP^(GY9Qf~R9Le_>h zk!kK?6Qz0SY>5cy@c17!hvAISfWYCZE z`0guAwd+GyvPI2_scN#Bh(Ym6nzBj`w?g!DfrcYHUXX>?ehnW+I`mAlGTu8cJ0iBn?^ zVhhJW7-SPoC0Bw5KZPK@$l80Fl0UC5-5-ym^#;zRI8;58A0e*@>p4duo9-sG77(^w zC7*lhIx~WsHC;;`kniqbNvz@cVTJ!Qqje@(uDsUS-UU>Y4gYwWNDxKg)BBBLwwi3X zhr{Q*sK&WM2M3UHE#n{sap4>(*EC5~$099qmG~XxVS=&CzR$xM#}s@f-Ar{C*3fm`KqD!z5>)j8dHvAc(RiUTYxA z-l3{ivjb7L8Vf4u+v0?T3hkx*rLA^j z6e!Ps7LOD&v{3&I9O`9j%34ZR1|ujKkddxdA)T4tcD+&?*ZHOJcdEtCm&SeZ8Qe|E z6eoovTzMkx()Fg*5UDJNL^!l??h6KSal#R#i^}UaNH|wVUhQv8AdxcrPx2#(A$I|D z6>9o1On9lmhEl)A{p{GI&eMj27&ak%eV%D{ar?3_hf3 zvi|QtzeWGC8#>v{}(I3l%-C+Oq>Y zE7wGk8q-9GSJYR_+kEk;Ozr^ZKO@NA0#F*92wlfa;JeKJF%EATQe|B-lHwS9;qC|v?&s9#m)+eQ!sOs ztt70O>pr%tbnmn5ZWxQ^oRvMg2}wpWk`otR?Dw)GQ~3d7*vq3|=S1%bf;|ksHLKL0 zFZYI@llL=e#mDq^q)Idg`=Eah2Z&-9PDBjPAiHn!ES_&}c+tn(Z1H`BV% z6^;X^pKC*m}M0j6Y57hL#o|%&Xju7QCMi! zsd&~@b*_BgGUPoBB24h?u_Q6Bd)vrZKoXfxT-f6_z)CQeZVo|QbULhPt{Q&-H5iIE zo&3wRMxDGt{!0t;&Z~6xER@pNN3H>7{?H|;W*(C_q_ z(?E8oh$kS0aHn9UtRI3!y@wDgZN>tdqn5X(Jz#Ad@4qV!seCq~wkwPhv&!fGo#0+m zR_5Uo+erd(&L&u~wrwuYKpyUJjxL!pS}YlF?baz$YS?;28;D)=f5aBXW|Ed%NR5pMv@2sfT?W|Z7e;-44OX?I%12JVge|L3Ye(-U%{TnkZxX;^6 zs(B;V{a&(Buj9{*vFE~-Eh>uKsiEKHTw)nn?=Xm9|MoMjelVJH5Q*rN97E`f_?>U_ zd8!V@y`6rye!Z_a{4c3}m*3lrY>|g#7 z)scRe?q%0;yndZCWd-1pc!+V_NG7JhCs6#jKNO%E6(n&DFHNVo{0>Bpy?ZjG{|;z8 zom#t82}X<8@zlT0JRPE2@VzAnf&l{%F- z)?w;K{7HT2{iL*}-b0YoD450`{AKOs@Y5m6@Jb)<;)H#}i~>Dka1yFv>X+%=QBtmJP~JO?C-pkD>x+5uE2f7htLg$G z)az%F%_OqFrRfcszg@h)2CdqclAsipkp>3Sz)3^L(Y9>#by(yvv?;7sYGscUuyN5Q zOV^!7Dbrl*M=DYgZR~?Y4z#+mU0j6%n9Y=1N&@gMfZ;gT>$Z7c!`r#3cz9anB9Lo1 z{Z98s73p*0sOGFrMqHpLnCPIl%PZX$pnh3V7n|Q{?bmhFK zqZ3M}i4TMB%okD{aM>}=qnJb;Tk@euQfFQ(gh3`SP~#fg{A17wa~D^*iczoyKcvTp z!aVu5P~kokMi$T4iA3YA7AybS_llmmV$`3=J{s{L?|(sgZqw1x z;=xf(84r6b(Ho+qhtdz`wlKZ7ABAR2bs}Z*eK1-yA*q2Bfek@y*qqws=chj*?#vB6 zvZ&JP|M~sQX62$A*F+rGS^>m|!77cxE`91w-$4AkiooYaiG!lZ^XNBc2c3G^cf^Fz z-Xmv{5QJ~*feboOIfRVRZfVXvgGz4qoAhf-LjdTHJ8p&uq{@|+b8u=e-P{%$&Sil|O>nlF_;lW+n`L@gZ|HFh z1U|3UN~ChA16{N|9eSGy+SvH_hrgVyLh8n+5yK`?JjF5WrN4b%fRr6v=}MtA6)jJ# zt^LT0k^1SHqyk_!4_dayM0njDuLat~8Qais+O9?KJI?`KsvB~@UyQu(rDyi4Er;A* z&*KMK&0eiPiS}I((G2=QCM6PGtWE?Op!^=T{aWU`JuY&TO^Oy5O)-tK?naZs89e@L zZg;ia$HtGqpQR6kJV&5BN22w#fL(a~HJw-fqy}}qGM?r_s!81O z^yTlxDc{$htGY@y4eW~m4b`h!u5ngAu4QI6nN+3TdjL}bP=17jDz?p;tkHvLQYA0W z)p25EMAcIZNGmU+O~Ns-aUMwZ?=9CoA+F}6QUL6@ zQCo8NeR0L6!-Ro_-HIGG5pNTkWi!!ESv`cyyXQ<>?4ykKLdD9Zx941TR{KVKSzO~M z=k~}vKJg5$4lTmI?pF0^$)D*>DQ#>n7x>QMh#1}GNop_jUmXVG+4U3 zRGx4PYDFH{s1=qH7xe~!Y4Nn#5t)7W#flHldHz!|@#pprPgcQZdz*T_V$r3={V;KZ z3; z90e>hrEfWgiuHOM3%}-TnpRJve74btt`;k%j0`%px1x0ZB-jMwT*zW@!s_C`Uyk|c zdf_VJ5OnG}5dM1>9JvRNyhIhx&u+xgD(iZU){CqBl>hoZ@6p{NX4zt@fD-L{gQ~Gh zx_>V826JdB5y!!y0{mhI6B|5Au>p}!ReT6S{b^N_Zft|6jG;7Aqx@`Zq)rHfi;s;|W$ze}O zgRpbIbGJWnA~8OSKb`)rZPz__d$RD>SdFy;mX91nZ-a`@cYO#>Q}V zG}8tx8|$#~Z{RJ!&Bu`YV75(+40WO*eNd!e07@A6+6l#v+T8^)WRt8Vv}Da(df;H7 zF7v9Jv+F53(c2sR{Z?B0H>s{`*Zi+l1=<6gUzOP%BS&=IjvJkilp}I^cIF1{PuWfl z5HVn3UtF?f7?#sVv17`c`%zBO}SOv0PbJ+K_K!IfG+q>-12WyQz1k63YmUif9 z@>K=VeNSqf4XPy~jx?Pv&-qnj|7%s^<9D1J8#P1n4Ej8`^R>Ml$fe8@F?U=3i*?&QBXkrL#cF-p_{#{Z={L_m~u zLC9jc8y5z@KRfdB0Wecqz#@EXJPJ|4dEXcQdl1q9-IQjfo=pBDS(=Sf zb?YbazUA#>*Gi5QfvWSVYi3E*nO|^!;bGk{0xJi>7%)j(b>HW|pczDXf`JetN5_Qk zD`@$ACCa5ey{t+3hxPU1Z5afJa+Q~^L{nKaFqPZe+V_&xxx_i@(r4qd1xbDz(ib~% zU1VJNK{Nypgqm%49;dv^20a4)Z>K+=zX|1g8DBF#=`pg7{n-69sX0;BtbJr`_B^p;f4Wa-g0ex`q()vU(!l^wolkuhJwe>JRPAyX#N%ib1^$l)12F)}7_g)0E1 zOG9z-b!dtx`m$)2Mx*eDf^siOT7K-E=@!uOkCKL9zdhBr-qIkYgTGubxU@3j%egfI zZ8bWZCM6}$rHEL;q05F%NvOkYL>5@|(33{)I~(8_;Qc0p#es3wW?YgctqdoE69EmY zaEIwOiXc6%7#9>PHnt1(spu~G_aBt-(fziby|z1r;NWfy7iX?X^Qp&zgF-LTl0M^K zNBvTJk^3PaF6MX90RAA^K@kZru=*02W42~X+->I_9wH%EkM8v$%l*rv?VMR!-PkzO zvd0ya(tkj{C&bMn*4vuF^0S>n1R*5N9Vi+iX3Ekh4>K)E9iDp~lQQZebk2ybx3~ns zJ{8-X)a4?EBo)Nshd)48L8 zYW4`lMPxW==uaU!H%Z~!yn=z512NaAG5jSOTw!f%(l>QnjT*vq+=g`7pN?rGx`xg3 zt87{pw3Yp~cSCb0TW_Y$hEp4D=SxdV+@anL%+rWncX-hq?*jJ@t`;nK6R#h{E|#5* zNw45*BeYvLJ@-g>A@E18g1{4fh_lJ`k zCT0!hEDimE-9#oaRh%y(@O?rfy}~gvJpPx6?zXJ5?1|hxNMwoQ%u45f9n(LA3bA~UiYq4ZPA=B1+<(-o>0KrlP5VeASb~A#q~U4% z$wt0rs z5wl5^cVXhc6>hqyQu+6rvz|1k1C&(cec7ZV4ccmpY!Q13&F7J$p5~XA)zb=%92HOj zq(MvqgAgdh`=hMIyD+O!tBZ`rA&vekK#98;OU)N6niN8kFDF&CokcL(Vsi4|;P!E9 zmB_VVD}%9}-GtvHdp0;fZ6=P89upzbz=CEVg~6nM#W5jy+nWx*vPzBKQK(fB0_!tN z3o;=Oo5!rf_oC-DII_GCE&-6X)z;Aq2UR?_pR#fQ0I!Xs-Z~(KQ6n>mUOhdvyD8)yhx|qsQmvi}07DsE`K?rx6{gsvjqk3=5OHSp= z8Fggcb9Yd0K`)TxGX#UCgWfYQqp$1K!dOQ~m9Hnw021)Eu^B!U@xkFcVAB%*YSzBh zvG{5d5t?y*{greX(qL_8yH#m1n+Y3^M#OBiXo?a8PhZuAgVRM`pIt<dhrer}qS#*nm8b8)-O4!HA2<#cdJQ^E1~Acw0SHLu&7z;{;)2e>#;Kx_AoRf!6T z1qr5ys6N?a<3onHi6-IO-M8__ zAf!nmQohtqrukdo*C~r^`DIY|Hta;Wp`cbOD;)9uC6?qAtQU(G>O1GeVA;f17a&(ePDgS)7#{Q=+UBoF^@_eX7 zLkae{k_=m*bWCBaPQE_m8gOZ`l{-j5k=ZW^`nzI&krB74L$SeY>Ov&t< z^}R{xSjc{`c-D!ElUP&6)N$a}>02ZFt}cW82fY5jGM zp<`CMnko|4&|gteCI;s=tVu^M?aCM@S~rm5U8qPVRI(@El2ya%C_Xo`@FPMqHRpwK z8ojk)8a-dbH{o3v;TV2^mu>ery2X}?L$X+kLy32J#8dsw`ZkNk?9GL?N_%uDR^eF? zipHMLCvK~czPM9qn34K21&v72ej18|us_fy4NoAEOhbN8j)72jb#;XrPy9S9*Z>ZM zq<4Q}i_R6OdTQMvmmH${l}_UNzn`T^v4P+F`Yg#G7Eu`jSowL!{;i|_@`+QR4R1~t zLfvM4%kUq%`%hbn@@88xc+gj5aWdG4d}hj3B4e?lS!6V>Ax;q8gQ9Z$JmVL4MSM*l z**sPb*s0RsbaXUvnzZUWiZ+_RgE@LFQVRfaar-vr6=$*;mXcl>Lo->FB z9uTWY!vI-PVd+>?=A^Kl7s5ErmU63(j#{Xg6=`)ZCEC}lS8piT62pUm2q)t@OD2;) z+W(=K$W*U5ouATX&jbq1QX3HHX-j|xR(fHdc0I0g`b)W5V7S?-sFqC0#&BF{Iz5wP zI*1Wy>)G>jUaEz_C4jQXn&Hg29X&Ewnc-wuI)E8M#;xgCDF}h5QA!EO9kUyTMSSJ${5=3dhMTYOhRyGbp&Lb(Y$6{jV~*Z1(e?k&#;K z({O=YIGA9n7;@>)5rqD4|F~LEp_B;zK~S*NJ+fhVU%N8T@Xqg~hc{n3iwx9R zy4GYWYqrW55aB!=ywumXv8&q@%`M%4l#4g;)02L=bs-e|jIB_gV8o`=>Cn7c^w#SG zu>n(}+nm8%hdKcMK@t=^NYw#0bBG_HLn#9_?_f|^xtwQr!L{RDTtbgkEzVdXRh%lV zLd6N?;{^XBcF7Wto3yJicH}@%!XR-W8jMqdh~Zbg%Ln#>woQ5l(6=)i-He<&3l}j?q~|ea4gH}S z5`)+j!&zv9u$@VCX2vpg`1Y1(Ob=Dk5aVLvPf;&Nzt^87wbHI$!!ghq$oR$iI48>p z`MB*6Z`ALUN0&m)W1C-^50`+z^cR8T*TaR$Y5rkfG2;bTS(ps`-RG+4@Qo@@qJ{WyTG2%X7Al4c zN*Y-Xg1h|A+?w*vDHiS=XE=7Ebx*RVr>-Dj9!PZo>slb`G6IwD_YaFEcZ2`DShWafZ|64>C{Z(e%3A;^~!91(#i!CWR?#FGwK-hPH*b3zT5Vh(o*RdDC*nZD@k1`84!@J>s!&4&HK4bB7P25E_s6 z_M%RUJ|txI7dA+Hd2u&r9~|kJhX>1b9pY8<8tos?qD}*18aP2}f5mI)kD$6u9}%>Z z`L%R?_cB6z=jThm;E1~dYTw#i-L9}^TS4FSwu!?pwr(8jedcL&OMsA&4}^S?^ar15_=8|c>US!bu~#2D^_;S(Q+*x0 z&>-YEY|#9}FbefoWy?8_1TKgKE;w;)n}*V}h5pco<_ykZn{mw@)8#9FjuJRMpdaE| zdg3*tUZ^&JN{y!whD!(x9^6$2AEbpFz?X(+Lqd}l(Wp4_n8R+aeSMGomp~s5ZP4g-!&^y1ipk@MgNQQ*t|jm`0i|? z+i4H3K-8+XL)lR;U1tpsKOB1@8-cgL&|X(Zr^1syxw7%)?S8_RJIOqO^`H|iljQS9 z*h=UKM^S{sJ^s;mzaQ56=|B^)PBUiEOj`L09ty)o4oSwp* zFCmq426FC?1c7(PEqj@3nMetMx9uB{j+#Q&lMBggs_LCY`UH^Y7+UXNaPEYNP z^NJGf5o6<|oHHdN4NL&U0!s=J4(TWDO?jXsny#O2)zvtN!e2F%cdDEAfD8e#TQu|> zSSRw>Gp2t9$Z&%m?h`vDL4Bbank#`_t=>mx!??d`z5RV0MYMPtDx~mr)F~f`elD#tl zDDf1`e@7A@t3ppvq~ZEvh~WaU??LM&L!v4KCp;SYW`w#ah%DxF z9l~KFkLdH)DwBV1jeOGWC1t%<9EeMU#%L5bT+Up5SkZ~4LjT(ws8Lf^P_(#Ya++lh zdj9^tD*Y0zMm6j3Np|UxMbIEl1c44LEawTgJnbjg3-Gl6)b80?rS&M<(#-+WSD=E2 zEcieYeY#auZbE!Gc5rY|I86twScsgH9V@C4oXS(W7`lx^mw0PBy|z&;f}F$ zx!hy4EGED|8gFm-upyR&1TuK>DJ;_%^y$~LbZOy!j6nmgGJxJQTUh~ zFE)loL2KWcVeU8h6E&=~!v61Hi>tQ3u~kW&Y20G=@#&olFd4=}GVu7P2QC%-@7w#Y zC#Fn>S9;DjZ4deHYsF{=0Ii`jBXY?eSp~8@a&%82AZ_?y1PUNwTm2;!^30zv^d^69 zIU`0tzfO3}ihso3f@Pqg=JFlKbQ{zxxoJ_9Ivj(nm8GFY zI_-*zw%ncbCH2i5d6IlM!1m595vTi4u8%9MoUmAA7 zqoP5R@ChA*2a##EKzw6t5p*L13DUJg4>{XUSV#Mg^qM`fCE}_|Dh9L>i<#ctXL~IQ zuI>m?$d=vBK;VeVXJ#)j5Ft6yEw|g??FH*+jqZcW&q7C7EQ?N=3m*a$d;Jsj>h~d@ z;8E-Oo-5y~4WSYpfG818NB~E&%nJ*SCto@<{XNF4%mV1+rtU0Vw<%*5BhLC^8;%$u zdRGy9`vF~Uxiqiy&RCKQ(8-ixab;p?Z{=XWq+1{JXdu>00J@e-uBEXHjAl)-4J7xz zqBz=+`f@C`^8WO9LP>)&1vo$HA7O>&^6k6M-GivloudvwGgqD@N@D2jyu1NDG$NFQ zZD6Y8m989gQ4)7gjY>sdbY<^(BW^~-hH*CuRlrDj&?J=2U3LeT%aP<}3Y>3R#_t7|*D+-Tp8gHSm9pIqWwEx~_8^=Hnw2q29Uy zY=j;wA(>pNy8i!YdIyI(|M!1&Bp z{`I27PZ>uUn#CZ6!s!yPPx4y(PAt1=MO_*_NCOd4b{M7(#gc2np zdTL>LuoOcGJgeOy9L~|IfaGVh?QhAd@rNAVCO~;hMI(N6QrM)=}AYJc4Cx*+SSX5>-0jfFS#2`1beiuIddi;6*I- z^@xH7MhBz23V)*JhACwD2vo`?gk6e$BEX;iOr0qEB_xnxfE9z|s7?oNWtI_+Pk+fV zIwT}ybTtLC9&}~IZcj-#UiF`CZqXcrl2*@iB7&nZZzwx>l~{J8_OprXe~uUoX&4j) z(GG=c8ym!~Q4Df`Gcy$UQ!V_{S8tQ5>}=5J-Kf*0Pf^J;WN6C7k(qgj$?dL#OId?g zkwv*}itS|fi}}hvsfxHQ0@5ICkLaOQ%n-zLE{w3n3p2WL`^GaQgqtsZBxrscBq1bv z2H)9?8APNcc!}L1EisLScrQJU`Ws5}oKM^jbetFPjM_oXCY`UcG@^MP>&v7ql!Hvb@mvf;R@Vzll|THl12oCGj~P-*&?Vy01#U8j>i8>@FVy~+y(v^>M??dZpTGH& z>egMI5_#U{WYtJ51g(l3Fho@TcE3}3Qpm18c-vF&xILZfMTlFV3=|-?H4VwJQXGwn?ndOc)fjbe+HX7f=~JzZ@bco`#7zRlM_yyLumE* z>K7}(6VYs0^Q(Z0lo{f83`GIkd*q1QN+x@d_4Y9NIc09`3VmEfeE?cqoGE#RJ(zHR zLli9J9=}xLNz9J+K11*o0o*`zb3@5ro+AjyT;&Eof2>sLI_ji0y*39+EG`k>W^YXR zAN@BBV@q|M=lH%O`EPXf3KgE>h(v(`F%hb`6+wNu`i=}ZN@){~&ru?vN54qmbr3^r z=2`bRK4tf{Jt|hKfx9Mbsj!K-Mau+7VdW-ca-%~HjZMFWItQvN5(?EgDFM_5_LzMBe2fVrSRFvt!- zx2zxLpdjp9r&}NR*eKe;Lt^e&XHn&VNZQ;&fBHK!_@GOqB=msotVS-yo_vPd%mMz%nbMHSX`3j}XW77R@L;lctH##Umifff zZM-CrPY#aGZ23uzX%GI0R%<~u{5hnHmZN8i*9V1XKJC0PtJq^H`wp!(_O>ZuQ6+#X zVdMiCtACQHV!f<<-h)dFws#~cu?#S$x$1A-Xta!*&B?ARbI{}aRStFZU|FU7gxvGgKF+s?KuIn@{9(&bmJvA5u9=vtNPMebk3-wlfsbyJn*j2f%m zMGV%)3Q@lL-Zx6dTkC$+_NG>2)r;NRcCA{b>YvL>er!mfQu7kA*ld@S6D;*$LCdhQ z4Z|aNF8&tbq4oICEK&Kg8oUZ$vmM=ZYY#z4s!fESwvce42qda}zgbG`hr z)NzakCI{0Q*8@=9f@0h%!l@;@hV`4z91B|H3bVnr6bLQ|m{mKew-dGw#Zh2Q_Q>ER z^YP!<4AenirMzSa4CN9rl|R^c{2EbXbXfdKPb(&jF<N{|uk(F#eQ@#W@Bi>ddKI2n&EB!eq`1gNp#NbrIM#$>GMw1EgLw6)orlOt^W~$4 z%MYr-7Jf39|H|^4dnf|pvD6qGEP$Gb6&QD7zyjkw2XLrUkdlOD(g#8@N5Y>|LnW|M ziD-3Ebz&cRgOlnFlVBV*N;vQU=J$-9>3T}Fp0xKYwDaz>e7hR4u)_%+!{XIbt~7}M zUCp7V(R0DSHs#;|DB(L=OFYkoO0FG_sOFksqn~_VT}btJL_Q>`Qvbz4Zjsen)dG;P zL)yf8{Rp zoT--=B;eKq6BAQ8GsM@kJ?_r3)7WuNY*J;jA}1z|L7|x)k0KEREL&#j0^*gr7Sjz&WFf=KnmrlOIv@DFNE{M}Lj7B+Sz;An zyMzoH-Pj48T0X_XLBXAUq&DnYCVdHm>jGjsY`#Iqk&}6MM%q8^RhgeYrCJwmU6K zLZ^%z33LtHw00&rW`hO-dsiqq*_85_f5<#gp6W>ZJ$RKfmU-bgM1v$%8zBy z+{1e-YnDn`t{*Bp`j0ypNQcbv?I~B_1^zJsh|9ptkPe$DkO2E_;}LA@T^A!d?0n zvIP|C>fx2{uioJj0;|Li?R1G9BL9?CUju?GTYaB+CSP)J#*Yj1(J|nz**{0>lHlI~ zGzX}{xFid(QhWi+7HeNW-dGQI+&M&s!>Sx<=Y<5uk=dC43BQjE$H!N zcJy$Zp{@f)E_7#JCd|{*bRD;z`TdSF{-u|VUONMOxH|dtepMJ4rZh(qRkd>6kq&+4 zNnoX@P3836U-QHA#^$901bC(@RMZB9uk_9XiJ0#`Sqo7u(}b>Zx`q*YbaoAjn5#_C=B2ggOd#JhO*BGZWL02^Gi!3 zkecc6(^b^7KXQCEeTmouQ6RC!0AdLJ|2e&_Yly(ZHZSsgwN7GARa5tMHXI28c*V=Lt~ z`{2hmJv;ZQfj_1lF2(EQh!p4TPiLOikN>`xw`glu6RJGseAI5U~HnEh?#-|YWe zu}od7+rol3@_`{Si4RQBRO|&TZlvxz$qeSyPMhfw`fQ(0jS2T=Be;ne9PlKTYgn9p zJm~!fWcfPq`lF94+iY~Ktd28RhuAd(lrh#@zSey3=TqBl>YA81-RTxu4Oqs}v>S>g z7Am*+IR2)~uLwnlu>>}WL}YETu&njfnD}X8??+~SAf5nl`IT$*Zr9n^`t{m_u5}lP&fp+qw@XIxvR$1w~QIt2=6VZi{j{C!IW_6FbjY;5bwS91@pp66K z(Z}{@4#LH1Q9IHw!sZryxWP{h7qTDq)kaL`6Zxk`w8sAhQ_H>DOl8=17ILk5<&IH% zrZ}ZdsH3_FaL;eKIC8b<0mIAEIVs9Mdu5Gb0j7(C#FUnK`B)DL!qoDx$69Cb_9*;i z2XFuRA~d$Tu`w34L&n5rm5S1aY_{&d+&mBeVHI`tp`#*_&0cAP$8E*R2BtV)%y0=? zCUBPWjc979s2V5((3$PaiO{1dC>Ew()j>#AF^y;mTTjjFTi}(`wF`ffU8nk z_NP(=3twM-=88YEckejVT-=`a#pY5o8BB8M%fJURHM_DleZ0g^IWCn7&37~>yFkVq zP12_rl_H`^I7+1F6{wzDvA+Hj+#OY|tpWV4;21 z))bYq`QL@)2PiP-a{janmm^A{F;I1Y@LD;5pN_KU1NinO9G6bgHk3Oqp#IriK-%4C zP-0v$_dT;m+B|PSh_Jl0q0~cMD5Cj~kH^;@udqg+-X|6UX|_=Ckvl`umbH_PpRBNo zPUV$|L~~yIv)p@WK25)nCsz68L*JVv=Ni#K8F%zv9YaW0Iwym2o1cY>kj`+CygC*v- z!05Fz8y8%d8KMDS$o)9^@ji0=oYIWnR{||5XK3XWh`2{g=h|$C4_;3aI&;y%yqh_} zjFb*3$mYS|J1G{HI_;~BHL5aod+~>>pw>hOAg@bj&*cKdi)ZR}+= z*<4ea&-T1$B5f;EzD96ucatl;v?xY`aWeOY9BIF)L=0=TAV1IH$%m--z^E>sV}I|x z7!$`?`@5}z2RCAU)!iRZK_U(YopzgIlEyl){0rn*fmRPy9InRg`2*w%pn><>#h17h zf@EcQ8f0dhyEzAeg_YBg@%n8JVvU_zp4yTq$u#OL?yY)6$T%;hgIAhFjQxk@50nz~ z7WRRrtAw&h@I(7A=r%E9RnOmUx1~FWOdUakTX*Q+k@+|K26xXEw6L}JE?50t=3+KK zWwf+}&*BX~1$>D2^okwYRu&*Z=U}|bO45kv?(yfq37~U+w`oLp$+Hb%nPQeK~R(*u1S;@g+x4gjmvWA4!Ya?A3#ltc&O*%)N!S4%Y2=`E#K_(HX{t+DgL z{AXR_%hSwTZ;?WlDy%uDkPJLOK>Jw^}RlV!9Lmy{JqmI zdxd#XLmzp^D5{xz2Z9(>j}$2hBz*1rw$U}|6RhoDKH(wn5fTh zn4iVVPL1X^>`5`$dqo>7bi9OAHhx-xXwS@2xkmvOhKO({jh_Dguq$jcWnL}rxf;Y{ z7v5+=D$yt;bBP$%njz9RT$esnUujzpq&Ove7~Sbop)js_WefIQ_#41O}3f0cRyTQ!C>pHM`# z7f*mD2P($|ltR_KA6rF>r?q+tiEKcZ(&%YOa;+r|HzMH;6(*BmVJuVLC(-b}Z?+v1 z^W`l+d!^+*B!XYIh1Vw)GkN1u64Z~^Hx7loqqshevmUzCI3#MS)$T96C9XN2znt_n z!VGxVN=|0Fl}~N~FV@pl=;nnYwHN|e0H{Tf6y0d~HL{SdsnIAuhDWC@n$m0uhoYY< zQ0NeFDA(Y){(CTbl{@0+bI=$TyLFU8#>U<*)9V^*=kSjkM$OtoSD(-{x{EA23_ysX z!>>*+!tt`W=4t63W38+7Jl~Z-r|h+~&9C_P!Ml6arnyP}vcEgQl|Dg?^FZBX~M1)8>@> zT5y2J_}|A|#BnHg>0_XPG;qa(#3Kw9(3qITs69PC;=_nVFY0o%o5$`Dsi5YL_i8iI z-dO{pk6ECvM>KKkKFNHCdmXtkhJ?`nSm|P)hp|9gX5C>IR=v@8Q#9dn$F~co-<`$z!eNFS5kG{ZF%umCS~4=45Hu>VSz~ z=`d!g~?3O-`d@=stK$0uP=!V8a$GY zGf4C9S8S0|4GnUv)YjYrPr^!XjNwECB~h_XymY99Rdq|BT6o-m^UnI-JaDbDZIa;! zw_K5tm@Xo6edt6M`Vrg~w6Ibicx0UKk{8^<_SV;R!&LfU3La$>8XRFBQi0j~^(>~x zWL}B$xP$dBRA`+8|1IU+-zl^zeearFTMALUkHAzEO}i=t269M({|ECxD_|R&)>D3L ztwhW>m;?ppk;(R2mU~^gem>S-ioA$F+l(#RV#<8p=N+ppzi{{|_$OHj7rz!}3u8on zm(`h~>CrmDii?WXT}Og%GV<&^_^zFzKj02+!bDIa$`Z7#^~`^M;0-5YpqHablg=672Xhnzh+GoMid?zdghU%P z$d-D&3O|cp*f%pqVFFhAAX8n6)Hfq}rqb`u{|2$g32T(@#L)pcA4$N$B$Cq3PKKGb zaNE8VmnMSX-5I<+dp%Y6u7d&gzECBFV@m?q;MG5I)?^N3D`I8CxwmG)8E8RhTs&kA z5zlZaxG^5(oFs3`mAByD{>I!~10#cmGvsWb@1aHpnr8$szfp5hAUJ;|AH*8o@%y$h zLi;oCrxg_6*Z3>y${-6SEj9z+y3(E=lH0?}7vx(e@61V#+eJ!rj@Y4QvVlvqfR+YB zHE;@c5~2W)U;P{dKY91oR~bkQTn|(sl?S*vH7Jb2O)>X(b-reFhIqv_jH7<1iPQuU zmn%E7=;=c^W(a^g>5zalL^u)9nJ~!5BZe&ZskR59J+pQ)e?XgD?J*Dg6+S4V99xT6 zStpyqBm2;4<3(9!nhE+E^otWvmrlUtQi{;m_LAkfXZ&!S6LQ1rD;qShW_Fqp}p2p zdDv1~C9^5POJhtvY`<01nt>1F2nDk0?~Gx`_L#Fu8JoxkVxejWr`aU-1nRb|n8}_Z z9d!>hZqNst&R@W4_V08^n{ow7$hflmH7&m|fc$OLj;@>y8iHsd<~!ksGOB^*voCNG zXzLv*i2$#bMPqg>BVyWeUFJ2L$QnXrvY85U9$s7$Pc5@tW|W{}%*wUT9e zzaCcV!P@r+DdJu5^6MQ$gvuSrc|{uUok52Jbe2q#CnX^fVP)KVIfj@GnqY{%iWC-F zsK>Vbr41X0#7Qjc;{*w!8e5LVXKgz0f-uSStQtLQxJ;VF1i&5aLfq-Jw7hs<*dBy1+oc+-N$YVfkYnApS7jj z{>v!a(yiB*JJW((uQ=JVX0$h(&Tf}DrAwgYndJV5m-p+-rL!M?nV#VoSi|M@VZ6nS zy>5P%Z6yjn^B0Dd?fwx$gU*ASo!8$8ocJfZp1g03cvp>SdMqQ^Cpsswf*|6J&fh*R zy&I{3aYL{^%h+5)^;YbjZEF$qMJQTo#hfpzkNzxI4d`%|Z$vRQ%<;8-@Aivor3s+p zZnW`ET1jTn>pg3~7O)#MrfI%d*vx-um48gnMZ!He<|E&^6be)mHVbDUp))|?8 z?sZLgvUVqISge>ua<@>Ld@^6XWEf|tNmi{sI`LiNb+8y&Y;f~m|8v2z<=kuqTvbvl z8l_I37|73$oJ*J!lDU!0Jnns17%+869|(r7Og?#FjzM>ovH32`4dOkanK>Bp^!P_j zjU|!&er{Ph%o(rC{u;>5g(WgLD*`Xqh`X}D$C^JlOz$hV<_%D*l7!na8>wjIy?qS+ z9xHXHu2n(&Q-T7aA+b=#e|rRprpGWRzt+K_8&ZS!bzBi7iF|&L%Kd|&?RwI-uB@^( z-n}DF0Tf0QA-VV=fuVi;uzr7c5yU6-yfI~cy9(C$y7FHNdjwq5%D~yvnchi^@2Kxk zhN`iwT62~UaFI|t)7LX@II6`JbyMaiT_pT?*4}?y@#l}iZoaa`IZstke z+&e9@vSmW2>wZ+}QRX~qUrKQg;A$9g%b5^r1y@#0Y~6YB6nd+sCU42S!w2fu@^?V4 zXS;du${hAT9c8S_xibjTGi*Bxj3-v~x@$l||{2gzG3_GHIN{r;rV z_UF;E?Za9psJjq7lgXd~#1`Z8i>IbMc{sGuca}eiUEPu>2%+$)*T1Ik-1qytvFIFL z9lEt$RN}C1rB4hRR&&(48#=MBCCw2rGMB1f4XAlM2NT0Yx=AG#brWy3T}qjy2`(?G zH@el7ALE-c06B&wpsfWcu6$R6nCUTYnjyQgdw`+#?7Vqo*qMS}YA4Y%c?4@ZVC39f zM_f`a+~2=5P`}ES9U#NQVOuM^qy11T(ezJpFq1h?^?7WbneWyuelTY%r4wAQ`zOGx zsR#H&ahuzq)M@=d)>ldQ+RrdB_kA5x1S9^k%IDL^K*2qgqgqblXLLiLuH^?DNv5)6 zGH#oq6W_+nZU4`-zXOY75|%SYc;^~Po&D6VYo%3a=%eAjpqJ-qY*SS9QVIf*Ty^{h zA7=)X%|r^JBh}bb!t#ip#qrOLt_{4UN>fZSACp@U;i$2$*hcQPO2D=9?v=K1M;=vGWJDxO>Z6Wt zWA`G#++~-okwc{GCa3hfQ2tG)67gSPAe{~-A89FwGpIN9f_K)YB!`NN7nkY3)o&$7 z%$G|6htnC zWmio0@~-4-aZIEuG7D;A*2OpaaD1tzuq2o*_+IH^p3H%xBJSwJMdJYl9^EOQy2CdG zH{4Lbp57~2$R9I&`JHKgI!ngdnuYNjm0BaTy|@yi2Z_FN31E`&8Qg8H=14#YxR&;j zv0+&NY&6m@9N(Qg%wX)rE$v4TH+yvSm=D(t@u4Ja=QCF!#ACc)x;H{l^R|>ZviA12 zH5}|g)Ud!GIvrm|Ah)aDt+?3aQehJZvlXaZ0pV^xVs;k)ua|MAkU9f!8QW>dEV9f+ zHJq$E789ME2$nzYAdgGx+cGlMq<$ifkU*nL`=kO!5REFTI5oBj%!eXt+m1Sb>d8-2 z$lwN+s?TdnzD)LHL8XkQS$$_L6^vGe0^B*m4}PdE9X_yJXOt~8>xaEZ1*PxY$GdjU-U0Y?0e70Bg|i}D!l zeJ$&L=D;(0q@_n|Mh;325ni#!1ObbMniV({czpCqLU$s>-_oHXxtBmh0YnWCJi7|8 znmdWwZUaV3mT$-r1Y@WYgy$#Ru!@}+fzC_1Dj1^gCYm&g1|_N3G6la7j7enOOk-_9 z%t*Tf%LMMDfxR9Z-J{SW#!9!~KP8o=@kGE3*DpW8;L|hZFXcZlNL&NON1o*a;dU=&=YhCXc zbyJc?OKV1;@fmH}H*IO_yV*Z|x-fI)SLZ^yJ7fxlb6}6M+??bPlOEKjKdzjOOnwMX zZ%G0v_DU(b1cBo}Svb?mMkKiFE5sj^Z1(Bo=i94+oTI;yPcxAYof` z@yM(SZtRGNIRlv%#fM}^?O*n`J6ppT(snS&ozGWvH84Dlk^56`CqEmlAF{H+m5Oys zEdSZ*YyN29*t4q!H)U8!N2(M3>s;UjkE%NKjsF&^oZEk*IC2m$uDOkIYZtes4h1G@ zE~>une~!`@XrKxaLw~G5IwCvA6I;(nEM7Bi?+`ws$LoR!fBFWllhr!mzIE@nK%~1a zMv_?PY$AeHSHWvrC(%nCru8$4JafU&=!NOpWp>!cm8BeWcC7eG;GePqtDYZ>mUB0QmwN z^fkTLI1IY(yeQ)_@W&6FCG+VN`4~I9*|!t(R!h=L^0lXJ(nyAl=0kb+$M1T^WIb&_ zU9H5B-^GWN@aYY+>@`;6#=*7ot||S8t~VYRAOY1POqBcsofcLi6ew`c{qqtx`zlKJ zuSh2s1}*MEv6#YMOjbEfsN+&@XNwFmPwV0F$3m^PG0*~wRyN07S<9!t{z!Y9KQs^S zNsD48CZ_eliIf~tFJ%L3ZfrdB68U@`AE|M_-a9rMPgP<3N3L1)Noc)=yAFWdS?`cyRrb?pUvAp0Dlbr7b)HSpI_p6y#5pD?bO5?Z6YZ{fxQ^} z5o)Jw+AvSqE;q4RgIplB`T-Hn>gIvqPMTsRF@gc``X{N{!*nYIRE%skgKocdni5e0 z(-jm1xwn4Te|dRAt8`nkI`CR{@=Q;ptszK60L8fBhQ-51YhmA3C6!h>VG?gm$SBpg z4aK6Lcms){qIR=jw%y!MZl597v>S$ZR48HMMmX9ARak>-uE@@ zA$|5!H}Lh=A0$Jhd`E1&yK>15b# zztSQSRc7VmgtfKu=lO3fn#*;rpU!po6=Hs4j`(h6V%eS3Wq@>$Cfou{sFe~px zFS10Egp?bb=xXz&lz40PPJr>A+~P0|2(fxeNzflXx;<7BOu|uONF5%D2{&Q!~aTZwX0QnR~Bqx}y)wnGh z@g)uXL&v{Qj3o^F$9}bJzIo;m=RO}(!N-sP&MPV_U&QqPS_9^CR3bi)c&-Ve6^$C% zLw@f}6pD%r{*1W=o+OhdoE}F^<_eph z4Azhxk&v`tgu@1r5)N8l%Lw1dv>g;Xq`hi+dM%%&!&k`?_5b;D;LaYdRc3~uf&N%; zfH{lrA#=szP+j%&_*tIA*CLcfUAJI{R zKTVli&)mP|7S0@M+1kc>IkbwJq(qyLVnA&SOsm z7%cYFO_1arC%>yuzrvop%1`3ut{h|!F0-Pi$>saDcc|R0w8Y-rx^!t92uH)B1&~EVP@aak%uf=6 z_|ZsL$Amt=vg1nVFo+FlU+*z2miF)8TXPblDL`#|rPA>ig`f8AhXF9))_Gt%|Lm@Rk%Nux_t&pq#n1Uw{=EZX z91H4H^o?~qkIi5VX(@1M-$qUI<0McQl=XFRxub{k`)HyHVEy}p729tjj+$x_eyVR% zg9n*73>%P|+wW~ed8!=S)xe3D1;NHC!NbdyxqK!-N=p0 zZ+t75*!^yghts^wRflkoA^VSHV=e^ESl=FfmX?=zrzpZI4w_LhRg@8!{_&o)nZEt( z;DJgg6Fm3oT5hUbcl}afb83N$*^BsX7+xF%$`n-`yd@T=$(HYJ;G9AQt+cQk?u{7I zvfT~difn~riDPc-qR?vjMKdi$S5u2vGRs(o&(AYAw0`T*SkNz?ENPv3`=!{{s%9=c zcl_j;?J=w8eDpNQhkDa-^Y(iF^!UtZ4PRD`1uLqhU?Dh)`6cF|z3$lfJ2w(>b5rw> zW772WW;kS1=JY=-#OnE~yQlL?#}>u!6&>n`f7BxjV}{9*7`+SXw?6%!7l6q13c|5e zxO1>bfOzto!UkI(t3ReNI$DY)wE9EFgoZy$M^sI;lW=$%z)$u^k%J?HXAYfO=JsJW zp_tWB`~!{e)6Dz924<3Iyb@$K*b#J@gX;%6{sL5QI+)TiVM%R~g+16n*c2n)u3cXK7PTal1NF;q^$wI-pB^=8Kk(3F^IKY`o9VLu zK{#)Ve7Tt8G4D>(QsSSu$)Cg?b0(Uu4avKmzcs8rc>x-0Y)6rgEDk#m!$2VZ3q%w# zUl~yUwdAz@h(ds46}R@VS7!hooBMsW78_}XZsq(uVZ``1IEcbH^;~5jJ+=`&8#xE9W+3Ndd9lfFM6*n`X4DF_nq!jJe5+bR4sKI@k@J(5#ToFoKs;LwOrD zLziix0-e45Ek;0oA*GKis^cO6k940BnK&!!M9uxduwo3y`YE!DjSC&1@qmf-z4&c6 zg)nP(*V<&WSAWk*hry2OYSx@@qZQ9%4_})$h(NieP_hV5i_S9Jt=CB!kBNUk0z3KZ z4Y>oX%Nh2{ETr;^A~+|+O`n}~!MHAsMJ|9yyCI80O;Xy=tVp4}p0gl`li&=J#KnW3 z6-b8IE6YE1Ta9qu;jOs(wd5F?MCO}z{XGpJ-7WT5F?_eFr+Ts<#E6#SFKDa=P9}{G zE85I7Ifw)|5>CS4%JoR$3^-}+o7ym>iLk9H&vk|egb8-=l92tDz z2lCDGGUIhXC=Ly7YnZFw@c(oyW=~1lUlS&N*}dAM*H+n7Iv2hpl^n^nbkjmotFHN$ zP=Z1chA9q>z<&C%>(xWt!z~s4!Haa?UBCPr6x=fM*xLOVtCf((BvP(K%~oNs2wc~# zxi3wOm6UdDLla|XjC*rC+`QxUM1p>3-IgxLL+&5E5^HYLdsxSRxb)B3QC~0Jp7umG zeDbfmuS#9U5psVE@VLL+AXVAgNOi!9jx#8SZd<;wef#~XDHA?$fh96FB0^_+PDPLN zGn{assgQ;`zKJop9_nYaPjpQD+}!+|5xNI1gqFC0|1g}Wzq_<(WXsVAB=VPXwdf|- z7lfO0P)ZxupdGr--c&<$!|f~*)fc#iJ7bzF*(BYWXhp(e2O`tzI`yM?q9Z_IFeq8Q zAjGTvBqH$oH=AkZYQyJ)jOCe1HlF_E{uSH0qal(Ru9Qr|mjC9fd~V+61nETOVctKQ zfLc_-$>7%3^a0jGcP`HMKLK`Q%&o+r1B<-fKz`CMWA8-gguHrOyjQG##nZlC=< z&$+0asBm;C1~y_yvi>n0L4NTuR*wZNgUvE=bjlhjn~`~mP7#}<#%EF#t&Un2xjr?U zZ}uinEm=3FB{2a|t9@s<27N!Xo19%ph)GCLU%1Q`2u}+XEzd#W4(Vd@DrCwdo>XgdS#%oks;&8-tH3&WramA zaO)l^lg17s<;@{L*b`tHeDTp}bfjhc+b~vp83}b)o6YYSmX@?SjQMW}{CyU;lCMyX_K1s1dIB%Z) zDPD-gvhHD+AkuoeX$Qm0FD0{Q-S<*z&dKHm?YFzEk`n)WQH3%XGur3{za|N0gf z5Xs2gg$dS-sSpo$dFNKw#j5k`Y`vZlK+N?-=dZ{%Y+wX#^h@He81~OX z%tz7v!A950P+t@+BeHY!SmivP8GV&NC3+EZ@;Qx8#_epx-z;=cB;+G>o^GFthyut{=q(X&#FsAqCl!(p~L8Sg7!CF=Mt&JmU9WfX8H`p3g3-$19rv)>*!kIv0dyZoSjx#$Mlf_{k z1ioc9(F??yQx=KQQ&e-}aX;<)fLUhMK3!ov*pU&NUYDE}HAMxg8l5wpNnpqi(kwj7 z$R@DW^?e&ZnUMpz10Z)CSn`}xnU`$21#LT>=QmJ>{W5+{|MssK2j$nG0^PCDV7wHZ zzt=`8;=uNzL*}AOke-GmW0_j?8e;r!|9CQu7y*8MuRr_O4XwIohxC`gXW4^Sw`6@% zVbDG$bp1Q)`qc#+OJJ1IYT)P1fAX(`r~#jnBG-~x-TP}W{(AkdHu=}$n2CL3Jg7l8Py2^$W~39kyq7%B;sHn`ej12GNwI=? z_x$FDF?|LvN9GEdn4*b90N%hC<<6RKh%QXb=1}KV;1^hp#4T&gpPS(-!b3}m)X4|? zbz?y7MDf!HknItpg$BN?93vc{v%*-qhydTaKX9-JDwqEo-K~T0Ba=Y?1e4O4@bhyB z5EDM+;BjY$1W$>(u`$52mG~qLI?dhXO$UmUa)_&3&vK_%%lr!Q?lT6n*XkdJ>X z`eyFtW21IOy~mW8CpIoCo5f8*ZcYg6Pb}cnL_Su$7f!1dyNQ5+8jBu)E@)`%d7DaL z%pz980G#iz%8@X{>hl%)V!r4&WPo*|h%Jt7}5qBr^QdO#T2{IDwM`sFxc@=2eEhV{+LHv%CO%iv%aZBs;%;7$ zcpYlWQTDKFI4k(i0Oe4gyw9>e8Jd(O^s?RGp^e~TK!_y3bNTIOq^FNgIs1@3*_0uV zGyY)d>9C?Y8eH`)EGkug2s-~{CoBMo|NOMDk z0*aYyTa^6k_4T^u=I=dxndj9=ID!NYbEG~QEv)wrC21N?OFW3D5g`zLmM@F3U>^{V zCR{bu1cPFjHO8SXVU1;P*CRd+mGUj~Q6oZt^i}?g=Fs9pq~>9jAx2$EU<4VWO5rRv z-$fzmByt#@9ls0&p&y}{giIna4=7?zhKU;{nVn!uNQVT;m6F;o?%Rzwdvoas@6 z2=kt@@atPe7=+&3`|2$01>}I07O5=Kwb=?^0#ea_!6UF!{$AE3M2Xc{A-N()3Lq|?=smrQ8?FAVLpnjfry3#Q5bn36vdEOZeu5eSbP z0s2mcuNkq31t=OVKgp@>IsdC#J|&#JqM>mMVrcsrHWZ8Z!!xoz#p_Z6BFZtDr--|K zQgDX}%YFm&W4IGOJ^3#8Wj|h>bN+OlPdziE0)TV_dvVtEw9(uwHZ`!|&2-#>TpX#q z&zs1#Hf4Lf>EXBN>h>=)WKYbVr!%Z?P3ea=d6HD3`&drA;rP~AW$Nu{AZg z2D9D@I;)eIVVqVZzPja4fL4y1#U|@4#W6zVErY>H5OENW??2zUY$=&`v@MPG1kcq0}2hVw1@$0!F`)1;Sv!q zFJo0R(Vs?u6^9b}aWMc$W?bp&ZZR^oi~u*g6)?Q9`D)w!X#+))$2ex#Ilz8GhOwK` z5PGh*L8wvwseQeA_h8Qm>CYInw3bR(TC+K@}MP`m~c^y@~ESoZfj&Jk6)u zX|+($lAu}T;f$^b`WnWZG4bbxrYLIxC=_}@$B2Z+HtP_1(D=H<-l)^YQXv9G>U&77 zeM1--ob7=*Zd5#j3Q?V2&9M zX`$-BF2DkdhE_hZKPPmoZ&82PVf0A}FYcW(xd5t}iwrDRSk0AXDj?Jv{xbRU*p&%d zc$n^Ls-qk#p8aizn7uFU;pwSgD4fCF__x&^7y)a7U%VG@o~|lxF|c|j;&{EZ>Ykw3 zvHM{^=lo#eKO#q);fP(r16^+}gRFWb-Ps!_&a0N{zt8;I zO#lVK0bjAaz)&pdn@MZ2IV%`}j~qG@%~AyqhfIvML#@7$QO$-4)^e^q+7FJd*7L3) z7~xt(Ce5<5-FOJm!R)5U)dB{H`%{wA-%z;kAZ~|-n8b22 z3Xz=!=1`<;vFouLhBtd|4@L|BWW*I8XC_h-e);tBCH%Xop`l?(e(jZTPe^DmwfjBW zSkVktF)T*j?bO?<8rS#p!RWlLOn!R^#QN7N-hwQTq!6!x69-0Q9)%q-0i?m;g`uvc zxYK@U>E-DKm8glI3Q-f1CNFmUr1A7}%s_-TK~JZcF|oGcz$`ftVH!dYi8OWy-n_d65BhuI zu)UJbqNN_gCw<^7=4n|QJK_H3mAWq(mtRxKeLr2n^SAm-jYmRbjC;(eEIXRS3#U`f zHot&v7$;-b1>6krJ?PGeq~Ay8Si~zlx$bOtY+yFFThBF(z?UX&#N@T5q~x$SvxN+z zDEdF@0S(P&(yR_LjmU%s`Vdd67*Ti z3a6S_lna`Ff$eN;+VlW8_mqV8cjL}Vwp6kk41(o8DtgogUMpq`{EQKk)SdFrkD|D3 z-%SC7B>%xFK19&h+r6x!)R0jJHv)R-Ld$J1(^!y1fQz5s!2v!q!i-F4b?3Tb{ou~m zI_vLSjaieYWZ6(%<=`%|6s%Ey`EQloyObZ-4=%F7gQs-G{?X_e%+PV$J)T0H6}5TK zA-tkx-Eru!2>k(G2BeM}8WDNYyOgnsCUq$6%>AfQ(OPyaMolZ8goK25QzelUdmncO zfI(x;-A4aLq>M-J{8-<7pw+QKHeiaj1j98`??B!5d%8!N4*OQ=U$Ukr>z}U?&Ro;T zIyIF5SE_&D;@U+T*?=oYE&5xnvX5Lf3O>b(+E~6(A!{96XX=&CRfMS)8%P#Lk1!xr z7%PiS{BrB+TF3gb$6SvB&c_{bFbFovR~qge z0$>eIW*fcwoQZKRYzk*o0HxcA0R;#6q4gJu49+G(TO(z90cdm})>)fAioi8lWDLCR zodA;hkcsn22yDZhra)G!Wcr{T{>fkTn2 zPuJA`>wV*oyMk@@CBeKT!UZr6&k+H0hng7elJ)%KmNTr;drFKGO0HAJ3JNDj#SZ%| zIsM{n4T6x8*1dIeOq(@;S*6)v`~^73TFSzS4qV=^#T|=dAnjS5J{{5EJ|l}`tO{dd zwV*WMw;w!oQb-3@r8-yM#InbH#VtIxDqSo-Yt33~{LbarRy5zg8Xs2Uk@16Er~I#u zM&rbZ8whJ7p2?Lr{lYIp%<`{IeU=Bg2RFGL(OwrHh;BK)1FtNZ+3Lna(A2Bh4LPoi zshc51Q9BGEk%|0a(ICqsW_9y-wG7au7U({^j1Zor%M=5aLqQmW$9Ous0u!A9onSUW zrb&O_q>E&Q7$pYvKVsuW#nrmfIQ0%mp2Q72uAv|w^nql*=n4vprJW;@{3{( zF*OEE0hA;{zfg*SDIaxXf#Bg`p2q!G4oO)_U0mF%M@3#jw0-|3XmHfu#mH^!2wdAh z8uIzx+Ick`zoug>O>Dn-dJ%I~Qd5E=L8*vJ`o2LtFc=5`*L9T9Y`uf`Ws>Y$RAs@v zr$UBW2!@4C9~$vxq<_w!c2GcFTqj39V7O-|QwPRC$LFpo| zz;p4GJ#&F_>49}Ljm-cN%IBFFj~wKX$AA{K`UB8GX$AgE9ac}09R*c72>@EN_5D3x zpqLx1+0Wz0?vVxj+|Z?}MJvmi4{`_uUeEV$Cxu{(=nv0qhQp$SH<{yq!gj)`HkWC7 zRvw^zxkB4^cmK#Az21ngXB1k$ZlW43FhpDz%g$b$oU#a6zi#*#KPY>|q9>Ur1r%pQ z)`W^CB(c>x(8clOInic}<~yN7-ngtiSl{?Y^e;n}7$}ha8Za#EaZre{UM_Q5Pb^+Q zk7R80#5}bfVYxB? zw#~RB62+(~gNm#_u89(@LOVFHY;E!Pg*-mJtqmhNZYOQf`C7o6_k7uF=FptNAnU|= zC{rL`TxV0}z~gVS_r^fz;LE${VHX9MP%AL?&5Y@Yfe}VJ+nJHs33~LG39I_$!65+q z8}to_Yx)k>dK&h)-GyP(G5(jFw}6o0`W+;-LVJ=7Ma(T`v?w-|(Mo=wu(t@|vasOG z>jV>Ej*cyLV<|~6XW}FsJ zSM+)KAt%=y3~Hs)dd+*Xx3}^S(GA|+gldyblJ+Na#ta%d)37@G{%)WYxeKqy9yjcZ zpSbq#hi7$&{>|0**k6RS-RCca&8^OT48t^e|LsOY!`^=vAfFQW97H3yFPbMUyS-58 zave~&x1q#GRf}WHfQwaQ7B?i3?0@qkjlgYV!8Q_R7;5C*fR|vuqdD~fl?@`JiDyO& z6?Vl33=(KMhb7uA9huh|cf4An|1Ms{fV?*)3O&TlPRAXeG~~;6MN76jabN#dEX!Je zg!n>UjzllZ3BU-r-dU;r@c14${r)o{pRZxn!m@?e1%;0aS6X^zx1z06dX$@|En}<{ zEs6g;i=%eIvJJjAI0dOQH=Wy^`|NJlsG258_9i|KL4C;zEFuhmvH_$D;Ub_NRMV)a zz{N>y9V-Jz{*rR~49?r%I9uWZYHvxxf7+`tZ+FqbXNyD*Oxm5oU`!b8tb&q@u%SE9$jjZ|3T@{a+Vc#mTU`*ojpAxT2U z&r-y_m~wO?9rrCWE(P(ni%25v@!mhokRO^(FaM5&=!9h1fLm*N$V2ab=mnSG{ck#S z-v@Kv?F??Ua8`bV;%T{E^$RnpX{bL^QfswRy`$(Lg%X-nhwp+fpY#H99ixB}fYT&| zOlkjgW9Q)+YFhJBf9moM+;)#!!yh%G9JRTnY=yoVp6$6~P2$VhT__=TH6~9xt6sKB zMOVGH0;f!yOxIrKoIl?iUHZivQtSyTH2#oIJKSrCy^u9w?S^z&*FVPXg}-t;4$vRu z$i(9XNN~QNrdN#t?081O(cVY&Q}5dOK~FG^)^DTD)b@fw_PjhE`)Q8CRPHW4_<0R z(0#OjXxP;N`vXzZI`{jMfI1nRCa>IKaMSe6H)B3pp56@hURQ`2c?R8uh-Phc7rpAMWjI3=+b7ixbt#utm#zP(URuiOy*=Tr;OrM3XhvNzx z;e+rlJUagK`{g8dtEYta8UAqUwO?hLy+8mz4nJ{tT?vA`+dm5)udJoR(!YzRO;${4 zp*SJ_9U|s{WnUf@RoU*k+Bu6c}B$uYQ$P}$y5cXkh6CLcR=vH(Uvh+_#TS@Pf=Qz z7aE7OZ}L$Gm=f`DW~VUbr2nFj(9$m@v+h0k#KNVZ#>ko|jHQKuOI0y~9iD?=HMLVY z?>)8bn8o+soQvnYM14i>fxDmIs$NV52+?e5;j6L~4UL-L4(gf+7(E)@;{qk_#PG;g zJoh$@V$)CeICCWmBGMN?QfPMAPY(jR33u>hnC}AKeBPcC^PZ^UE*<{=&jsjG)?#2> zt2?%p1(e>u-dJGE$g=RQXBs~nnHDS*OGk^zd#-PGH?d%%zCH2L?128L&BSG#aljFd z>y90)T&lA~i;fPQzn{}OQQ=!Fulw;niWflltTBW2fS)aiA3K$@4v9-Sgw#16zg|Sd zZ9+3kCp7lrZtxZep`=yQbR*ElMar419~q(Fn4=dx1QzH&@xSrAgdDZf!E< zA?A`G%HFw~HPLg)&jL(siY1-r&`nC2N&A=2cQXVlUe7}XBP_1GyilC zgsDxtx(_rGAiP)Nxa`knrF*t91|vMg4ahMM@Tn0gR$~g5J-1O+_@FuLVR#xO3oquY zpd{PzZY<5P(<&&CCn}ln3;(CCh!9LPYiS6ktF#Og6U^F>r`IHKy=Kg@xJk2AQ zClh|W^Q;0mt4Dc}EV7*nNAG5SWCJ)Ig^~1^Oliw&HSAM^56mSvvi~Z{)qE-^8^rY7 zCCLkQT@h1Mr31OceYw!sGSz^*{bRy*5XXM7(os069oaAN+sKs?CtA^e(9rj9>q0-6 zkSGjM*k#f?Z`Zdoc|6b#m{Xf7!uCoXx8Hy5HLT5VFZ7MqGCPga3x^AjtR2w2{`w$) z-emdjWu^WcF6TU&25Th+$gX(oCnP*8G_W#$wnQG9SsFV;fLZgHq=n7;seTxgnU$B8 z*3%*QqV@GFDydzvRgnw`J}UqaycRlb4yQ}?#}lw*a*<@tA!-v% zhCtB|%@IzG=gX|H$;_CDc-{RLIdZWFH+5@xp8D1@UI>n@HYqM-`%;;xqhaJUQg2ga zzZ!6x=1v{sD;J$f7u3LIqxVE2EdMPCEc8XM{1feMbkG{ouCOCu*H2R1?*L$LaUirN z5tMh^BOJYH9ZQD7a~ZkGn`7S1$cpxbvF zEo5RNW6T684Y{5st2}lCklZ20r@$UU!oRBgv70-8{sg4K13)g3DfShEwFt<~#?DUP zRxM8p4Y;T^h%pS;sT5MSm)BQE+y1Sp_x`SCCz+XVm|`Dj8q-di+!Cjd)X=!yu&tVF zcCFl?G&C4(^Lo6+!{&T5r=Dw?%rBoCMB9kn`9nI~mE&@nKaPtq+?hI|K8-f8q0@mf zFzG9E&kxPi7V)$$EZw+dTYv~!0F{2*db?Lx#`M6Wq#UtU(k;(FYjXJ)xy#{|PQ}f+ z_qf}t$SqB|uN;%0L+Crn?sJ$|yzc+5{g)$zlOy_zjns>i&o@mVplA-M{tdjO~l~l!xkf%_qTfU$CV?i(|C=0(Hqi6XMPU% zY-7glmA>ubGGd}M`QVWKW*GPFY>I>#ypsSMDjvxP?Qs0?d7f+q9~D&N+cgFhVf6l} zI1T52?o-@*pF%}FjXe3BDyyq4`aRq6;e~!-%xp;(jG7k#Iw!%jC@szklh?ml)qHj= zH2b>m5G(t~&O=nF^yn5sq}AhGq*%D?7+4$TONmyyre^@NQ_Y_^0lY@a^UU|EMd6*7 zM@nTk_j4T0tH-Gkhn5V%PU=z9I1L>-_H0Qfnp@Z9W_FEg?pEN@Dv^pHZkJWp+uw0A zTJshpH3TpSzTKrBBEqHrZn{uor{ZG946g1WPaQBibv!#0({4zO9{Y0_fLQJOvc4(p)Idq&LFg=+!#Kjdz`vAmV+%mNto~mA;fNsX64wuQO+d^@!BVX$s>bfsMy)! z0{rSo3+-)f8D5t;S`fq46*}txLTtBOLwm&&g64_QsmZ~!i7Y40*kc&yB65KZ-!b}8 z=6UHd68Vj1!Bf<-ee{Bldj=8CDm=uUVx;nxaov+Dr%pq76urdKbq#(n?Tj_dq& zz$0&}r8S825Xol6XaUqeCZTSW2DwaS!^3jzO|Z; z>eyU`#t`1;*(zfhyksoCjR~I+-;43xR4NO*!_OYu3Be1=xYj3o91QybDI%2XvoXY| zRWa=QqUsWSy@yz&)ISKrkmjm6yxT2;<8-5V&Ht`YxCCt3x4cj<4Gc9(qBQ61I1UHZ zm1Q(|9b*8UPRrl2kxEvG7}cAzS@#02@Z<~_eC{%XMvaoI)%|^xF7AQxd{3nz<1LgP zFeoIdc9;}=M9EaD#U-2ajyqc1&3LXYl4EkW4z)8d+O{91_sD9Xs4^K%zML+Q58hoX zKy-;*;!9_$EFJ6H$_AOtJ$No(y0$9Naxf!P4Uk}5JPpu}M;GEk84#EH!C){u7B{jV zErMDTR~U>?Hb8NGY=zB&W3(za6sVB6X>I){!WbhNYKYUs{@0=D80)yvJ#w|mxjWUt zQPQo1-Z4$Y#(>HT?&*d>U7eWMIiD9R{8+6b7egPI8roEKZ6{TvaywF6m=zK~u8URo zY@3&jIAe)eNLP*e^))SRv}W8LSdXG#=P!>-tEddWa2n)!z_F-KP1ueC@IQAiy=9-JIvU#>Cb9Xbh+n|LK zm>B}l{Kz3^TZw}sVw}OmUh{~}EKYidXH5&!UsykvY8mP6-&SZHUC2tuiL(9CZoZ~N zIHcwMZLL%PoR6DQmR?_8m9%Pq?$5~={gtMMW0;!Uh8DL*f)Q`Ab=fXPu_tL1NRdj8 z3N-8qv4r1344XZMLHKL0qiJaNGL^TT;kJz~gR+1fp!#}p5V<2nHPK|u?79n5&@#GQ z+_fvtX95}($V;JHhs3*y#6@c{xpp3zTZ+; zYNZuBtXfM;z*7uSbaIMWUR~L{C`IQYu2WKEukG8e(O`}rjL5B7#39C;l>G>$E;I6A zb*oo;t|T_|aAhU*LgiJr=-(2UZChIp)^0cgPnVmrHK@KJBSw)rh#UI?LALBvTfV;vLhAo zm3yu877-$zo`~18Wr^!S{^hUPy595d%habYO3JyyN#Z_le8c7|nTwe)#Bt7rdwS0X z-Yo_Sjc*mfVDNF<{6HJ5pyEJrf99$ zjPmkJGQ0=yxakYG;P^KfXOVz#Cxgx1+s-M|uQhqV{<|u$_k|#XiKt=#Y+Q+TU7Hxo zv1mGs)Gd7KB%7`I1j z9UI+TuAIG~ct|n90wlbyKD;VFnf6UWZeP)4SGZ@cov)R?rUTA+hlbAeyc%kr2>lgG<=1qSizn5LZ=!G7dCv~OV-7B2UiLLo5F_D$1t zIvz6O7H4^WV~8l7i&r9MimQ_AmuTsFp_08{dzFh;^;Qd&ot}zVewE0tnq5G;15Wuz zFF+gI_I#afQ9tYFFIt6z$!JwbZGElH9{IUHuYS$__=^QUQ|lNK6=kp*j994uiEH;%3hHNd$d=NCcrmjzYzUIC{IlZ z;_m|z!_Cb2Eb{(Tx$IW&9Swz5KP)9LW~O21pM6-6grI%oKri!DEG;cE(bbvs^)ybt3H4V(AHUoT_7{S;~r~G-VjIgC|7Ipw}Eo zpbz0nEB|)7wJ~Mx^4AIf7>EVUFB|ENuT~=uB_k+KeDf(q@E>|VW0Cc)ZmXsh9nnIg zBXbk@tj`1I2;!OT}2P&e+=@zm;9pGe~JgdU0a+GC@rxKn(ls&dv zO`WNnDk3K8J23e(M8lpCNWZ7N%QmGlB_MhmxJcB_*MrgW-Ot|K8!`2rB7L%!v~Ksz zCvuC-pcQRAPKS~7FDPs*ua`R*fUb)Cq66&7?R><5mfGwYK$(n(_`^l%+@UB8pE+f; z_8Pa$D2}J-mqtu_7eT@2V7zyE$ucnmz=@jI(JQ3AuYHSqQ&DklS}?AY&HG70qq4!e zZQbv^L>pBKuoJz)a^m0=rh?`#{EWKox~b}4wF^0ar2oVO#KRh9;aP@92+hIYtC>^$~*e(bq)h&{k+{&g!K{9V)X$~OgW*Nk}_TW zLj#yMYd3sh2YxadiuO!^X`Rf+|pCOn$&H^232l98sAjhqlu2q~1&WXBz8d({uO z-77A{lZQ-gIq|$7FF0i0r^qW~wAG=W+qY|`-AOwg`FM*6?EqHB9t+a%o`|WDY#>W< zmvg-3Ri5Lco;$2lr%APX^8B=R{uE%9_FBT8?rJ`7^VrvJy)r`wzfR_w6WJV)#j!M~ zIzdf<>p317=MPRY<-=pr(h_WCW@h@CUlYsxy|kpwI#n1Uc;dJLge3}C{vC@()rOV; zvJ}hqm5%duqcXsq=Pk~>fvhy1mpXCVR&baG5XUm4+>|{0#0qQpjER3A zHoJqz)0!Oe3Kl#z*C5-s=auXx#VYrO6e#hjZd>Z& z>e;`@$VmKAJrW==@O95PI6iLfHK|FeXE%cn@7w@B%KNaNk~}Y(8iNE2AC8MM(@!MP zPDS-S9-nx+SNuhHcXfr~8Q|^&S}oVfxy%Ul3_4@r`nP$ikiT)-q;efW)aQ!~Y2EezEB@3G2`?7VLSI?^#aj4K zKY`xrKaLSq(YPr@TOy46)g5qT6DA~h-GDre9u0YWJ9fra-Ljykw^JG7hHCqD=6O&eKdc3m8h|E#4AE|h_k&Uyf;G5lV_#A_} zOIw=4xEb%Zq<%#;^_l$k9Ca7jmiYdljQ8!djwoG17WqO5i;wcl{a}xH0#IkORb?%Q_3XopZu*be-UTVBD z9<>ELGOyZyChcaI(=lORxNl)OK;2oN-Zx|6m5%Ph4RQlf0-uM-Z!t@oHnVD`?0>hy zw}M;Ls6EKW(7)se7EWDfO<=E^mX8^O@lqAC5}G7$DzyRxyP#2TyhLIdzOf z_L~8!4*yq_ui2Y-Z>|{tNzix76q0uYGJIaBzLhW}ts2lX#L~V)mHR&M)SUxO&6RNT zaa4^aC%1N@08dk)>67M0(2i2&IqUnQZWF!Zozd><1(6KX$g!^fwoVp{`omCh5N7II zk_~mbDA#$>nomK_7JZ!>Q2+h=rw2@SmU)e0!>cvpYYNT6!i-iap)hzIcssEy2 z-U~u5*1emL{7~!>yCU9IhLbb9BVi7W1@;1F`j@$hyI9GBUTDEqVv_7$#>;&M@9f%7 zY>ia|e(@LrzC7$0Wf*K%kQB65NQ* zQ1Pm7U~}Dz*weV|#jtWPfRiu#h@48x=FhC#)1fJbk#kW>1wyX%I&)lSb@GEZU~_58 z>T%MqS^P*Zwh2e{Tc8dHt0ihhoS*CuL~vqlh&B=1x@{(;j|u{E^Bm zg_E+Lo?hNHKZQ^Tafs;625Mvc_Bc%}k_e9y4~mq@C*lBvnYJIidsd$o%V!Y8SpZ%% zYM7YjcWrMAN!7x!S}4)IzHG$5nv09`?ftGt9F$0xKw-o9alo?p)FH$SuQ7E0S&KPW zqr=AZx1T>e^C+Txs)^3a%|}$7N-J{;S*3Yb>!~+|Ngwk`awJ<&?n%TWeD2t?J|T_) zSsjX%zMOwY*u(5e_a?By>3uCH9oC_zINqQdve(lIf$SgnL=*G=!6V;8LdcypRuUrar@>F?&rq9hWQZVD#qO}MQI4fseQik@4JLyCnL z;LWf4`?cZ<4i?vD~)b1)jor%dfyb0_@S&?%A}W=5r26I21d-* z_a0gpO00BL`)&)LStU_G2-s3+Rwbc4z%+V%H=NMBB1xrBA;_GsRAFmx&t9}vlUf67 zn6+TeRym+q^(Ql_!$oZRz^gif!dU|ZI|p+99z`vW zZZkEjY$?GVzy;PZbk?fwDejOdnc}S0Qv=Vo`oGtA(Txw;zWV^FD6#yq3$^rSkj6L= zsRYM1Ubzl+6&Hd=ZbL8{I?~_le%%9AMk`+?TqUnG?9W|SFVhT+n^9PIP#md*Owb~V zMk$T6DFbn$RQ~>OuR~WBYH;_Uo355YZ)3!$iD{J4lM&HyIlFrjh-d9(w?gi^b$-%$ zU&3~ErOB)_?A}|iAgu39x0_w#gB`7Pu5Yc_#e2czYHB-ue~ft_O}iGUcfFgpHSsK7 zF>h@!x3#ordPkuJT}?b}*Zqv={1-jj_0QLOM9YoT$f#L3xX_{db}db9f4%##Lrkj= z;gs-i83al{Y~axmf8UVNs}@}mT#~#tjHV+s3{-%7muF|1SyxxL^tS_ucNN8uR;NG~ zX84uwptA#fqtou~EFvY6>#1S;RXCCEnD6)XoJ;MuL(zJNZ4R@SI8xag=lGE|g1Khk z(hyBWxiO%$qo}(L=nCiS%W@#q6!cWP-HD9_Pk~&!6bs_NyR1K7u!`vcp)<+I(l%NCblE4cKz}xkkwsFavh;? zUic+Vzmul!yGGc(5_lyF7UXYm< zPOrv$eJx#@S63z`>eMN0B*)wFBS}SlEvO8KS}PO|Hom2a2_S1gw>NiSQ~cF=@+W*%-n?)stZM(xe`}GPtk}DIO2jV@ow%Cr`YNZ2-+!B73D8QLS7mOJg z4`HJb2w))fZaA>K6V|iw9e^WZJ|ddB8e8S+l?9ym)Gm=ljdTu+UjxGAtgQmdi7;&(xTRlT|`2Z;MSW zgm`e%Ailcf`>uZqf#Z7^=be+;*%Gu2Y9UC-_F+Lr{-cyEo%)*R)rFC3eG_B3aIfi? zVNb1{_D86Ju(M?jDhXcf(w7&DGt&j+TfrP5L)tt{PC6%NFV~xf{nim; zM;67FI?ObFt8!M+~B0}wQ_X2e1qxUkJ5O`%Q&IRX`B*U2g8pgQ6hyVl%Xz!h! zJfKFmW$+|*6gq+IUE7q}H~Im_Z>(V>G~CfHVrx>MQ(-$5oWiSLKQ9Rz-fx4CIDIHo zcPo|?W79sbzG>G~sK5yHRST6YShnyyn+*Cp`MKLqr&{9pR%* zGsTKx&+1aK#*U986^+dsEkncYmmJGaezY(E4x>CK`1#@6dj3~SWg0nxBMeIVUP4vp z_yn>d8XDyipP!g`@QgtaCkn;|ZDz5Htf!g`+;v0v6U~j*XY1vj`|2u);yYkI)MQgh z7&d+cEF^bXOXlRD6;d>Ti4BJ`K|um1t|JP>j?jsti&Cw_&BZ?0I2f%SFe;36q|S0FR~8JHNTJ|#8oZ~f3FlI)f$XnY2;{WxQ~ z3QWh5? zkGfESW--C z|H)(_{Yi+g?G{R(N9!Q@Jyx+kSm!3L4I2}HN>F>;ic}or{>^SI+3{3-r<47Ntpf+= zb*dH_c};O(7qWGW8x^~r#oBoTklYRC_dnwR+I7hRaqnG4>vj0NyqBA9%ejYI`BOJk zJ&I*6a{c-DUJ4}|X3fswG;|r#Bc%yg_%RGIs7TI0S6ST|gptiIY%e01bS_{;%7^KU z>Vp*9H9LN;TY#{ynD42~6d{9N-}%BZ0#PA%&7>kFNLU7(p6Q(b1sDT$B;=5 zuzF}|?)i!s74_$gS0wcVh@8$>1)+W%99#|_B!b=hGr)|en`e0W@=>uMT<0>uyt)bS zxPABOV8e&`QG>bd zTmN?zeWTwX@!MMKW@2D~CJbE%;1lzC5(NK*03^(o&q|Q`ZZ~F17^etJD>VwpfqX5X zS-41{SdDy%{6@s{Sdlj3OW=QSzWl8e=!)odO4z@<*cN-q@t^SZ`~rC*cL^~k<<29p zfoJ$-7Anh}CnBwtL=o=yLGo5H8g&=AU%jvD=5>$bJanRKvVq{!c9dW}^rD&ZiDM8Q zc>LJVa9y1jLr1naO-@?|2TW!R-%h|*A@%PU(EK!LZ zX7Wz}76K=>7C~Qu6!O7QYG$B+z{|?qT(ML_ao^$n@2M_>%Bg*=Tiws@3TFgdq$43j zQ+y!kFRNa=&_sZ{aHw!y)#qWd4F3(q_&|eNZkRORT=wT%26<)Nq`ixP0yB_%ECjOS zL$0YslgP59N*Q(N?)LXEtTL0DlE@G5rjc{reus9qnliUG(^TuMXz3`@dgyHQ`_E?J znexvD7@OikGo#knTWxYa$OoHB?MKxHml&n4+^+Lx7Y)4NEzefVIaZr>fscQ0szv27 zW%{9xnk)MAFJ!C#ksE5S{Ms+W{wUSu0pTy(kT%aoD6>q`7&Ixc5O+C1pB48ucXqpq zT7M*zO$;FlI3z{^u-nMRFoX-xFV+vfB?tV7OyPmO$;8{tM+%altF*h(OD1G+A;xPbT}ZvlwR=+Cg&Sc`3D5 zTEQZ<#M)PSzq)SxtWA?+_G$2^FLy?y3J2VnZ{q&zT1E#>`C4cFk?p#+wwCrcA;+=g zM$O`{sbf_r)CH4(}_k$2UI(QE=VfKPTo1u^j#0R-BgyD~FW( z?y=ss{<9c2+2AOz>VnrZU5aJX>jJ$0B!4R2axwWf+6oxQc{3o?HPAgUhmJb ziYxZ))7GNdiR3>pi?<)Y@+d;ed1b!~p{nODSYg1QRZTSl2r7^2-O8ZblMzqKR|v6Bua}Qm!0d` zbLV;?3+BwZ4h@SZ70w}kMSy2w&%&CiXhRgF_G(wlTd?~5`(9}QuU9}K{rlQfHY6~U zkP9V0868%eIiVygtJ4t}tcX(a)EY>GrVhPp3=7!`DeV|PC8cN2yh9wnaXA~a&S5vFgoheF(|O=N|_lSjU5TejXV zf>m(Az20w6!;2jn>#mu~;F~N(^z_UW7+8?-t#wOV!jNrs-nFX06&|w>f)o(@7|-%g zHnS@Ip6CdYnKc$R{X5l;n#bWr*mb^{r2h+}la=I#u7Pz)X-NupI4&`5(IvSfI8M#~ zC(3?}w)Hy(gb*of+jZ}h!0&&ls*p>B%YG6a`M>K?c@=)n%6gC%)q?b4XlKvf>c2i)g9XH>Bc5vV-?R|&Kreb064xOJ2YPm zs=OW{fNXzHx5^J7dvu=Iytf8yEldn9q|&$y7PT9qVoWoP7o9YpNM0NOaktxbxbQ$Cn?x`?Vqri6rZ2C{Z*7IoACd5}ptf=<^9)>h_DE4oyFbUjVf zxrj#r;eVL1?s*@$!qwP+SarL45ki>~d9_%Y74COz;Ha?(WYwDU=>d_DT}w`p`xOL9 z5>hJzNEz#2ZEmYYKe7|3nHT7u@XXzLa)umvQVwEu=P)|tMFYsIkqCfnN!pTy-{=@l z0zc?J`-E>olA9G94oMaJfW#~GD$t|663}@q)EUw&PJ~V~y6hGYb9|cPi&MOzxfN@Opbf@ozQ({xF=Fr#OW`t*TeLf2B+MyqJj?*+nwHep^~S8dzg(4SP~mx3FB!n7BP7&Zz&v@L4(s8ax|kgrBS74`nqAjfu@a6OZNxb2 zLTGyNIO4S+7d|C$c*2YVnoH>%pFhhMlTomm49YDw0D8@W%(Z|d;e3GhUA-4xMawBO zn?3T_ab$}-iZc1+0e<+`w8~O=o@Lq(YED9;jN#XU^Ci(dTQ}obot^b)Y;9|^Pgy5} zl(_H#3$lOG-UjX7(i;YPzLRk^m8$a-hUb_l6)exF?J9xWq;EW==g5aRh(KwDTJ!5vS9<8g(vW(R zt8R`FrFs(cXj#JuKwUnfKsDcohsUIfBB|1TMLvgVj5BnoR3iZ^*`T!nbzd*vJ&|*- zq>D?nFN>FyRegBWXO$HHL^>caJ5dP{5s_4E$?`ch8|xqbcZ%XpJ03x%AbRxO_fha? zE8LS=8?+4A?X^S*WOF&|4{DRHG||NGdT|+D0;Owp``WI{h)(>l8Zdww!@v;}!>D3< zk$IfORxLHv@eI^ku>HXgH!}N{1(dISLS6RS55ZraHiM_mft9#=;1t~Ypa&fK(Qkz% z4+&0A{?Bw|6t(8`Fay}G3Y{X{Fu+>5Q-@Y_$K_l}k}YukKuxv%$*j|ZaL1;dMe9fS zBjAO_QC1G~P3r~7ijC^!Mu&o$tcAMH&8axqHb=&UW0G*O3RaVFU@I|685QRSuE~Di zj?Sy6TD{yf25KY$To$y}GLn*8xfu@h0F5(x{~xw@|AAA%%={i$-^ z9ZtUPn4JVqLL8Z{{+4T)SX^l-=~|LAOGqS2|*BE zHyI%3^AA!WERqt_-R9N@!atpKD5OAcBkDUP>BMCwW_NddD$hHpVk{i=4X`sJ#gT0v zf29!;FmlRxFy+DHL?&tYDCKEaUuUj+vJ*haOrPa{uPI} zJHd%TNn$NroWsjp!cG(5(<5_ZJVDVf^hu+|JaVAVE+1n1W5j|L`fA_{z_(I>Vp`yvKk!NpGi!3;g4LZrO{{S8!xsw{2yH&u*L&gHe2IOAL?KSu>(HH&N|Gwp!n}9D;qJ zx9MyqghL9pnc-7E=*3TB6)5*0wfe*TO$0cA)NKB@Vbn@4kguf)zwblX6O`yi=~$%&RfH5G z9z(b1fJoN=T$Zcw$N`05LUMM9{b{wEx{f(?Ol80BKo(|HYP^o; zJf{5pqhy6^8vh_xzP*s6u9mO?%Bj>`q9@&z?unzsZ}FA`1nI}){WNJU@mWmHR`T)N z7^&7`!1aH*K$pHmFg9x3m#cLl(Ghc{$n8(nrT+B<3oFvZe1(m2h~Ra~idK_@6}!kp z8OzkruR=LoL&L4s?YAD|?@4{gWuXN`lCm^aoa>)I^NJ$j*!>LSDuP)~jrZ&ou2k4; z?X|GLfwk`*Aikdu;GwplZB(e;(y7Tmh_SY|j&-TaCB!s9cm9kbv=N}@;l3VBhy!?| z)ayn=kOz^Zn~cO+SQ^T=e5JLW*rxM4$^3g>8Bwdl?3{fTTV1vJ3w(;*wj8==Hk*Y*&X%L&B!SsQ|O ziRw)VgQ}xxjMldMc_FoF3ynuF!G=H`r^7@e4HKQg|4 zT>eH9D8ajZ;gZAjPhsS1GBzD$Z&c@%S)4_lpaN|?xwBCdLP!x*KeK`#htP7|Lh>4j zS-4?~3lu+fLAr7aYX)}|*l6|YdY`y1_$6P4?h^z0|9v0@&6zwfZ)LMGSC1wv6)%h! z*jLVe3xfsD$tv00?8~k?=oaA7&QlAY?41F$f#FYB7;D1 z6GEa)H?b2+j5Q!2=TPjJnEbMjsA(_JDe9u3ym7<_qI$Rlrcg!x_jZvYLpe{IG>1#RD z676}65b_1wCNrU>z|SKoJD(@bW12PR>Rs_MC&giLpTo_j&-2quo0I16 zhZ_LTNL#UV_hFq#ko!)69YCwZNWQbJ7d&cm2sn3?oNNcbV?;^wuWJ126CeyfWVR?v zz{Gy55schaEDFCFCtlxNG`hX$hrzwoXui-hISnIU(Lez+39~AFl4>*;NSjDpiqLaRC_VY-*tT4ejBN+?} z@na^9ugdM&awIOEzqJSKaIn%q4AzlA(kV68MNC`U+G@s<(=-)H_uP{!pv(EIY=MLn z7SdHk!HIcf-SV{XUB3hmSI_^XlN{T@TH>G0zfHOoSm}&q@#TPhs`*ottMst`<;kPj z6JjhHXjN_$y*umITv$(gZ?ev>)zbYA zz}K_`Nu@0hgm4Kl5C zSxXfuxOuhUZ@vx=++mXRF~ivQjsCgt6Aeg2Ss5GZZq;GD>F?`2AbKn=O-v2Ml#+HE+=PA>>r^f*jFQ_kr)n#g`Toad=N7#9(sT z`z*>r`Ge69?+>kpop3;myA-(@p0ftne+rzoKwW@ss_a0c*NWqk;ZzsXP^pZgfCT8f za{~Qp!xAcP*wcppJWyrVQ>r3pWIm1kVl|lIEENQPiF`Iqg1*Q10Wy3>Sv`~z4eR25 z9Sl3$tDjcb_CF~~$^a47Ls`V;<&CD2)KBAW!m-Wn#!ms5PDKM4!Ft8LgkNxj%<@44 z!GY)jG+R~LSw@l+j@B5e)9q3zTdbHW+dq0gdK=>`z#)teT4igZ_JFmhojOqTVxwWi z_SIBh<_<#nAjl2{&+`u6`#}@0);)BJwANc5^aahd_%|#K;2C=*=Umb70!`akeqyB) zcL5wj3XpW3-w~_l=_pO+b$ZPk@0V^{cO>F+h60Trh}i3 zWS_J{hR%a? zZE_ji87GuvFwn_vWh`rIi9b}*(=@^M9{R7@-N(T; z*bX6K1o4_ib@=W^KVApTD6vT4$&o4S))lO(v)fxQ6Kw4Abp`lU($z7*`mElM@L71`ZEX~Kdf#H`VZ;nd_QJpuP?uJb#5lv>)vVhDzw_0Pd#DUv+?55CqUQ) zWs71VaM95qe#xUv=Rz$B%3cypE=3g%S~|!U#e_oS3XJL)Rzd;Syo95+!nV?EHdasV z)Vbw;c*&5~cv|*$R5R=D-gy6QD9*`ovb30aoCPw=8)O%02FC=q%0`GX*ioIcd&34E z{O*U!#>P!n1_m36=%@wu6Q3Sr>kw=EhzoBA@8_IGXN^eLI=kO`Ok@JRe`9$xC;5WPhy@M7<%2M=Wq9g*2o) z&LGh=jxVIjU#)E7j)ic6n1G=scx*B$Mmc}MZ|%yhVMCvrd=nweapjX2s>lkZbomU# zx@xp!__`LOF|5u@(De-!hwz)lQD>RFmcE3KiC&g#AEKHNEuW=7ofVyil0cuP84nv_ zkA#Jzrwr61p6rb8dBQXQG zMlTLhk6vs8Qcd&zt3t>C(W6X}{)~=8gE0ap*XE#2(4f0l0W3gX$NH4iD1lJgM1~(i z=Yu@^#>Zycn0b}yHE|S8c&!+iP)47EXi37-W#t$mqqG{l%F8?kOncR4b~G zS=$(9;2$kGSp~PWRg;U1Kmw)h+fBhj#&q#Orcet)pz|!19Q2OFo2}Y7uDntz>5Mi+ zAs(E-7E1{AEMnlXTwt06KcS;~GzQBk>3@H7}Pd3-^?H6$%6QGPD1hZOZpuE=* zD4}9wlwj~CB;8H_a3Y^svSrRmz>iA0TsQi4Q3Ty^=tO!Y66H&IJrdR$fpyp;d*smM zhNc&sCrcYoqD+ha6H&Y;<}m!rDA4BOg=dZgJzX|fG#(CleV=>1eNyWF%{|&;$I8TI zsm-|Z^|(Dw<=p+{?}*vvXL;%~WNYlbrGY(;%=QG@e^{0?lu>^@mjykj>B*KhEol&aRMveTQ9+T#Zm{eu3b9oj&frtxB=`SYqe~T+adoXlQrD0Fz|GB# zo<#_JLkL)W_*A37sl$IX?bDta_Zj)<%(;If$_?C;rSH379f|*Mk(QjD9XulSaczt_1j8|@LYkOo22zQUe3F?1< z8uPwylTpFndqxC7TY3qxfY7|aQ-3Tu{G{jLZ5X~X4nmNQ6K!9^isaHE?8IK{BNF3+ zc&#^fHTiSmq@}>PeIHm#V9wO3AQMu`v9XCG|C)Zkv{gag1UeW3*wsJwv`Yop>W&$L z-sjcPm^OVN-jr4snyM4-1pWujqbonMM2n52(h(E3Xq1|MNOtH!I9rGL<}|4vDK|Sk zVwfT|l%ogKZZBKV8sQ1!rQgtdqF>2L^WVK$y9^elwO=_2B({Z-f?lhqfN{7-A6Qwk zbvriUuR_7kI?4%U`)MZisg_-npZrz75e;WVK28IFvSNqR?{p&He{-AlDfacgBHWUh znR1fc)yE_wBrkAx;4EZfwLW!@%iYJU=%)Lr8{3zCZ#~UaevP5n*@er?rOH zJXG4?e9R{_M~ar*oLG?>glUZtJeEIykykcm`ZWb@L> z7mse6O+1z+`Hl=Ad#NVxUncK#Su{n&Ha-obatA>xRx!}ERp%;uk_k%*_)1$eBn+6O zlV{B&*=s56@o8Iylt$7|loY>h;(df}&GU@)8p{ZLS)`k_S*3xx`F9O$DwX&i2wkWI zIzM_PQ4`vUku+*;V$!T3U)JQy2{{lrx3Wi%*lo4@KykRXx65MZ#m%a0%lS-4J)b~k zwHS#m>rnAD)t4e-hka@6s(nN}q&Em{CfRJo%?ZZT_3HOBFk<%^ZnT_}Lgf(vDRX75rwKdnj-;)o{Rp?C~k7r~YtEK}AiX0ddm~)^&>ye(Ez&apC3Y z0N#F8S5#!0#iPId(5;5JM^Ojee>P_HV7&`L{wfPZt4Xb#3KWDyL=o68!M;O^58g*d ztuODZFW$L~pV}raN-A~5Ts@dJ)TMhlrUq%rwt5|K-~}^;<(5xlYiiW;%Vne z;lq9;iccoH)A*Svd#QVNzas8s9WTAhxpA!#kA83);>R!6vF5>qKZKZ)(k>U@Yjn)H z&MyV#yk*PfcMC@mdfckV{fPWfxtIo1mP8J00n^&pR+PD#p0q*qL4+=zI1(hpPS*wu zXrbdleoNT6+{g#cf@UsoMfkvFWP$I&>{6 z;TYUR2ha7USJW~?31F>BhoNp`bHh8AtMRz?N=MyLz?ph3B*<33K3kYAPoB1Au2Ddeng8^h>XwcJlQR9si%TlW_QzB+J;b*OsJwXj(2R3WeMTRSg=5>r%~4h>DfuD@ z!>}bA`OtBA@5^U&l*v@}S;6X~XxgTWs&V81UjcnOiv%O} zOMf2jyVE8HU){D6(<6HHj+Yl}TDzEQMa;;?;|NSGmhIPq5q@0!`8(pehmw*un-;Rw zA#J^LaTMBep=`hixbM+OzphwA&}=3XLw9Sim%=?3_tuo!nUA;x??abEnreDr0H0yH zCjIo%lRil!Hi~Y=rT4XL+jF2{)??L>_t%fUw_}&;#dH^~qay7a%D%vCRl=?7pXO1L z5n2$j{nO_id-rSc8}c~kPCDy-Ng{DCL|=Ij0p0aa0?t$>=3D}K-n|dX4OZ(zou4a? zE{`4N^G3WeU4f1&AuJm{3Us8Imb_SydB`a;4~;5pnB@LEA!55pV1fZ%DuY;^gAz9j z?(2JvQ3RFf1q^Y`_@OB-38TSsPWv%n8PEmo@8a_#%bu!2*M zq!2;q=(HY*Tu{k_2BYDA;J_-hjN_v;{qK4=FkKabTvst-+0!&V{z%Ax>5zVGXkM8A zdwWg=@ttow>YvMD6TxWn{p_{YXgTnkFKq_fmNm)GObRUoW6_YYbh$@KiOB*bm6B_o9J$gn|MZ^@vM&}}FfH6hg@dEDRo(-#2V3dfN_ig4^% zytAiQ5k(~L%%VzmacJRMW+Y%mapYr0HR9!}5zAFb&jAmA7~BtoHY&@0u3>=vBk97| zi@DXdC*hCK-!+q4##xh39xSEGd91>sKQ>bwF(xdzp*utA2fa;gn13kgYr&)O@Pc|SPH2URY+uPaCnioh?RGIQP&$^5!~F^@bN%J2XJbt z*Ik|&S7DM5Dm&kf9F<1QO2?L{%do|X1CxiQB|30HWG64*?e0%=f)wFuG<`eOE0mV; z*!BAgjX>wPFWTc$_ymxKvTvwa(ug- z;dOB9*3i(94Jyeybzm6U&YQ?y@adz=x#n7`7@^OZI3k5H()wF~Lwtujf|aqOSgLUG zUTe`fbpCLzREB;GpBrN<@1W423dKA2sn;JFxV~)(-_UdNKgdG{@Ksqu0R|zZFsW#f zDaAlj%adr%MVu@7*Ds|q!TGDNz zxjn**DB?B)j}^+MSF)RYWJUk3P5(UQXkOK}VKfluqwxEm1YwGuVdTOHEuTL-J-%gg zd7nRidwmGAOXKq|mnqoRrYDN}qx}{k>>Tg! zivTN169-8_(-H95g_{Snw|aUJ-?`wA2=`l~cstOhcT_S5fvqe$}!3z?EB95(ee_W&T(Mk$LSY&|wD0CZ{P2n3c|iub zxa_;ldMs=U4e77XbjGTzJ(s24dZ-;fzZ6~f)(Czor48W2_O}FSH0o>3(K*Jne7hv~ zEscn5Xm2hHp@Sc9Xi6ODIq1~`GDnYKmDN;v50h&)&Le|7C$S271*h1cj&dW=iIPhf zk)O~F@wmlHEO!SJA^?G+`)e7|cmXB4**U_)9&Gbk3kC2>aaj zGFrOr4Aw@T+!Y^(a&Kp?h-w)k`=Y?>`!_Xg-^S2kFYuww2z>U`th1MbL6KB7ru{d8 zQ~^J}M85e%#cMgNMLOqfBC*B|D{{UbEF=epKRd!PWizSwJBD%U(OSA9XKu+v8z=u? zskF?A6av(R21L6(cF-AG=6&flY4-Grjee)N2;`2UN8|91?E+%u=wF-4;b?C_ z=JPn`N!%Lp1`6x=4xsS1aPBKv|7`1YRMtNq%x@Ds#eF>FWzb^H!~Y|9Q5vX;Q|`V$ zFGz~7j0DXxpazSsgc~9wNGIC2G6e)dtp3WpsLK=nIuPuJtP(FQjR}v2GHQ`~a$<@; z;~A(^^LkU6d&=HRuV^WG=y!w&-;E)9B+c9l!8{`JJU3976r(Iqk&45+@oN} zZN{8rg4=LQ6axNM0G&kP{{%kVsi>%6&?_*3D*`F*nPBGt{Q^yA;>Y}-eD%Hiw2XM~ z)Ez{ewE1g)uNI*Nj3&@U5|+)j%4ZZsL8^mweZUdZlEp&bilqyzq|66R=<*j-1j*qf zLuxp2GQlTm8zue~L#}0kL09zbO=a?!tGTHti)^Z7T=4%>Zu0dQ4*fD9R&u9Q_j!<~ z!Tzs%4!H_^*xCo!`H6;;#|#0ZOub?VN69KRja+mV2N(5&mDqoM9Eo&`Sf_!5QiM2q zY*(Z|{0_e5Kw(oX$I1V-y|c z|L8M_50nh{?pd;&xAWx+1w@K~S{^jX*j}g#+~;u{Qk6az=#kZOD={W_S*$_x zc-1cmAT(;Rk^CnJ!NQ-#S_sFJkSR`jNMB~TWb-hjW*Umk)aE`bfA{bEJqM588;V0J z3@I811gvZGi6fVds}d9Np|~ct2Xl2K5r?y=C@65VaQauajx{&RVK-h>_g3CSx+7IN zHkkpMOruJ_Y!><#=-R_5jdSOoO<@TUIzAOZ0j;ye@!f2;oke=KTg|2&)?N@x>DuDJDd8X!XPH~xdqB2fYEbIg&NY;~#UI0FMlTo`Mtl{6>;@MU<4g==C> z1q228JZ>m6E9RYFD_L&QlngVLQOeGVJ8iqP8Bl##!bd4M2)4DZCm>rI&_yQmjEm$z*Yl>GMYo8uZbd(He^d$1A62B_6FNFHHMS$-W2}xQ zl2>WIZ-a)OGw++s+oUKwYN8|D4k5(9i)TNXl|9n-j3VLyae!$tZ}z{1zxUxF*+df| z)4@bU>d^n?P0F_$0!pWtKfeKa=+f#}wcOEz)2`C>CST{rXt=u?!@?)8Xz|?tN(IVo zF{e#fkzJ^&k*2B~r5VN@=SUp~nOb;aAJ0p8w;HWe+^U>qwunJ)FUb-beu1BS#(vyY zcuS&O`8a4uL2F1-YvzO%J=qyF+Q_t7rrL5KYBs{sz_=JKe#nD9f7|{>hWPPzO2m8G+PMM7)Bk_e5Jynx6>CRUalBlP^05`&|wRV$k7HZUIEEt2G8W%t7zMoP~N zJ~(rGp}bVKAS`Vhk`8JZK~M@F7_m<=R3o2XV{sh6j34>yUZUpvAxP-=klNd871s(^ z47-Za$C>%gs|f>_$4D%u9!@fq?+Z=Z>wnwUCW~&40yh-i$5bcU>o+D)5wlS4;Xt1t zSTWAEa`r7VBENqAwCf-#DT$}0wWyqqef!Et^-Nf>0w}*O*9^Z2)NB}STPo&%)rhaG|mhl_c+2L!UL!bN((pM$S)nQvpv_T=~t^ zBM5mcqQTiQgLCM^*X52~s)$-O-zZ0wPpsXUB?JEu7YOOm;GunM6{4Z>;Q~0xFmYZR z8dnSkrZYt10^`lY{-GmiEBSx?`@V|yk z$EueK5O|0i^?KXrCxSKJv+{oE8R!QtUn0K7k?V-WQ{A?ga;h3h7L3G>2VKn|px;^9 zWVZ|#Q|ThYpbZD;-CAyiw`UyHnt$KzHT{eS;3@k~?>)!tZ+1UHyWFeTmm0$+*vSi; zn$hgnve@k%nG}96T>DkaK!K2)jFW^5WH)E}VE=>3Yn&*9%2*PwlUbTtIL#S3aT{X; z10!&pX0q@;ifrV8!dZo~tC+4Y^u`IWr0)FG61DEPel+*i^A%6dRwTYB@yk2UKj24YL{jHPCk?uJLvPhXQZXrr?E^7R!+nsm|INv9bb ztE$<+S?VvYo^lx`LbVsD;q>!4N=5j3tAfzbpPK}?p>%Qt~^uRo=|Xe#xHvLW`niJ-@zpX5Xu_iTss+RVP!u(tfELepW zi{s_>cUN{uN8=m4i!*)Vl2+@bhZ83B6d*j^Iyjg~C0Zv3=p2-gI#W zXVK+xCi@<&3Pw($T%NAbh#+@8O|QV;kOjM7Y#d>ieLxyf6f794)>P zpTX|K5S^s_@JyS&&U+ScLa?2(8H-wrBy0r-w8fE>*#SL4|X2czCTFK{hs4)$^eW_T3nAtYqdVOX-rX``1(ZHB&uRZ*tQM>CA#H1X}DaJ(Frq|y-|R#xSPvahtpNREIc-Mf`|eA zS4lWz8&75=GvZ>gDheHU$;12S2HG)~y!vK!xFPcY@>vq_;RaHiskTqFkqoHNSu`Co zZz&Tc@(TlpPZdbb5H0zXT*9qJ7P8@Z>f$H2KA{&%;Gi=Ih8*Rr1%fzk`qn4H1MW9J zaq754UuE?rk8nXz=`bhtxW>ki43k$nFaZ}K2xl%7oKjOp21wDar!VXaBqQ|MkKg|W zYh@x0BiE!I(f^F%l3CW~cuA;*84NK(Dl!~h%u?KF+ROGcOM8*3lm zytEr8t{HEs1T+Wm};TliR+x;JmvLMsi!NEwM$;Q^KfF!SJ|K z)e$E{hr2T5G-O5`Vu}O2?5y~nILCjcvt(Lwas%_jon{EPqhN1*QA+*kgAQsmsWnN9 zUJ4?Zqloovc;pip)t~#JL*)NuFD?=;h3LUJMvwRhFm1fz*nKcT2env#I-Alg`Q#=L zqZI>%h7pO%NB0ctG7@bEllNewvHS!1TC88S3tUC3jrI>-LqsFivtBPQLa^GX&MsHL z5}Y+q4|Q%Y@S^mRc>3`Q}?1DJEk3=a|FVs|SO;${e5 zs!~x&F(Q{thp+o^<^!o>T_0%3+g(R#xA=I$@T0SMy3Wi2#cw%$aB$^|CYqn?u<|JW zHl54YW9}{l{xM~FgqvU~UKn+@CHIj0^mEuObN!;kg|xEe>AyG376^Njf;Zjjx@u}V z*=dzk?1-F+F=!YyKyLv+1U3{~C0;!Gm?=w~&v#MaJT`ky1m&^OkjaR*0*^6FYP zei5G(r&A(WP*A|&nsBx#T9eT6DZ6(uSR8A$Mrxk)#^cocydU+fCXhrZCD0jfi0ufw zn@#6HhZMkv#=X`W@|@`PX2L2pPFJ`+pf3{>Tgy2f8O6Oa>17ku%mlqQCARLYwQ{EV zc-F3V!n9p$w9q{J+Vf=25xI@KL&qwsxB;( zzkKrlSODSd)LR?ex;;Ie7KH_rIU0aIW75&=ozxf_~@I6((exaP2S1 zlz0(1IK{b#t1_8=iY|0)@PQjrdIE-C8;~dI39aUGds0Amr(u8d&dYXV=aQv6FY{$!ogB`HRaVre7@=eHjtT zqb5!*x2_5+w6j*DQbMF{^W=+TwlPUcu)6;N%%FDMWH@7|=vn{JZeyw3k)(1Y4&_$^ z?EIh8&;c9Ly}pld9A&*v+_2KfUUy&e_^et%Uhv)yA1a5i+4upm(%;hg4YtfbE73l> z5#!z8fA2^>L{b_A!Gh_MyS{}EZN`CvUhRNhw+B7xZVvVcDg4-1XC+oJk>yBelbH~ z7c&5*y|UVCd6w?1B&$72Nrt=X)t48!P<~EHYQXxHaYSmtKEJf|gbalQBE%H(Kj?%_ zWrUz3S?eYIRjZDtxu^Ib;Gt@n6}hM*%Q-oJ1dle?x;89hM@P*86{{n)kq|usc68u~ zP&?x{n;21#mOLRLA#G((1WplV1XW-&IE9|}b)0$-qQu`O{AAxeObk8?r4Kh-w=Wk=9elE~*6vUEr#9YF!0TADq#KcK zl{we00p-S0-wFRXsb4U!z=!uWX073DZydhWZ|yOoD1<#NsNUtZGcBf+Gg>v}musrG zlr)7`LHqm$u_CxZ)Z4K0k_+qZFGRpGS!*Kvs+~ z)FFO&5{6)LByb$kuJ!Am=rqB4r^lMNt%nkZ)a?NiXc&LR*_MPAA4L%8gs-0RfnV`z z4CQ*JfgQ0A`v#~8(6+V>xFBdB(tvE+%?-M|Vx=HeXi7BNVDaS2;!3+eLcGw!INju4 zCI`tciMzga$KvJ2ZwGh*w?FlrP%BmIAC)}1e&qK`6kN@e>W{yUN{Gy~jz3(@S#+X} zn)$}Ydg!vXFUT`}jwCHltD|Ye$Kkyj;4a4CR~a*pCU4FpfM$VErRjUGopQ`3{w+@# zVWoSKfCh&Lt$1bggK@>;>uT~_I9B%>`Q%xuv~6dm(Ope;KWZfgRE zcygKbC{uB@&Oc0b;Ccl{5d=+FROykWO5O^aB? zZo3RN+SC?jMnl41XLS?pG|-Vj>rB84xs2RiH9BQ{#?U(D%yTSs$odPb`tiHujkB03h z%8=@M9;a%z;$x8fr>1ZnQXE4et9S-J)tw6N641K$>ze+62*TI9ra#PP8@M|lM#V=* zw)HuX1~cjD=@~J-h_R0fhnAGHNn?4<|8Q`whZ#KQ{rz?i8()7nW!y@QVqz958qA&` zpOi;y-UjqLc|K3dnP{kKYvYOP$u#W-z&bQ=xz+|++NCb7w^I=VE457_H){!8pvjMm z0rcw6W&4BUV|^!)<#)@wA?va(DE5Y~@ol5Kft#Se-v(TW?c7H3+0*+6 z=o#1TTf+`x@y18v^k&&L1X%L7%#-R5X<6fg@RlF`{90O^laYTWwVTf3ceAb9b*fy! zgNgYMTwB>flLs)4FIucK*loUPx&5jauIrQ{f%!|iWpAWVGwyA^VTP}C{QH)fo7)xB zyW#ag=WkeswX{^h>J+7Lej%s*#ugO}w&UVsQMr(EXI`eSuSNHw1bEyER$r2~2o={< z;Bz!AfSPyA^1)nMtlQ`&|BIZmdteb%VTfU^cFXN0DIHmb*ZWnQx<^3Ac>Pz?sDb>T z|Ma`y$qB8$=wI=J;VwfxSCZ&qU{GmotvMT7e=go&qVNAFz??@BhjnJ+i(PjX!Y!&# z3rOCHk$~UwT3+6XF4x*HmkE9;mV`(0SfkptUQ3JIpHIRC6f&Rll8UaT%3K>L|Az>? znQguvWw3O~(T`@|#2&c%DJ=)ikIs)`2pONq)nW~|JDZ?|A*-=E#)(%0B`hiDgUb2& zIb+JMgu7^4^7qHuZv3yj_;V|3vM;&*dK;X?I9f=qwvYob+iIf)^%R^UTFUrE|Md~0 zk!-uu|Eq*pzK<}b4ChPyewH06mOHvcyifDjJ@T?L*|Q2;)J)hY&}v?0wS^gQH&rFT zZr>zD>d`nOo-JJ>(c9LIO{%)TwPnAbp@R`-c)p0?7nVXsAOZ2uB9g$5bLwwQypGMq z?m%0{@*fQr@HWq+{p({tQxV|npJ}375q|s^rMixDBo5ecOmkfyA%#lZRA+Fqa?J#(D5*rUx&}J2~m64CemBrcrE>Zz&%f1vDSL|jG z8(G-yyp=0tK5PmFUsMhZP{d2B+BXTnVev}Cqb`-{WAe!=9qC{o*iY95#xH~6+BO@h z3O*$-pd2yYtI1E-^Ac`XYAM6CaA?6n1sihn?Rhb9X^l&M%M=$CtpG-^xJMPDqj7a~ z$B;b)$UW=-;DqDo5Jr1A8z&*hu~stF5ZeJmeMnh;y)^%_eL)Um@IXtuYojt5YJ2QR zd`}$)a#mdK`)43vx>IA4Si-nXFZgWFu+bWUo=;!CPh4x9C+I~qUDS3tHg5QnJ1ag# z1SIs5Mu}fCk1~sBk!+)cWBl*inwgntYiVnf=xEt$Fslxp{8_KRVc6_WE%u04UCQ+( zL)>$njn#nAfrf^+P(qeD3)Pzh9B3E}0VQ4Y7$W2ZY!mB@G!pIP#9VI`0I?Y|Yo5G& zeXq*A!h@vBrq&|)L`H)tn8m07XBQsZhK<9LAQHH```s1idF1co#FD;e@+_&oJI$yR z+7=;*%h7msdW(=JpP5UbjKjn(6DitCyUU=3K~*sqND8hTg^^7mW=DipB^+9o0o#xSGMIBQm1(0mS{7eC)-?%z@iCQk@UcV!jiw^nwH`4QqADMh`c4 z;z!U3p5JtSvB^N6cT?aJPobeXrP?xS7f z3m?;*Y8Xt-;Zlxe+sQn`@Uax%g2ieuO|K0OjJtlOO<=S10}ucM_A8OBwv&}^aD^Yl=KRquM?g{@=DtaV8$rF@otjD zRYsr5C%l-oifGktu5DQGWNFOKP5t=Pc3Db%CA!S_`gBO0YgeKd3n=3leitlB=Vu8A zihGg*isn?e(^*yuejQ8bB7DUoH3sRLVBYPHA6nn1T($y_p-tK7fe*%95dBbfatiu~`6FSX0Zd-2hERY}w=T7krQO)eIh1smc%Yzs+pywjE5fqu`%A1_x@ z<~{Kf?YcyyhR=lCnRKF;!;@ISoPxGaoRW zF^;l;nM=?39MwqQ$luCIVB1s@VH_U)Dh!F+oOKYI-$?f2Y{sHY{43$Gz01B20wo*?&^co9LHwRKJE%BfO|e ztOK_&4rDl0*~c@bvOK4U*Ujoqei0>Vt`M9^If|kmVVu5f%xk)A5}TL*T$`!9r2q0X4H`QRDBzqa8%&+=Frr7)=p2W zOr1O?5dw&W`(?sA$}u}H)0M%1wC=y@Q)$dzjn|HI1B zc}dea$wlVGawgEpFDiQ(U9@3y4^%(AX40R4=50=d|JNK>ow+I+EHYKf1_!&|)I;re z(CvM_wvNERNJ87*N3jCsHb#*1qVPPvEp6R4rnADg(;c|#;O zXPgLMP;l1@JKSv|iMiOxYgM~@wtwGJq)C6j00fEO{vW5ASy>+|zm@P&kpE+V3YUNW z9PRAv^jDKT3T#&$hl|MKAf2Uf-8+emLhJ}ne~OKS0;%|rdWY(PAiUbg(x0jm<+KPd z8pg^;2Vo-R&=1M2lC%^DVDMg!KUKub!C@&E_T+eNZn)F&E&m<=)|s-rn%u+aIU?Sl z_*<3ICEHRTrra-Mx-JTX>-CdGJln0zgZmJ&)Ge`?}E$Cf!&@JyUFL8-vM&yfR-6% z|8#IVLj(PYi#(0_=({L$I4t>NxA*XV(_dcjQ+2@oN$?Ft?J#9#%1cAQXStIDU8-RC zt%2tl<>o!NX5c*4DcU$ullYDw`~xN&+TL?2NZ9akO&AzsF{~B}rL4XIwlo|2&fPTH znzLc zw|qUaCdIUVY#Lq zyW^={d&-2!CXb>%w;-`Ib;uQogs)NF;yi$aMuzM_>W1LNP| zgJOEVC_K?1wc^J7_sgz`>K1)VYh0UxdWrJ7-^r+X@5~+h z3dWQHD?gLTyf=stjuvbhweJbg|MTuj(mt^$%0;&Z3*T4&+9RZU9(@#wM*C&7VUV#@PDy#nFuXU_4A8s z45aJ15KN3%+FqOJfuO~^%ir#PXnuyIC`S^#NhL$qGh6uE5@nFKn zZ>f>uM;YiszOxZf#$$rfgl{QqUBvrCDLv>GCh|gE>!vTbqTh6d6Ne^;p_8I1HNsT% zN%o2sF8Q^qct9}LYSKtSK<5@x=HOPs2bK#XeV<}ynopjMmh|5)-BE(UoVce5wIsX6 zUxVe*26N-)Za^x_{&kB&^mwwK42K*$*fGGro}!|tl8^lwI|?wiGn4>3IcIi zu$${HQEMriHz&+su4Wh|oe6Ni1qz8QK83-LH?J!cJAEA7j!k^@zB>N8ul zw1jSlb6Sb%LrkG?XE<1aaF0OIcD2*HP2hXelT||uPfJ;YI9`d#0!<;Uyf@GECI>Bv zrnsetWjkGHGW1J_Z3PAlfOY0p)OSoUNwzgNN>!6EUdOq_-3u@)Rw zfFv2wyfLUp@QA)&&k{Up4Z-9FU^u3f^M#rBu+pi9NcbakyW5b|1BZKvcmEn3UH6^{ z7T3*t?J&&wAnQaeSG5()MzdcSPv-G!ESeV7vGTQ76lykkV@}i9YG~DYiG> zbAQ4!c7e6ot`E9=n{g@@Pn!|h#q4?gmP4-NsSS{mnu4~Pf;p`kGB36I5r*mYq)A-)`T1=J|GW2xh^TF-xH6TIjX!k)=Q>oB-!|&(ybVmyc zL+nkz&;C3Q-+5g0`b>Q5y-yF5FlS>P0?=OAvaci2%Hg;y0*ifis~SvWPzw1Q!^zDy z;vkPjC2}O47PQHJmqNg#@A(jS*&|R$ouygLM5M)5^C7wK{i;cpssbw%wsAg4JmWv| zwfz$_i2*5I)*hQ)x;g>hCubNPpUE(3Pt5WDW5@#NLU>y*@{!~BL#xqSoI?0nly-It zcIa7xlUe+C=ZO?*N9Xlw_v-G~Zir(Y7o7dN?w&pVt@o$HqyE2FYL)UeQ`~*Ar;p_= z@nI%LSFXC}Yp|;!TD}_qDWA5S*hFh9LICOJDT9HFh_sNSgbr3$Q{#}-4ZUBPro=uV zcQ?%VeOA=DNy*dHI8RfCp&f8Ylt~$Z1OI8oCB3>QQMn>q0iQB%0m%8JkHb*|TK^=< zxJBQ) zQpLTynkjjjlJ;}BY26cnz-t0ms|t)dI?l0hL!iM;T>Wpf9Qr!=`$EW(tvAXrX3}qr zXqsYdyhw_}FK-DX1j(*uaG@yAne3ya-}&UTtzO|qQ2Tv_)a0YFYU89I!l`>j1K-vq z&=Ujv_8@<~dW#s_6)cYc;iS64@ez~zk%Gk;Wb2?edY`t910svo%#(w2aC$hox^~}4 zBbs6lOITc6<13b8c9@A4CqIU1NHpq+jSTWE)64gin!!@W-hvuqH<_nNidR1ss%CXe z%=U%05wXSpqHKBqXWl#j+?(=&%JKchvvRW^2Q}PqFo;!H=r{Km%6`HW+}vvHEHr16 zX05WeBC<^jP42ci3aRvHh)U`8>^wG=%mfBsEzrOXAqHbb^C8`rFXW9NOkt~=-GcJl zAnbG%`#=9CST(Z&$36(%ewBZ*E-rhQLuo1(z3l)as9~I=mwe@^CGOo`Jv$U= z;CiWBNH8?Z?|#SPgdSWSlSw>{J<%xpZCl+fh#MN1;dHZe;6Hfuk7q(f@ONKU zvMI0s`TtaKk9E_PcrfunI(5aIy&$;xaa1V!%Y^N~BEgV?3e`qbHp7zQGkGJ`TSMGZ9%8+Gh48pgN==W)h8h<3Q z+XYo_CglrMHwd+4F$^ys=~5Ufn){;~KM|57wQkJMv#I_gEDR*6)nKVcqNm0aoM_p3 zs=WUy=ltf0Kt$d4RJ`>~#Ir>I^i%$E(Q%~K;4tc_br_(;sYVb0_)vW26U5hT*5*6b znp!jshwd~!1Js3)9P!?7dN=So(4;rf3O8k}Bnr$K#AY zeCB`+$W{4Li0B(X;6mcG)HGBABtCfzgI&O?k?37T3pM{~fSCmFX7Pzv$0-`vyize+ ziQlZQjOp~0+ z6x^I2xFeqDBo(&APn|c3hmy4O@1HYe7OLr%w`LFpYxYsDAGL4m4+P{h{e5--3L?0R ziJGLwt)`iH-az;EF?g6z{^@_WqJ7~Hc>AJtl^uu?p>Ngrf5818rrt6rj;;$A4G`Q0 zcX#*TuE8CGyCt}L@WCB|zqmticlY29!GgQ{ZN7W&sq*al9s3tfi( z`#!p%{X@4C_onoFwXKA)ax>bAOq(PVe5DH_{|p~}*A>=08!5IGuYq-sSXR7dy~T7{ z2U)(Beay$zfbwAyzLPVFlEt@cJ@Mfl!|4>$4W)bg3J>leJllX3!G*%Y%y&#_>oJZdO-=x^pQQydwsYUES*&@7Co&`9emxk$^p5{5(O!95Dh2 z^oKsA+5m?pi-9f{>6{9P??Juaeec#C9yENi|NZ*CJ}t2g8vN-z1$dkfePOo6y$x2t zSb$*%Gg$!^ajdBOvSt!&A1pmghFJkaQeNIz@&8mf?iMbCSDk%b5a?$8;`tcE=#L z^bd4OUCsZrA;TMmI1``WNkZe>&m;ZE0hY4t(7GzcTPfS%tG07$pER$vpYYIplz-F6IcVV-i0GLRVbbUmI9NnH{B54 z5gB?$RkTbUH4A&`h&>S1;mnIScn0TzHmT)|Nh3FZVA5?!5A;s%?f)R!p#9PWtiOO4 zwWxwNGz!d!3sBtX6|yL$*nH+^dRM|gO6j&!+eqf#*vQp!6$Q!ps`OjIG)Ma%L~7`G zQ1xHxZ}pbDT&RG1iuFLWBRad&ct9diVeG5Vo`S?p>WUkiuTajPrKN+H#|@l#5S);q z-=co{V&rh7wXN+;UW$`3;A@}t%n1Q>F1AyoKy3^ooBHMCw#j-=E}ml zipGD>3k|{BBiI%>tZX{6zwE`r z+R6d=(sSJnGAajc#+%2LbO6f(k=W=}!E3Ieut&bWEzlP`d%aDONp-^qBqab=0J%sL zkDtBldSKvsTq|o&LSq6&iJ6tUv_KBgmaPSa2pP(~d6F^#bm!Gfvaqh}^+Yg3j!1vZ zYj8o>n;;w&mBfV?JV`j(^d4p2nEAgXJR}%X5OY?%9)S;|&;v*5!r*9zjExinS^F#A ztb&391`3JLT7&(j(8TkXe;^)GKyHm5!`E<1DgZ?Aku>fsks6RFQlk7Nu69}b5DuRM zAoo&@KO8*|3z!Eas92;Lc5x1S`4C_NCaCuT?yYuZm6equgvJ_}z${C~POE^B(%rY$ zA~hN1I5mdBq@G98%Ebx}Nu`qb_{c0-yI6JE*3f!KChP&L$&g(WOFi9XwiEPV2ZzI% zM>!I|2ikcQ+$hA4;=vS>D;|pbDT2jE^hpbGt%QtN1j$h`UBakSt8B(AY129O#>oCN zn7mVue_cKP&YeS-2A@76f1l+X|Jycf24R3s-l9DqSI z4jpI%BAzla23Iec0G6SU8wtW@?)2BU+eei6DWB(6vw+c2jE{b$Fcky+kY;=28ltGJ zJ(EX}cti*#9;&?R+k$Zj;7aUAi~hPDO5yvKhTrgI+m;)Bx;jI_7`{?H*+;Qhwb-$1 z0w;e8;IRN7t-BR}3~nxe)>(yno8^B5z#|BVMERT~W~A5|*Bd%+DRi9{0%R+yzG4Uz z=zcwy)Z3XW#SwKPm+T}6z~-U;JUV9phIMEu5_z)4GNflgFz!C(%b*O)Fz^+)FwR@v8d7$xUAv!NttEP0z`!{>CWONnSG zSQH<^;3fpjL9gFw_u{cPcb8f=~0of~BNjmP}pf^{N0ku7% z-jrd-OF`o@huEtJfK(MR(>^f0Q}VHvY4JO%frO4DQk4*E1bYI)W_yl(mcnvX^KxIE zTEV7w=-a>e&NDM8h^gMfG2n}36dWlN`q7l)qNc`4qXv)SX z>{T1v1JT5?ywA=u((En8!il_Zn>9;~9W_fR1-`#r&krGbAnx6Hm?F3at#+#4j;dEY z-d-q!ej$;=>S0R}HiFZvaO}*uA+cMV_4H9zYGm!(6gUKVNf<-Ft{*A4MLDrCIm{}g z5H{APFmD)v*^?xR2%{XkrXb#eGXzKE>v&Mu1=GM6Hd1BRf*-_ zg%Udr*fbNfl2P8Fvd{oS*48A}BYcuxXW6zc{kk}(jWlvUNPC4fQYY?|NkwbOFjlAm zgYw>HtS8|o@V)OvPnlTD*u%0}Q`<xw$trb#=dwl8qVZ(ekXo2ln79wBJ|SuMZo# zEx!XS?0TM2efP>DV5Xnhh0=n+hQJ^ejm{JRC8=5rCszLQ zy7|)eE^WbLXy+=^oAUnWif`yA zI3jQL+s99_7?_{KBbly89#1+#=?k-4Hzm||eVy~(Zd<8>H`sF4dQ5GcBELNW(1e_kgKI!1$t3sXu+-rfW}^-zN{`;?JOf z`Xf!Wk6+m(BPNPTyoRwIgJfE+kSU$^_QA(iZMz456ZYFkj6xQCUnsvSlqB_|zyz^P zipq{25+81m7Uqu|$|WeIYIjnDI7xr-AQlXgX;5V;CjOYD%Nw$7T3>itbDnbjv0OW# zy3aJoyKj`Zxccv3bB_;2eU1Xy#ELZWkQeZTVy7RcvKT5RqepO}^H}BEcTn*%0M6kY z2DcU$I=YTmH)=afw3r>CCWkGtc}XC5it)pO{!5C?=_QOdLM!@ylllalYxu5{{u0E! zuAanZw6CstRF%mYev`?Q`^*c*2C?|@vtIZJWH2?KG>)GemLvVDUOC8^^lRQIBr?3P5nyu`j6yEYpa6n#m&*kg&}+%dn1dA}dWsUxiFn`(R9|u@_F0tzDj67Pz9MwthwhYg%JF zaF8zMB=!cJ`jG*^!<~Wb3TP2*ob&KLlDEoTTmB_xiulnd^EC@&ubM96K30jQt@&u_ zp1PR4QCW*6bR4=20c8pCx08$K*SU8#(9nN=&<0W4eU5|`T87qkb{0U>I^L(Mj*EkQ zdU`q)k>_#j@ft0);iFdTlAuRcnNE}a+w~o!1e5Kph%Y@dO{X?Y0Hf2MySD+z0LveR zwGh)QettUE>gW*GjM>`eac>yo8Y`3g{DTOHfz|r&sv~PZ59q#Ym~E}CUo&#v=3Lg1 zb(C|&m)eq>V@`;#!Ylrgm%?jExLj$vO&PHc;sPgz5KeAgWxG-<;m5MX7|nlsE40D- zrSy*>m2Ik}9UnfJG{IQ0?nlO}7o5ZPRW^D0;9a=qO6Ge3EJrSRk9 zRJDzj)$g~QU}FYeM^k-g=eicZ4x~ZaASz`JW_)F&@SSFVyx1-k9(prJsQ-v;bE{Y_ z0-7C<$_Yo~@?=HNUd@RAE%~jx_KClDD>Z48A`6N^*9}Zia;+k>_DOo% z@hGsYb?2Zy9~nA`$p3QvJYoQw8=RzOD7&4iC!KeEmPBl227tF{d`e##T0SoJu*CO& z9E#|=u884PZGC__ATN|ee-O##yI5I7pNJr7L0N@vlby`gzF6<4e-ZNm-B=EK%IA7e zrnwpH|pJ#%* z$AiI*i$hSMz_^o_2Z&A=ixsnap|+$tt^;X7p0BQSd*rK|_TS4jE7|t2tF#N9a4})$ zaF^OWWme#1++9HSx*2m{#_27I|L3}-YsNAB3cvg{K5zTN>#Gc=(iwbMlV6fNv05h% z;JOAp+gc^-72lNSZt^9zo3D0&9hf@TsyVGXkED&fiict!US3f0cfSybBIv#bs+Vg6 z%B#kOFT#Fz%W~y&w2^0j%E)QVI-n_qhe`hG*nGLcQIYL<=VnlM|I;Sl(SlGPQCQ`4=B`(Z<>=#?H|_m^(=&^lwl*4UzLOvo^m`xZv?NA z@I2l;(S5HK0LL(s!*p#Uh;Zl>L-H~qB_*ZrnxL zIbRrhJ@hrBK0Q_~`znx{2S>Z5Wk9x-YDlb!MmXR7s%5AESgf>H{P!(|buR=@gn`OQ zwT8J)vSqF+IjX!i;bklUD*f33CWx}x$Mb1m(ZKs`e7O!<9~Ex$cduz!+qMIFjecdf zm7lIg+dWIr^*2BwQ$ItlSxqpWA1l=QH{1J+4bx#80#foZN&x8~K&+rQyRskcFtHIc zOEIC0-V#~{FDf$pM+(n#J|#zCNI`nas;XtsE+MW59@dvDw#2e4;qwl6)QNVe8oU^h zO7dkLTm{|!4u4C^+6fuH@Z}bTs@dFR1bAQ_5S3R)58lk_sTIiY-#6dC-|d)U_bY49 zCB*NrwMDEP4_JMQwC>5UpRBg5RlppGE-`nH*LQ*m0xIyx)VsSos^B=LM{?Mtv#RH_ zSwVX+Q7w-Vb~C*fvA4V|-ZbP{{1tF8T-Yn6w*qfG^Nk<@z3AxvCJW?S?P3z2ILhla zvPS`u*u=L0i23`hI*U;KhKBG7mKW8AW&*q(>>6BHXr&2EPK|OhRk(8UFr8@BPm#AQ zewUF1(I-=TPG8FlNE1imJOmWi1Af}Pdy2s_h>RNP5y~7|2GCKqSOwYk!srngR4*!f zg=2#)RUGDq1yAJ`^=6mr+*veqz~AEgDm+LgEWAIIN_kkk6$^ed1m_=k%ndYK_2ND$i-eVy?v&! z@$&v%XN?YS63&VLsl-EBe;Gj)E?B`H3UrSBr-{j0YGa4Gy7O=1>ACWM5(-VPzug1!l9xGNy=h&rfMmiqVv}7 zaqVlm$&H5R-&1ahzs>}yESypY|8EnrNq>>!c{fWi@Id~mWJ?{~wBdt#PslSuYNzdL zyL*mv&s85&XnwXm5WxMmBV5urm>Jx12t?C##k(Yb00+ENiv)rsI75$d#IuQtBwBJ| z>g+?u`X*Ep7(2I?>_f2X61NsP_S%=K6ywkRG{f}+k)=WbOHeg9+nDVq@?@dM4IhC4 z{Sf`0SBN!es(c`l5Cfmf%m*^KnI#KV-x`*JNUH$Hozv5VKJFI(uKG^{smUri(o+<% zGIX@{MgsfY-3x{8>$fzaO5h$`aX=N}r~(zAUtWGpgAxX%(M4k<#`D~9j>l&{H~te$ zI-dDeaAb5c`Xvcdkdh1_b?8rtpVgWx|XvlQ0zvek4g<3--Z?H7i;ol!@UC zEMagoW!777I-Ci_3uXbbmPgNx(_#nb?vPpv!i}oCHv;>1M^{^0CVk8##1}FV z&$FX^JcNq1gEQi!7ZpI8{A!CWNYuT@cOppFWnbBi;SC=27)`x|Qpp=^d zk{rB87e+=} zM|r9T4z6x8F)@s)WHo$)4m>XYt{4sO+gHv9 z`n0YOq_6N3TCzAUkFQY8)hI((>x=(ubv3>aDU2zSDj|GU4{iwQ=EXfr`%gU6j^+Hm z;E-gf%C9J^z-TzL-AskKy+4o)pEdt5I7zlWb>H9FbiRw)pSPtGV1DxKE^!TL^i*3r z`zD%Qo%r3tsIXKx@sKZFhLBVDMj?7fUth4gv2>fC5bJ!%q_N&_z;o}8 zt68`rhV1v;Si{@PzVK$VUvAMgf)P4lNu?Epc+7JzCm*krhZkB1Vz&d*1&7tgxX z{J>KRzY`?chN`51SltRqN8h{Okkjw#l^qXmj=Fx7StfEnu!~$8ktKvflV;KXR{bR% zs1?}tYrJlW$KIrad-J~VN*6fG)tgjQG z#rAV}8U#mJ>BeV?Y{stdB`H@aMlthW$w42g@DEy8e1$pHXkD8um4SI20s1j9 zH@nn_13;Gyv<8&Rb9m%@-)vD}b^^CBWs2N{MiwS1f}2=EkjSAVqT?NYU_#ytwObuK zjvI7l{&+aC9I?;#itvi^0%#qj{0!`sG99|nuTJ`-?9;ToSO`Q<0Np`>NDt~OZe5of z#~fwuzcf>=WB3)h!>E-~x$sRn+y-+;9g6KwX|-Rny6_EXJ}`Rz7ktceH`n3;0)34; za`hn+S*~-Y*ZG(SwL(Oyf!E<$A*!&?+zbR8t|`(#42vlK|H(@*?3=e{f1jlBx|dva zY`**T+&{S@$l?{URFl$EbM5A3x4-*MjIMDS?TLR+D9REsr=G}cLA54y&>9v#mMy#k z?!*!FD43BS!s5)a54<1eNn2U{=A%12zV#~25&1h9$6xdd8kH8rcj6}lzy+k2d;YSj zk-}827Tx05z`d7O!X18OjwR&{W^3iQ+FG|Slp-s*97k*|uIF`X_<`H!P_Dq{%IxU$ zBY46`1CDf#pW#z~bizPnqW!>523hSs;+9ulFj`D0W_=2v^Y0yfni5FQt?JU#t9DUU%+dPspIYZmZR_3bh^UAj3y`Uut(**kQ5%P)zYQF!k0Cp`ZQ} zwOnC{a@DXc%^TPE&%tBU$bO?BD>f8$EfgR{>^Wqv5{f` zn0DLO2;^a@=?0_CthJ&=d*9#pl@x`iJ4y_p>s z>8PtkcBC@E1+y*S8u1=sC8^nj1HF`9r&%5wJ2}7^>M+4_GMnia%tx$;+Og9F`)a5j z%psju=@+1KL1D0F-Q(g~8T#$tRhWd*Z|0C?0}rJs39CaY^rtAcBv;EHYQIeKaWwh7 z!sm!iPSO%Dss_m!04bS3y#Luf7bz8&&m{G=nZcL(UX2((#y_-VRgRO|?JoYksBV}m zv;~#M3@1>fuNELH{?W+OHtx%1yYjf1md2^jZ(C4~=MymF`N6zPC(PJAZR{@8ap06F z--n)H@Isf6))@g7m8-IY35u6)%nK;k*B75btZvd@i~D|mfW^@X8ZM=;2VR^Kn05mu zpco0SIOfuZjJOUZo!Ycbva0UJW6G?KtH12Miw^LflFIKDK}(LAumjg zW?f3|uShZG$3pUd2%^6mt+$;316hNTWB>7qxO|Ay5R2T5_CB32i;_7)8R<2o6H1B1 zs|zAh+ACK$-rsxM@_G)Emb5ue3Eo$*I!TfWVb=YZlli2IlnZ4>GfsZ!sg-!sOE4)2 zuDQX2=_6DWb^0#TYdq^k4%47D9i7*X6ZOSd{3{?m2JCa`bmZ%p`kM73WVRi)P6N$` z`2Q_wB6nQJ@g~T)w9hQwGpedsOQ2DmiHJ1({6f4iF}FE9R63nY<@_&d?{&;-{z)Vn zg+Cax(wU4NQCX%<>WORSHxtRHAhtn(+zJwf`v&N7I7>Ek79p#`W>)PN+x31uSkeFZ zo=a^v{Mo)W9FFg(lbD$39_He(;P-AKpQDL{>V{^0BXjd%`u8u2Rh12T^Bo{sq^6~F z`wm9jHJ%9*6j!o8UqH`8h=%z=vbm?g?8{}#oOLU+O}DvqRzA&|V3cV?QFabZIWEWx zmWo>d2K{GWe6_YYIU`JyHn^wSfy_^Lx7oQqe8!=(tB%E_Y$(f82{ljy*k0Y!1&LhX z^OsS`hX|mcSVl~F+YL(nU=1=S&tZGP8=kvCoa!z-01W&_G8;j3J26oNUy?+N`(6Xv0K;q5fN5?U#F> zA4@*6GsH4gq}rF_{c^mhb}NEoF`4vKINPYL0qIz9v!Kh>wDmav5Z@NO9RbY)=WRIy z5b$g*tV6mE!yE$;UUMC5G!69yO+S--1&IoK@nGs>Cs{yRb*;a)*AIW? z7%=Z4@W&o8tTe(B&`#^qsFjN2iCz56apWZwf+cIkK`kXcojyP*3(|<1AG?-@QX`n{ zN#n@u87vjj($}YV-2SYjem3U)k1v{W7h{lsnmh2sST@b2lCcs4%$wg(RT)^;g_^b$qYvHgwqO#(0ynEh5dq=hu= zo>eV`gu_&k*!sN@;q18kA3HnO=n6~g$MNaG11ScAej-XpC=WUish)9R?lP58G8J!S zPm|`?dPV%}&*)ieWKxBpQiEVWypmibr($Eghe4N62g@=bNnxA|5#05e^Q<=>yQK}+~_fDC)^RF2h2pRRNlr%9L2Io=k5z; zhj#KxY-$RPT}d5W;it-<6v;|}Id-=ofw!}op?^$rY)$r(?UY*r}90nj-hvwfO`hrNGa<;S=v8TEees-sRbtHppLr6i9G z0FnNHG+6`ZSykp?l{GL|dQ^87|6{Fy^$O5y+H0(b<% zL;k&vi9rUTCe=d`GHb1NuB<@uyPYrJ-g0lA*t)mG{Bv=+!LYlBwF#sz6}v6z9sO7)Xqvpa=`C$pwm%> zmGSlIQPnmtS_+;fPsWHb)HE>dAjy18>X!d{e6R$cigMt;Zc&*}uamr%-hHWtWDdsDp39+Wc89^(QX5-AW*)pq4KDX&*Wn^H zzFAv~&qhh1!j#(F#i}RyX?}0Xv}GtSA2?|{Q%yPxLZBHzr$1wH`FsBhj!0EqdfI4< z37@?EAE)tw6&j3^dMX52>nA#zjl7;-j$Ou_p->i`zLJiMIQrhuV9fPU85CaanHh;q zHANtIL1%CEDKaMJo|~UAB9A^W;CWspwiqq28!gt-ux8#X!e1S>KUM)ndM@`9Ai$bj z5f8)vp|4LZf%GIC=7P->Lj?k}XBpV{1x!xrlkjH|phff4H!u0^Wx1!oN=2tX-`z?I zNHD=AB|oaVQ{;wBNxx>=1i-wt8U`Z zxil8jTsQ=;!QJVFPX9u@BpWkhpO-Q|&`bm7a^7Jbc_Im+>8qq?3)KVIgQ&I4d2>aD zOd4K^jMkj@+1;n=62>&t@L-G@zjb@cuw1|Wucn-aOrFx9HtwM zgHAY?jJoR>XK+W?vg`;H==^!7t8pnrca<|xg8Zapl|<(a0Hu}hI8ZgVmr21LLg4QD zjbO~EdA|S4$dPY**p`b92`S53`TO@&yJ^xrXkcP0a4xn~jY5+>yhw1@D({S+u!9Oh zVv=6Eo{{IcV(0Fs==@?<)~d05k;|eCLAAa{XN)$qc-ROBgy@?(A-*Yg$p;~cf3uW6zRj8BVSgnWK1KlF;()Vn5ru)qepPy z&zyZL7p{VU|K#4-U>jy_#klenlY7(Wx)eZsZHH?MajOY^PuMi(r9mAk9{20DP0~8@ z$4B#J!7*j!-)1>J;RshAfous!2@7Akdz zygD{gjc0qVv9h}+(>10{NBOc5fz#fAu zJZ%m+cxmtO6{p;iI(yq%5ta=2M3ojHw)=-*I4JB78MnHC4y_wV&{2MFn1nW%?#?^` z%{+vYThK4H1bS1L$ZrEbeyP@ctdnC(;5u6S2AbTvZE-c;rZ==d2rxswwO>z0;zAyK z>=SKicj&m#vs#^ZIOJ|eP~_>VTfg6^ZLKs-HC62b1cjq|%K^%;XszO3LTSsU?mBWmrOI_i}^IPL{OAnWFYbOd5X$?5sIO3Co+ zu0fFLzj88&0L(lo7}*H7=e--sq@uE$(^c;KgXw(a3~u{{wQ)4-Or4?vN`gg0e_u~y zV`IevyPkFo>kgS9$+AjyDoRYyXLhWVx>S(}))nz1wiTq*jmR%^N$=7KD5@THMN0RQ z<_|Ap4pYu8G1o+wg@xm36eqLAu$!?xe}1sy`l+a>I96X#P!(AA!l8&^*18@qzye!? zNWi{l`Rb^AyFvJcZ1)=M<55>??b$p}-!M%OKx$*ArMvo^JENIY&>aj}%JvGcnsVfzEf;$&EUq(9T3|+t5-EnFSG!9KH@yoBCTu$pI=BQjPb%B6 zKq~WR^Dp_L{&31=RSgqp`6?n}rSh2@g-Q<~)Pb3p$HBl3e|>VJOECst4rVby&pDeDR7EpiaZs!B^rz@39kWP)(M%* zHGmvv!D=QN2cP0KJ7mLzvf5?0iA-e_m>|0ydZDW@2vuH|u!Q!#J?*hKk@vDq$fX`Z z-1*eKlyL&Ez>=l!l)nVsV89WiJvs{Z2(lqlp(iX+aBEOeQ1rF>JYLZ=scC>Dd3XeU z58R5K+cckVq-EnJzAkCQ6M~c@#{Z$$_55`na`WyWs?^s8T2ZI4`y~H{=y%JI zlY{%h_>xZyx&$Gja!ACA{1G{dP|s!790qYOxVXB${_-OTrVWFHC8NjXb=tiKc*WOI zBUXXKTd%NdLO-SR8I186CDQ6PML$~hSJ_^vzO%bK*IWVi(A6I*kp$?uWo5g+MYxZ?cL*_;9zx_1%0Ro~JSDhyZ`Nq|9 zue1sA3-8Wly#zZ>y9KBB9@%EOT|^c3ZW}C&=bP|W!2KvJaC+S&JTi`84A17C0jAHC=!DGwIn6iB(iJW z-SYSkl8CD6V#xS?@LYBKQ#gIpit2NG{n6RAkPMQpW)>Dtc}6 zuwizgAsx28wlsQVqvCto5MdA$E?bsrj}(GAAE4)1(MVoKVSuIW^Q&UBvfJI8icrqd zx(o|uA5F^RMtxj!s{spKm1(jy!F(5P5-uj&^z)Jx8rfWCA0=61_osSt7>S?9$;omZ zcZoIX_TWQB1s>?>^&Pe56L~*&*iO#$8VS?@GCY_tIV}z6u0hA$XKAIZ>>M2=TdPp? zo9-8B6VEnvtte$!Lp`U(-Yo|5%NKd-*#Qcvs0VT?)VMevv49{D^2e?g2X?hDgC5;- zm0g(KTIPHbSLElr&6i%p-qU?ZyEAM;&?H?r>hwvM-A4P)m67Ow5V*lHWHdR9LdZ2a z=`k@(@lFBpedVqBVqmY-@Ad++XFdI#dTC2WLlA1y1jL>aD*V6dNzL<%gTgZ~onq^; zzMg=K*-GJLEHAeXF$arufR@@vn9MJ3uJ69n65AybZ@}?>8tyZOvk&**YZ3eCgYJ8V zPNiMH)bU?zru}=VhMngv``K!{-_c~(;(o#f>{H-5hHdZG*C)tKhhOaeN=a0!DEQ$` z8Z;>FuhmmuoTlqmBOC@Kyo) zQe=t8q^$tO@fYDhC25|{qk|=kv&R%rHlD0V((vHI!fy-bw$;_9sHxE-24o9k`lmX{ zNX$pOg1piaY?<;Z4vH0Ra7ohv;AV= zrqO2w@7MY;WWiFHI5Kt*v~FO*trzP=nf4q_=Bi*nc1ICNd<)%BvBSd|%zS zQom$uPyW4~yx)v%&MGebT5rEjPiWss*Up^!BcB4|!W#S5R8? z40kgoLae3oUyD%%NJp{ePKV53T5j~RkYhOy6GsiV?F;HC>ycWy#63 zf@z_^S$HGo{dbS~H9#dgqVU;I5eMZX@$L$f7LHa2=H+0_B z^)@Vy+Oe_cGKwG0x8XT-udL=y#H~Ojq9@9SXm`YV79sJQ?`F$^ixZrA@?&~#&1X&X z*{llFcpjmYF=%E+QEl$ReH&a6XIzj%2#f=ODK1WB;3AaV+zq|^;w8Xj&&6Hs_0aiD zE#Godi$Ha1B-R%m#qQAQuyG;dVJ7|Q!V2!j`r^@(v^Af9bZ2Q(!n-w}J*F`If%ws} z+KwFdYkeXyrBFY;hPjW0g$AYgqzGsLoP^PWhTXx0t+6*BR#>d%>gMV?n3t6pTF$~A zcB%Yaq|m!c#2aC?I9^6SF{2)soO2snp+F)eaMZ{;c@?`MsmsIc?0l_t1_jHE+ho+E zrNSiw2OmL}%b*urz?1QBip6%h{n2zE$8eXHSG6DkbHlf(f)iaLU~b*7?Fa)tfP(c0 zI|vEVK~1ywE|0v%aVW;LnrGYXTz7K@{YxQ5T&deLXJIKl&`K>PEj$k$=@>>9+SknM z1fn-?iGk5NE?1`WmFSn>0Yp;&;%bb=uxyu0yT;rm!i_Rx2@T%RCCtp?=dW)2XoREttUhzX$~Ez`U==l5UkP#FACej2vm#rgl%KfV0$l|w%lHzb@Dkt~tesS#2Q`mP2 zirdLu%yc7n{?+P=XttI9ITfnk!qDsVX*sz!_~TAN{aMOQfAi1F}# zM1atVfMzWmDv{X#B~QV9jqP~&=~k%)AK%RPEDk#`!-ugS*1w%SN?eJRB{@LQXq%Q> zaDW63l~qUFqdHS2M$pz)CAl-P+X(#?nY!u(Ud`_dE`wH8h156EmQ@N)A`5p)HyI3E zc>fx4)M=ujepIwp#!|{apL_4I`>v)Y!t>YZ=>%mKP!3Ia4lP7Hq)7-Wp=tW-()%s7 z!Dpx(dpcPtVLBU18l9ptS_K98g5e*`%S^%K#`?$|ooz#*?Ohrc7K#YePhn!V(8(z{ z2H3)y3H;6DRKpwzWxkH^ z??g#czr5WymD(kN@^FC%eSf^&Z6~*?X1egpg;>+9HQXW}ISoh=?`ZIp*GGF^Hdy!{ z90QuoJ&Q(+sNH$7;(m(N6P%C}Pvabr>O}FQk^WtSvY?Rg;AD-t_@!dS?Na%v6;N^1 zd@lErH3%w!RQ!o9XXGMX21hJ=fg=req7;S7F&8K}B9t(+0(7X}Mg=p!x8kmK;I5i+ z=)-@*^-s@Z&HOFi*yGdwQA69BbNhZJXJ`W}z+qPGN_+DJ$$FWTF%t=g#JhLax5a^= z51=f1xj(@s1e_&w-s8U_2jBj2ALrY|{l7;?`H9ZF(0XU^-4+07;w%t{*^s$etvp|E zOZe^S;By|Q@g##~%soA?4TTD0Shc$)-@}sC4khcGAp9e}D#5KhLJBnISM=$4 z&3wl!^g8wY)ziq|BA)6VTHPfa=r$Bm@iUQ)akc0%ZXsA(b0%E43krU(w;Ve&xMaJZ zabXo?0!2ngdA~1OkaBZqqyFXtF$+S+6WM6;L)J)vcmz}=z&A{c0%e0Y9E94Xy+W5V zQjSnXd676QRjS)Sf7X!M>cJpP@Z*@_9e|t6082wt5 zmx+6b0mfJTYAEk=>egnz9SP4$-Hs`E6HRF$bI$S^xxEX-iCa0%5myD#^7q+)B!Oy( zoQ`z#+=XwkRPfsbacqSoWIX_6=kjEs2SQ8W@~)C6K<$}rNnVKr22*E<_(EagzWnCh z_QRjfLxsy*Ai_q{-j!!V*#t7ic1y0IsK)UzbYTJKyM7hXHy5<#yUGzEOJUZ9iR}KdW^D z5`7_j6K78f^|ER`Y-3?=sSjn}RJSujmSO1+hDo+rc`za6G~&Nrr{T%TMr1-B<@URk z??dGDHu_aM#;o<2=@VNM)vapM8@ATp_U^p)xM({jk8gc;oP4JjZ3IV5ScBU~NUu!F zXCK2g?S)nZf$-$N8$Nr(@lZ1;L|4&ZwKo zhA)7f7dzlkFUL~>bE$VH=wJj z$d}OC#VN~Rlp2*Xf_RmuA%qLVQ*P9r{L3i9(Gx@{TgyQqe3rphAv0z4G8&$5kNfwJ zS{kC1uzpfyGI^Y?{Uq&nzH(z_K>3Qa)&-dpR!U3GV&ZCS=H^O-=sqG^VErpe*CWCj zBJW#}r>Rx6?OL-Sa3Y3)#^RE0L<~*^$&?lTtBJ)#I+yc$t1E|&u5Jd!Ejss|P$W)R zYpy*}Z`v%#o2aE;5Gi z=rfvm%fjT`yGdOfh{lq5LiLeW=r8Ao#W~rWz;{fjPN&tAN+f07<3|y8AZp~x4g%(I zM))C7>7b>&Wa5!$DDW=MQDersx@H_@tUtOhmmf2{GDSONrIFaB^m)3waQh=@wnyL# z4Bj~Q?RS4L!FfY{$rr)opu);iZ7-XG8kj+h>4Fv6?lwk3a67m$tNrK*6$u(Tk=72B zu*NDG5=Uvd-5>6)RiS<9PaJD0Au8JQpG?Pq5hS-$k`*HMM8I%F`*HQ+$$w}l=|VP1 z4(*TsYTn8CB=G078L|5!uo&)2)`k1S(D3jqVZA45gGcPxv62f4lPQw>E!fjC1hb_I z$vP5G?+&-bJcAlC?7!r=9FC_AEN(c-_22iC&`D&+X$KC&9Fi59${gaqp?)R3@c(QV z1WWDaBz`UFE)k+Gq~#?;Oc}p&eO~?U2ueV*iZ6qVn{@2oS=Rc|kR9k9aiA!-yt?sL zg}H~u)Qm%J4*YO9VPdJhKtD1oKR*yv@-03)5OdLi)D_wk98;;Qp~V~E5RkN_Y|T3J z#b&hz6SEm{l6U`Z7MrQHs=2vYL4yV!7-R_4hI~d>yCY0}VW{uVax5L{iK(gXDf2eS z-#5Yuc#$M(*aI_KcGCh5PZ)##VViS8P1S44sN9mB4LRQ(P%Cpcb8yIZ3-yY3-A0HjXw4w3=umHYb z_NyfJ*e7FFaCBv5xeXs5ij{A=gK+S#+O|qtErE?d5_8Mv(Oog+IE_js?nQ13w!OW_ zm;NLK5O1BuNQA5;Klnx@2T9w?p(VJulfaFyY-g#rwCkkm$5^2yL$Dv> zN})|D|DT$^IxNcW`CG{a9$@K?r8`7gK$b;XIt7%HlHOWx_kHDU4ouVTNJnx9~I3ov7t(##0I+nA2 ziVYQ6y{M5-uovs!>)9wuR4u)_A_kFrIGzW#ak7-#BvTDAsu6h8=~aJ#lH0j?d;K>y ztfBLh?B*l{8`c&on`6l}D&U7y_@Gr|*=&S{$B}%=4ynNE9*10wklo?p;qA4xwdFZ= zUv3okZaS;$WE*8w8$184DCtV1--{P~JZ1K&Bp%*BRad}|MAxL+%Ml5${uM#`qhE4g zV>SZAH1_NR2!68kOOmd1Yx=*Ljh&XU8 z01~4a3B+Kv_hDXzns`@d!`4&zHEz{f`Eh*2#G;lpEU_`KV3pf|%6M`p{Ve1Z!-EK;%x_llgFA%~uX0=a>M{cf)3PI%*7 z1c!%>5x=ri0`ln4QFu8dPRlEP% z+YMOA+-^tT6RxHR-kwa4|DCOxdo+~JtLN3|yZAQt(~(iDmY?#C=t@Vu%_l5i{_z?^ zZstX4M3oABfCT2~?)kzAr+56Zk_RIOSG1n*&C$^EYv1!l-a$QkrR=^pk%+VG&!7Jo z<+DZ6tT#5iec#!3(t}@9!%y$pM%@%B`Le<2n&72+-N5ZhJ2nI9ExYPOdvxaHWFt^^8we1C``@LSI98rew^s3SqGyDe5xzpnP z^4C13v`>wj^rLjiQ^0zeRhZOOR9?H36Td|{v{l4h&^ZJt@~-E4xQInrmhqt{AU1oW zD4Kr$F;+F%K?w8&11a`qfZJ>GFuSTY`{Kv)y`z}_%5^B`ACXs=sL>R8Wc;<=`_{*Y zJv9VFG>H9p<>x)vB_(vR1e{#_b9Qrr*qq(KHA4N@0jIMb?b}ZwEKI7J5SGErF6Y&{ zbD7KEt#z*hFBc4GshC932Jx5g^IlFiIT#Mlozh91%pa7WCT_)?^71-ixWyCFrdIU* zm@WCiHM@KHZ}3Aj30W5#GjkXjOB7!pi<+(ByyA17BX6yKIYbhPMs8(tn$^V*=0w`_ zo)BBxH1@KRG#eMsFHfF~hAk=_^^AV~idXh?Z@S6GzG2by55ME1Dgt;w@d;Bi1!p&@ zC`d`l0LZAM#W#^M)pWiaS&5xqJ2kfXCLL_C>EvOY+$t%`T)cJNTt7cL;$P7+Ng7|D zMK?j@UfNW79+)np`%nD50v3yTgr;;3e29x1Ex+DAqOIKCyuG2= zsz1QetK9C8J;CkYvslduDF^%WaoiwuU@p38cemk8`@z6})S3F_3Jmh|n za|^_^Xa+1?jSZFY-HanEmXz^rHan?tamT=XvUczdSOG}YtncDRzE%vjqMyN{*8{*z`iPAt4DCs*`LWZ={HTL^(3CkZERDx{mOE zjN-k&DLYix-L?`T+)hgq#yIaY%CJAM-rMsFm6wP>Lr}REG1lkRNj3TmPsGK2ual4v zIdHUJpxO2iz+rgPoc{rg$j{^bnA6akS+u$uDPMQ_FW_y_q=vr!N2j@36VdTJ$#Y>f zNhOeyL?#ldNciTeah$vvpUO3C&Suxnr11r+ohs&k(1o76b)UQVD>S7)F`*(^wApZ8o8ea1Rmy{uGn!OIK16TQ9*s3q(q_DLo3wVu+=XG?H zGM_+3F!b`9j~7AV=}Yu*7MiG+T5G~#*D7x+N9#A^KBE-}-gGh1F@IF-h$MPlkl1G4ev_{SX*Mqd@pn^O^0(v5UJ zwOj~fT`j`I6EH|3T8!leOQs%=wY=k9cP`)0-$UxmncJ(YPcntx=06xiSoPYMa}hYJ3#E4lbWw^u?*&C#EVh@c&rp$( z-TrorefDN%*GUgid#tN4M9{Y28B6Q*z7h{kaN)=yOcuV0r6wP3>e6Q1J%jKjPIRY) z5@QZHvYM){YU$pDvC@3gYbDxOY{EgCbRV(cd;SZ^>DW3YQw%TK}5%aC&|ceUEH_V;%!n}K5kj_rFs3+_wVaSjH;TsW3|5``jX`{YG+5}#^^A6xz57nm#e7p|mA3|sn#BstaY>Q0CU$K}0OIlJS zCw|+6g;kS_5$UiCOg(U{-TvW>%XT{L{IzrO^k`O0d+E#%`x!%S%ZYsT>~eV3AQD(W zGX80oG?1|`pGL+U&LQLOf9l2K0313i%I#>7qTmt;g?Efk1i@m&$tx=b6_Ao{s{<5t zf1%J))@|DK?kB14Z>$dlv|HRq=?Bik{7S@Fsoqj7 zu&}MI`7&Sj$IpQJB_%bA2I+U2wFbB`2TqPnqk4rq4~zh+h0m#rSs*N~Siu$4y6Ua| zm0v<)X?fp0UnAtd^ZswOwd8K8R*!T~C0z_`8&kZS73`!((73jQ4--`n_-axjh>56NN2faM>?})44U| zHm-8Al`X@Q@=<1?sKIyjuV9FdPIMpoWumZws{oGP)=CT<2ML|X7_7fZU+;!u;*oPa zc^hUOOpGoLO~&E0W6BDiM-Eg4gQbYnbkig_)VZEL$ zd<`wF2TRQV z_*U(6TF|A6!9Q)luOgW}pixYzIz^m>yPthwlm3xH=d$Mdaxp1K?itZj1Q1g%}owWY$fOtY+ zFk>KWA`8PF9q9(xTLXYC!a7PgEsOarElF6Vu32Kf?gNC?zqIPRIVML(^JWjatf411 zO##gClV=>xV5p9u-$?RMeZ$(nO%4u_MC*vez5i<;gCGE_cs$b->3hGqx$*5v)^ur{ z@9UQitkVnimnz(v?F`isysx|cBa-LdXi(P)1VGInYssWWVHuhJi+ZHVM4)W`->sM; z7xF1Fn5>(x=jOP3G8ebF?L7w1=-Aag!z7LJS9v+jOazgL*Q`xrblkq3o!Q5#%AY|t zCtD481%bZaO#w{s6Jr#M$o|doqb0x6=RpZ^^%nAHRvDO!r!y7Wew?;Ki#AOOtERK)+ zBdq7Yi81f)0L_!L8UXmSd%~)Mb@Mx#-P3lG9jZ9adNmKIeEV$Edu<~plGLcC?kq>b z!=}}FW@<|7`s#Ft`BkNt5Rhcc#bIO;H!{l(e0>%gMn7!@R6kXc_B*2Mm*xjv*#e%4 zl(fz+MZ)TybM(TMaq17V5ik;<$#E?V7E@(QVY7V#XCVerx8_4cDx+1oI5>u(m7^%Q z6U>iN@l`$Lf3_ZcbF#ch(ctDP?&=HTOyIqC0B+g|V7Knuw@Y*Kt7~h&Be~&V6yP$- z)40d`Xo=z3@$iR5`#IC5py|>iw1_EXE}+NcAfy5FA$`TeT-nfA2cyPA${gNH?zdWi zpaE%3vC;Hw2JkJik_vh-iTNMlBDOtwTRVKn2%NP3u^Azn!c$v)qvA?M#$>s7e^TGf z=YFf!7`MuI`HWLh2^JA?TDqA?<t=V>7`!*1BMzw5z$B;`9|w+&(1o&{Q3K<&21A8)${1MyV`M5Z&_!A7o*Bs zh@iz;e|S%A_s#KtAi5fS{Gqo-%3Kw>md!7k&1c#9>ww@nsH^M`An0slu*yK3Y%nM9 zXY_;g8uV#TL-YX_e{XH zr>v|r^y=@*%_cX0g!nylRV(9^zosF@4cOAR9{-vX?9*}$8ak!p3cx@Mo8Hz5_^tR4 z_vv5VM)ln=P74;pkPn65EtqNh_GK1YJbX6C{M^Q6?hU)7C(DX_FAmr4-8KyJpR%*F?=vO6_R|MWlE72bz~v24v?M=ZDP`QIfo(^F=SvGj6??Yg;u)1n zn)UPl267{pNG!@CYfQ^PxO6bW=VHOZj2Umx;4<}KG1xg=Ln#$UI%u9yElBCfV@>qA z`tPQKuKS|)bM3#*m;CNaPj@IB2%GWAaZq(9ovG6oV6aSH6DQAF+rAQN)|j1L+P>5C zaWS-YQrPbdQMdDV|LzCyHh|$509yUOB!sitHR#rh(OO?Yt$r6)3Um%g;B zf!+IUI#(M1IWr*U)7nDUaB6Kqn96J>tNx-l(Ivf)8KsfAHOAm~p|`7U3W}XcUmeqm zgGO%sZ48q;Yrk=m-}nx#esa2fKQZh2bhjmHOYE=bfp$(i3d1uT5KFG+IXip1qwsI@ zHCU|&2Lj_pMgQcOg7bZ;8Sa7m?;XY|%%^zLG;#`jBt3>?F4GnoTZ|PTEP@nL`(iDO~>)ITwkx9FVE8iU7HZL7UL#1TfIr zIO2n&B72FxfJmV;!S+N2++8>{A-g}e$niE8c@rF85xcy~qNl@$M$G{b_6UPhph!ic zFe5A#IHVFQjV^<;L12oTX9|su>{FNpNj4hmW{CX!+O6!k$Xws~5HN|$c+t7xznj4K;aCDPczGx`2c-`B>=>UehKSrHH_%03_lt`vj?l))eeQs}% z2B#TN>`9uVawsu>h+KI!nw$&)5|ff}{ilks8FNxukT$z%(Ax-`>$87J3+~=sH2`ov z!|PtjEDVf%5W4$dfKWl(S?aOS-Az%)b?H#$GO0uqeXr$za}~xjS9$~5D~|+d!;fsL z&(x!2>W{6I&knAK?smA34uVXGw6?s9Dr^yrRXg&yfWddk0zg@$3gBq@anzHKOObX= zbZflMZ;V5SNm2r38Yw z76O51QaE|SW#40P8}rs&TN9EF#l8V2v$|((g?ZyWIwBXFX^9rOFl2I#8uV&64c{3l z(~tfBU2jq*ptbB|qK6^iBsLFNH}eWGcWRW{Q&;k{)Z@QM`uug1X>Tqr_Hqiqp&Lmr zQcI>$y-CyYj1mcFCPIshvcM(S79Rk1GtAMz@TFdWyH3x1kG7E3FotnXC+U`}j7>J# z3?Ta0p)6J_W~Xjhtf|R;1yA(Xgda>ZZdZ}hJqcF$8BS8cIjMR@!s;9)mQ|iSgFPo8 zEozkRp9aT=z1z~%dDT(fY(EyuZ5rhL=ahm~)(ZrI2|bWZ_xX3$<$F4d&POT8B*ID# z2-7>c{7Gdrsn|?v-=H;i%1bDRL+)^lA7M*S_if&N>&_+jeYyis=Ye@q5nIWJ(LFcN z_efmmZSkO`Enpwf!maui$hzOu)1%%(2sG^H@?<)C2t1V`V*i&c=$gC;IDVJOEBs~e z!AhAud+EbJ*dI0KffOl$iW5>1uW!uHZ`VKPofPPsq-D{?S|p@Rgphfw>WG`|w4p{% z+10B?vUV}#EGVB$EC{5PB8;;os+Toemy}-EC32E#JJ)!(_!;lO=Z-xmxlkPrCbma? zt1qq0{iOm$9JTP4Q-*1_HYr{~f&mVlFP&w|R_`esr`xzG;f*3z2s46+hvhO_cSPT~ zqujmZppRfQ;2~(^3!|nGIvPk)OY)m#w zqx4EutPnYti7+^esMbKl_x=d_Y4rPpd)l!ak-eZ3^&slAWu*x^C`bu}`sU(=GKY*6Y3o}7S(Wqt_(hwp`sT$!4)<3v7<)N&t8o3Azczl?dv*FeMo%w(vTPAR;4CPtAA|)hHt_gvsO+^!srj$Cr(>z; zxO6O}BO)Q{A|Z0`3MR1AjlVNQ%{+e)Wqvn%Rs<9TIey^iN!vj~27{Q@Z}_Vw)z^g+ zvS@t+CL@-7-#IBqIGm$clvg43kNYD|7RykDbWrFdo)?8Mo(@|4SiTEdTb3nvQsXEJS=fa>qyT>~yHlai`Ibc-Ugj`&EK z!1sw&;LTB~T!-hZbe|mu;QX|J^Mi>od%D&bg7~SVkF{!$66Vcz6$&I>`7avMW!2t> z$f;48R4?s}xD}Rxt87G!gUaKQcl)u_;yPR%C4-+#QZX4#Z)6w!982{}8*~+;QI-;ox@6K)RZ-VSn5$DXZS!AD(XCy>DlrUdV3;se==P}^UeY-nCxY>o;^-@!a$f3J=>OR zv=>GwJw}3MLNJ7#I5xR%HcHi!V^v5&LB(9YhbF>o?GF))~!C zp6z!uJ2epF0<2*_h})XJ{di9_QjOB*v%DLg&Um#stNRwKla%g+92vL^L<_YdqrP$( z$TukYDLbS1!VI00gIoXm!3|KH2X?t{XU?U(SAm14EFNqD2g)TXd9>D$>>@O!6F~*p`I!RmM8+Q6?0HB|xS&0DtL(hW%MMDo*oBcOgS$%RuFCZl=sbY1WhvM}HZp ze@S}o-5-7{DJo?_h3MiTIUvD7ljE-W{4PVZU%YJn^J^z&I_=710Lc{skmdBv3Eojd zRVH!L$5#nJG@}_gyKS`9jXV!a17-zJ-*v3zZw57RJ_x^<1|_ZJf!?~J@vYVM@s84A z)8hAA4m{xmnZ{F%&!v1-3MYzsA?~SYsaz|P*qg>*T&$jCF{mH`Na_CdzVF>=4{N6! za6>2*bwdT}-rwnSZOY4k;PF{k-|Fp`J(p^Dg5}qcIdnT!0YrB4u+m3Uz`jUG^t(u6 z4>Bz|FRy;QP4qsvtji(vKN=}G@Lf%oB>71N_;SO8=q1*#c0>ur#`&-Ei0i|k3Tu=0 zRN7K_w05J1Ok`+tPjM0#_RgX`i~`G^52tVyvEVArl;59KMLPQZt-ki50z9Yte{^0{ z%s)n;6V~)xbGpN^H)%-Tv8MD{3U<#l_CneRyUxx$e=Ib*J9wL$*~Gc=1w^ti8EyAU z*I6$_eCsL*_;Iunw3v1q_rn;#NF5vP9n+SK7ie&04@&gE!+fU!@}GmcJ%Gdn2DB&z``vKMEB2}pFeZG z2413evCjlU6@NW&B^500*0S`}`%vklT28v;n}MixYf@4P^GIq!kWRc}QyWsIg3%d7 z=l7lkHrscg)so27UfJi`5Qw-DrV?Jg7titzAM4b2R~Wux-X#5@^0wVA3eg> zRD#Ls1g*!fC1i@c0HXW$|Cps5DQ;?d>J*wf%7jDbZKI}6EFpl}4Hf*^23jTIoKx&FtQX7#Ie_b!Eatn$sFN0`-`V@p(R?PIDcj?mVLVnh-t7;R7^{H zuQ*9pmY?nQlQ1wz&qhRhD@m?W?Y%b2mlAP?z&j@~-o#a@O@KpbrGEan9HZ~pZFnO) zoks%rI29^LgAjwfA06)Ht*j=;D=VL0*~U#4>-#aRZ(gDoJR2U$Mic>wYLGj6cSo4 zQ@NEu`Zq(1-61~6pjYxVlT((gs32na5XTMJW%Gkjh=tW}&UdWI$OtcPgBzqjDZj8X zP)pz1=k+C(5O8sDa?(GcmP&=FS)tO-YvUY&u^GJj<9YC6h3+JXhGP|1wy5@H^?Pv+ zfZ{_r2Z6bzFaF!;TtdgX8R{hpzr|H=$ewDLS+rl%HF{zs5Dj}8OnhQ)oHYvY#;Gd1 z5*6-Knm(X4ufhG?@dp!i&yAKtNg@^?Vgpol4psbmlz6xmWEY`Zv4Z#tjm+kFBvm3& z+zy=SoH@wQl68M8lAC>!`2#1S21K%kiSi1F3wEf2sp)~_OZwTM<6d092v(DPLMV@l zdZlc9Ylw58>cwet;4}#aL1&QI3)VndrV$uHr}|;ArnxgWg?N8N52uYq(FFx2K0qrv z_(9>tD3Zna|@!aiMv>^Ye>eI3xM7<@YoW=Bw7vFHVgYT^1h34%Im zUW4n~@Z$nO*h@?jkz)6h2&|*K)lcR)Rk?urm9QSHKuOuu=VqDWRK};5!4H3UKVxpr zTrj&+mc1ZafJJwGfzkbU$EvzIkr+H-Nk58etLi(MCJUN&zvlt@yX*7Vutq_7(7O+huAwvlZ-umj=okhin?A=j%e{fS6e%KGnQZVw7J=waO^n_1ipojivLje zu~%QbI*p&cUvc-7ebGX?9nwU`J4o=0n|1w#@VVN_x3MA!uxDcpv%V%4J$@$1h+J8ZPuH=0gnZR~~G zXlUXU=mYDPj`|3qWPrjf{^0^#!uLIv``C#oS&*` z+4TJ6jHS)R*{e^H1d(Rzmz%H1*~}CGIV80{7(EE5uj7E;C_lxbhKHw#V0aj;XW&cu zp9#^lZnEaD!xnLW!sUa#nxR1Kd}fcrk7JzR{M8hlkM=f>;8Hpo%Xjuon|%Xo*K^r5 z{h4{^x65bGmhb(0tSztT>)8-Yk$rDSP3!u0oHMf*9m5*yClAd6x>i40=iA;1?B@Z> zfVw|=a3dJzm-M}RKcnn=^#WBYc6b;& z)}HEgEIKO(b{D=5?B*E$N^1KlBKkk6yo3B)ByrRfaYNMaBj5NTjQ?()`Oja71SU|L zwXyK!u>pMgf**96gz>?lor2r^7dhlsw*KWGN43!n&+S z3Xr%bf7ouhcHo=vW%Rk7luuG1U4KWJsaThlm(;VP+=%jj{3(qFoJWU2g(K!>C zuayCFOImqwOQ=?qeCz-jc`QeIf?^C9arbSE>=wbd9yG8DBbEZu-mSr9UI%ivT-`5D zFfMtu4G1dCma-ikn|MWMXL=?8@#25@P2iiM$MY5@*7#IwcZJD9IvOi^cJ)yXtFaLR xO$Q6sw<69t&+BCgM3;H)dc9&$|0hcXy$Pab-&Ym;cKZnRrzHOpRttR-`hNrp5(xkR literal 0 HcmV?d00001 From 8d7cc20b70069e89c03db7eaa802bde33904f9dc Mon Sep 17 00:00:00 2001 From: Sultan Khan Date: Fri, 4 Dec 2020 09:36:05 +0300 Subject: [PATCH 09/71] localized value updated --- lib/config/localized_values.dart | 2 +- pubspec.yaml | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/config/localized_values.dart b/lib/config/localized_values.dart index 4401a293..59283a0f 100644 --- a/lib/config/localized_values.dart +++ b/lib/config/localized_values.dart @@ -1198,7 +1198,7 @@ const Map localizedValues = { "referralNumber": { "en": "Referral Number", "ar": "رقم الإحالة" - } + }, "requestID": { "en": "Request ID", "ar": " رقم الطلب" diff --git a/pubspec.yaml b/pubspec.yaml index 804405bc..f375d63d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -153,7 +153,6 @@ dependencies: twilio_programmable_video: ^0.5.0+3 flutter_tts: ^1.3.0 vibration: ^1.7.2 - fit_kit: ^1.1.2 speech_to_text: path: speech_to_text From 8c5746f7b19b4ecece4efede00a29665c9d7c701 Mon Sep 17 00:00:00 2001 From: Sultan Khan Date: Thu, 3 Dec 2020 19:43:45 +0300 Subject: [PATCH 10/71] bug fixes --- lib/config/localized_values.dart | 387 ++++++------------ .../weather/weather_view_model.dart | 2 +- .../all_habib_medical_service_page.dart | 6 +- .../health-weather-indicator.dart | 156 +++---- lib/pages/DrawerPages/family/my-family.dart | 24 +- lib/pages/landing/landing_page.dart | 8 +- lib/uitl/location_util.dart | 10 +- lib/uitl/translations_delegate_base.dart | 89 +++- 8 files changed, 324 insertions(+), 358 deletions(-) diff --git a/lib/config/localized_values.dart b/lib/config/localized_values.dart index 59283a0f..6464db31 100644 --- a/lib/config/localized_values.dart +++ b/lib/config/localized_values.dart @@ -111,10 +111,7 @@ const Map localizedValues = { 'login': {'en': 'Login', 'ar': 'تسجيل الدخول'}, 'loginregister': {'en': 'Login / Register', 'ar': 'تسجيل الدخول'}, 'poweredBy': {'en': 'Powered By', 'ar': 'مشغل بواسطة'}, - "welcome": { - "en": "Welcome", - "ar": "مرحبا" - }, + "welcome": {"en": "Welcome", "ar": "مرحبا"}, "welcome_text": { "en": "Dr. Sulaiman Al Habib Mobile Application", "ar": "الدكتور سليمان الحبيب لتطبيقات الهاتف المتحرك" @@ -130,12 +127,11 @@ const Map localizedValues = { "ar": "اختر من الخيارات أدناه لتسجيل الدخول إلى ملفك الطبي." }, "registernow": {"en": "Register Now", "ar": "تسجيل الان"}, - "nationalID": { "en": "Enter the Identification Number", - "ar": "أدخل رقم الهوية الوطنية او الاقامة"}, - "national-id": { - "en": "National ID", - "ar": "رقم الهوية" + "nationalID": { + "en": "Enter the Identification Number", + "ar": "أدخل رقم الهوية الوطنية او الاقامة" }, + "national-id": {"en": "National ID", "ar": "رقم الهوية"}, "fileNo": {"en": "File Number", "ar": "رقم الملف"}, "fileno": {"en": "File No", "ar": "رقم الملف"}, "forgotFileNo": {"en": "Forgot file Number?", "ar": "نسيت رقم الملف الطبي؟"}, @@ -680,38 +676,20 @@ const Map localizedValues = { }, // pharmacy module - "medicationRefill": { - "en": "MEDICATION REFILL", - "ar": "إعادة تعبئة الدواء" - }, + "medicationRefill": {"en": "MEDICATION REFILL", "ar": "إعادة تعبئة الدواء"}, "offersAndPromotions": { "en": "OFFERS & SPECIAL PROMOTIONS", "ar": "العروض والترقيات الخاصة" }, - "myPrescriptions": { - "en": "MY PRESCRIPTIONS", - "ar": "وصفاتي" - }, + "myPrescriptions": {"en": "MY PRESCRIPTIONS", "ar": "وصفاتي"}, "searchAndScanMedication": { "en": "SEARCH & SCAN FOR MEDICATION", "ar": "البحث والمسح للأدوية" }, - "shopByBrands": { - "en": "Shop By Brands", - "ar": "تسوق حسب الماركات" - }, - "recentlyViewed": { - "en": "Recently Viewed", - "ar": "شوهدت مؤخرا" - }, - "bestSellers": { - "en": "Best Sellers", - "ar": "أفضل البائعين" - }, - "deleteAllItems": { - "en": "Delete All Items", - "ar": "حذف كافة العناصر" - }, + "shopByBrands": {"en": "Shop By Brands", "ar": "تسوق حسب الماركات"}, + "recentlyViewed": {"en": "Recently Viewed", "ar": "شوهدت مؤخرا"}, + "bestSellers": {"en": "Best Sellers", "ar": "أفضل البائعين"}, + "deleteAllItems": {"en": "Delete All Items", "ar": "حذف كافة العناصر"}, "select-gender": {"en": "Select Gender", "ar": "اختر الجنس"}, "i-am-a": {"en": "I am a ...", "ar": "أنا ..."}, "select-age": {"en": "Select Your Age", "ar": "حدد العمر"}, @@ -720,9 +698,12 @@ const Map localizedValues = { "drag-point": { "en": "Drag point to change your age", "ar": "اسحب لتغيير عمرك" - },"HHCNotAuthMsg": { - "en": "This service provides a set of home health care services, continuous and comprehensive follow-up in their places of residence for those who cannot access health facilities, such as (laboratory analyzes - radiology - vaccinations - physical therapy), etc.", - "ar": "من خلال هذه الخدمة يمكنك طلب مجموعة من الفحوصات التي تساعدك وتساعد طبيبك في فهم حالتك الصحية الحالية ومن ثم تحديد المخاطر المحتملة" + }, + "HHCNotAuthMsg": { + "en": + "This service provides a set of home health care services, continuous and comprehensive follow-up in their places of residence for those who cannot access health facilities, such as (laboratory analyzes - radiology - vaccinations - physical therapy), etc.", + "ar": + "من خلال هذه الخدمة يمكنك طلب مجموعة من الفحوصات التي تساعدك وتساعد طبيبك في فهم حالتك الصحية الحالية ومن ثم تحديد المخاطر المحتملة" }, "email": {"en": "Email", "ar": "البريد الالكتروني"}, "Book": {"en": "Book", "ar": "احجز"}, @@ -912,8 +893,14 @@ const Map localizedValues = { "LiveChat": {"en": "Live Chat", "ar": "محادثة مباشرة"}, "Service": {"en": "Service", "ar": "خدمة"}, "HMGServiceLabel": {"en": "HMG Service", 'ar': 'خدمات الحبيب'}, - "HealthWeatherIndicators": {"en": "Health Weather Indicators", 'ar': ' مؤشرات الطقس الصحية '}, - "HealthTipsBasedOnCurrentWeather": {"en": "Health Tips Based On Current Weather", 'ar': ' نصائح صحية على أساس الطقس الحالي '}, + "HealthWeatherIndicators": { + "en": "Health Weather Indicators", + 'ar': ' مؤشرات الطقس الصحية ' + }, + "HealthTipsBasedOnCurrentWeather": { + "en": "Health Tips Based On Current Weather", + 'ar': ' نصائح صحية على أساس الطقس الحالي ' + }, "MoreDetails": {"en": "More details", "ar": " المزيد من التفاصيل "}, "SendCopy": {"en": "Send Copy", "ar": "ارسال نسخة"}, "ResendOrder": {"en": "Resend order & deliver", "ar": "إعادة طلب و توصيل"}, @@ -922,125 +909,59 @@ const Map localizedValues = { "Average": {"en": "Average", "ar": "المعدل"}, "DailyDoses": {"en": "Daily Doses", "ar": "جرعات يومية"}, "Period": {"en": "Period", "ar": "الفترة"}, - "cm": { - "en": "CM", - "ar": "سم" - }, - "kg": { - "en": "kg", - "ar": "كجم" - }, - "mass": { - "en": "Mass", - "ar": "كتلة" - }, - "temp-c": { - "en": "°C", - "ar": "°س" - }, - "bpm": { - "en": "bpm", - "ar": "نبضة" - }, - "respiration-signs": { - "en": "Respiration", - "ar": "تنفس" - }, - "sys-dias": { - "en": "SBP/DBP", - "ar": "إنقباض/إنبساط" - }, - "body": { - "en": "Body \n Mass", - "ar": "كتلة\nالجسم" - }, - "feedback": { - "en": "Feedback", - "ar": "رأيك يهمنا" - }, - "send": { - "en": "Send", - "ar": "أرسل" - }, - "status": { - "en": "Status", - "ar": "الحالة" - }, + "cm": {"en": "CM", "ar": "سم"}, + "kg": {"en": "kg", "ar": "كجم"}, + "mass": {"en": "Mass", "ar": "كتلة"}, + "temp-c": {"en": "°C", "ar": "°س"}, + "bpm": {"en": "bpm", "ar": "نبضة"}, + "respiration-signs": {"en": "Respiration", "ar": "تنفس"}, + "sys-dias": {"en": "SBP/DBP", "ar": "إنقباض/إنبساط"}, + "body": {"en": "Body \n Mass", "ar": "كتلة\nالجسم"}, + "feedback": {"en": "Feedback", "ar": "رأيك يهمنا"}, + "send": {"en": "Send", "ar": "أرسل"}, + "status": {"en": "Status", "ar": "الحالة"}, "like-to-hear": { - "en": "We would love to hear the feedback, concerns on healthcare services and eServices experience. Please use the below form", - "ar": "يسعدنا سماع ملاحظاتك حول خدمات الرعاية الصحية والخدمات الإلكترونية. يرجى تعبئة الحقول المطلوبة" - }, - "subject": { - "en": "Subject", - "ar": "الموضوع" - }, - "message": { - "en": "Message", - "ar": "رسالة" + "en": + "We would love to hear the feedback, concerns on healthcare services and eServices experience. Please use the below form", + "ar": + "يسعدنا سماع ملاحظاتك حول خدمات الرعاية الصحية والخدمات الإلكترونية. يرجى تعبئة الحقول المطلوبة" }, + "subject": {"en": "Subject", "ar": "الموضوع"}, + "message": {"en": "Message", "ar": "رسالة"}, "empty-subject": { "en": "Please enter the subject", "ar": "يرجى ادخال الموضوع" }, - "empty-message": { - "en": "Please enter message", - "ar": "يرجى ادخال الموضوع" - }, - "select-attachment": { - "en": "Select Attachment", - "ar": "إختر المرفق" - }, - "complain-appo": { - "en": "Complaint for appointment", - "ar": "شكوى على موعد" - }, + "empty-message": {"en": "Please enter message", "ar": "يرجى ادخال الموضوع"}, + "select-attachment": {"en": "Select Attachment", "ar": "إختر المرفق"}, + "complain-appo": {"en": "Complaint for appointment", "ar": "شكوى على موعد"}, "complain-without-appo": { "en": "Complaint without appointment", "ar": "شكوى بدون موعد" }, - "question": { - "en": "Question", - "ar": "سؤال" - }, - "message-type": { - "en": "Message Type", - "ar": "نوع الرسالة" - }, - "compliment": { - "en": "compliment", - "ar": "ثناء" - }, - "suggestion": { - "en": "Suggestion", - "ar": "إقتراح" - }, - "your-feedback": { - "en": "Your feedback was sent", - "ar": "إقتراح" - }, + "question": {"en": "Question", "ar": "سؤال"}, + "message-type": {"en": "Message Type", "ar": "نوع الرسالة"}, + "compliment": {"en": "compliment", "ar": "ثناء"}, + "suggestion": {"en": "Suggestion", "ar": "إقتراح"}, + "your-feedback": {"en": "Your feedback was sent", "ar": "إقتراح"}, "select-part": { "en": "Please select the part that complain about", "ar": "يرجى تحديد الجزء الذي تشكو منه" }, - "number": { - "en": "Number", - "ar": "الرقم" - }, - "not-classified": { - "en": "Not classified", - "ar": "غير محدد" - }, + "number": {"en": "Number", "ar": "الرقم"}, + "not-classified": {"en": "Not classified", "ar": "غير محدد"}, "selectClinic": {"en": "Select Clinic", "ar": " بحث بالعيادة"}, "reviews": {"en": "Reviews", "ar": "تقييمات"}, - "searchItemError": {"en": "Item name should be more than 3 character ", "ar": "يجب أن يكون اسم العنصر أكثر من 3 أحرف"}, + "searchItemError": { + "en": "Item name should be more than 3 character ", + "ar": "يجب أن يكون اسم العنصر أكثر من 3 أحرف" + }, "YouCanFind": {"en": "You Can Find ", "ar": "باستطاعتك العثور على "}, "ItemInSearch": {"en": " Item In Search", "ar": " عنصر في البحث "}, - "blood-donation": { - "en": "Blood Donation", - "ar": "التبرع بالدم" - }, + "blood-donation": {"en": "Blood Donation", "ar": "التبرع بالدم"}, "blood-instruction": { - "en": "Enter the required information, In order to register for Blood Donation Service", + "en": + "Enter the required information, In order to register for Blood Donation Service", "ar": "ادخل المعلومات المطلوبة للتسجيل بخدمة التبرع بالدم" }, "view-terms": { @@ -1050,64 +971,26 @@ const Map localizedValues = { "InvoiceNo": {"en": " Invoice No", "ar": "رقم الفاتورة"}, "SpecialResult": {"en": " Special Result", "ar": "نتيجة خاصة"}, "GeneralResult": {"en": "General Result", "ar": "نتيجة عامة"}, - "show-more-btn": { - "en": "Flow Chart", - "ar": "النتائج التراكمية" - }, + "show-more-btn": {"en": "Flow Chart", "ar": "النتائج التراكمية"}, - "value": { - "en": "Value", - "ar": "القيمة" - }, - "range": { - "en": "Range", - "ar": "المدى" - }, - "out-patient": { - "en": "Out Patient", - "ar": "عيادات خارجية" - }, - "in-patient": { - "en": "In Patient", - "ar": "تنويم" - }, - "report": { - "en": "Radiology Report", - "ar": "تقرير الاشعة" - }, - "open-rad": { - "en": "Open Image", - "ar": "فتح صور الاشعة" - }, - "send-copy": { - "en": "Email the Report", - "ar": "أرسل التقرير" - }, - "appoSurvey": { - "en": "Survey", - "ar": "إستبيان" - }, - "appoSurveySubtitle": { - "en": "Survey", - "ar": "إستبيان" - }, + "value": {"en": "Value", "ar": "القيمة"}, + "range": {"en": "Range", "ar": "المدى"}, + "out-patient": {"en": "Out Patient", "ar": "عيادات خارجية"}, + "in-patient": {"en": "In Patient", "ar": "تنويم"}, + "report": {"en": "Radiology Report", "ar": "تقرير الاشعة"}, + "open-rad": {"en": "Open Image", "ar": "فتح صور الاشعة"}, + "send-copy": {"en": "Email the Report", "ar": "أرسل التقرير"}, + "appoSurvey": {"en": "Survey", "ar": "إستبيان"}, + "appoSurveySubtitle": {"en": "Survey", "ar": "إستبيان"}, - "vaccination": { - "en": "Vaccination", - "ar": "جدول التطعيمات" - }, - "welcomeBack": { - "en": "Welcome back", - "ar": "مرحبا مرة أخرى" - }, + "vaccination": {"en": "Vaccination", "ar": "جدول التطعيمات"}, + "welcomeBack": {"en": "Welcome back", "ar": "مرحبا مرة أخرى"}, "instructions": { - "en": "Please ensure that the email address is up-to-date and process to view the schedule", + "en": + "Please ensure that the email address is up-to-date and process to view the schedule", "ar": "يرجى التأكد من صحة عنوان البريد الالكتروني و المتابعة لعرض الجدول " }, - "update-email": { - "en": "Update Email", - "ar": "تحديث البريد الالكتروني" - }, + "update-email": {"en": "Update Email", "ar": "تحديث البريد الالكتروني"}, "updated-email": { "en": "Updated email successfully", @@ -1119,42 +1002,19 @@ const Map localizedValues = { "ar": "عرض قائمة الأطفال" }, - "add-child": { - "en": "Add New Child", - "ar": "اضافة طفل" - }, - "child-name": { - "en": "Child Name", - "ar": "اسم الطفل" - }, - "childDob": { - "en": "Birth Date", - "ar": "تاريخ الولادة" - }, - "delete": { - "en": "Delete", - "ar": "حذف" - }, + "add-child": {"en": "Add New Child", "ar": "اضافة طفل"}, + "child-name": {"en": "Child Name", "ar": "اسم الطفل"}, + "childDob": {"en": "Birth Date", "ar": "تاريخ الولادة"}, + "delete": {"en": "Delete", "ar": "حذف"}, "deleted-child-mes": { - "en": "The request was successful. The children have removed from the vaccination schedule subscription service.", + "en": + "The request was successful. The children have removed from the vaccination schedule subscription service.", "ar": "تم حذف الطفل بنجاح" }, - "deleted-child":{ - "en":"Delete child", - "ar":"إالغاء الطفل" - }, - "visit": { - "en": "Visit", - "ar": "زيارة" - }, - "description-vaccination": { - "en": "Description", - "ar": "وصف" - }, - "due-date": { - "en": "Due date", - "ar": "تاريخ الاستحقاق" - }, + "deleted-child": {"en": "Delete child", "ar": "إالغاء الطفل"}, + "visit": {"en": "Visit", "ar": "زيارة"}, + "description-vaccination": {"en": "Description", "ar": "وصف"}, + "due-date": {"en": "Due date", "ar": "تاريخ الاستحقاق"}, "valid-email": { "en": "Please enter valid email", "ar": "الرجاء إدخال عنوان بريد صحيح" @@ -1164,57 +1024,60 @@ const Map localizedValues = { "ar": "ارسال جدول التطعيمات الى بريدك الالكتروني؟" }, "email-success": { - "en": " The request was successful. You will receive the Schedule in moments.", + "en": + " The request was successful. You will receive the Schedule in moments.", "ar": "تم ارسال جدول التطعيمات " }, "add-instructions": { - "en": "Add the child's information below to recieve the schedule of vaccinations.", + "en": + "Add the child's information below to recieve the schedule of vaccinations.", "ar": "أضف معلومات الطفل لاستلام جدول التطعيمات" }, "added-child": { - "en": "The request was successful. You have added a child to the vaccination schedule subscription service.", + "en": + "The request was successful. You have added a child to the vaccination schedule subscription service.", "ar": "تمت الاضافة بنجاح." }, - "appUpdate": { - "en": "UPDATE THE APP", - "ar": "تحديث التطبيق" - }, + "appUpdate": {"en": "UPDATE THE APP", "ar": "تحديث التطبيق"}, "ereferralSaveSuccess": { - "en": "The referral request has been submitted successfully, you will be contacted ASAP to complete the process. Referral request no is ", - "ar": " تم إرسال طلب الإحالة بنجاح ، وسيتم الاتصال بك في أسرع وقت ممكن لإكمال العملية. رقم طلب الإحالة" - }, - "referralStatus": { - "en": "Referral Status", - "ar": "حالة الإحالة" - }, - "referralDate": { - "en": "Referral Date", - "ar": "تاريخ الإحالة" - }, - "patientName": { - "en": "Patient Name", - "ar": "اسم المريض" - }, - "referralNumber": { - "en": "Referral Number", - "ar": "رقم الإحالة" - }, - "requestID": { - "en": "Request ID", - "ar": " رقم الطلب" - }, - "OrderStatus": { - "en": "Status", - "ar": "الحاله" - },"pickupDate": {"en": "Pickup Date", "ar": "التاريخ"}, + "en": + "The referral request has been submitted successfully, you will be contacted ASAP to complete the process. Referral request no is ", + "ar": + " تم إرسال طلب الإحالة بنجاح ، وسيتم الاتصال بك في أسرع وقت ممكن لإكمال العملية. رقم طلب الإحالة" + }, + "referralStatus": {"en": "Referral Status", "ar": "حالة الإحالة"}, + "referralDate": {"en": "Referral Date", "ar": "تاريخ الإحالة"}, + "patientName": {"en": "Patient Name", "ar": "اسم المريض"}, + "referralNumber": {"en": "Referral Number", "ar": "رقم الإحالة"}, + "requestID": {"en": "Request ID", "ar": " رقم الطلب"}, + "OrderStatus": {"en": "Status", "ar": "الحاله"}, + "pickupDate": {"en": "Pickup Date", "ar": "التاريخ"}, "serviceName": {"en": "Service Name", "ar": " اسم الخدمة"}, "orderLocation": {"en": "Location", "ar": "الموقع"}, "selectService": {"en": "Select Service", "ar": "حدد الخدمة"}, "coveredService": {"en": "Covered Service : ", "ar": " الخدمات المغطاة : "}, "selectAddress": {"en": "Select Address", "ar": "حدد العنوان"}, "addNewAddress": {"en": "Add New Address", "ar": "أضف عنوان جديد"}, - "selectedService": {"en": "Selected Service : ", "ar": " الخدمات المختارة : "}, - "cancelOrderMsg": {"en": "Are you sure!! want to cancel this order", "ar": "هل أنت واثق!! تريد إلغاء هذا الطلب"}, - "processDoneSuccessfully": {"en": "Process Done Successfully", "ar": "تمت العملية بنجاح"}, - "selectHomeHealthCareServices": {"en": "Select Home Health Care Services", "ar": " حدد خدمات الرعاية الصحية المنزلية"}, + "selectedService": { + "en": "Selected Service : ", + "ar": " الخدمات المختارة : " + }, + "cancelOrderMsg": { + "en": "Are you sure!! want to cancel this order", + "ar": "هل أنت واثق!! تريد إلغاء هذا الطلب" + }, + "processDoneSuccessfully": { + "en": "Process Done Successfully", + "ar": "تمت العملية بنجاح" + }, + "selectHomeHealthCareServices": { + "en": "Select Home Health Care Services", + "ar": " حدد خدمات الرعاية الصحية المنزلية" + }, + "family-info": { + "en": + "Through this service, you will be able to link your family medical files to your medical file so that you can manage their records by login to your medical file.", + "ar": + "هذه الخدمة تم تصميمها لتتمكن من ربط الملفات الطبية للعائلة بملفك الطبي حتى تتمكن من إدارة سجلاتهم عن طريق تسجيل الدخول إلى ملفك الطبي." + } }; diff --git a/lib/core/viewModels/weather/weather_view_model.dart b/lib/core/viewModels/weather/weather_view_model.dart index 85b019e4..bb201843 100644 --- a/lib/core/viewModels/weather/weather_view_model.dart +++ b/lib/core/viewModels/weather/weather_view_model.dart @@ -13,7 +13,7 @@ class WeatherViewModel extends BaseViewModel { WeatherService _weatherService = locator(); List get weatherIndicatorData => _weatherService.weatherIndicatorData; - getWeatherData({int id, int projectID}) async { + getWeatherData() async { setState(ViewState.Busy); // if (id != null && projectID != null) { diff --git a/lib/pages/AlHabibMedicalService/all_habib_medical_service_page.dart b/lib/pages/AlHabibMedicalService/all_habib_medical_service_page.dart index 143b6435..49c49811 100644 --- a/lib/pages/AlHabibMedicalService/all_habib_medical_service_page.dart +++ b/lib/pages/AlHabibMedicalService/all_habib_medical_service_page.dart @@ -52,6 +52,8 @@ class _AllHabibMedicalServiceState extends State { void initState() { WidgetsBinding.instance.addPostFrameCallback((timeStamp) { getAuthUser(); + locationUtils = + new LocationUtils(isShowConfirmDialog: true, context: context); locationUtils.getCurrentLocation(); }); super.initState(); @@ -384,7 +386,7 @@ class _AllHabibMedicalServiceState extends State { }); } var data = await this.sharedPref.getObject(WEATHER); - weather = data['Temperature'].toString() + '\u2103' ?? '--'; - + weather = data != null ? data['Temperature'].toString() + '\u2103' : '--'; + print(data); } } diff --git a/lib/pages/AlHabibMedicalService/health-weather/health-weather-indicator.dart b/lib/pages/AlHabibMedicalService/health-weather/health-weather-indicator.dart index 19974e0e..2f2540e8 100644 --- a/lib/pages/AlHabibMedicalService/health-weather/health-weather-indicator.dart +++ b/lib/pages/AlHabibMedicalService/health-weather/health-weather-indicator.dart @@ -18,110 +18,120 @@ class HealthWeatherIndicator extends StatefulWidget { _HospitalsPageState createState() => _HospitalsPageState(); } - class _HospitalsPageState extends State { var data; AppSharedPreferences sharedPref = AppSharedPreferences(); LocationUtils locationUtils; var weather = '--'; - @override + @override void initState() { locationUtils = - new LocationUtils(isShowConfirmDialog: true, context: context); + new LocationUtils(isShowConfirmDialog: true, context: context); WidgetsBinding.instance .addPostFrameCallback((_) => locationUtils.getCurrentLocation()); - + getWeather(); super.initState(); } + @override Widget build(BuildContext context) { ProjectViewModel projectViewModel = Provider.of(context); return BaseView( onModelReady: (model) => model.getWeatherData(), + allowAny: true, builder: (_, mode, widget) => AppScaffold( isShowDecPage: false, appBarTitle: TranslationBase.of(context).healthWeatherIndicators, isShowAppBar: true, - baseViewModel: mode, - body: mode.weatherIndicatorData.length>0 ? SingleChildScrollView( - child: Column(children: [ + body: mode.weatherIndicatorData.length > 0 + ? SingleChildScrollView( + child: Column(children: [ Container( - margin: EdgeInsets.all(8), - width: double.infinity, - height: 150, - decoration: BoxDecoration( - image: DecorationImage( - image: ExactAssetImage('assets/images/Weather_img.png'), - fit: BoxFit.cover, - ), - borderRadius: BorderRadius.circular(8.0)), - child: Padding( - padding: EdgeInsets.symmetric(horizontal: 10.0), - child: Row( - children: [ - Expanded( - flex: 3, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Texts( - TranslationBase.of(context) - .healthWeatherIndicators, - color: Colors.white, - fontWeight: FontWeight.w600, - ), - Texts( - TranslationBase.of(context) - .healthTipsBasedOnCurrentWeather, - color: Colors.white, - fontSize: 14, - ), - ], - )), - Expanded( - flex: 2, - child: InkWell( - onTap: () { - - }, + margin: EdgeInsets.all(8), + width: double.infinity, + height: 150, + decoration: BoxDecoration( + image: DecorationImage( + image: + ExactAssetImage('assets/images/Weather_img.png'), + fit: BoxFit.cover, + ), + borderRadius: BorderRadius.circular(8.0)), + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 10.0), + child: Row( + children: [ + Expanded( + flex: 3, child: Column( mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Image.asset( - 'assets/images/Weather_ico.png', - width: 60, - height: 60, - ), - AppText(weather, - fontSize: 22, color: Colors.white) - ], + AppText( + TranslationBase.of(context) + .healthWeatherIndicators, + color: Colors.white, + fontWeight: FontWeight.w600, + ), + AppText( + TranslationBase.of(context) + .healthTipsBasedOnCurrentWeather, + color: Colors.white, + fontSize: 14, ), ], )), - ) - ], + Expanded( + flex: 2, + child: InkWell( + onTap: () {}, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Image.asset( + 'assets/images/Weather_ico.png', + width: 60, + height: 60, + ), + AppText(weather, + fontSize: 22, color: Colors.white) + ], + ), + ], + )), + ) + ], + ), ), ), - ), - Padding(padding: EdgeInsets.all(15), child:AppText( projectViewModel.isArabic ? mode.weatherIndicatorData[0].cityNameN : mode.weatherIndicatorData[0].cityName, fontSize: 24, fontWeight: FontWeight.bold,)), - Padding( - padding: EdgeInsets.all(15), - child: Column(children: - mode.weatherIndicatorData - .map((data) { - return WeatherSlider( - data); - }).toList() - - ))])) : Container(child:AppText('Loading...'))), + Padding( + padding: EdgeInsets.all(15), + child: AppText( + projectViewModel.isArabic + ? mode.weatherIndicatorData[0].cityNameN + : mode.weatherIndicatorData[0].cityName, + fontSize: 24, + fontWeight: FontWeight.bold, + )), + Padding( + padding: EdgeInsets.all(15), + child: Column( + children: mode.weatherIndicatorData.map((data) { + return WeatherSlider(data); + }).toList())) + ])) + : Container()), ); } - getWeather() async{ + + getWeather() async { var data = await this.sharedPref.getObject(WEATHER); - weather = data['Temperature'].toString() + '\u2103' ?? '--'; + setState(() { + weather = data['Temperature'].toString() + '\u2103' ?? '--'; + }); } } diff --git a/lib/pages/DrawerPages/family/my-family.dart b/lib/pages/DrawerPages/family/my-family.dart index 6a6e98c4..80de8ecd 100644 --- a/lib/pages/DrawerPages/family/my-family.dart +++ b/lib/pages/DrawerPages/family/my-family.dart @@ -1,12 +1,13 @@ import 'dart:ui'; import 'package:diplomaticquarterapp/config/size_config.dart'; +import 'package:diplomaticquarterapp/core/model/ImagesInfo.dart'; import 'package:diplomaticquarterapp/core/service/AuthenticatedUserObject.dart'; import 'package:diplomaticquarterapp/core/viewModels/appointment_rate_view_model.dart'; import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/locator.dart'; import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; -import 'package:diplomaticquarterapp/models/Authentication/check_activation_code_response.dart'; +import 'package:diplomaticquarterapp/models/Authentication/check_activation_code_response.dart' as list; import 'package:diplomaticquarterapp/models/FamilyFiles/GetAllSharedRecordByStatusResponse.dart'; import 'package:diplomaticquarterapp/pages/BookAppointment/widgets/BranchView.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; @@ -28,7 +29,6 @@ import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart'; import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/routes.dart'; import 'package:provider/provider.dart'; - class MyFamily extends StatefulWidget { final bool isAppbarVisible; MyFamily({this.isAppbarVisible =true}); @@ -37,6 +37,7 @@ class MyFamily extends StatefulWidget { } class _MyFamily extends State with TickerProviderStateMixin { + List imagesInfo = List(); final familyFileProvider = FamilyFilesProvider(); AppSharedPreferences sharedPref = new AppSharedPreferences(); var userID; @@ -56,12 +57,27 @@ class _MyFamily extends State with TickerProviderStateMixin { } bool expandFlag = false; + Widget build(BuildContext context) { - projectViewModel = Provider.of(context); + imagesInfo.add(ImagesInfo( + imageEn: + 'https://hmgwebservices.com/Images/MobileApp/images-info-home/family-file/en/0.png', + imageAr: + 'https://hmgwebservices.com/Images/MobileApp/images-info-home/family-file/ar/0.png'), + ); + imagesInfo.add(ImagesInfo( + 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 = Provider.of(context); return AppScaffold( appBarTitle: TranslationBase.of(context).myFamilyFiles, isShowAppBar: widget.isAppbarVisible, + imagesInfo: imagesInfo, + description: TranslationBase.of(context).familyInfo, body: Scaffold( extendBodyBehindAppBar: true, appBar: PreferredSize( @@ -648,7 +664,7 @@ class _MyFamily extends State with TickerProviderStateMixin { // Navigator.of(context).pushNamed( // HOME, // ); - result = CheckActivationCode.fromJson(result); + result = list.CheckActivationCode.fromJson(result); var familyFile = await sharedPref.getObject(FAMILY_FILE); var mainUser = await sharedPref.getObject(MAIN_USER); this.sharedPref.clear(); diff --git a/lib/pages/landing/landing_page.dart b/lib/pages/landing/landing_page.dart index b47a1e75..e08f1773 100644 --- a/lib/pages/landing/landing_page.dart +++ b/lib/pages/landing/landing_page.dart @@ -19,6 +19,7 @@ import 'package:diplomaticquarterapp/theme/theme_notifier.dart'; import 'package:diplomaticquarterapp/theme/theme_value.dart'; import 'package:diplomaticquarterapp/uitl/CalendarUtils.dart'; import 'package:diplomaticquarterapp/uitl/LocalNotification.dart'; +import 'package:diplomaticquarterapp/uitl/location_util.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/bottom_navigation/bottom_nav_bar.dart'; import 'package:diplomaticquarterapp/widgets/buttons/floatingActionButton.dart'; @@ -71,7 +72,7 @@ class _LandingPageState extends State with WidgetsBindingObserver { } bool isPageNavigated = false; - + LocationUtils locationUtils; _changeCurrentTab(int tab) { setState(() { currentTab = tab; @@ -138,7 +139,10 @@ class _LandingPageState extends State with WidgetsBindingObserver { pageController = PageController(keepPage: true); _firebaseMessaging.setAutoInitEnabled(true); - + locationUtils = + new LocationUtils(isShowConfirmDialog: true, context: context); + WidgetsBinding.instance + .addPostFrameCallback((_) => locationUtils.getCurrentLocation()); if (Platform.isIOS) { diff --git a/lib/uitl/location_util.dart b/lib/uitl/location_util.dart index e3012734..1c85d898 100644 --- a/lib/uitl/location_util.dart +++ b/lib/uitl/location_util.dart @@ -15,12 +15,12 @@ class LocationUtils { void getCurrentLocation() async { print("current location"); - isLocationServiceEnabled().then((value) { + Geolocator.isLocationServiceEnabled().then((value) { if (value) { - checkPermission().then((permission) { + Geolocator.checkPermission().then((permission) { if (permission == LocationPermission.always || permission == LocationPermission.whileInUse) { - getLastKnownPosition().then((value) => setLocation(value)); + Geolocator.getLastKnownPosition().then((value) => setLocation(value)); } if (permission == LocationPermission.denied || @@ -48,9 +48,9 @@ class LocationUtils { okFunction: () => { ConfirmDialog.closeAlertDialog(context), if (isPermissionError) - openAppSettings() + Geolocator.openAppSettings() else - openLocationSettings() + Geolocator.openLocationSettings() }, cancelFunction: () => {}); return dialog.showAlertDialog(context); diff --git a/lib/uitl/translations_delegate_base.dart b/lib/uitl/translations_delegate_base.dart index f58c5cb7..57804e4a 100644 --- a/lib/uitl/translations_delegate_base.dart +++ b/lib/uitl/translations_delegate_base.dart @@ -953,15 +953,86 @@ class TranslationBase { String get OrderStatus => localizedValues['OrderStatus'][locale.languageCode]; String get pickupDate => localizedValues['pickupDate'][locale.languageCode]; String get serviceName => localizedValues['serviceName'][locale.languageCode]; - String get orderLocation => localizedValues['orderLocation'][locale.languageCode]; - String get selectService => localizedValues['selectService'][locale.languageCode]; - String get coveredService => localizedValues['coveredService'][locale.languageCode]; - String get selectAddress => localizedValues['selectAddress'][locale.languageCode]; - String get addNewAddress => localizedValues['addNewAddress'][locale.languageCode]; - String get selectedService => localizedValues['selectedService'][locale.languageCode]; - String get cancelOrderMsg => localizedValues['cancelOrderMsg'][locale.languageCode]; - String get processDoneSuccessfully => localizedValues['processDoneSuccessfully'][locale.languageCode]; - String get selectHomeHealthCareServices => localizedValues['selectHomeHealthCareServices'][locale.languageCode]; + String get orderLocation => + localizedValues['orderLocation'][locale.languageCode]; + String get selectService => + localizedValues['selectService'][locale.languageCode]; + String get coveredService => + localizedValues['coveredService'][locale.languageCode]; + String get selectAddress => + localizedValues['selectAddress'][locale.languageCode]; + String get addNewAddress => + localizedValues['addNewAddress'][locale.languageCode]; + String get selectedService => + localizedValues['selectedService'][locale.languageCode]; + String get cancelOrderMsg => + localizedValues['cancelOrderMsg'][locale.languageCode]; + String get processDoneSuccessfully => + localizedValues['processDoneSuccessfully'][locale.languageCode]; + String get selectHomeHealthCareServices => + localizedValues['selectHomeHealthCareServices'][locale.languageCode]; + String get labResults => localizedValues['labResults'][locale.languageCode]; + String get doctorRating => + localizedValues['doctorRating'][locale.languageCode]; + String get good => localizedValues['good'][locale.languageCode]; + String get v_good => localizedValues['v-good'][locale.languageCode]; + String get excellent => localizedValues['excellent'][locale.languageCode]; + String get below_average => + localizedValues['below-average'][locale.languageCode]; + String get infoSigns => localizedValues['info-signs'][locale.languageCode]; + String get infoAdvancePayment => + localizedValues['info-advance-payment'][locale.languageCode]; + String get infoMyBalance => + localizedValues['info-my-balance'][locale.languageCode]; + String get erContant => localizedValues['er-contant'][locale.languageCode]; + String get er => localizedValues['er'][locale.languageCode]; + String get transportationService => + localizedValues['transportation-Service'][locale.languageCode]; + String get infoAmbulance => + localizedValues['info-ambulance'][locale.languageCode]; + String get transportHeading => + localizedValues['RRT-transport-heading'][locale.languageCode]; + String get sar => localizedValues['sar'][locale.languageCode]; + String get directionHeading => + localizedValues['RRT-direction-heading'][locale.languageCode]; + String get toHospital => localizedValues['to-hospital'][locale.languageCode]; + String get fromHospital => + localizedValues['from-hospital'][locale.languageCode]; + String get oneDirec => localizedValues['one-direc'][locale.languageCode]; + String get twoDirec => localizedValues['two-direc'][locale.languageCode]; + String get pickupLocation => + localizedValues['pickup-location'][locale.languageCode]; + String get pickupSpot => localizedValues['pickup-spot'][locale.languageCode]; + String get insideHome => localizedValues['inside-home'][locale.languageCode]; + String get haveAppo => localizedValues['have-appo'][locale.languageCode]; + String get dropoffLocation => + localizedValues['dropoff-location'][locale.languageCode]; + String get selectAll => localizedValues['select-all'][locale.languageCode]; + String get selectMap => localizedValues['select-map'][locale.languageCode]; + String get noAppointment => + localizedValues['no-appointment'][locale.languageCode]; + String get patientShareB => + localizedValues['patient-share'][locale.languageCode]; + String get patientShareTax => + localizedValues['patient-share-tax'][locale.languageCode]; + String get patientShareTotal => + localizedValues['patient-share-total'][locale.languageCode]; + String get selectAmbulate => + localizedValues['select-ambulate'][locale.languageCode]; + String get wheelchair => localizedValues['wheelchair'][locale.languageCode]; + String get walker => localizedValues['walker"'][locale.languageCode]; + String get stretcher => localizedValues['stretcher'][locale.languageCode]; + String get none => localizedValues['none'][locale.languageCode]; + String get RRTSummary => localizedValues['RRT-Summary'][locale.languageCode]; + String get billAmount => localizedValues['bill-amount'][locale.languageCode]; + String get transportMethod => + localizedValues['transport-method'][locale.languageCode]; + String get directions => localizedValues['directions'][locale.languageCode]; + + String get infoMyAppointments => + localizedValues['info-my-appointments'][locale.languageCode]; + String get infoTodo => localizedValues['info-todo'][locale.languageCode]; + String get familyInfo => localizedValues['family-info'][locale.languageCode]; } class TranslationBaseDelegate extends LocalizationsDelegate { From e3e868e47c858e9599080b06a37cbbe9c2f90423 Mon Sep 17 00:00:00 2001 From: Sultan Khan Date: Fri, 4 Dec 2020 12:12:39 +0300 Subject: [PATCH 11/71] flutter tts updated --- .../.github/ISSUE_TEMPLATE/bug_report.md | 21 + .../.github/ISSUE_TEMPLATE/feature_request.md | 19 + .../ISSUE_TEMPLATE/questions-and-help.md | 9 + .../.github/workflows/main.yml | 34 + flutter_tts-voice_enhancement/.gitignore | 94 +++ flutter_tts-voice_enhancement/CHANGELOG.md | 197 ++++++ .../CODE_OF_CONDUCT.md | 46 ++ flutter_tts-voice_enhancement/LICENSE | 21 + flutter_tts-voice_enhancement/README.md | 194 ++++++ .../analysis_options.yaml | 35 + .../android/.gitignore | 8 + .../android/build.gradle | 48 ++ .../android/gradle.properties | 4 + .../gradle/wrapper/gradle-wrapper.properties | 6 + .../android/settings.gradle | 1 + .../android/src/main/AndroidManifest.xml | 4 + .../fluttertts/FlutterTtsPlugin.java | 454 ++++++++++++ .../example/.gitignore | 11 + .../example/.metadata | 8 + .../example/README.md | 16 + .../example/android/.gitignore | 10 + .../org.eclipse.buildship.core.prefs | 2 + .../example/android/app/.classpath | 6 + .../org.eclipse.buildship.core.prefs | 2 + .../example/android/app/build.gradle | 50 ++ .../android/app/src/debug/AndroidManifest.xml | 7 + .../android/app/src/main/AndroidManifest.xml | 46 ++ .../main/res/drawable/launch_background.xml | 12 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 544 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 442 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 721 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 1031 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 1443 bytes .../app/src/main/res/values/styles.xml | 18 + .../app/src/profile/AndroidManifest.xml | 7 + .../example/android/build.gradle | 29 + .../example/android/gradle.properties | 4 + .../gradle/wrapper/gradle-wrapper.properties | 6 + .../example/android/settings.gradle | 15 + .../example/android/settings_aar.gradle | 1 + .../example/ios/.gitignore | 42 ++ .../example/ios/Flutter/.last_build_id | 1 + .../ios/Flutter/AppFrameworkInfo.plist | 30 + .../example/ios/Flutter/Debug.xcconfig | 2 + .../example/ios/Flutter/Flutter.podspec | 18 + .../example/ios/Flutter/Release.xcconfig | 2 + .../example/ios/Podfile | 41 ++ .../ios/Runner.xcodeproj/project.pbxproj | 488 +++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../xcshareddata/xcschemes/Runner.xcscheme | 91 +++ .../contents.xcworkspacedata | 10 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../example/ios/Runner/AppDelegate.swift | 13 + .../AppIcon.appiconset/Contents.json | 122 ++++ .../Icon-App-1024x1024@1x.png | Bin 0 -> 11112 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 0 -> 564 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 0 -> 1283 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 0 -> 1588 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 0 -> 1025 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 0 -> 1716 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 0 -> 1920 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 0 -> 1283 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 0 -> 1895 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 0 -> 2665 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 0 -> 2665 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 0 -> 3831 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 0 -> 1888 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 0 -> 3294 bytes .../Icon-App-83.5x83.5@2x.png | Bin 0 -> 3612 bytes .../LaunchImage.imageset/Contents.json | 23 + .../LaunchImage.imageset/LaunchImage.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/README.md | 5 + .../Runner/Base.lproj/LaunchScreen.storyboard | 37 + .../ios/Runner/Base.lproj/Main.storyboard | 26 + .../example/ios/Runner/Info.plist | 49 ++ .../ios/Runner/Runner-Bridging-Header.h | 1 + .../example/lib/main.dart | 292 ++++++++ .../example/macos/.gitignore | 6 + .../macos/Flutter/Flutter-Debug.xcconfig | 2 + .../macos/Flutter/Flutter-Release.xcconfig | 2 + .../Flutter/GeneratedPluginRegistrant.swift | 12 + .../example/macos/Podfile | 82 +++ .../macos/Runner.xcodeproj/project.pbxproj | 656 ++++++++++++++++++ .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/xcschemes/Runner.xcscheme | 97 +++ .../contents.xcworkspacedata | 10 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../example/macos/Runner/AppDelegate.swift | 9 + .../AppIcon.appiconset/Contents.json | 68 ++ .../AppIcon.appiconset/app_icon_1024.png | Bin 0 -> 46993 bytes .../AppIcon.appiconset/app_icon_128.png | Bin 0 -> 3276 bytes .../AppIcon.appiconset/app_icon_16.png | Bin 0 -> 1429 bytes .../AppIcon.appiconset/app_icon_256.png | Bin 0 -> 5933 bytes .../AppIcon.appiconset/app_icon_32.png | Bin 0 -> 1243 bytes .../AppIcon.appiconset/app_icon_512.png | Bin 0 -> 14800 bytes .../AppIcon.appiconset/app_icon_64.png | Bin 0 -> 1874 bytes .../macos/Runner/Base.lproj/MainMenu.xib | 339 +++++++++ .../macos/Runner/Configs/AppInfo.xcconfig | 14 + .../macos/Runner/Configs/Debug.xcconfig | 2 + .../macos/Runner/Configs/Release.xcconfig | 2 + .../macos/Runner/Configs/Warnings.xcconfig | 13 + .../macos/Runner/DebugProfile.entitlements | 12 + .../example/macos/Runner/Info.plist | 32 + .../macos/Runner/MainFlutterWindow.swift | 15 + .../example/macos/Runner/Release.entitlements | 8 + .../example/pubspec.yaml | 59 ++ .../example/test/widget_test.dart | 30 + .../example/web/favicon.png | Bin 0 -> 917 bytes .../example/web/icons/Icon-192.png | Bin 0 -> 5292 bytes .../example/web/icons/Icon-512.png | Bin 0 -> 8252 bytes .../example/web/index.html | 10 + .../example/web/manifest.json | 23 + flutter_tts-voice_enhancement/ios/.gitignore | 31 + .../ios/Assets/.gitkeep | 0 .../ios/Classes/AudioCategory.swift | 21 + .../ios/Classes/AudioCategoryOptions.swift | 42 ++ .../ios/Classes/FlutterTtsPlugin.h | 4 + .../ios/Classes/FlutterTtsPlugin.m | 8 + .../ios/Classes/SwiftFlutterTtsPlugin.swift | 386 +++++++++++ .../ios/flutter_tts.podspec | 22 + .../lib/flutter_tts.dart | 342 +++++++++ .../lib/flutter_tts_web.dart | 184 +++++ .../macos/Classes/FlutterTtsPlugin.swift | 315 +++++++++ .../macos/flutter_tts.podspec | 22 + flutter_tts-voice_enhancement/pubspec.yaml | 28 + lib/core/model/ImagesInfo.dart | 6 + 131 files changed, 5707 insertions(+) create mode 100644 flutter_tts-voice_enhancement/.github/ISSUE_TEMPLATE/bug_report.md create mode 100644 flutter_tts-voice_enhancement/.github/ISSUE_TEMPLATE/feature_request.md create mode 100644 flutter_tts-voice_enhancement/.github/ISSUE_TEMPLATE/questions-and-help.md create mode 100644 flutter_tts-voice_enhancement/.github/workflows/main.yml create mode 100644 flutter_tts-voice_enhancement/.gitignore create mode 100644 flutter_tts-voice_enhancement/CHANGELOG.md create mode 100644 flutter_tts-voice_enhancement/CODE_OF_CONDUCT.md create mode 100644 flutter_tts-voice_enhancement/LICENSE create mode 100644 flutter_tts-voice_enhancement/README.md create mode 100644 flutter_tts-voice_enhancement/analysis_options.yaml create mode 100644 flutter_tts-voice_enhancement/android/.gitignore create mode 100644 flutter_tts-voice_enhancement/android/build.gradle create mode 100644 flutter_tts-voice_enhancement/android/gradle.properties create mode 100644 flutter_tts-voice_enhancement/android/gradle/wrapper/gradle-wrapper.properties create mode 100644 flutter_tts-voice_enhancement/android/settings.gradle create mode 100644 flutter_tts-voice_enhancement/android/src/main/AndroidManifest.xml create mode 100644 flutter_tts-voice_enhancement/android/src/main/java/com/tundralabs/fluttertts/FlutterTtsPlugin.java create mode 100644 flutter_tts-voice_enhancement/example/.gitignore create mode 100644 flutter_tts-voice_enhancement/example/.metadata create mode 100644 flutter_tts-voice_enhancement/example/README.md create mode 100644 flutter_tts-voice_enhancement/example/android/.gitignore create mode 100644 flutter_tts-voice_enhancement/example/android/.settings/org.eclipse.buildship.core.prefs create mode 100644 flutter_tts-voice_enhancement/example/android/app/.classpath create mode 100644 flutter_tts-voice_enhancement/example/android/app/.settings/org.eclipse.buildship.core.prefs create mode 100644 flutter_tts-voice_enhancement/example/android/app/build.gradle create mode 100644 flutter_tts-voice_enhancement/example/android/app/src/debug/AndroidManifest.xml create mode 100644 flutter_tts-voice_enhancement/example/android/app/src/main/AndroidManifest.xml create mode 100644 flutter_tts-voice_enhancement/example/android/app/src/main/res/drawable/launch_background.xml create mode 100644 flutter_tts-voice_enhancement/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 flutter_tts-voice_enhancement/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 flutter_tts-voice_enhancement/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 flutter_tts-voice_enhancement/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 flutter_tts-voice_enhancement/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 flutter_tts-voice_enhancement/example/android/app/src/main/res/values/styles.xml create mode 100644 flutter_tts-voice_enhancement/example/android/app/src/profile/AndroidManifest.xml create mode 100644 flutter_tts-voice_enhancement/example/android/build.gradle create mode 100644 flutter_tts-voice_enhancement/example/android/gradle.properties create mode 100644 flutter_tts-voice_enhancement/example/android/gradle/wrapper/gradle-wrapper.properties create mode 100644 flutter_tts-voice_enhancement/example/android/settings.gradle create mode 100644 flutter_tts-voice_enhancement/example/android/settings_aar.gradle create mode 100644 flutter_tts-voice_enhancement/example/ios/.gitignore create mode 100644 flutter_tts-voice_enhancement/example/ios/Flutter/.last_build_id create mode 100644 flutter_tts-voice_enhancement/example/ios/Flutter/AppFrameworkInfo.plist create mode 100644 flutter_tts-voice_enhancement/example/ios/Flutter/Debug.xcconfig create mode 100644 flutter_tts-voice_enhancement/example/ios/Flutter/Flutter.podspec create mode 100644 flutter_tts-voice_enhancement/example/ios/Flutter/Release.xcconfig create mode 100644 flutter_tts-voice_enhancement/example/ios/Podfile create mode 100644 flutter_tts-voice_enhancement/example/ios/Runner.xcodeproj/project.pbxproj create mode 100644 flutter_tts-voice_enhancement/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 flutter_tts-voice_enhancement/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 flutter_tts-voice_enhancement/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 flutter_tts-voice_enhancement/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 flutter_tts-voice_enhancement/example/ios/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 flutter_tts-voice_enhancement/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 flutter_tts-voice_enhancement/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 flutter_tts-voice_enhancement/example/ios/Runner/AppDelegate.swift create mode 100644 flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png create mode 100644 flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png create mode 100644 flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png create mode 100644 flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png create mode 100644 flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png create mode 100644 flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png create mode 100644 flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png create mode 100644 flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png create mode 100644 flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png create mode 100644 flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png create mode 100644 flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png create mode 100644 flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png create mode 100644 flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png create mode 100644 flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png create mode 100644 flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png create mode 100644 flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json create mode 100644 flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png create mode 100644 flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png create mode 100644 flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png create mode 100644 flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md create mode 100644 flutter_tts-voice_enhancement/example/ios/Runner/Base.lproj/LaunchScreen.storyboard create mode 100644 flutter_tts-voice_enhancement/example/ios/Runner/Base.lproj/Main.storyboard create mode 100644 flutter_tts-voice_enhancement/example/ios/Runner/Info.plist create mode 100644 flutter_tts-voice_enhancement/example/ios/Runner/Runner-Bridging-Header.h create mode 100644 flutter_tts-voice_enhancement/example/lib/main.dart create mode 100644 flutter_tts-voice_enhancement/example/macos/.gitignore create mode 100644 flutter_tts-voice_enhancement/example/macos/Flutter/Flutter-Debug.xcconfig create mode 100644 flutter_tts-voice_enhancement/example/macos/Flutter/Flutter-Release.xcconfig create mode 100644 flutter_tts-voice_enhancement/example/macos/Flutter/GeneratedPluginRegistrant.swift create mode 100644 flutter_tts-voice_enhancement/example/macos/Podfile create mode 100644 flutter_tts-voice_enhancement/example/macos/Runner.xcodeproj/project.pbxproj create mode 100644 flutter_tts-voice_enhancement/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 flutter_tts-voice_enhancement/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 flutter_tts-voice_enhancement/example/macos/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 flutter_tts-voice_enhancement/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 flutter_tts-voice_enhancement/example/macos/Runner/AppDelegate.swift create mode 100644 flutter_tts-voice_enhancement/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 flutter_tts-voice_enhancement/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png create mode 100644 flutter_tts-voice_enhancement/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png create mode 100644 flutter_tts-voice_enhancement/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png create mode 100644 flutter_tts-voice_enhancement/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png create mode 100644 flutter_tts-voice_enhancement/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png create mode 100644 flutter_tts-voice_enhancement/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png create mode 100644 flutter_tts-voice_enhancement/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png create mode 100644 flutter_tts-voice_enhancement/example/macos/Runner/Base.lproj/MainMenu.xib create mode 100644 flutter_tts-voice_enhancement/example/macos/Runner/Configs/AppInfo.xcconfig create mode 100644 flutter_tts-voice_enhancement/example/macos/Runner/Configs/Debug.xcconfig create mode 100644 flutter_tts-voice_enhancement/example/macos/Runner/Configs/Release.xcconfig create mode 100644 flutter_tts-voice_enhancement/example/macos/Runner/Configs/Warnings.xcconfig create mode 100644 flutter_tts-voice_enhancement/example/macos/Runner/DebugProfile.entitlements create mode 100644 flutter_tts-voice_enhancement/example/macos/Runner/Info.plist create mode 100644 flutter_tts-voice_enhancement/example/macos/Runner/MainFlutterWindow.swift create mode 100644 flutter_tts-voice_enhancement/example/macos/Runner/Release.entitlements create mode 100644 flutter_tts-voice_enhancement/example/pubspec.yaml create mode 100644 flutter_tts-voice_enhancement/example/test/widget_test.dart create mode 100644 flutter_tts-voice_enhancement/example/web/favicon.png create mode 100644 flutter_tts-voice_enhancement/example/web/icons/Icon-192.png create mode 100644 flutter_tts-voice_enhancement/example/web/icons/Icon-512.png create mode 100644 flutter_tts-voice_enhancement/example/web/index.html create mode 100644 flutter_tts-voice_enhancement/example/web/manifest.json create mode 100644 flutter_tts-voice_enhancement/ios/.gitignore create mode 100644 flutter_tts-voice_enhancement/ios/Assets/.gitkeep create mode 100644 flutter_tts-voice_enhancement/ios/Classes/AudioCategory.swift create mode 100644 flutter_tts-voice_enhancement/ios/Classes/AudioCategoryOptions.swift create mode 100644 flutter_tts-voice_enhancement/ios/Classes/FlutterTtsPlugin.h create mode 100644 flutter_tts-voice_enhancement/ios/Classes/FlutterTtsPlugin.m create mode 100644 flutter_tts-voice_enhancement/ios/Classes/SwiftFlutterTtsPlugin.swift create mode 100644 flutter_tts-voice_enhancement/ios/flutter_tts.podspec create mode 100644 flutter_tts-voice_enhancement/lib/flutter_tts.dart create mode 100644 flutter_tts-voice_enhancement/lib/flutter_tts_web.dart create mode 100644 flutter_tts-voice_enhancement/macos/Classes/FlutterTtsPlugin.swift create mode 100644 flutter_tts-voice_enhancement/macos/flutter_tts.podspec create mode 100644 flutter_tts-voice_enhancement/pubspec.yaml create mode 100644 lib/core/model/ImagesInfo.dart diff --git a/flutter_tts-voice_enhancement/.github/ISSUE_TEMPLATE/bug_report.md b/flutter_tts-voice_enhancement/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..614a6708 --- /dev/null +++ b/flutter_tts-voice_enhancement/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,21 @@ +--- +name: Bug report +about: Create a report to help us improve + +--- + +## 🐛 Bug Report + + + +### Expected behavior + +### Reproduction steps + +### Configuration + +**Version:** 0.1.x + +**Platform:** +- [ ] :iphone: iOS +- [ ] :robot: Android diff --git a/flutter_tts-voice_enhancement/.github/ISSUE_TEMPLATE/feature_request.md b/flutter_tts-voice_enhancement/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000..35a881a3 --- /dev/null +++ b/flutter_tts-voice_enhancement/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,19 @@ +--- +name: Feature request +about: Suggest an idea for this project + +--- + +## 🚀 Feature Requests + + + +### Contextualize the feature + + +### Describe the feature + + +### Platforms affected (mark all that apply) +- [ ] :iphone: iOS +- [ ] :robot: Android diff --git a/flutter_tts-voice_enhancement/.github/ISSUE_TEMPLATE/questions-and-help.md b/flutter_tts-voice_enhancement/.github/ISSUE_TEMPLATE/questions-and-help.md new file mode 100644 index 00000000..ba501f3c --- /dev/null +++ b/flutter_tts-voice_enhancement/.github/ISSUE_TEMPLATE/questions-and-help.md @@ -0,0 +1,9 @@ +--- +name: Questions and Help +about: If you have questions, please use this for support + +--- + +## 💬 Questions and Help + +Provide question related to this flutter plugin. diff --git a/flutter_tts-voice_enhancement/.github/workflows/main.yml b/flutter_tts-voice_enhancement/.github/workflows/main.yml new file mode 100644 index 00000000..832dd069 --- /dev/null +++ b/flutter_tts-voice_enhancement/.github/workflows/main.yml @@ -0,0 +1,34 @@ +name: github pages + +on: + push: + branches: + - master + +jobs: + deploy: + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@v2 + + - name: Setup Flutter + run: | + git clone https://github.com/flutter/flutter.git --depth 1 -b beta _flutter + echo "::add-path::${GITHUB_WORKSPACE}/_flutter/bin" + + - name: Install + run: | + cd example + flutter config --enable-web + flutter pub get + + - name: Build + run: | + cd example + flutter build web + + - name: Deploy + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./example/build/web diff --git a/flutter_tts-voice_enhancement/.gitignore b/flutter_tts-voice_enhancement/.gitignore new file mode 100644 index 00000000..bc0883df --- /dev/null +++ b/flutter_tts-voice_enhancement/.gitignore @@ -0,0 +1,94 @@ +# Miscellaneous +*.class +*.lock +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.project +.svn/ +bin/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# Android Studio related +android/.classpath +android/.settings/ + +# Visual Studio Code related +.vscode/ + +# Flutter repo-specific +/bin/cache/ +/bin/mingit/ +/dev/benchmarks/mega_gallery/ +/dev/bots/.recipe_deps +/dev/bots/android_tools/ +/dev/docs/doc/ +/dev/docs/lib/ +/dev/docs/pubspec.yaml +/packages/flutter/coverage/ +version + +# Flutter/Dart/Pub related +**/doc/api/ +.dart_tool/ +.flutter-plugins +.packages +.pub-cache/ +.pub/ +build/ +flutter_*.png +linked_*.ds +unlinked.ds +unlinked_spec.ds + +# Android related +**/android/**/gradle-wrapper.jar +**/android/.gradle +**/android/captures/ +**/android/gradlew +**/android/gradlew.bat +**/android/local.properties +**/android/**/GeneratedPluginRegistrant.java + +# iOS/XCode related +**/ios/**/*.mode1v3 +**/ios/**/*.mode2v3 +**/ios/**/*.moved-aside +**/ios/**/*.pbxuser +**/ios/**/*.perspectivev3 +**/ios/**/*sync/ +**/ios/**/.sconsign.dblite +**/ios/**/.tags* +**/ios/**/.vagrant/ +**/ios/**/DerivedData/ +**/ios/**/Icon? +**/ios/**/Pods/ +**/ios/**/.symlinks/ +**/ios/**/profile +**/ios/**/xcuserdata +**/ios/.generated/ +**/ios/Flutter/App.framework +**/ios/Flutter/Flutter.framework +**/ios/Flutter/Generated.xcconfig +**/ios/Flutter/app.flx +**/ios/Flutter/app.zip +**/ios/Flutter/flutter_assets/ +**/ios/ServiceDefinitions.json +**/ios/Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!**/ios/**/default.mode1v3 +!**/ios/**/default.mode2v3 +!**/ios/**/default.pbxuser +!**/ios/**/default.perspectivev3 +!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages +example/ios/Flutter/flutter_export_environment.sh diff --git a/flutter_tts-voice_enhancement/CHANGELOG.md b/flutter_tts-voice_enhancement/CHANGELOG.md new file mode 100644 index 00000000..bff8b759 --- /dev/null +++ b/flutter_tts-voice_enhancement/CHANGELOG.md @@ -0,0 +1,197 @@ +# ChangeLog + +## 1.3.0 + +- All: Adding await speak completion + +## 1.2.7 + +- iOS: Adding utterance settings to synthesizeToFile +- Android: Fix crash when utterance completes after Engine is detached + +## 1.2.6 + +- Android: Fixing new API onAttachedToEngine call + +## 1.2.5 + +- macOS: Adding support + +## 1.2.4 + +- iOS: Deactivate audio session only when needed +- Android: Better exception handling for getLanguages +- Android: Adding getEngines +- Android: Adding new Android plugin APIs + +## 1.2.3 + +- iOS: Adding synthesize to file +- iOS: Fix set category ios + +## 1.2.2 + +- Web: Adding pause and continue + +## 1.2.1 + +- iOS: Fix setting iOS Category +- iOS/Android: Adding additional platform calls + +## 1.2.0 + +- iOS: Adding Set Audio Session Category +- Android: Bug fixes + +## 1.1.0 + +- iOS: Adding Pause +- iOS: Adding set Shared Instance + +## 1.0.0 + +- iOS/Android: Feature - Speech marks +- iOS/Android: Breaking changes to Speech rate + +## 0.9.2 + +- iOS: Changing audio session to playAndRecord + +## 0.9.1 + +- Android: Fixing method call error + +## 0.9.0 + +- Android: Adding synthesize to file + +## 0.8.7 + +- Android: Fix sporadic ANR on initialization + +## 0.8.6 + +- iOS: Reducing volume of other sessions while TTS is playing + +## 0.8.5 + +- Android: Fix Android async platform initialization +- Android: Removing initHandler + +## 0.8.2 + +- Web: Adding isLanguageAvailable method +- All: Fixing isLanguageAvailable platform channel and making it case insensitive + +## 0.8.0 + +- Web: Adding Web Support + +## 0.7.0 + +- iOS: Adding Swift version 4.2 to podspec and correct audio playback category + +## 0.6.0 + +- Android: AndroidX support + +## 0.5.2 + +- Android: Bug Fix on isLanguageAvailable + +## 0.5.1 + +- Applying flutter format to fix health suggestion + +## 0.5.0 + +- Android: Adding silence before speak +- Android: Removing deprecated API + +## 0.2.6 + +- IOS: Add voice selection implementation + +## 0.2.5 + +- Android: Ensure invokeMethod runs on main thread + +## 0.2.4 + +- Android: setting minSDK back to 21 and adding instructions to readme +- Android: Adding fallback for getLanguages and defaultLanguage + +## 0.2.3 + +- IOS: Audio continues with the Ring/Silent switch set to silent + +## 0.2.2 + +- Android: Fixing Locale bug + +## 0.2.1 + +- IOS: Fixing getLanguages bug + +## 0.2.0 + +- Android: Adding exception catch for samsung devices +- Android: Using default com.google.android.tts engine +- Android: Get and Set Voice +- Android: InitHandler +- Cleaning up the example + +## 0.1.2 + +- Support for Android background execution +- Updating Android build gradle version to 3.2.1 + +## 0.1.1 + +- Fixing TTS bound error in the example +- Fixing default voice language not found error on Android + +## 0.1.0 + +- Updating version for improved maintenance score +- Updating package description for improved maintenance score + +## 0.0.8 + +- Adding analysis_options.yaml for improved health score +- Fixing info/errors from flutter analyze + +## 0.0.7 + +- Updating SDK version in pubspec.yaml +- Adding package link to README +- Fixing language string warning received from xcode + +## 0.0.6 + +- Android: Upgrading Gradle 4.1 to 4.4 +- Android: Setting minSdk version to 21 +- Android: Adding try/catch to getAvailableLanguages & getDefaultVoice methods (Issues with API 21 & 22) + +## 0.0.5 + +- Adding IOS/Android isLanguageAvailable +- Rename setRate to setSpeechRate + +## 0.0.4 + +- Simplify podspec for Cocoapods 1.5.0 + +## 0.0.3 + +- Adding IOS/Android speech pitch and volume + +## 0.0.2 + +- Flutter formatting and fixing pubspec sdk versioning + +## 0.0.1 + +- first POC : + - methods : speak, stop, setRate, setLangauge, getLanguages + - a globalHandler for completion diff --git a/flutter_tts-voice_enhancement/CODE_OF_CONDUCT.md b/flutter_tts-voice_enhancement/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..43989576 --- /dev/null +++ b/flutter_tts-voice_enhancement/CODE_OF_CONDUCT.md @@ -0,0 +1,46 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at eyedea32@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/flutter_tts-voice_enhancement/LICENSE b/flutter_tts-voice_enhancement/LICENSE new file mode 100644 index 00000000..56dcdf22 --- /dev/null +++ b/flutter_tts-voice_enhancement/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Daniel Lutton + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/flutter_tts-voice_enhancement/README.md b/flutter_tts-voice_enhancement/README.md new file mode 100644 index 00000000..4e32d45d --- /dev/null +++ b/flutter_tts-voice_enhancement/README.md @@ -0,0 +1,194 @@ +# Text To Speech + +[![pub package](https://img.shields.io/pub/v/flutter_tts.svg?style=for-the-badge&colorB=green)](https://pub.dartlang.org/packages/flutter_tts) + +A flutter text to speech plugin (Swift,Java) + +## Features + +- [x] Android, iOS, Web, & macOS + - [x] speak + - [x] stop + - [x] get languages + - [x] set language + - [x] set speech rate + - [x] set speech volume + - [x] set speech pitch + - [x] is language available +- [x] Android, iOS + - [x] get voices + - [x] set voice + - [x] speech marks (requires iOS 7+ and Android 26+) + - [x] synthesize to file (requires iOS 13+) +- [x] iOS, Web + - [x] pause +- [x] Android + - [x] set Silence +- [x] iOS + - [x] set shared instance + - [x] set audio session category + +## Usage + +## macOS + +```bash +OSX version: 10.15 +``` + +[Example App](https://github.com/dlutton/flutter_tts/tree/macOS_app) from the macOS_app branch + +## Web + +[Website](https://dlutton.github.io/flutter_tts) from the example directory. + +## Android + +Change the minimum Android sdk version to 21 (or higher) in your `android/app/build.gradle` file. + +```java +minSdkVersion 21 +``` + +## iOS + +There's a known issue with integrating plugins that use Swift into a Flutter project created with the Objective-C template. [Flutter#16049](https://github.com/flutter/flutter/issues/16049) + +[Example](https://github.com/dlutton/flutter_tts/blob/master/example/lib/main.dart) + +To use this plugin : + +- add the dependency to your [pubspec.yaml](https://github.com/dlutton/flutter_tts/blob/master/example/pubspec.yaml) file. + +```yaml + dependencies: + flutter: + sdk: flutter + flutter_tts: +``` + +- instantiate FlutterTts + +```dart +FlutterTts flutterTts = FlutterTts(); + +``` + +To set shared audio [instance](https://developer.apple.com/documentation/avfoundation/avaudiosession/1616504-sharedinstance) (iOS only): + +```dart +await flutterTts.setSharedInstance(true); +``` + +To set audio [category and options](https://developer.apple.com/documentation/avfoundation/avaudiosession) (iOS only): + +```dart +await flutterTts + .setIosAudioCategory(IosTextToSpeechAudioCategory.playAndRecord, [ + IosTextToSpeechAudioCategoryOptions.allowBluetooth, + IosTextToSpeechAudioCategoryOptions.allowBluetoothA2DP, + IosTextToSpeechAudioCategoryOptions.mixWithOthers + ]); +``` + +To await speak completion. + +```dart +await flutterTts.awaitSpeakCompletion(true); +``` + +### speak, stop, getLanguages, setLanguage, setSpeechRate, setVoice, setVolume, setPitch, isLanguageAvailable, setSharedInstance + +```dart +Future _speak() async{ + var result = await flutterTts.speak("Hello World"); + if (result == 1) setState(() => ttsState = TtsState.playing); +} + +Future _stop() async{ + var result = await flutterTts.stop(); + if (result == 1) setState(() => ttsState = TtsState.stopped); +} + +List languages = await flutterTts.getLanguages; + +await flutterTts.setLanguage("en-US"); + +await flutterTts.setSpeechRate(1.0); + +await flutterTts.setVolume(1.0); + +await flutterTts.setPitch(1.0); + +await flutterTts.isLanguageAvailable("en-US"); + +// iOS and Web only +await flutterTts.pause(); + +// iOS, macOS, and Android only +await flutterTts.synthesizeToFile("Hello World", Platform.isAndroid ? "tts.wav" : "tts.caf"); + +await flutterTts.setVoice({"name": "Karen", "locale": "en-AU"}); + +// iOS only +await flutterTts.setSharedInstance(true); + +// Android only +await flutterTts.setSilence(2); + +await flutterTts.getEngines(); +``` + +### Listening for platform calls + +```dart +flutterTts.setStartHandler(() { + setState(() { + ttsState = TtsState.playing; + }); +}); + +flutterTts.setCompletionHandler(() { + setState(() { + ttsState = TtsState.stopped; + }); +}); + +flutterTts.setProgressHandler((String text, int startOffset, int endOffset, String word) { + setState(() { + _currentWord = word; + }); +}); + +flutterTts.setErrorHandler((msg) { + setState(() { + ttsState = TtsState.stopped; + }); +}); + +flutterTts.setCancelHandler((msg) { + setState(() { + ttsState = TtsState.stopped; + }); +}); + +// iOS and Web +flutterTts.setPauseHandler((msg) { + setState(() { + ttsState = TtsState.paused; + }); +}); + +flutterTts.setContinueHandler((msg) { + setState(() { + ttsState = TtsState.continued; + }); +}); +``` + +## Getting Started + +For help getting started with Flutter, view our online +[documentation](https://flutter.dev/). + +For help on editing plugin code, view the [documentation](https://flutter.dev/platform-plugins/#edit-code). diff --git a/flutter_tts-voice_enhancement/analysis_options.yaml b/flutter_tts-voice_enhancement/analysis_options.yaml new file mode 100644 index 00000000..e8779c50 --- /dev/null +++ b/flutter_tts-voice_enhancement/analysis_options.yaml @@ -0,0 +1,35 @@ +analyzer: + strong-mode: + implicit-casts: false + errors: + unused_import: error + unused_local_variable: error + dead_code: error +linter: + rules: + - avoid_empty_else + - comment_references + - control_flow_in_finally + - empty_statements + - hash_and_equals + - only_throw_errors + - test_types_in_equals + - throw_in_finally + - unrelated_type_equality_checks + - valid_regexps + - avoid_init_to_null + - avoid_return_types_on_setters + - await_only_futures + - camel_case_types + - directives_ordering + - empty_catches + - empty_constructor_bodies + - library_names + - library_prefixes + - non_constant_identifier_names + - omit_local_variable_types + - prefer_final_fields + - prefer_is_not_empty + - prefer_typing_uninitialized_variables + - slash_for_doc_comments + - type_init_formals \ No newline at end of file diff --git a/flutter_tts-voice_enhancement/android/.gitignore b/flutter_tts-voice_enhancement/android/.gitignore new file mode 100644 index 00000000..c6cbe562 --- /dev/null +++ b/flutter_tts-voice_enhancement/android/.gitignore @@ -0,0 +1,8 @@ +*.iml +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build +/captures diff --git a/flutter_tts-voice_enhancement/android/build.gradle b/flutter_tts-voice_enhancement/android/build.gradle new file mode 100644 index 00000000..1308c920 --- /dev/null +++ b/flutter_tts-voice_enhancement/android/build.gradle @@ -0,0 +1,48 @@ +def PLUGIN = "flutter_tts"; +def ANDROIDX_WARNING = "flutterPluginsAndroidXWarning"; +gradle.buildFinished { buildResult -> + if (buildResult.failure && !rootProject.ext.has(ANDROIDX_WARNING)) { + println ' *********************************************************' + println 'WARNING: This version of ' + PLUGIN + ' will break your Android build if it or its dependencies aren\'t compatible with AndroidX.' + println ' See https://goo.gl/CP92wY for more information on the problem and how to fix it.' + println ' This warning prints for all Android build failures. The real root cause of the error may be unrelated.' + println ' *********************************************************' + rootProject.ext.set(ANDROIDX_WARNING, true); + } +} + +group 'com.tundralabs.fluttertts' +version '1.0-SNAPSHOT' + +buildscript { + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.4.2' + } +} + +rootProject.allprojects { + repositories { + google() + jcenter() + } +} + +apply plugin: 'com.android.library' + +android { + compileSdkVersion 28 + + defaultConfig { + minSdkVersion 21 + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + targetSdkVersion 27 + } + lintOptions { + disable 'InvalidPackage' + } +} diff --git a/flutter_tts-voice_enhancement/android/gradle.properties b/flutter_tts-voice_enhancement/android/gradle.properties new file mode 100644 index 00000000..a6738207 --- /dev/null +++ b/flutter_tts-voice_enhancement/android/gradle.properties @@ -0,0 +1,4 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true +android.enableR8=true diff --git a/flutter_tts-voice_enhancement/android/gradle/wrapper/gradle-wrapper.properties b/flutter_tts-voice_enhancement/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..8d9c8a3f --- /dev/null +++ b/flutter_tts-voice_enhancement/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Sep 27 12:18:40 PDT 2019 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip diff --git a/flutter_tts-voice_enhancement/android/settings.gradle b/flutter_tts-voice_enhancement/android/settings.gradle new file mode 100644 index 00000000..26aeb433 --- /dev/null +++ b/flutter_tts-voice_enhancement/android/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'flutter_tts' diff --git a/flutter_tts-voice_enhancement/android/src/main/AndroidManifest.xml b/flutter_tts-voice_enhancement/android/src/main/AndroidManifest.xml new file mode 100644 index 00000000..9cad3a1b --- /dev/null +++ b/flutter_tts-voice_enhancement/android/src/main/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + diff --git a/flutter_tts-voice_enhancement/android/src/main/java/com/tundralabs/fluttertts/FlutterTtsPlugin.java b/flutter_tts-voice_enhancement/android/src/main/java/com/tundralabs/fluttertts/FlutterTtsPlugin.java new file mode 100644 index 00000000..92e6a092 --- /dev/null +++ b/flutter_tts-voice_enhancement/android/src/main/java/com/tundralabs/fluttertts/FlutterTtsPlugin.java @@ -0,0 +1,454 @@ +package com.tundralabs.fluttertts; + +import android.content.Context; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.speech.tts.TextToSpeech; +import android.speech.tts.UtteranceProgressListener; +import android.speech.tts.Voice; +import android.util.Log; +import androidx.annotation.NonNull; +import io.flutter.embedding.engine.plugins.FlutterPlugin; +import io.flutter.plugin.common.BinaryMessenger; +import io.flutter.plugin.common.MethodCall; +import io.flutter.plugin.common.MethodChannel; +import io.flutter.plugin.common.MethodChannel.MethodCallHandler; +import io.flutter.plugin.common.MethodChannel.Result; +import io.flutter.plugin.common.PluginRegistry.Registrar; +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.UUID; + +/** FlutterTtsPlugin */ +public class FlutterTtsPlugin implements MethodCallHandler, FlutterPlugin { + private Handler handler; + private MethodChannel methodChannel; + private MethodChannel.Result speakResult; + private boolean awaitSpeakCompletion = false; + private boolean speaking = false; + private Context context; + private TextToSpeech tts; + private final String tag = "TTS"; + private final String googleTtsEngine = "com.google.android.tts"; + private boolean isTtsInitialized = false; + private ArrayList pendingMethodCalls = new ArrayList<>(); + private final HashMap utterances = new HashMap<>(); + Bundle bundle; + private int silencems; + private static final String SILENCE_PREFIX = "SIL_"; + private static final String SYNTHESIZE_TO_FILE_PREFIX = "STF_"; + + /** Plugin registration. */ + public static void registerWith(Registrar registrar) { + FlutterTtsPlugin instance = new FlutterTtsPlugin(); + instance.initInstance(registrar.messenger(), registrar.activeContext()); + } + + private void initInstance(BinaryMessenger messenger, Context context) { + this.context = context; + methodChannel = new MethodChannel(messenger, "flutter_tts"); + methodChannel.setMethodCallHandler(this); + handler = new Handler(Looper.getMainLooper()); + bundle = new Bundle(); + tts = new TextToSpeech(context, onInitListener, googleTtsEngine); + } + + /** Android Plugin APIs */ + @Override + public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) { + initInstance(binding.getBinaryMessenger(), binding.getApplicationContext()); + } + + @Override + public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { + stop(); + tts.shutdown(); + context = null; + methodChannel.setMethodCallHandler(null); + methodChannel = null; + } + + private UtteranceProgressListener utteranceProgressListener = + new UtteranceProgressListener() { + @Override + public void onStart(String utteranceId) { + if (utteranceId != null && utteranceId.startsWith(SYNTHESIZE_TO_FILE_PREFIX)) { + invokeMethod("synth.onStart", true); + } else { + Log.d(tag, "Utterance ID has started: " + utteranceId); + invokeMethod("speak.onStart", true); + } + if (Build.VERSION.SDK_INT < 26) { + this.onProgress(utteranceId, 0, utterances.get(utteranceId).length()); + } + } + + @Override + public void onDone(String utteranceId) { + if (utteranceId != null && utteranceId.startsWith(SILENCE_PREFIX)) return; + if (utteranceId != null && utteranceId.startsWith(SYNTHESIZE_TO_FILE_PREFIX)) { + invokeMethod("synth.onComplete", true); + } else { + Log.d(tag, "Utterance ID has completed: " + utteranceId); + if (awaitSpeakCompletion) { + speakCompletion(1); + } + invokeMethod("speak.onComplete", true); + } + utterances.remove(utteranceId); + } + + @Override + public void onStop(String utteranceId, boolean interrupted) { + Log.d( + tag, + "Utterance ID has been stopped: " + utteranceId + ". Interrupted: " + interrupted); + if (awaitSpeakCompletion) { + speaking = false; + } + invokeMethod("speak.onCancel", true); + } + + private void onProgress(String utteranceId, int startAt, int endAt) { + if (utteranceId != null && !utteranceId.startsWith(SYNTHESIZE_TO_FILE_PREFIX)) { + final String text = utterances.get(utteranceId); + final HashMap data = new HashMap<>(); + data.put("text", text); + data.put("start", Integer.toString(startAt)); + data.put("end", Integer.toString(endAt)); + data.put("word", text.substring(startAt, endAt)); + invokeMethod("speak.onProgress", data); + } + } + + // Requires Android 26 or later + @Override + public void onRangeStart(String utteranceId, int startAt, int endAt, int frame) { + if (utteranceId != null && !utteranceId.startsWith(SYNTHESIZE_TO_FILE_PREFIX)) { + super.onRangeStart(utteranceId, startAt, endAt, frame); + this.onProgress(utteranceId, startAt, endAt); + } + } + + @Override + @Deprecated + public void onError(String utteranceId) { + if (utteranceId != null && utteranceId.startsWith(SYNTHESIZE_TO_FILE_PREFIX)) { + invokeMethod("synth.onError", "Error from TextToSpeech (synth)"); + } else { + if (awaitSpeakCompletion) { + speaking = false; + } + invokeMethod("speak.onError", "Error from TextToSpeech (speak)"); + } + } + + @Override + public void onError(String utteranceId, int errorCode) { + if (utteranceId != null && utteranceId.startsWith(SYNTHESIZE_TO_FILE_PREFIX)) { + invokeMethod("synth.onError", "Error from TextToSpeech (synth) - " + errorCode); + } else { + if (awaitSpeakCompletion) { + speaking = false; + } + invokeMethod("speak.onError", "Error from TextToSpeech (speak) - " + errorCode); + } + } + }; + + void speakCompletion(final int success) { + speaking = false; + handler.post( + new Runnable() { + @Override + public void run() { + speakResult.success(success); + } + }); + } + + private TextToSpeech.OnInitListener onInitListener = + new TextToSpeech.OnInitListener() { + @Override + public void onInit(int status) { + if (status == TextToSpeech.SUCCESS) { + tts.setOnUtteranceProgressListener(utteranceProgressListener); + + try { + Locale locale = tts.getDefaultVoice().getLocale(); + if (isLanguageAvailable(locale)) { + tts.setLanguage(locale); + } + } catch (NullPointerException | IllegalArgumentException e) { + Log.e(tag, "getDefaultLocale: " + e.getMessage()); + } + + // Handle pending method calls (sent while TTS was initializing) + isTtsInitialized = true; + for (Runnable call : pendingMethodCalls) { + call.run(); + } + } else { + Log.e(tag, "Failed to initialize TextToSpeech"); + } + } + }; + + @Override + public void onMethodCall(@NonNull final MethodCall call, @NonNull final Result result) { + // If TTS is still loading + if (!isTtsInitialized) { + // Suspend method call until the TTS engine is ready + final Runnable suspendedCall = + new Runnable() { + public void run() { + onMethodCall(call, result); + } + }; + pendingMethodCalls.add(suspendedCall); + return; + } + switch (call.method) { + case "speak": + { + String text = call.arguments.toString(); + if (this.speaking) { + result.success(0); + break; + } + speak(text); + if (this.awaitSpeakCompletion) { + this.speaking = true; + this.speakResult = result; + } else { + result.success(1); + } + break; + } + case "awaitSpeakCompletion": + { + this.awaitSpeakCompletion = Boolean.parseBoolean(call.arguments.toString()); + result.success(1); + break; + } + case "synthesizeToFile": + { + String text = call.argument("text"); + String fileName = call.argument("fileName"); + synthesizeToFile(text, fileName); + result.success(1); + break; + } + case "stop": + stop(); + result.success(1); + break; + case "setSpeechRate": + String rate = call.arguments.toString(); + setSpeechRate(Float.parseFloat(rate)); + result.success(1); + break; + case "setVolume": + String volume = call.arguments.toString(); + setVolume(Float.parseFloat(volume), result); + break; + case "setPitch": + String pitch = call.arguments.toString(); + setPitch(Float.parseFloat(pitch), result); + break; + case "setLanguage": + { + String language = call.arguments.toString(); + setLanguage(language, result); + break; + } + case "getLanguages": + getLanguages(result); + break; + case "getVoices": + getVoices(result); + break; + case "getSpeechRateValidRange": + getSpeechRateValidRange(result); + break; + case "getEngines": + getEngines(result); + break; + case "setVoice": + HashMap voice = call.arguments(); + setVoice(voice, result); + break; + case "isLanguageAvailable": + { + String language = call.arguments().toString(); + Locale locale = Locale.forLanguageTag(language); + result.success(isLanguageAvailable(locale)); + break; + } + case "setSilence": + String silencems = call.arguments.toString(); + this.silencems = Integer.parseInt(silencems); + break; + case "setSharedInstance": + result.success(1); + break; + default: + result.notImplemented(); + break; + } + } + + void setSpeechRate(float rate) { + tts.setSpeechRate(rate); + } + + Boolean isLanguageAvailable(Locale locale) { + return tts.isLanguageAvailable(locale) >= TextToSpeech.LANG_AVAILABLE; + } + + void setLanguage(String language, Result result) { + Locale locale = Locale.forLanguageTag(language); + if (isLanguageAvailable(locale)) { + tts.setLanguage(locale); + result.success(1); + } else { + result.success(0); + } + } + + void setVoice(HashMap voice, Result result) { + for (Voice ttsVoice : tts.getVoices()) { + if (ttsVoice.getName().equals(voice.get("name")) && ttsVoice.getLocale().toLanguageTag().equals(voice.get("locale"))) { + tts.setVoice(ttsVoice); + result.success(1); + return; + } + } + Log.d(tag, "Voice name not found: " + voice); + result.success(0); + } + + void setVolume(float volume, Result result) { + if (volume >= 0.0F && volume <= 1.0F) { + bundle.putFloat(TextToSpeech.Engine.KEY_PARAM_VOLUME, volume); + result.success(1); + } else { + Log.d(tag, "Invalid volume " + volume + " value - Range is from 0.0 to 1.0"); + result.success(0); + } + } + + void setPitch(float pitch, Result result) { + if (pitch >= 0.5F && pitch <= 2.0F) { + tts.setPitch(pitch); + result.success(1); + } else { + Log.d(tag, "Invalid pitch " + pitch + " value - Range is from 0.5 to 2.0"); + result.success(0); + } + } + + void getVoices(Result result) { + ArrayList> voices = new ArrayList<>(); + try { + for (Voice voice : tts.getVoices()) { + HashMap voiceMap = new HashMap<>(); + voiceMap.put("name", voice.getName()); + voiceMap.put("locale", voice.getLocale().toLanguageTag()); + voices.add(voiceMap); + } + result.success(voices); + } catch (NullPointerException e) { + Log.d(tag, "getVoices: " + e.getMessage()); + result.success(null); + } + } + + void getLanguages(Result result) { + ArrayList locales = new ArrayList<>(); + try { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + // While this method was introduced in API level 21, it seems that it + // has not been implemented in the speech service side until API Level 23. + for (Locale locale : tts.getAvailableLanguages()) { + locales.add(locale.toLanguageTag()); + } + } else { + for (Locale locale : Locale.getAvailableLocales()) { + if (locale.getVariant().isEmpty() && isLanguageAvailable(locale)) { + locales.add(locale.toLanguageTag()); + } + } + } + } catch (MissingResourceException | NullPointerException e) { + Log.d(tag, "getLanguages: " + e.getMessage()); + } + result.success(locales); + } + + void getEngines(Result result) { + ArrayList engines = new ArrayList<>(); + try { + for (TextToSpeech.EngineInfo engineInfo : tts.getEngines()) { + engines.add(engineInfo.name); + } + } catch (Exception e) { + Log.d(tag, "getEngines: " + e.getMessage()); + } + result.success(engines); + } + + void getSpeechRateValidRange(Result result) { + // Valid values available in the android documentation. + // https://developer.android.com/reference/android/speech/tts/TextToSpeech#setSpeechRate(float) + final HashMap data = new HashMap(); + data.put("min", "0"); + data.put("normal", "1"); + data.put("max", "3"); + data.put("platform", "android"); + result.success(data); + } + + private void speak(String text) { + String uuid = UUID.randomUUID().toString(); + utterances.put(uuid, text); + if (silencems > 0) { + tts.playSilentUtterance(silencems, TextToSpeech.QUEUE_FLUSH, SILENCE_PREFIX + uuid); + tts.speak(text, TextToSpeech.QUEUE_ADD, bundle, uuid); + } else { + tts.speak(text, TextToSpeech.QUEUE_FLUSH, bundle, uuid); + } + } + + private void stop() { + tts.stop(); + } + + private void synthesizeToFile(String text, String fileName) { + File file = new File(context.getExternalFilesDir(null), fileName); + String uuid = UUID.randomUUID().toString(); + bundle.putString(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, SYNTHESIZE_TO_FILE_PREFIX + uuid); + + int result = tts.synthesizeToFile(text, bundle, file, SYNTHESIZE_TO_FILE_PREFIX + uuid); + if (result == TextToSpeech.SUCCESS) { + Log.d(tag, "Successfully created file : " + file.getPath()); + } else { + Log.d(tag, "Failed creating file : " + file.getPath()); + } + } + + private void invokeMethod(final String method, final Object arguments) { + handler.post( + new Runnable() { + @Override + public void run() { + if (methodChannel != null) methodChannel.invokeMethod(method, arguments); + } + }); + } +} diff --git a/flutter_tts-voice_enhancement/example/.gitignore b/flutter_tts-voice_enhancement/example/.gitignore new file mode 100644 index 00000000..7e6bbd47 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/.gitignore @@ -0,0 +1,11 @@ +.DS_Store +.dart_tool/ + +.packages +.pub/ + +build/ + +.flutter-plugins +.flutter-plugins-dependencies +lib/generated_plugin_registrant.dart \ No newline at end of file diff --git a/flutter_tts-voice_enhancement/example/.metadata b/flutter_tts-voice_enhancement/example/.metadata new file mode 100644 index 00000000..3c0dd2c8 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/.metadata @@ -0,0 +1,8 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: b397406561f5e7a9c94e28f58d9e49fca0dd58b7 + channel: beta diff --git a/flutter_tts-voice_enhancement/example/README.md b/flutter_tts-voice_enhancement/example/README.md new file mode 100644 index 00000000..a1356260 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/README.md @@ -0,0 +1,16 @@ +# example + +A new Flutter project. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) + +For help getting started with Flutter, view our +[online documentation](https://flutter.dev/docs), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/flutter_tts-voice_enhancement/example/android/.gitignore b/flutter_tts-voice_enhancement/example/android/.gitignore new file mode 100644 index 00000000..65b7315a --- /dev/null +++ b/flutter_tts-voice_enhancement/example/android/.gitignore @@ -0,0 +1,10 @@ +*.iml +*.class +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build +/captures +GeneratedPluginRegistrant.java diff --git a/flutter_tts-voice_enhancement/example/android/.settings/org.eclipse.buildship.core.prefs b/flutter_tts-voice_enhancement/example/android/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 00000000..9f105273 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/android/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,2 @@ +#Sat Apr 14 11:55:40 PDT 2018 +connection.project.dir= diff --git a/flutter_tts-voice_enhancement/example/android/app/.classpath b/flutter_tts-voice_enhancement/example/android/app/.classpath new file mode 100644 index 00000000..8d8d85f1 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/android/app/.classpath @@ -0,0 +1,6 @@ + + + + + + diff --git a/flutter_tts-voice_enhancement/example/android/app/.settings/org.eclipse.buildship.core.prefs b/flutter_tts-voice_enhancement/example/android/app/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 00000000..0601ea50 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/android/app/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,2 @@ +#Sat Apr 14 11:55:40 PDT 2018 +connection.project.dir=.. diff --git a/flutter_tts-voice_enhancement/example/android/app/build.gradle b/flutter_tts-voice_enhancement/example/android/app/build.gradle new file mode 100644 index 00000000..563b8f89 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/android/app/build.gradle @@ -0,0 +1,50 @@ +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +apply plugin: 'com.android.application' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + compileSdkVersion 28 + + lintOptions { + disable 'InvalidPackage' + } + + defaultConfig { + applicationId "com.tundralabs.flutterttsexample" + minSdkVersion 21 + targetSdkVersion 28 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies { + testImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test:runner:1.1.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0' +} diff --git a/flutter_tts-voice_enhancement/example/android/app/src/debug/AndroidManifest.xml b/flutter_tts-voice_enhancement/example/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 00000000..49f10e46 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/flutter_tts-voice_enhancement/example/android/app/src/main/AndroidManifest.xml b/flutter_tts-voice_enhancement/example/android/app/src/main/AndroidManifest.xml new file mode 100644 index 00000000..1caca009 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/flutter_tts-voice_enhancement/example/android/app/src/main/res/drawable/launch_background.xml b/flutter_tts-voice_enhancement/example/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 00000000..304732f8 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/flutter_tts-voice_enhancement/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/flutter_tts-voice_enhancement/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..db77bb4b7b0906d62b1847e87f15cdcacf6a4f29 GIT binary patch literal 544 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAj~WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!h8bpbvhu0Wd6uZuB!w&u2PAxD2eNXD>P5D~Wn-+_Wa#27Xc zC?Zj|6r#X(-D3u$NCt}(Ms06KgJ4FxJVv{GM)!I~&n8Bnc94O7-Hd)cjDZswgC;Qs zO=b+9!WcT8F?0rF7!Uys2bs@gozCP?z~o%U|N3vA*22NaGQG zlg@K`O_XuxvZ&Ks^m&R!`&1=spLvfx7oGDKDwpwW`#iqdw@AL`7MR}m`rwr|mZgU`8P7SBkL78fFf!WnuYWm$5Z0 zNXhDbCv&49sM544K|?c)WrFfiZvCi9h0O)B3Pgg&ebxsLQ05GG~ AQ2+n{ literal 0 HcmV?d00001 diff --git a/flutter_tts-voice_enhancement/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/flutter_tts-voice_enhancement/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..17987b79bb8a35cc66c3c1fd44f5a5526c1b78be GIT binary patch literal 442 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5Xx&nMcT!A!W`0S9QKQy;}1Cl^CgaH=;G9cpY;r$Q>i*pfB zP2drbID<_#qf;rPZx^FqH)F_D#*k@@q03KywUtLX8Ua?`H+NMzkczFPK3lFz@i_kW%1NOn0|D2I9n9wzH8m|-tHjsw|9>@K=iMBhxvkv6m8Y-l zytQ?X=U+MF$@3 zt`~i=@j|6y)RWMK--}M|=T`o&^Ni>IoWKHEbBXz7?A@mgWoL>!*SXo`SZH-*HSdS+ yn*9;$7;m`l>wYBC5bq;=U}IMqLzqbYCidGC!)_gkIk_C@Uy!y&wkt5C($~2D>~)O*cj@FGjOCM)M>_ixfudOh)?xMu#Fs z#}Y=@YDTwOM)x{K_j*Q;dPdJ?Mz0n|pLRx{4n|)f>SXlmV)XB04CrSJn#dS5nK2lM zrZ9#~WelCp7&e13Y$jvaEXHskn$2V!!DN-nWS__6T*l;H&Fopn?A6HZ-6WRLFP=R` zqG+CE#d4|IbyAI+rJJ`&x9*T`+a=p|0O(+s{UBcyZdkhj=yS1>AirP+0R;mf2uMgM zC}@~JfByORAh4SyRgi&!(cja>F(l*O+nd+@4m$|6K6KDn_&uvCpV23&>G9HJp{xgg zoq1^2_p9@|WEo z*X_Uko@K)qYYv~>43eQGMdbiGbo>E~Q& zrYBH{QP^@Sti!`2)uG{irBBq@y*$B zi#&(U-*=fp74j)RyIw49+0MRPMRU)+a2r*PJ$L5roHt2$UjExCTZSbq%V!HeS7J$N zdG@vOZB4v_lF7Plrx+hxo7(fCV&}fHq)$ literal 0 HcmV?d00001 diff --git a/flutter_tts-voice_enhancement/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/flutter_tts-voice_enhancement/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..d5f1c8d34e7a88e3f88bea192c3a370d44689c3c GIT binary patch literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q8Ax83A=Cw=BuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFa`(sgt!6~Yi|1%a`XoT0ojZ}lNrNjb9xjc(B0U1_% zz5^97Xt*%oq$rQy4?0GKNfJ44uvxI)gC`h-NZ|&0-7(qS@?b!5r36oQ}zyZrNO3 zMO=Or+<~>+A&uN&E!^Sl+>xE!QC-|oJv`ApDhqC^EWD|@=#J`=d#Xzxs4ah}w&Jnc z$|q_opQ^2TrnVZ0o~wh<3t%W&flvYGe#$xqda2bR_R zvPYgMcHgjZ5nSA^lJr%;<&0do;O^tDDh~=pIxA#coaCY>&N%M2^tq^U%3DB@ynvKo}b?yu-bFc-u0JHzced$sg7S3zqI(2 z#Km{dPr7I=pQ5>FuK#)QwK?Y`E`B?nP+}U)I#c1+FM*1kNvWG|a(TpksZQ3B@sD~b zpQ2)*V*TdwjFOtHvV|;OsiDqHi=6%)o4b!)x$)%9pGTsE z-JL={-Ffv+T87W(Xpooq<`r*VzWQcgBN$$`u}f>-ZQI1BB8ykN*=e4rIsJx9>z}*o zo~|9I;xof literal 0 HcmV?d00001 diff --git a/flutter_tts-voice_enhancement/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/flutter_tts-voice_enhancement/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..4d6372eebdb28e45604e46eeda8dd24651419bc0 GIT binary patch literal 1443 zcmb`G{WsKk6vsdJTdFg%tJav9_E4vzrOaqkWF|A724Nly!y+?N9`YV6wZ}5(X(D_N(?!*n3`|_r0Hc?=PQw&*vnU?QTFY zB_MsH|!j$PP;I}?dppoE_gA(4uc!jV&0!l7_;&p2^pxNo>PEcNJv za5_RT$o2Mf!<+r?&EbHH6nMoTsDOa;mN(wv8RNsHpG)`^ymG-S5By8=l9iVXzN_eG%Xg2@Xeq76tTZ*dGh~Lo9vl;Zfs+W#BydUw zCkZ$o1LqWQO$FC9aKlLl*7x9^0q%0}$OMlp@Kk_jHXOjofdePND+j!A{q!8~Jn+s3 z?~~w@4?egS02}8NuulUA=L~QQfm;MzCGd)XhiftT;+zFO&JVyp2mBww?;QByS_1w! zrQlx%{^cMj0|Bo1FjwY@Q8?Hx0cIPF*@-ZRFpPc#bBw{5@tD(5%sClzIfl8WU~V#u zm5Q;_F!wa$BSpqhN>W@2De?TKWR*!ujY;Yylk_X5#~V!L*Gw~;$%4Q8~Mad z@`-kG?yb$a9cHIApZDVZ^U6Xkp<*4rU82O7%}0jjHlK{id@?-wpN*fCHXyXh(bLt* zPc}H-x0e4E&nQ>y%B-(EL=9}RyC%MyX=upHuFhAk&MLbsF0LP-q`XnH78@fT+pKPW zu72MW`|?8ht^tz$iC}ZwLp4tB;Q49K!QCF3@!iB1qOI=?w z7In!}F~ij(18UYUjnbmC!qKhPo%24?8U1x{7o(+?^Zu0Hx81|FuS?bJ0jgBhEMzf< zCgUq7r2OCB(`XkKcN-TL>u5y#dD6D!)5W?`O5)V^>jb)P)GBdy%t$uUMpf$SNV31$ zb||OojAbvMP?T@$h_ZiFLFVHDmbyMhJF|-_)HX3%m=CDI+ID$0^C>kzxprBW)hw(v zr!Gmda);ICoQyhV_oP5+C%?jcG8v+D@9f?Dk*!BxY}dazmrT@64UrP3hlslANK)bq z$67n83eh}OeW&SV@HG95P|bjfqJ7gw$e+`Hxo!4cx`jdK1bJ>YDSpGKLPZ^1cv$ek zIB?0S<#tX?SJCLWdMd{-ME?$hc7A$zBOdIJ)4!KcAwb=VMov)nK;9z>x~rfT1>dS+ zZ6#`2v@`jgbqq)P22H)Tx2CpmM^o1$B+xT6`(v%5xJ(?j#>Q$+rx_R|7TzDZe{J6q zG1*EcU%tE?!kO%^M;3aM6JN*LAKUVb^xz8-Pxo#jR5(-KBeLJvA@-gxNHx0M-ZJLl z;#JwQoh~9V?`UVo#}{6ka@II>++D@%KqGpMdlQ}?9E*wFcf5(#XQnP$Dk5~%iX^>f z%$y;?M0BLp{O3a(-4A?ewryHrrD%cx#Q^%KY1H zNre$ve+vceSLZcNY4U(RBX&)oZn*Py()h)XkE?PL$!bNb{N5FVI2Y%LKEm%yvpyTP z(1P?z~7YxD~Rf<(a@_y` literal 0 HcmV?d00001 diff --git a/flutter_tts-voice_enhancement/example/android/app/src/main/res/values/styles.xml b/flutter_tts-voice_enhancement/example/android/app/src/main/res/values/styles.xml new file mode 100644 index 00000000..1f83a33f --- /dev/null +++ b/flutter_tts-voice_enhancement/example/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/flutter_tts-voice_enhancement/example/android/app/src/profile/AndroidManifest.xml b/flutter_tts-voice_enhancement/example/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 00000000..49f10e46 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/flutter_tts-voice_enhancement/example/android/build.gradle b/flutter_tts-voice_enhancement/example/android/build.gradle new file mode 100644 index 00000000..cd23eff8 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/android/build.gradle @@ -0,0 +1,29 @@ +buildscript { + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:4.0.0' + } +} + +allprojects { + repositories { + google() + jcenter() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/flutter_tts-voice_enhancement/example/android/gradle.properties b/flutter_tts-voice_enhancement/example/android/gradle.properties new file mode 100644 index 00000000..b6e61b62 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/android/gradle.properties @@ -0,0 +1,4 @@ +android.enableJetifier=true +android.useAndroidX=true +org.gradle.jvmargs=-Xmx1536M +android.enableR8=true diff --git a/flutter_tts-voice_enhancement/example/android/gradle/wrapper/gradle-wrapper.properties b/flutter_tts-voice_enhancement/example/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..495eba36 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Tue Jul 07 01:11:38 PDT 2020 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip diff --git a/flutter_tts-voice_enhancement/example/android/settings.gradle b/flutter_tts-voice_enhancement/example/android/settings.gradle new file mode 100644 index 00000000..5a2f14fb --- /dev/null +++ b/flutter_tts-voice_enhancement/example/android/settings.gradle @@ -0,0 +1,15 @@ +include ':app' + +def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() + +def plugins = new Properties() +def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') +if (pluginsFile.exists()) { + pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } +} + +plugins.each { name, path -> + def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() + include ":$name" + project(":$name").projectDir = pluginDirectory +} diff --git a/flutter_tts-voice_enhancement/example/android/settings_aar.gradle b/flutter_tts-voice_enhancement/example/android/settings_aar.gradle new file mode 100644 index 00000000..e7b4def4 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/android/settings_aar.gradle @@ -0,0 +1 @@ +include ':app' diff --git a/flutter_tts-voice_enhancement/example/ios/.gitignore b/flutter_tts-voice_enhancement/example/ios/.gitignore new file mode 100644 index 00000000..1e1aafd6 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/ios/.gitignore @@ -0,0 +1,42 @@ +.idea/ +.vagrant/ +.sconsign.dblite +.svn/ + +.DS_Store +*.swp +profile + +DerivedData/ +build/ +GeneratedPluginRegistrant.h +GeneratedPluginRegistrant.m + +*.pbxuser +*.mode1v3 +*.mode2v3 +*.perspectivev3 + +!default.pbxuser +!default.mode1v3 +!default.mode2v3 +!default.perspectivev3 + +xcuserdata + +*.moved-aside + +*.pyc +*sync/ +Icon? +.tags* + +/Flutter/app.flx +/Flutter/app.zip +/Flutter/flutter_assets/ +/Flutter/App.framework +/Flutter/Flutter.framework +/Flutter/Generated.xcconfig +/ServiceDefinitions.json + +Pods/ diff --git a/flutter_tts-voice_enhancement/example/ios/Flutter/.last_build_id b/flutter_tts-voice_enhancement/example/ios/Flutter/.last_build_id new file mode 100644 index 00000000..bfaaeba1 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/ios/Flutter/.last_build_id @@ -0,0 +1 @@ +b443c2d1b6b1e4df6c6fcc277a981410 \ No newline at end of file diff --git a/flutter_tts-voice_enhancement/example/ios/Flutter/AppFrameworkInfo.plist b/flutter_tts-voice_enhancement/example/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 00000000..6c2de808 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,30 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + UIRequiredDeviceCapabilities + + arm64 + + MinimumOSVersion + 8.0 + + diff --git a/flutter_tts-voice_enhancement/example/ios/Flutter/Debug.xcconfig b/flutter_tts-voice_enhancement/example/ios/Flutter/Debug.xcconfig new file mode 100644 index 00000000..e8efba11 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/flutter_tts-voice_enhancement/example/ios/Flutter/Flutter.podspec b/flutter_tts-voice_enhancement/example/ios/Flutter/Flutter.podspec new file mode 100644 index 00000000..5ca30416 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/ios/Flutter/Flutter.podspec @@ -0,0 +1,18 @@ +# +# NOTE: This podspec is NOT to be published. It is only used as a local source! +# + +Pod::Spec.new do |s| + s.name = 'Flutter' + s.version = '1.0.0' + s.summary = 'High-performance, high-fidelity mobile apps.' + s.description = <<-DESC +Flutter provides an easy and productive way to build and deploy high-performance mobile apps for Android and iOS. + DESC + s.homepage = 'https://flutter.io' + s.license = { :type => 'MIT' } + s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' } + s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s } + s.ios.deployment_target = '8.0' + s.vendored_frameworks = 'Flutter.framework' +end diff --git a/flutter_tts-voice_enhancement/example/ios/Flutter/Release.xcconfig b/flutter_tts-voice_enhancement/example/ios/Flutter/Release.xcconfig new file mode 100644 index 00000000..399e9340 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/flutter_tts-voice_enhancement/example/ios/Podfile b/flutter_tts-voice_enhancement/example/ios/Podfile new file mode 100644 index 00000000..1e8c3c90 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/ios/Podfile @@ -0,0 +1,41 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '9.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/flutter_tts-voice_enhancement/example/ios/Runner.xcodeproj/project.pbxproj b/flutter_tts-voice_enhancement/example/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 00000000..28d4b795 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,488 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 72BCD356E80F9F5F32A2B586 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BE3436CECE15DEA290DCD6B6 /* Pods_Runner.framework */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + BE3436CECE15DEA290DCD6B6 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + CED86603210BC43D753C699B /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + CF068A80D9BD19FC43D3FE99 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 72BCD356E80F9F5F32A2B586 /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 04223708A30129901099FE16 /* Frameworks */ = { + isa = PBXGroup; + children = ( + BE3436CECE15DEA290DCD6B6 /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 1ED2DC2A248FC04D7FB5EA8C /* Pods */ = { + isa = PBXGroup; + children = ( + CF068A80D9BD19FC43D3FE99 /* Pods-Runner.debug.xcconfig */, + CED86603210BC43D753C699B /* Pods-Runner.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 1ED2DC2A248FC04D7FB5EA8C /* Pods */, + 04223708A30129901099FE16 /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 97C146F11CF9000F007C117D /* Supporting Files */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; + 97C146F11CF9000F007C117D /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 3B0CA933DCDA45D4F71410D4 /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 46F7EA90EF3F4667EDB9E562 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0940; + ORGANIZATIONNAME = "The Chromium Authors"; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 0910; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 3B0CA933DCDA45D4F71410D4 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 46F7EA90EF3F4667EDB9E562 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", + "${PODS_ROOT}/../Flutter/Flutter.framework", + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = 1; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.tundralabs.flutterTtsExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = On; + SWIFT_VERSION = 4.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = 1; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.tundralabs.flutterTtsExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_SWIFT3_OBJC_INFERENCE = On; + SWIFT_VERSION = 4.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/flutter_tts-voice_enhancement/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/flutter_tts-voice_enhancement/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..1d526a16 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/flutter_tts-voice_enhancement/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/flutter_tts-voice_enhancement/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/flutter_tts-voice_enhancement/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/flutter_tts-voice_enhancement/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..f9b0d7c5 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/flutter_tts-voice_enhancement/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/flutter_tts-voice_enhancement/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 00000000..4bafc458 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/flutter_tts-voice_enhancement/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/flutter_tts-voice_enhancement/example/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..21a3cc14 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/flutter_tts-voice_enhancement/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/flutter_tts-voice_enhancement/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/flutter_tts-voice_enhancement/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/flutter_tts-voice_enhancement/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..f9b0d7c5 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/flutter_tts-voice_enhancement/example/ios/Runner/AppDelegate.swift b/flutter_tts-voice_enhancement/example/ios/Runner/AppDelegate.swift new file mode 100644 index 00000000..71cc41e3 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..d36b1fab --- /dev/null +++ b/flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..3d43d11e66f4de3da27ed045ca4fe38ad8b48094 GIT binary patch literal 11112 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 P-1+_A+?hGkL;m(J7kc&K literal 0 HcmV?d00001 diff --git a/flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..28c6bf03016f6c994b70f38d1b7346e5831b531f GIT binary patch literal 564 zcmV-40?Yl0P)Px$?ny*JR5%f>l)FnDQ543{x%ZCiu33$Wg!pQFfT_}?5Q|_VSlIbLC`dpoMXL}9 zHfd9&47Mo(7D231gb+kjFxZHS4-m~7WurTH&doVX2KI5sU4v(sJ1@T9eCIKPjsqSr z)C01LsCxk=72-vXmX}CQD#BD;Cthymh&~=f$Q8nn0J<}ZrusBy4PvRNE}+1ceuj8u z0mW5k8fmgeLnTbWHGwfKA3@PdZxhn|PypR&^p?weGftrtCbjF#+zk_5BJh7;0`#Wr zgDpM_;Ax{jO##IrT`Oz;MvfwGfV$zD#c2xckpcXC6oou4ML~ezCc2EtnsQTB4tWNg z?4bkf;hG7IMfhgNI(FV5Gs4|*GyMTIY0$B=_*mso9Ityq$m^S>15>-?0(zQ<8Qy<_TjHE33(?_M8oaM zyc;NxzRVK@DL6RJnX%U^xW0Gpg(lXp(!uK1v0YgHjs^ZXSQ|m#lV7ip7{`C_J2TxPmfw%h$|%acrYHt)Re^PB%O&&=~a zhS(%I#+V>J-vjIib^<+s%ludY7y^C(P8nmqn9fp!i+?vr`bziDE=bx`%2W#Xyrj|i z!XQ4v1%L`m{7KT7q+LZNB^h8Ha2e=`Wp65^0;J00)_^G=au=8Yo;1b`CV&@#=jIBo zjN^JNVfYSs)+kDdGe7`1&8!?MQYKS?DuHZf3iogk_%#9E|5S zWeHrmAo>P;ejX7mwq#*}W25m^ZI+{(Z8fI?4jM_fffY0nok=+88^|*_DwcW>mR#e+ zX$F_KMdb6sRz!~7KkyN0G(3XQ+;z3X%PZ4gh;n-%62U<*VUKNv(D&Q->Na@Xb&u5Q3`3DGf+a8O5x7c#7+R+EAYl@R5us)CIw z7sT@_y~Ao@uL#&^LIh&QceqiT^+lb0YbFZt_SHOtWA%mgPEKVNvVgCsXy{5+zl*X8 zCJe)Q@y>wH^>l4;h1l^Y*9%-23TSmE>q5nI@?mt%n;Sj4Qq`Z+ib)a*a^cJc%E9^J zB;4s+K@rARbcBLT5P=@r;IVnBMKvT*)ew*R;&8vu%?Z&S>s?8?)3*YawM0P4!q$Kv zMmKh3lgE~&w&v%wVzH3Oe=jeNT=n@Y6J6TdHWTjXfX~-=1A1Bw`EW8rn}MqeI34nh zexFeA?&C3B2(E?0{drE@DA2pu(A#ElY&6el60Rn|Qpn-FkfQ8M93AfWIr)drgDFEU zghdWK)^71EWCP(@(=c4kfH1Y(4iugD4fve6;nSUpLT%!)MUHs1!zJYy4y||C+SwQ! z)KM&$7_tyM`sljP2fz6&Z;jxRn{Wup8IOUx8D4uh&(=O zx-7$a;U><*5L^!%xRlw)vAbh;sdlR||& ze}8_8%)c2Fwy=F&H|LM+p{pZB5DKTx>Y?F1N%BlZkXf!}JeGuMZk~LPi7{cidvUGB zAJ4LVeNV%XO>LTrklB#^-;8nb;}6l;1oW&WS=Mz*Az!4cqqQzbOSFq`$Q%PfD7srM zpKgP-D_0XPTRX*hAqeq0TDkJ;5HB1%$3Np)99#16c{ zJImlNL(npL!W|Gr_kxl1GVmF5&^$^YherS7+~q$p zt}{a=*RiD2Ikv6o=IM1kgc7zqpaZ;OB)P!1zz*i3{U()Dq#jG)egvK}@uFLa`oyWZ zf~=MV)|yJn`M^$N%ul5);JuQvaU1r2wt(}J_Qgyy`qWQI`hEeRX0uC@c1(dQ2}=U$ tNIIaX+dr)NRWXcxoR{>fqI{SF_dm1Ylv~=3YHI)h002ovPDHLkV1g(pWS;;4 literal 0 HcmV?d00001 diff --git a/flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..f091b6b0bca859a3f474b03065bef75ba58a9e4c GIT binary patch literal 1588 zcmV-42Fv-0P)C1SqPt}wig>|5Crh^=oyX$BK<}M8eLU3e2hGT;=G|!_SP)7zNI6fqUMB=)y zRAZ>eDe#*r`yDAVgB_R*LB*MAc)8(b{g{9McCXW!lq7r(btRoB9!8B-#AI6JMb~YFBEvdsV)`mEQO^&#eRKx@b&x- z5lZm*!WfD8oCLzfHGz#u7sT0^VLMI1MqGxF^v+`4YYnVYgk*=kU?HsSz{v({E3lb9 z>+xILjBN)t6`=g~IBOelGQ(O990@BfXf(DRI5I$qN$0Gkz-FSc$3a+2fX$AedL4u{ z4V+5Ong(9LiGcIKW?_352sR;LtDPmPJXI{YtT=O8=76o9;*n%_m|xo!i>7$IrZ-{l z-x3`7M}qzHsPV@$v#>H-TpjDh2UE$9g6sysUREDy_R(a)>=eHw-WAyfIN z*qb!_hW>G)Tu8nSw9yn#3wFMiLcfc4pY0ek1}8(NqkBR@t4{~oC>ryc-h_ByH(Cg5 z>ao-}771+xE3um9lWAY1FeQFxowa1(!J(;Jg*wrg!=6FdRX+t_<%z&d&?|Bn){>zm zZQj(aA_HeBY&OC^jj*)N`8fa^ePOU72VpInJoI1?`ty#lvlNzs(&MZX+R%2xS~5Kh zX*|AU4QE#~SgPzOXe9>tRj>hjU@c1k5Y_mW*Jp3fI;)1&g3j|zDgC+}2Q_v%YfDax z!?umcN^n}KYQ|a$Lr+51Nf9dkkYFSjZZjkma$0KOj+;aQ&721~t7QUKx61J3(P4P1 zstI~7-wOACnWP4=8oGOwz%vNDqD8w&Q`qcNGGrbbf&0s9L0De{4{mRS?o0MU+nR_! zrvshUau0G^DeMhM_v{5BuLjb#Hh@r23lDAk8oF(C+P0rsBpv85EP>4CVMx#04MOfG z;P%vktHcXwTj~+IE(~px)3*MY77e}p#|c>TD?sMatC0Tu4iKKJ0(X8jxQY*gYtxsC z(zYC$g|@+I+kY;dg_dE>scBf&bP1Nc@Hz<3R)V`=AGkc;8CXqdi=B4l2k|g;2%#m& z*jfX^%b!A8#bI!j9-0Fi0bOXl(-c^AB9|nQaE`*)Hw+o&jS9@7&Gov#HbD~#d{twV zXd^Tr^mWLfFh$@Dr$e;PBEz4(-2q1FF0}c;~B5sA}+Q>TOoP+t>wf)V9Iy=5ruQa;z)y zI9C9*oUga6=hxw6QasLPnee@3^Rr*M{CdaL5=R41nLs(AHk_=Y+A9$2&H(B7!_pURs&8aNw7?`&Z&xY_Ye z)~D5Bog^td-^QbUtkTirdyK^mTHAOuptDflut!#^lnKqU md>ggs(5nOWAqO?umG&QVYK#ibz}*4>0000U6E9hRK9^#O7(mu>ETqrXGsduA8$)?`v2seloOCza43C{NQ$$gAOH**MCn0Q?+L7dl7qnbRdqZ8LSVp1ItDxhxD?t@5_yHg6A8yI zC*%Wgg22K|8E#!~cTNYR~@Y9KepMPrrB8cABapAFa=`H+UGhkXUZV1GnwR1*lPyZ;*K(i~2gp|@bzp8}og7e*#% zEnr|^CWdVV!-4*Y_7rFvlww2Ze+>j*!Z!pQ?2l->4q#nqRu9`ELo6RMS5=br47g_X zRw}P9a7RRYQ%2Vsd0Me{_(EggTnuN6j=-?uFS6j^u69elMypu?t>op*wBx<=Wx8?( ztpe^(fwM6jJX7M-l*k3kEpWOl_Vk3@(_w4oc}4YF4|Rt=2V^XU?#Yz`8(e?aZ@#li0n*=g^qOcVpd-Wbok=@b#Yw zqn8u9a)z>l(1kEaPYZ6hwubN6i<8QHgsu0oE) ziJ(p;Wxm>sf!K+cw>R-(^Y2_bahB+&KI9y^);#0qt}t-$C|Bo71lHi{_+lg#f%RFy z0um=e3$K3i6K{U_4K!EX?F&rExl^W|G8Z8;`5z-k}OGNZ0#WVb$WCpQu-_YsiqKP?BB# vzVHS-CTUF4Ozn5G+mq_~Qqto~ahA+K`|lyv3(-e}00000NkvXXu0mjfd`9t{ literal 0 HcmV?d00001 diff --git a/flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d0ef06e7edb86cdfe0d15b4b0d98334a86163658 GIT binary patch literal 1716 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 literal 0 HcmV?d00001 diff --git a/flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c8f9ed8f5cee1c98386d13b17e89f719e83555b2 GIT binary patch literal 1895 zcmV-t2blPYP)FQtfgmafE#=YDCq`qUBt#QpG%*H6QHY765~R=q zZ6iudfM}q!Pz#~9JgOi8QJ|DSu?1-*(kSi1K4#~5?#|rh?sS)(-JQqX*}ciXJ56_H zdw=^s_srbAdqxlvGyrgGet#6T7_|j;95sL%MtM;q86vOxKM$f#puR)Bjv9Zvz9-di zXOTSsZkM83)E9PYBXC<$6(|>lNLVBb&&6y{NByFCp%6+^ALR@NCTse_wqvNmSWI-m z!$%KlHFH2omF!>#%1l3LTZg(s7eof$7*xB)ZQ0h?ejh?Ta9fDv59+u#MokW+1t8Zb zgHv%K(u9G^Lv`lh#f3<6!JVTL3(dCpxHbnbA;kKqQyd1~^Xe0VIaYBSWm6nsr;dFj z4;G-RyL?cYgsN1{L4ZFFNa;8)Rv0fM0C(~Tkit94 zz#~A)59?QjD&pAPSEQ)p8gP|DS{ng)j=2ux)_EzzJ773GmQ_Cic%3JJhC0t2cx>|v zJcVusIB!%F90{+}8hG3QU4KNeKmK%T>mN57NnCZ^56=0?&3@!j>a>B43pi{!u z7JyDj7`6d)qVp^R=%j>UIY6f+3`+qzIc!Y_=+uN^3BYV|o+$vGo-j-Wm<10%A=(Yk^beI{t%ld@yhKjq0iNjqN4XMGgQtbKubPM$JWBz}YA65k%dm*awtC^+f;a-x4+ddbH^7iDWGg&N0n#MW{kA|=8iMUiFYvMoDY@sPC#t$55gn6ykUTPAr`a@!(;np824>2xJthS z*ZdmT`g5-`BuJs`0LVhz+D9NNa3<=6m;cQLaF?tCv8)zcRSh66*Z|vXhG@$I%U~2l z?`Q zykI#*+rQ=z6Jm=Bui-SfpDYLA=|vzGE(dYm=OC8XM&MDo7ux4UF1~0J1+i%aCUpRe zt3L_uNyQ*cE(38Uy03H%I*)*Bh=Lb^Xj3?I^Hnbeq72(EOK^Y93CNp*uAA{5Lc=ky zx=~RKa4{iTm{_>_vSCm?$Ej=i6@=m%@VvAITnigVg{&@!7CDgs908761meDK5azA} z4?=NOH|PdvabgJ&fW2{Mo$Q0CcD8Qc84%{JPYt5EiG{MdLIAeX%T=D7NIP4%Hw}p9 zg)==!2Lbp#j{u_}hMiao9=!VSyx0gHbeCS`;q&vzeq|fs`y&^X-lso(Ls@-706qmA z7u*T5PMo_w3{se1t2`zWeO^hOvTsohG_;>J0wVqVe+n)AbQCx)yh9;w+J6?NF5Lmo zecS@ieAKL8%bVd@+-KT{yI|S}O>pYckUFs;ry9Ow$CD@ztz5K-*D$^{i(_1llhSh^ zEkL$}tsQt5>QA^;QgjgIfBDmcOgi5YDyu?t6vSnbp=1+@6D& z5MJ}B8q;bRlVoxasyhcUF1+)o`&3r0colr}QJ3hcSdLu;9;td>kf@Tcn<@9sIx&=m z;AD;SCh95=&p;$r{Xz3iWCO^MX83AGJ(yH&eTXgv|0=34#-&WAmw{)U7OU9!Wz^!7 zZ%jZFi@JR;>Mhi7S>V7wQ176|FdW2m?&`qa(ScO^CFPR80HucLHOTy%5s*HR0^8)i h0WYBP*#0Ks^FNSabJA*5${_#%002ovPDHLkV1oKhTl@e3 literal 0 HcmV?d00001 diff --git a/flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..a6d6b8609df07bf62e5100a53a01510388bd2b22 GIT binary patch literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ literal 0 HcmV?d00001 diff --git a/flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a6d6b8609df07bf62e5100a53a01510388bd2b22 GIT binary patch literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ literal 0 HcmV?d00001 diff --git a/flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..75b2d164a5a98e212cca15ea7bf2ab5de5108680 GIT binary patch literal 3831 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 literal 0 HcmV?d00001 diff --git a/flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..c4df70d39da7941ef3f6dcb7f06a192d8dcb308d GIT binary patch literal 1888 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 iW8Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 00000000..89c2725b --- /dev/null +++ b/flutter_tts-voice_enhancement/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/flutter_tts-voice_enhancement/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/flutter_tts-voice_enhancement/example/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 00000000..f2e259c7 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/flutter_tts-voice_enhancement/example/ios/Runner/Base.lproj/Main.storyboard b/flutter_tts-voice_enhancement/example/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 00000000..f3c28516 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/flutter_tts-voice_enhancement/example/ios/Runner/Info.plist b/flutter_tts-voice_enhancement/example/ios/Runner/Info.plist new file mode 100644 index 00000000..dd2d9263 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/ios/Runner/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + flutter_tts_example + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + arm64 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/flutter_tts-voice_enhancement/example/ios/Runner/Runner-Bridging-Header.h b/flutter_tts-voice_enhancement/example/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 00000000..7335fdf9 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" \ No newline at end of file diff --git a/flutter_tts-voice_enhancement/example/lib/main.dart b/flutter_tts-voice_enhancement/example/lib/main.dart new file mode 100644 index 00000000..97530bbb --- /dev/null +++ b/flutter_tts-voice_enhancement/example/lib/main.dart @@ -0,0 +1,292 @@ +import 'dart:async'; +import 'dart:io' show Platform; +import 'package:flutter/foundation.dart' show kIsWeb; + +import 'package:flutter/material.dart'; +import 'package:flutter_tts/flutter_tts.dart'; + +void main() => runApp(MyApp()); + +class MyApp extends StatefulWidget { + @override + _MyAppState createState() => _MyAppState(); +} + +enum TtsState { playing, stopped, paused, continued } + +class _MyAppState extends State { + FlutterTts flutterTts; + dynamic languages; + String language; + double volume = 0.5; + double pitch = 1.0; + double rate = 0.5; + + String _newVoiceText; + + TtsState ttsState = TtsState.stopped; + + get isPlaying => ttsState == TtsState.playing; + + get isStopped => ttsState == TtsState.stopped; + + get isPaused => ttsState == TtsState.paused; + + get isContinued => ttsState == TtsState.continued; + + @override + initState() { + super.initState(); + initTts(); + } + + initTts() { + flutterTts = FlutterTts(); + + _getLanguages(); + + if (!kIsWeb) { + if (Platform.isAndroid) { + _getEngines(); + } + } + + flutterTts.setStartHandler(() { + setState(() { + print("Playing"); + ttsState = TtsState.playing; + }); + }); + + flutterTts.setCompletionHandler(() { + setState(() { + print("Complete"); + ttsState = TtsState.stopped; + }); + }); + + flutterTts.setCancelHandler(() { + setState(() { + print("Cancel"); + ttsState = TtsState.stopped; + }); + }); + + if (kIsWeb || Platform.isIOS) { + flutterTts.setPauseHandler(() { + setState(() { + print("Paused"); + ttsState = TtsState.paused; + }); + }); + + flutterTts.setContinueHandler(() { + setState(() { + print("Continued"); + ttsState = TtsState.continued; + }); + }); + } + + flutterTts.setErrorHandler((msg) { + setState(() { + print("error: $msg"); + ttsState = TtsState.stopped; + }); + }); + } + + Future _getLanguages() async { + languages = await flutterTts.getLanguages; + if (languages != null) setState(() => languages); + } + + Future _getEngines() async { + var engines = await flutterTts.getEngines; + if (engines != null) { + for (dynamic engine in engines) { + print(engine); + } + } + } + + Future _speak() async { + await flutterTts.setVolume(volume); + await flutterTts.setSpeechRate(rate); + await flutterTts.setPitch(pitch); + + if (_newVoiceText != null) { + if (_newVoiceText.isNotEmpty) { + await flutterTts.awaitSpeakCompletion(true); + await flutterTts.speak(_newVoiceText); + } + } + } + + Future _stop() async { + var result = await flutterTts.stop(); + if (result == 1) setState(() => ttsState = TtsState.stopped); + } + + Future _pause() async { + var result = await flutterTts.pause(); + if (result == 1) setState(() => ttsState = TtsState.paused); + } + + @override + void dispose() { + super.dispose(); + flutterTts.stop(); + } + + List> getLanguageDropDownMenuItems() { + var items = List>(); + for (dynamic type in languages) { + items.add( + DropdownMenuItem(value: type as String, child: Text(type as String))); + } + return items; + } + + void changedLanguageDropDownItem(String selectedType) { + setState(() { + language = selectedType; + flutterTts.setLanguage(language); + }); + } + + void _onChange(String text) { + setState(() { + _newVoiceText = text; + }); + } + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + appBar: AppBar( + title: Text('Flutter TTS'), + ), + body: SingleChildScrollView( + scrollDirection: Axis.vertical, + child: Column(children: [ + _inputSection(), + _btnSection(), + languages != null ? _languageDropDownSection() : Text(""), + _buildSliders() + ])))); + } + + Widget _inputSection() => Container( + alignment: Alignment.topCenter, + padding: EdgeInsets.only(top: 25.0, left: 25.0, right: 25.0), + child: TextField( + onChanged: (String value) { + _onChange(value); + }, + )); + + Widget _btnSection() { + if (!kIsWeb && Platform.isAndroid) { + return Container( + padding: EdgeInsets.only(top: 50.0), + child: + Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ + _buildButtonColumn(Colors.green, Colors.greenAccent, + Icons.play_arrow, 'PLAY', _speak), + _buildButtonColumn( + Colors.red, Colors.redAccent, Icons.stop, 'STOP', _stop), + ])); + } else { + return Container( + padding: EdgeInsets.only(top: 50.0), + child: + Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ + _buildButtonColumn(Colors.green, Colors.greenAccent, + Icons.play_arrow, 'PLAY', _speak), + _buildButtonColumn( + Colors.red, Colors.redAccent, Icons.stop, 'STOP', _stop), + _buildButtonColumn( + Colors.blue, Colors.blueAccent, Icons.pause, 'PAUSE', _pause), + ])); + } + } + + Widget _languageDropDownSection() => Container( + padding: EdgeInsets.only(top: 50.0), + child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [ + DropdownButton( + value: language, + items: getLanguageDropDownMenuItems(), + onChanged: changedLanguageDropDownItem, + ) + ])); + + Column _buildButtonColumn(Color color, Color splashColor, IconData icon, + String label, Function func) { + return Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + IconButton( + icon: Icon(icon), + color: color, + splashColor: splashColor, + onPressed: () => func()), + Container( + margin: const EdgeInsets.only(top: 8.0), + child: Text(label, + style: TextStyle( + fontSize: 12.0, + fontWeight: FontWeight.w400, + color: color))) + ]); + } + + Widget _buildSliders() { + return Column( + children: [_volume(), _pitch(), _rate()], + ); + } + + Widget _volume() { + return Slider( + value: volume, + onChanged: (newVolume) { + setState(() => volume = newVolume); + }, + min: 0.0, + max: 1.0, + divisions: 10, + label: "Volume: $volume"); + } + + Widget _pitch() { + return Slider( + value: pitch, + onChanged: (newPitch) { + setState(() => pitch = newPitch); + }, + min: 0.5, + max: 2.0, + divisions: 15, + label: "Pitch: $pitch", + activeColor: Colors.red, + ); + } + + Widget _rate() { + return Slider( + value: rate, + onChanged: (newRate) { + setState(() => rate = newRate); + }, + min: 0.0, + max: 1.0, + divisions: 10, + label: "Rate: $rate", + activeColor: Colors.green, + ); + } +} diff --git a/flutter_tts-voice_enhancement/example/macos/.gitignore b/flutter_tts-voice_enhancement/example/macos/.gitignore new file mode 100644 index 00000000..d2fd3772 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/macos/.gitignore @@ -0,0 +1,6 @@ +# Flutter-related +**/Flutter/ephemeral/ +**/Pods/ + +# Xcode-related +**/xcuserdata/ diff --git a/flutter_tts-voice_enhancement/example/macos/Flutter/Flutter-Debug.xcconfig b/flutter_tts-voice_enhancement/example/macos/Flutter/Flutter-Debug.xcconfig new file mode 100644 index 00000000..785633d3 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/macos/Flutter/Flutter-Debug.xcconfig @@ -0,0 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/flutter_tts-voice_enhancement/example/macos/Flutter/Flutter-Release.xcconfig b/flutter_tts-voice_enhancement/example/macos/Flutter/Flutter-Release.xcconfig new file mode 100644 index 00000000..5fba960c --- /dev/null +++ b/flutter_tts-voice_enhancement/example/macos/Flutter/Flutter-Release.xcconfig @@ -0,0 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/flutter_tts-voice_enhancement/example/macos/Flutter/GeneratedPluginRegistrant.swift b/flutter_tts-voice_enhancement/example/macos/Flutter/GeneratedPluginRegistrant.swift new file mode 100644 index 00000000..1e6ac53b --- /dev/null +++ b/flutter_tts-voice_enhancement/example/macos/Flutter/GeneratedPluginRegistrant.swift @@ -0,0 +1,12 @@ +// +// Generated file. Do not edit. +// + +import FlutterMacOS +import Foundation + +import flutter_tts + +func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + FlutterTtsPlugin.register(with: registry.registrar(forPlugin: "FlutterTtsPlugin")) +} diff --git a/flutter_tts-voice_enhancement/example/macos/Podfile b/flutter_tts-voice_enhancement/example/macos/Podfile new file mode 100644 index 00000000..5bf4307c --- /dev/null +++ b/flutter_tts-voice_enhancement/example/macos/Podfile @@ -0,0 +1,82 @@ +platform :osx, '10.15' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def parse_KV_file(file, separator='=') + file_abs_path = File.expand_path(file) + if !File.exists? file_abs_path + return []; + end + pods_ary = [] + skip_line_start_symbols = ["#", "/"] + File.foreach(file_abs_path) { |line| + next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } + plugin = line.split(pattern=separator) + if plugin.length == 2 + podname = plugin[0].strip() + path = plugin[1].strip() + podpath = File.expand_path("#{path}", file_abs_path) + pods_ary.push({:name => podname, :path => podpath}); + else + puts "Invalid plugin specification: #{line}" + end + } + return pods_ary +end + +def pubspec_supports_macos(file) + file_abs_path = File.expand_path(file) + if !File.exists? file_abs_path + return false; + end + File.foreach(file_abs_path) { |line| + return true if line =~ /^\s*macos:/ + } + return false +end + +target 'Runner' do + use_frameworks! + use_modular_headers! + + # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock + # referring to absolute paths on developers' machines. + ephemeral_dir = File.join('Flutter', 'ephemeral') + symlink_dir = File.join(ephemeral_dir, '.symlinks') + symlink_plugins_dir = File.join(symlink_dir, 'plugins') + system("rm -rf #{symlink_dir}") + system("mkdir -p #{symlink_plugins_dir}") + + # Flutter Pods + generated_xcconfig = parse_KV_file(File.join(ephemeral_dir, 'Flutter-Generated.xcconfig')) + if generated_xcconfig.empty? + puts "Flutter-Generated.xcconfig must exist. If you're running pod install manually, make sure flutter packages get is executed first." + end + generated_xcconfig.map { |p| + if p[:name] == 'FLUTTER_FRAMEWORK_DIR' + symlink = File.join(symlink_dir, 'flutter') + File.symlink(File.dirname(p[:path]), symlink) + pod 'FlutterMacOS', :path => File.join(symlink, File.basename(p[:path])) + end + } + + # Plugin Pods + plugin_pods = parse_KV_file('../.flutter-plugins') + plugin_pods.map { |p| + symlink = File.join(symlink_plugins_dir, p[:name]) + File.symlink(p[:path], symlink) + if pubspec_supports_macos(File.join(symlink, 'pubspec.yaml')) + pod p[:name], :path => File.join(symlink, 'macos') + end + } +end + +# Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system. +install! 'cocoapods', :disable_input_output_paths => true diff --git a/flutter_tts-voice_enhancement/example/macos/Runner.xcodeproj/project.pbxproj b/flutter_tts-voice_enhancement/example/macos/Runner.xcodeproj/project.pbxproj new file mode 100644 index 00000000..39fbd18c --- /dev/null +++ b/flutter_tts-voice_enhancement/example/macos/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,656 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 51; + objects = { + +/* Begin PBXAggregateTarget section */ + 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; + buildPhases = ( + 33CC111E2044C6BF0003C045 /* ShellScript */, + ); + dependencies = ( + ); + name = "Flutter Assemble"; + productName = FLX; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; + 33D1A10422148B71006C7A3E /* FlutterMacOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 33D1A10322148B71006C7A3E /* FlutterMacOS.framework */; }; + 33D1A10522148B93006C7A3E /* FlutterMacOS.framework in Bundle Framework */ = {isa = PBXBuildFile; fileRef = 33D1A10322148B71006C7A3E /* FlutterMacOS.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 3640FC23D5951A8FB0D6ECA0 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A470206CCCE0007DE0E2807A /* Pods_Runner.framework */; }; + D73912F022F37F9E000D13A0 /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D73912EF22F37F9E000D13A0 /* App.framework */; }; + D73912F222F3801D000D13A0 /* App.framework in Bundle Framework */ = {isa = PBXBuildFile; fileRef = D73912EF22F37F9E000D13A0 /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC111A2044C6BA0003C045; + remoteInfo = FLX; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 33CC110E2044A8840003C045 /* Bundle Framework */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + D73912F222F3801D000D13A0 /* App.framework in Bundle Framework */, + 33D1A10522148B93006C7A3E /* FlutterMacOS.framework in Bundle Framework */, + ); + name = "Bundle Framework"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; + 33CC10ED2044A3C60003C045 /* example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; + 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; + 33D1A10322148B71006C7A3E /* FlutterMacOS.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FlutterMacOS.framework; path = Flutter/ephemeral/FlutterMacOS.framework; sourceTree = SOURCE_ROOT; }; + 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; + 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; + 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 517AA5C8DE31A9B49D27971F /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 66FE8AA741C2B7FC12BF1304 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; + A470206CCCE0007DE0E2807A /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + C15A67B64555E7FFE7AD8B76 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + D73912EF22F37F9E000D13A0 /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/ephemeral/App.framework; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 33CC10EA2044A3C60003C045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D73912F022F37F9E000D13A0 /* App.framework in Frameworks */, + 33D1A10422148B71006C7A3E /* FlutterMacOS.framework in Frameworks */, + 3640FC23D5951A8FB0D6ECA0 /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 33BA886A226E78AF003329D5 /* Configs */ = { + isa = PBXGroup; + children = ( + 33E5194F232828860026EE4D /* AppInfo.xcconfig */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, + ); + path = Configs; + sourceTree = ""; + }; + 33CC10E42044A3C60003C045 = { + isa = PBXGroup; + children = ( + 33FAB671232836740065AC1E /* Runner */, + 33CEB47122A05771004F2AC0 /* Flutter */, + 33CC10EE2044A3C60003C045 /* Products */, + D73912EC22F37F3D000D13A0 /* Frameworks */, + 5F9F48FBDE9334256A3D8D1C /* Pods */, + ); + sourceTree = ""; + }; + 33CC10EE2044A3C60003C045 /* Products */ = { + isa = PBXGroup; + children = ( + 33CC10ED2044A3C60003C045 /* example.app */, + ); + name = Products; + sourceTree = ""; + }; + 33CC11242044D66E0003C045 /* Resources */ = { + isa = PBXGroup; + children = ( + 33CC10F22044A3C60003C045 /* Assets.xcassets */, + 33CC10F42044A3C60003C045 /* MainMenu.xib */, + 33CC10F72044A3C60003C045 /* Info.plist */, + ); + name = Resources; + path = ..; + sourceTree = ""; + }; + 33CEB47122A05771004F2AC0 /* Flutter */ = { + isa = PBXGroup; + children = ( + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, + D73912EF22F37F9E000D13A0 /* App.framework */, + 33D1A10322148B71006C7A3E /* FlutterMacOS.framework */, + ); + path = Flutter; + sourceTree = ""; + }; + 33FAB671232836740065AC1E /* Runner */ = { + isa = PBXGroup; + children = ( + 33CC10F02044A3C60003C045 /* AppDelegate.swift */, + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, + 33E51913231747F40026EE4D /* DebugProfile.entitlements */, + 33E51914231749380026EE4D /* Release.entitlements */, + 33CC11242044D66E0003C045 /* Resources */, + 33BA886A226E78AF003329D5 /* Configs */, + ); + path = Runner; + sourceTree = ""; + }; + 5F9F48FBDE9334256A3D8D1C /* Pods */ = { + isa = PBXGroup; + children = ( + 66FE8AA741C2B7FC12BF1304 /* Pods-Runner.debug.xcconfig */, + 517AA5C8DE31A9B49D27971F /* Pods-Runner.release.xcconfig */, + C15A67B64555E7FFE7AD8B76 /* Pods-Runner.profile.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + D73912EC22F37F3D000D13A0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + A470206CCCE0007DE0E2807A /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 33CC10EC2044A3C60003C045 /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 9A62F257D3FF7C7C94E365B2 /* [CP] Check Pods Manifest.lock */, + 33CC10E92044A3C60003C045 /* Sources */, + 33CC10EA2044A3C60003C045 /* Frameworks */, + 33CC10EB2044A3C60003C045 /* Resources */, + 33CC110E2044A8840003C045 /* Bundle Framework */, + 3399D490228B24CF009A79C7 /* ShellScript */, + F7AADAC6A864E8BF8890B1EC /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 33CC11202044C79F0003C045 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 33CC10ED2044A3C60003C045 /* example.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33CC10E52044A3C60003C045 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 1150; + ORGANIZATIONNAME = "The Flutter Authors"; + TargetAttributes = { + 33CC10EC2044A3C60003C045 = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + 33CC111A2044C6BA0003C045 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 8.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 33CC10E42044A3C60003C045; + productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 33CC10EC2044A3C60003C045 /* Runner */, + 33CC111A2044C6BA0003C045 /* Flutter Assemble */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 33CC10EB2044A3C60003C045 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3399D490228B24CF009A79C7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename\n"; + }; + 33CC111E2044C6BF0003C045 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + Flutter/ephemeral/FlutterInputs.xcfilelist, + ); + inputPaths = ( + Flutter/ephemeral/tripwire, + ); + outputFileListPaths = ( + Flutter/ephemeral/FlutterOutputs.xcfilelist, + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh\ntouch Flutter/ephemeral/tripwire\n"; + }; + 9A62F257D3FF7C7C94E365B2 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + F7AADAC6A864E8BF8890B1EC /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 33CC10E92044A3C60003C045 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; + targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 33CC10F52044A3C60003C045 /* Base */, + ); + name = MainMenu.xib; + path = Runner; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 338D0CE9231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Profile; + }; + 338D0CEA231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter/ephemeral", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Profile; + }; + 338D0CEB231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profile; + }; + 33CC10F92044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 33CC10FA2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 33CC10FC2044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter/ephemeral", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 33CC10FD2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter/ephemeral", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 33CC111C2044C6BA0003C045 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 33CC111D2044C6BA0003C045 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10F92044A3C60003C045 /* Debug */, + 33CC10FA2044A3C60003C045 /* Release */, + 338D0CE9231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10FC2044A3C60003C045 /* Debug */, + 33CC10FD2044A3C60003C045 /* Release */, + 338D0CEA231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC111C2044C6BA0003C045 /* Debug */, + 33CC111D2044C6BA0003C045 /* Release */, + 338D0CEB231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 33CC10E52044A3C60003C045 /* Project object */; +} diff --git a/flutter_tts-voice_enhancement/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/flutter_tts-voice_enhancement/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/flutter_tts-voice_enhancement/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/flutter_tts-voice_enhancement/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 00000000..6111bd0a --- /dev/null +++ b/flutter_tts-voice_enhancement/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/flutter_tts-voice_enhancement/example/macos/Runner.xcworkspace/contents.xcworkspacedata b/flutter_tts-voice_enhancement/example/macos/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..21a3cc14 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/flutter_tts-voice_enhancement/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/flutter_tts-voice_enhancement/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/flutter_tts-voice_enhancement/example/macos/Runner/AppDelegate.swift b/flutter_tts-voice_enhancement/example/macos/Runner/AppDelegate.swift new file mode 100644 index 00000000..d53ef643 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/macos/Runner/AppDelegate.swift @@ -0,0 +1,9 @@ +import Cocoa +import FlutterMacOS + +@NSApplicationMain +class AppDelegate: FlutterAppDelegate { + override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } +} diff --git a/flutter_tts-voice_enhancement/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/flutter_tts-voice_enhancement/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..a2ec33f1 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_16.png", + "scale" : "1x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "2x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "1x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_64.png", + "scale" : "2x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_128.png", + "scale" : "1x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "2x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "1x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "2x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_1024.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/flutter_tts-voice_enhancement/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/flutter_tts-voice_enhancement/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png new file mode 100644 index 0000000000000000000000000000000000000000..3c4935a7ca84f0976aca34b7f2895d65fb94d1ea GIT binary patch literal 46993 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 literal 0 HcmV?d00001 diff --git a/flutter_tts-voice_enhancement/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/flutter_tts-voice_enhancement/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png new file mode 100644 index 0000000000000000000000000000000000000000..ed4cc16421680a50164ba74381b4b35ceaa0ccfc GIT binary patch literal 3276 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 N;OXk;vd$@?2>?>Ex^Vyi literal 0 HcmV?d00001 diff --git a/flutter_tts-voice_enhancement/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/flutter_tts-voice_enhancement/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png new file mode 100644 index 0000000000000000000000000000000000000000..bcbf36df2f2aaaa0a63c7dabc94e600184229d0d GIT binary patch literal 5933 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 f$KZHO*s&vt|9^w-6P?|#0pRK8NSwWJ?9znhg z3{`3j3=J&|48MRv4KElNN(~qoUL`OvSj}Ky5HFasE6@fg!ItFh?!xdN1Q+aGJ{c&& zS>O>_%)r1c48n{Iv*t(u1=&kHeO=ifbFy+6aSK)V_AxLppYn8Z42d|rc6w}vOsL55 z`t&mC&y2@JTEyg!eDiFX^k#CC!jq%>erB=yHqUP0XcDOTw6ko}L zX;EmMrq(fKk*eygEuA616;0)>@A{TK|55PV@70 z$OfzS*(VJxQev3J?yY?O=ul(v`fp}?u9z`JK3ugibK>)DyCwImZOF4d{xK%%Ks1*} zv$oa)9anR%lXIBUqYnhLmT>VOzHfNP?ZwJNZ!5$s9M08RynIvaXw>@G^T9@r9^KH1 zVy??F&uuk)bH9Y4pQY!hP58i_H6 znl-NcuCpLV6ZWU;4C zu@9exF&OZi`Bovq_m%T+WhU2kvkz@^_LpycBvqm3bMpLw8X-Or5sL>0AKE1$(k_L=_Zc=CUq#=x1-QZf)G7nHu@fmsQ1eN_N3+nTEz`4HI4Z6uVlE zJH+X&det8JU?tO?upcM4Z=cV!JV;yF>FfL5Q$M|W_2Z!P`S=}Wzp|_1^#d%e?_H`> zV@%vA$+bFVqhw9`U;TfP|5|PD{||OiYdor8P*i??|NJcb%kzT_73*7WE?Ua5hAnR2 z=7WE=PhTlJ#ZeRznjTUb;`E(wkMZrj4e|Hilz-mK>9cZHQY**5TUPw~u}k;u73KI}xAx!0m-)GVia|x^d3p~s_9gh83jA&Ra<8rM%`>U3x69t&NzbwWY}7Ar?)FK#IZ0z|d0H0EkRO w3{9;}4Xg|ebq&m|3=9_N6z8I7$jwj5OsmAL;bP(Gi$Dzwp00i_>zopr02+f8CIA2c literal 0 HcmV?d00001 diff --git a/flutter_tts-voice_enhancement/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/flutter_tts-voice_enhancement/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png new file mode 100644 index 0000000000000000000000000000000000000000..e71a726136a47ed24125c7efc79d68a4a01961b4 GIT binary patch literal 14800 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 + + + + + + + + + + + + + + + + + + + + + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/flutter_tts-voice_enhancement/example/macos/Runner/Configs/AppInfo.xcconfig b/flutter_tts-voice_enhancement/example/macos/Runner/Configs/AppInfo.xcconfig new file mode 100644 index 00000000..f960fd48 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/macos/Runner/Configs/AppInfo.xcconfig @@ -0,0 +1,14 @@ +// Application-level settings for the Runner target. +// +// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the +// future. If not, the values below would default to using the project name when this becomes a +// 'flutter create' template. + +// The application's name. By default this is also the title of the Flutter window. +PRODUCT_NAME = example + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = com.tundralabs.example + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright © 2020 com.tundralabs. All rights reserved. diff --git a/flutter_tts-voice_enhancement/example/macos/Runner/Configs/Debug.xcconfig b/flutter_tts-voice_enhancement/example/macos/Runner/Configs/Debug.xcconfig new file mode 100644 index 00000000..36b0fd94 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/macos/Runner/Configs/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Debug.xcconfig" +#include "Warnings.xcconfig" diff --git a/flutter_tts-voice_enhancement/example/macos/Runner/Configs/Release.xcconfig b/flutter_tts-voice_enhancement/example/macos/Runner/Configs/Release.xcconfig new file mode 100644 index 00000000..dff4f495 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/macos/Runner/Configs/Release.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Release.xcconfig" +#include "Warnings.xcconfig" diff --git a/flutter_tts-voice_enhancement/example/macos/Runner/Configs/Warnings.xcconfig b/flutter_tts-voice_enhancement/example/macos/Runner/Configs/Warnings.xcconfig new file mode 100644 index 00000000..42bcbf47 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/macos/Runner/Configs/Warnings.xcconfig @@ -0,0 +1,13 @@ +WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings +GCC_WARN_UNDECLARED_SELECTOR = YES +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES +CLANG_WARN_PRAGMA_PACK = YES +CLANG_WARN_STRICT_PROTOTYPES = YES +CLANG_WARN_COMMA = YES +GCC_WARN_STRICT_SELECTOR_MATCH = YES +CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES +GCC_WARN_SHADOW = YES +CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/flutter_tts-voice_enhancement/example/macos/Runner/DebugProfile.entitlements b/flutter_tts-voice_enhancement/example/macos/Runner/DebugProfile.entitlements new file mode 100644 index 00000000..dddb8a30 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/macos/Runner/DebugProfile.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.network.server + + + diff --git a/flutter_tts-voice_enhancement/example/macos/Runner/Info.plist b/flutter_tts-voice_enhancement/example/macos/Runner/Info.plist new file mode 100644 index 00000000..4789daa6 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/macos/Runner/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + $(PRODUCT_COPYRIGHT) + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/flutter_tts-voice_enhancement/example/macos/Runner/MainFlutterWindow.swift b/flutter_tts-voice_enhancement/example/macos/Runner/MainFlutterWindow.swift new file mode 100644 index 00000000..2722837e --- /dev/null +++ b/flutter_tts-voice_enhancement/example/macos/Runner/MainFlutterWindow.swift @@ -0,0 +1,15 @@ +import Cocoa +import FlutterMacOS + +class MainFlutterWindow: NSWindow { + override func awakeFromNib() { + let flutterViewController = FlutterViewController.init() + let windowFrame = self.frame + self.contentViewController = flutterViewController + self.setFrame(windowFrame, display: true) + + RegisterGeneratedPlugins(registry: flutterViewController) + + super.awakeFromNib() + } +} diff --git a/flutter_tts-voice_enhancement/example/macos/Runner/Release.entitlements b/flutter_tts-voice_enhancement/example/macos/Runner/Release.entitlements new file mode 100644 index 00000000..852fa1a4 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/macos/Runner/Release.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.app-sandbox + + + diff --git a/flutter_tts-voice_enhancement/example/pubspec.yaml b/flutter_tts-voice_enhancement/example/pubspec.yaml new file mode 100644 index 00000000..54cbe6ed --- /dev/null +++ b/flutter_tts-voice_enhancement/example/pubspec.yaml @@ -0,0 +1,59 @@ +name: flutter_tts_example +description: Demonstrates how to use the flutter_tts plugin. + +dependencies: + flutter: + sdk: flutter + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^0.1.2 + +dev_dependencies: + flutter_test: + sdk: flutter + + flutter_tts: + path: ../ + +# For information on the generic Dart part of this file, see the +# following page: https://www.dartlang.org/tools/pub/pubspec + +# The following section is specific to Flutter. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.io/assets-and-images/#resolution-aware. + + # For details regarding adding assets from package dependencies, see + # https://flutter.io/assets-and-images/#from-packages + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.io/custom-fonts/#from-packages diff --git a/flutter_tts-voice_enhancement/example/test/widget_test.dart b/flutter_tts-voice_enhancement/example/test/widget_test.dart new file mode 100644 index 00000000..6db856cd --- /dev/null +++ b/flutter_tts-voice_enhancement/example/test/widget_test.dart @@ -0,0 +1,30 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility that Flutter provides. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../lib/main.dart'; + +void main() { + testWidgets('Counter increments smoke test', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(MyApp()); + + // Verify that our counter starts at 0. + expect(find.text('0'), findsOneWidget); + expect(find.text('1'), findsNothing); + + // Tap the '+' icon and trigger a frame. + await tester.tap(find.byIcon(Icons.add)); + await tester.pump(); + + // Verify that our counter has incremented. + expect(find.text('0'), findsNothing); + expect(find.text('1'), findsOneWidget); + }); +} diff --git a/flutter_tts-voice_enhancement/example/web/favicon.png b/flutter_tts-voice_enhancement/example/web/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..8aaa46ac1ae21512746f852a42ba87e4165dfdd1 GIT binary patch literal 917 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|I14-?iy0X7 zltGxWVyS%@P(fs7NJL45ua8x7ey(0(N`6wRUPW#JP&EUCO@$SZnVVXYs8ErclUHn2 zVXFjIVFhG^g!Ppaz)DK8ZIvQ?0~DO|i&7O#^-S~(l1AfjnEK zjFOT9D}DX)@^Za$W4-*MbbUihOG|wNBYh(yU7!lx;>x^|#0uTKVr7USFmqf|i<65o z3raHc^AtelCMM;Vme?vOfh>Xph&xL%(-1c06+^uR^q@XSM&D4+Kp$>4P^%3{)XKjo zGZknv$b36P8?Z_gF{nK@`XI}Z90TzwSQO}0J1!f2c(B=V`5aP@1P1a|PZ!4!3&Gl8 zTYqUsf!gYFyJnXpu0!n&N*SYAX-%d(5gVjrHJWqXQshj@!Zm{!01WsQrH~9=kTxW#6SvuapgMqt>$=j#%eyGrQzr zP{L-3gsMA^$I1&gsBAEL+vxi1*Igl=8#8`5?A-T5=z-sk46WA1IUT)AIZHx1rdUrf zVJrJn<74DDw`j)Ki#gt}mIT-Q`XRa2-jQXQoI%w`nb|XblvzK${ZzlV)m-XcwC(od z71_OEC5Bt9GEXosOXaPTYOia#R4ID2TiU~`zVMl08TV_C%DnU4^+HE>9(CE4D6?Fz oujB08i7adh9xk7*FX66dWH6F5TM;?E2b5PlUHx3vIVCg!0Dx9vYXATM literal 0 HcmV?d00001 diff --git a/flutter_tts-voice_enhancement/example/web/icons/Icon-192.png b/flutter_tts-voice_enhancement/example/web/icons/Icon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..b749bfef07473333cf1dd31e9eed89862a5d52aa GIT binary patch literal 5292 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 literal 0 HcmV?d00001 diff --git a/flutter_tts-voice_enhancement/example/web/icons/Icon-512.png b/flutter_tts-voice_enhancement/example/web/icons/Icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..88cfd48dff1169879ba46840804b412fe02fefd6 GIT binary patch literal 8252 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 literal 0 HcmV?d00001 diff --git a/flutter_tts-voice_enhancement/example/web/index.html b/flutter_tts-voice_enhancement/example/web/index.html new file mode 100644 index 00000000..20b0c00a --- /dev/null +++ b/flutter_tts-voice_enhancement/example/web/index.html @@ -0,0 +1,10 @@ + + + + + Flutter TTS example + + + + + diff --git a/flutter_tts-voice_enhancement/example/web/manifest.json b/flutter_tts-voice_enhancement/example/web/manifest.json new file mode 100644 index 00000000..8c012917 --- /dev/null +++ b/flutter_tts-voice_enhancement/example/web/manifest.json @@ -0,0 +1,23 @@ +{ + "name": "example", + "short_name": "example", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + } + ] +} diff --git a/flutter_tts-voice_enhancement/ios/.gitignore b/flutter_tts-voice_enhancement/ios/.gitignore new file mode 100644 index 00000000..956c87f3 --- /dev/null +++ b/flutter_tts-voice_enhancement/ios/.gitignore @@ -0,0 +1,31 @@ +.idea/ +.vagrant/ +.sconsign.dblite +.svn/ + +.DS_Store +*.swp +profile + +DerivedData/ +build/ + +*.pbxuser +*.mode1v3 +*.mode2v3 +*.perspectivev3 + +!default.pbxuser +!default.mode1v3 +!default.mode2v3 +!default.perspectivev3 + +xcuserdata + +*.moved-aside + +*.pyc +*sync/ +Icon? +.tags* + diff --git a/flutter_tts-voice_enhancement/ios/Assets/.gitkeep b/flutter_tts-voice_enhancement/ios/Assets/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/flutter_tts-voice_enhancement/ios/Classes/AudioCategory.swift b/flutter_tts-voice_enhancement/ios/Classes/AudioCategory.swift new file mode 100644 index 00000000..74e8ea0b --- /dev/null +++ b/flutter_tts-voice_enhancement/ios/Classes/AudioCategory.swift @@ -0,0 +1,21 @@ +import AVFoundation + +enum AudioCategory: String { + case iosAudioCategoryAmbientSolo + case iosAudioCategoryAmbient + case iosAudioCategoryPlayback + case iosAudioCategoryPlaybackAndRecord + + func toAVAudioSessionCategory() -> AVAudioSession.Category { + switch self { + case .iosAudioCategoryAmbientSolo: + return .soloAmbient + case .iosAudioCategoryAmbient: + return .ambient + case .iosAudioCategoryPlayback: + return .playback + case .iosAudioCategoryPlaybackAndRecord: + return .playAndRecord + } + } +} diff --git a/flutter_tts-voice_enhancement/ios/Classes/AudioCategoryOptions.swift b/flutter_tts-voice_enhancement/ios/Classes/AudioCategoryOptions.swift new file mode 100644 index 00000000..f593bfdb --- /dev/null +++ b/flutter_tts-voice_enhancement/ios/Classes/AudioCategoryOptions.swift @@ -0,0 +1,42 @@ +import AVFoundation + +enum AudioCategoryOptions: String { + case iosAudioCategoryOptionsMixWithOthers + case iosAudioCategoryOptionsDuckOthers + case iosAudioCategoryOptionsInterruptSpokenAudioAndMixWithOthers + case iosAudioCategoryOptionsAllowBluetooth + case iosAudioCategoryOptionsAllowBluetoothA2DP + case iosAudioCategoryOptionsAllowAirPlay + case iosAudioCategoryOptionsDefaultToSpeaker + + func toAVAudioSessionCategoryOptions() -> AVAudioSession.CategoryOptions? { + switch self { + case .iosAudioCategoryOptionsMixWithOthers: + return .mixWithOthers + case .iosAudioCategoryOptionsDuckOthers: + return .duckOthers + case .iosAudioCategoryOptionsInterruptSpokenAudioAndMixWithOthers: + if #available(iOS 9.0, *) { + return .interruptSpokenAudioAndMixWithOthers + } else { + return nil + } + case .iosAudioCategoryOptionsAllowBluetooth: + return .allowBluetooth + case .iosAudioCategoryOptionsAllowBluetoothA2DP: + if #available(iOS 10.0, *) { + return .allowBluetoothA2DP + } else { + return nil + } + case .iosAudioCategoryOptionsAllowAirPlay: + if #available(iOS 10.0, *) { + return .allowAirPlay + } else { + return nil + } + case .iosAudioCategoryOptionsDefaultToSpeaker: + return .defaultToSpeaker + } + } +} diff --git a/flutter_tts-voice_enhancement/ios/Classes/FlutterTtsPlugin.h b/flutter_tts-voice_enhancement/ios/Classes/FlutterTtsPlugin.h new file mode 100644 index 00000000..13e3a21a --- /dev/null +++ b/flutter_tts-voice_enhancement/ios/Classes/FlutterTtsPlugin.h @@ -0,0 +1,4 @@ +#import + +@interface FlutterTtsPlugin : NSObject +@end diff --git a/flutter_tts-voice_enhancement/ios/Classes/FlutterTtsPlugin.m b/flutter_tts-voice_enhancement/ios/Classes/FlutterTtsPlugin.m new file mode 100644 index 00000000..3a1f187c --- /dev/null +++ b/flutter_tts-voice_enhancement/ios/Classes/FlutterTtsPlugin.m @@ -0,0 +1,8 @@ +#import "FlutterTtsPlugin.h" +#import + +@implementation FlutterTtsPlugin ++ (void)registerWithRegistrar:(NSObject*)registrar { + [SwiftFlutterTtsPlugin registerWithRegistrar:registrar]; +} +@end diff --git a/flutter_tts-voice_enhancement/ios/Classes/SwiftFlutterTtsPlugin.swift b/flutter_tts-voice_enhancement/ios/Classes/SwiftFlutterTtsPlugin.swift new file mode 100644 index 00000000..5c78c135 --- /dev/null +++ b/flutter_tts-voice_enhancement/ios/Classes/SwiftFlutterTtsPlugin.swift @@ -0,0 +1,386 @@ +import Flutter +import UIKit +import AVFoundation + +public class SwiftFlutterTtsPlugin: NSObject, FlutterPlugin, AVSpeechSynthesizerDelegate { + final var iosAudioCategoryKey = "iosAudioCategoryKey" + final var iosAudioCategoryOptionsKey = "iosAudioCategoryOptionsKey" + + let synthesizer = AVSpeechSynthesizer() + var language: String = AVSpeechSynthesisVoice.currentLanguageCode() + var rate: Float = AVSpeechUtteranceDefaultSpeechRate + var languages = Set() + var volume: Float = 1.0 + var pitch: Float = 1.0 + var voice: AVSpeechSynthesisVoice? + var awaitSpeakCompletion: Bool = false + var speakResult: FlutterResult! + + var channel = FlutterMethodChannel() + lazy var audioSession = AVAudioSession.sharedInstance() + init(channel: FlutterMethodChannel) { + super.init() + self.channel = channel + synthesizer.delegate = self + setLanguages() + + // Allow audio playback when the Ring/Silent switch is set to silent + do { + try audioSession.setCategory(.playAndRecord, options: [.defaultToSpeaker]) + } catch { + print(error) + } + } + + private func setLanguages() { + for voice in AVSpeechSynthesisVoice.speechVoices(){ + self.languages.insert(voice.language) + } + } + + public static func register(with registrar: FlutterPluginRegistrar) { + let channel = FlutterMethodChannel(name: "flutter_tts", binaryMessenger: registrar.messenger()) + let instance = SwiftFlutterTtsPlugin(channel: channel) + registrar.addMethodCallDelegate(instance, channel: channel) + } + + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + switch call.method { + case "speak": + let text: String = call.arguments as! String + self.speak(text: text, result: result) + break + case "awaitSpeakCompletion": + self.awaitSpeakCompletion = call.arguments as! Bool + result(1) + break + case "synthesizeToFile": + guard let args = call.arguments as? [String: Any] else { + result("iOS could not recognize flutter arguments in method: (sendParams)") + return + } + let text = args["text"] as! String + let fileName = args["fileName"] as! String + self.synthesizeToFile(text: text, fileName: fileName, result: result) + break + case "pause": + self.pause(result: result) + break + case "setLanguage": + let language: String = call.arguments as! String + self.setLanguage(language: language, result: result) + break + case "setSpeechRate": + let rate: Double = call.arguments as! Double + self.setRate(rate: Float(rate)) + result(1) + break + case "setVolume": + let volume: Double = call.arguments as! Double + self.setVolume(volume: Float(volume), result: result) + break + case "setPitch": + let pitch: Double = call.arguments as! Double + self.setPitch(pitch: Float(pitch), result: result) + break + case "stop": + self.stop() + result(1) + break + case "getLanguages": + self.getLanguages(result: result) + break + case "getSpeechRateValidRange": + self.getSpeechRateValidRange(result: result) + break + case "isLanguageAvailable": + let language: String = call.arguments as! String + self.isLanguageAvailable(language: language, result: result) + break + case "getVoices": + self.getVoices(result: result) + break + case "setVoice": + guard let args = call.arguments as? [String: String] else { + result("iOS could not recognize flutter arguments in method: (sendParams)") + return + } + self.setVoice(voice: args, result: result) + break + case "setSharedInstance": + let sharedInstance = call.arguments as! Bool + self.setSharedInstance(sharedInstance: sharedInstance, result: result) + break + case "setIosAudioCategory": + guard let args = call.arguments as? [String: Any] else { + result("iOS could not recognize flutter arguments in method: (sendParams)") + return + } + let audioCategory = args["iosAudioCategoryKey"] as? String + let audioOptions = args[iosAudioCategoryOptionsKey] as? Array + self.setAudioCategory(audioCategory: audioCategory, audioOptions: audioOptions, result: result) + break + default: + result(FlutterMethodNotImplemented) + } + } + + private func speak(text: String, result: @escaping FlutterResult) { + if (self.synthesizer.isPaused) { + if (self.synthesizer.continueSpeaking()) { + if self.awaitSpeakCompletion { + self.speakResult = result + } else { + result(1) + } + } else { + result(0) + } + } else { + let utterance = AVSpeechUtterance(string: text) + if self.voice != nil { + utterance.voice = self.voice! + } else { + utterance.voice = AVSpeechSynthesisVoice(language: self.language) + } + utterance.rate = self.rate + utterance.volume = self.volume + utterance.pitchMultiplier = self.pitch + + self.synthesizer.speak(utterance) + if self.awaitSpeakCompletion { + self.speakResult = result + } else { + result(1) + } + } + } + + private func synthesizeToFile(text: String, fileName: String, result: FlutterResult) { + var output: AVAudioFile? + var failed = false + let utterance = AVSpeechUtterance(string: text) + + if self.voice != nil { + utterance.voice = self.voice! + } else { + utterance.voice = AVSpeechSynthesisVoice(language: self.language) + } + utterance.rate = self.rate + utterance.volume = self.volume + utterance.pitchMultiplier = self.pitch + + if #available(iOS 13.0, *) { + self.synthesizer.write(utterance) { (buffer: AVAudioBuffer) in + guard let pcmBuffer = buffer as? AVAudioPCMBuffer else { + NSLog("unknow buffer type: \(buffer)") + failed = true + return + } + print(pcmBuffer.format) + if pcmBuffer.frameLength == 0 { + // finished + } else { + // append buffer to file + let fileURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent(fileName) + NSLog("Saving utterance to file: \(fileURL.absoluteString)") + + if output == nil { + do { + output = try AVAudioFile( + forWriting: fileURL, + settings: pcmBuffer.format.settings, + commonFormat: .pcmFormatInt16, + interleaved: false) + } catch { + NSLog(error.localizedDescription) + failed = true + return + } + } + + try! output!.write(from: pcmBuffer) + } + } + } else { + result("Unsupported iOS version") + } + if failed { + result(0) + } + result(1) + } + + private func pause(result: FlutterResult) { + if (self.synthesizer.pauseSpeaking(at: AVSpeechBoundary.word)) { + result(1) + } else { + result(0) + } + } + + private func setLanguage(language: String, result: FlutterResult) { + if !(self.languages.contains(where: {$0.range(of: language, options: [.caseInsensitive, .anchored]) != nil})) { + result(0) + } else { + self.language = language + self.voice = nil + result(1) + } + } + + private func setRate(rate: Float) { + self.rate = rate + } + + private func setVolume(volume: Float, result: FlutterResult) { + if (volume >= 0.0 && volume <= 1.0) { + self.volume = volume + result(1) + } else { + result(0) + } + } + + private func setPitch(pitch: Float, result: FlutterResult) { + if (volume >= 0.5 && volume <= 2.0) { + self.pitch = pitch + result(1) + } else { + result(0) + } + } + + private func setSharedInstance(sharedInstance: Bool, result: FlutterResult) { + do { + try AVAudioSession.sharedInstance().setActive(sharedInstance) + result(1) + } catch { + result(0) + } + } + + private func setAudioCategory(audioCategory: String?, audioOptions: Array?, result: FlutterResult){ + let category: AVAudioSession.Category = AudioCategory(rawValue: audioCategory ?? "")?.toAVAudioSessionCategory() ?? audioSession.category + let options: AVAudioSession.CategoryOptions = audioOptions?.reduce([], { (result, option) -> AVAudioSession.CategoryOptions in + return result.union(AudioCategoryOptions(rawValue: option)?.toAVAudioSessionCategoryOptions() ?? []) + }) ?? [] + + do { + try audioSession.setCategory(category, options: options) + result(1) + } catch { + print(error) + result(0) + } + } + + private func stop() { + self.synthesizer.stopSpeaking(at: AVSpeechBoundary.immediate) + } + + private func getLanguages(result: FlutterResult) { + result(Array(self.languages)) + } + + private func getSpeechRateValidRange(result: FlutterResult) { + let validSpeechRateRange: [String:String] = [ + "min": String(AVSpeechUtteranceMinimumSpeechRate), + "normal": String(AVSpeechUtteranceDefaultSpeechRate), + "max": String(AVSpeechUtteranceMaximumSpeechRate), + "platform": "ios" + ] + result(validSpeechRateRange) + } + + private func isLanguageAvailable(language: String, result: FlutterResult) { + var isAvailable: Bool = false + if (self.languages.contains(where: {$0.range(of: language, options: [.caseInsensitive, .anchored]) != nil})) { + isAvailable = true + } + result(isAvailable); + } + + private func getVoices(result: FlutterResult) { + if #available(iOS 9.0, *) { + let voices = NSMutableArray() + var voiceDict: [String: String] = [:] + for voice in AVSpeechSynthesisVoice.speechVoices() { + voiceDict["name"] = voice.name + voiceDict["locale"] = voice.language + voices.add(voiceDict) + } + result(voices) + } else { + // Since voice selection is not supported below iOS 9, make voice getter and setter + // have the same bahavior as language selection. + getLanguages(result: result) + } + } + + private func setVoice(voice: [String:String], result: FlutterResult) { + if #available(iOS 9.0, *) { + if let voice = AVSpeechSynthesisVoice.speechVoices().first(where: { $0.name == voice["name"]! && $0.language == voice["locale"]! }) { + self.voice = voice + self.language = voice.language + result(1) + return + } + result(0) + } else { + setLanguage(language: voice["name"]!, result: result) + } + } + + private func shouldDeactivateAndNotifyOthers(_ session: AVAudioSession) -> Bool { + var options: AVAudioSession.CategoryOptions = .duckOthers + if #available(iOS 9.0, *) { + options.insert(.interruptSpokenAudioAndMixWithOthers) + } + options.remove(.mixWithOthers) + + return !options.isDisjoint(with: session.categoryOptions) + } + + public func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) { + if shouldDeactivateAndNotifyOthers(audioSession) { + do { + try audioSession.setActive(false, options: .notifyOthersOnDeactivation) + } catch { + print(error) + } + } + if self.awaitSpeakCompletion { + self.speakResult(1) + } + self.channel.invokeMethod("speak.onComplete", arguments: nil) + } + + public func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didStart utterance: AVSpeechUtterance) { + self.channel.invokeMethod("speak.onStart", arguments: nil) + } + + public func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didPause utterance: AVSpeechUtterance) { + self.channel.invokeMethod("speak.onPause", arguments: nil) + } + + public func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didContinue utterance: AVSpeechUtterance) { + self.channel.invokeMethod("speak.onContinue", arguments: nil) + } + + public func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didCancel utterance: AVSpeechUtterance) { + self.channel.invokeMethod("speak.onCancel", arguments: nil) + } + + public func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, willSpeakRangeOfSpeechString characterRange: NSRange, utterance: AVSpeechUtterance) { + let nsWord = utterance.speechString as NSString + let data: [String:String] = [ + "text": utterance.speechString, + "start": String(characterRange.location), + "end": String(characterRange.location + characterRange.length), + "word": nsWord.substring(with: characterRange) + ] + self.channel.invokeMethod("speak.onProgress", arguments: data) + } + +} diff --git a/flutter_tts-voice_enhancement/ios/flutter_tts.podspec b/flutter_tts-voice_enhancement/ios/flutter_tts.podspec new file mode 100644 index 00000000..03099f45 --- /dev/null +++ b/flutter_tts-voice_enhancement/ios/flutter_tts.podspec @@ -0,0 +1,22 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html +# +Pod::Spec.new do |s| + s.name = 'flutter_tts' + s.version = '0.0.1' + s.summary = 'A flutter text to speech plugin.' + s.description = <<-DESC +A flutter text to speech plugin + DESC + s.homepage = 'https://github.com/dlutton/flutter_tts' + s.license = { :file => '../LICENSE' } + s.author = { 'tundralabs' => 'eyedea32@gmail.com' } + s.source = { :path => '.' } + s.source_files = 'Classes/**/*' + s.public_header_files = 'Classes/**/*.h' + s.dependency 'Flutter' + s.ios.deployment_target = '8.0' + s.swift_version = '4.2' + s.static_framework = true +end + diff --git a/flutter_tts-voice_enhancement/lib/flutter_tts.dart b/flutter_tts-voice_enhancement/lib/flutter_tts.dart new file mode 100644 index 00000000..c823a91d --- /dev/null +++ b/flutter_tts-voice_enhancement/lib/flutter_tts.dart @@ -0,0 +1,342 @@ +import 'dart:async'; +import 'dart:io' show Platform; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; + +typedef void ErrorHandler(dynamic message); +typedef ProgressHandler = void Function( + String text, int start, int end, String word); + +const String iosAudioCategoryOptionsKey = 'iosAudioCategoryOptionsKey'; +const String iosAudioCategoryKey = 'iosAudioCategoryKey'; +const String iosAudioCategoryAmbientSolo = 'iosAudioCategoryAmbientSolo'; +const String iosAudioCategoryAmbient = 'iosAudioCategoryAmbient'; +const String iosAudioCategoryPlayback = 'iosAudioCategoryPlayback'; +const String iosAudioCategoryPlaybackAndRecord = + 'iosAudioCategoryPlaybackAndRecord'; + +const String iosAudioCategoryOptionsMixWithOthers = + 'iosAudioCategoryOptionsMixWithOthers'; +const String iosAudioCategoryOptionsDuckOthers = + 'iosAudioCategoryOptionsDuckOthers'; +const String iosAudioCategoryOptionsInterruptSpokenAudioAndMixWithOthers = + 'iosAudioCategoryOptionsInterruptSpokenAudioAndMixWithOthers'; +const String iosAudioCategoryOptionsAllowBluetooth = + 'iosAudioCategoryOptionsAllowBluetooth'; +const String iosAudioCategoryOptionsAllowBluetoothA2DP = + 'iosAudioCategoryOptionsAllowBluetoothA2DP'; +const String iosAudioCategoryOptionsAllowAirPlay = + 'iosAudioCategoryOptionsAllowAirPlay'; +const String iosAudioCategoryOptionsDefaultToSpeaker = + 'iosAudioCategoryOptionsDefaultToSpeaker'; + +enum TextToSpeechPlatform { android, ios } + +enum IosTextToSpeechAudioCategory { + /// Audio is silenced by screen lock and the silent switch; audio will not mix + /// with other apps' audio. + ambientSolo, + + /// Audio is silenced by screen lock and the silent switch; audio will mix + /// with other apps' (mixable) audio. + ambient, + + /// Audio is not silenced by screen lock or silent switch; audio will not mix + /// with other apps' audio. + /// + playback, + + /// The category for recording (input) and playback (output) of audio, + /// such as for a Voice over Internet Protocol (VoIP) app. + /// The default value. + playAndRecord, +} + +enum IosTextToSpeechAudioCategoryOptions { + /// An option that indicates whether audio from this session mixes with audio + /// from active sessions in other audio apps. + mixWithOthers, + + /// An option that reduces the volume of other audio session while audio + /// from this session plays. + duckOthers, + + /// An option that determines whether to pause spoken audio content + /// from other sessions when your app plays its audio. + interruptSpokenAudioAndMixWithOthers, + + ///An option that determines whether Bluetooth hands-free devices + /// appear as available input routes. + allowBluetooth, + + ///An option that determines whether you can stream audio + /// from this session to Bluetooth devices that support the Advanced Audio Distribution Profile (A2DP). + allowBluetoothA2DP, + + ///An option that determines whether you can stream audio + /// from this session to AirPlay devices. + allowAirPlay, + + ///An option that determines whether audio + /// from the session defaults to the built-in speaker instead of the receiver. + /// The default value. + defaultToSpeaker, +} + +class SpeechRateValidRange { + final double min; + final double normal; + final double max; + final TextToSpeechPlatform platform; + + SpeechRateValidRange(this.min, this.normal, this.max, this.platform); +} + +// Provides Platform specific TTS services (Android: TextToSpeech, IOS: AVSpeechSynthesizer) +class FlutterTts { + static const MethodChannel _channel = const MethodChannel('flutter_tts'); + + VoidCallback startHandler; + VoidCallback completionHandler; + VoidCallback pauseHandler; + VoidCallback continueHandler; + VoidCallback cancelHandler; + ProgressHandler progressHandler; + ErrorHandler errorHandler; + + FlutterTts() { + _channel.setMethodCallHandler(platformCallHandler); + } + + /// [Future] which sets speak's future to return on completion of the utterance + Future awaitSpeakCompletion(bool awaitCompletion) async => + _channel.invokeMethod('awaitSpeakCompletion', awaitCompletion); + + /// [Future] which invokes the platform specific method for speaking + Future speak(String text) async => + _channel.invokeMethod('speak', text); + + /// [Future] which invokes the platform specific method for pause + /// ***iOS supported only*** + Future pause() async => _channel.invokeMethod('pause'); + + /// [Future] which invokes the platform specific method for synthesizeToFile + /// ***Android and iOS supported only*** + Future synthesizeToFile(String text, String fileName) async => + _channel.invokeMethod('synthesizeToFile', { + "text": text, + "fileName": fileName, + }); + + /// [Future] which invokes the platform specific method for setLanguage + Future setLanguage(String language) async => + _channel.invokeMethod('setLanguage', language); + + /// [Future] which invokes the platform specific method for setSpeechRate + /// Allowed values are in the range from 0.0 (slowest) to 1.0 (fastest) + Future setSpeechRate(double rate) async => + _channel.invokeMethod('setSpeechRate', rate); + + /// [Future] which invokes the platform specific method for setVolume + /// Allowed values are in the range from 0.0 (silent) to 1.0 (loudest) + Future setVolume(double volume) async => + _channel.invokeMethod('setVolume', volume); + + /// [Future] which invokes the platform specific method for shared instance + /// ***iOS supported only*** + Future setSharedInstance(bool sharedSession) async => + _channel.invokeMethod('setSharedInstance', sharedSession); + + /// [Future] which invokes the platform specific method for setting audio category + /// ***Ios supported only*** + Future setIosAudioCategory(IosTextToSpeechAudioCategory category, + List options) async { + const categoryToString = { + IosTextToSpeechAudioCategory.ambientSolo: iosAudioCategoryAmbientSolo, + IosTextToSpeechAudioCategory.ambient: iosAudioCategoryAmbient, + IosTextToSpeechAudioCategory.playback: iosAudioCategoryPlayback + }; + const optionsToString = { + IosTextToSpeechAudioCategoryOptions.mixWithOthers: + 'iosAudioCategoryOptionsMixWithOthers', + IosTextToSpeechAudioCategoryOptions.duckOthers: + 'iosAudioCategoryOptionsDuckOthers', + IosTextToSpeechAudioCategoryOptions.interruptSpokenAudioAndMixWithOthers: + 'iosAudioCategoryOptionsInterruptSpokenAudioAndMixWithOthers', + IosTextToSpeechAudioCategoryOptions.allowBluetooth: + 'iosAudioCategoryOptionsAllowBluetooth', + IosTextToSpeechAudioCategoryOptions.allowBluetoothA2DP: + 'iosAudioCategoryOptionsAllowBluetoothA2DP', + IosTextToSpeechAudioCategoryOptions.allowAirPlay: + 'iosAudioCategoryOptionsAllowAirPlay', + IosTextToSpeechAudioCategoryOptions.defaultToSpeaker: + 'iosAudioCategoryOptionsDefaultToSpeaker', + }; + if (!Platform.isIOS) return; + try { + return _channel + .invokeMethod('setIosAudioCategory', { + iosAudioCategoryKey: categoryToString[category], + iosAudioCategoryOptionsKey: + options.map((o) => optionsToString[o]).toList(), + }); + } on PlatformException catch (e) { + print( + 'setIosAudioCategory error, category: $category, error: ${e.message}'); + } + } + + /// [Future] which invokes the platform specific method for setPitch + /// 1.0 is default and ranges from .5 to 2.0 + Future setPitch(double pitch) async => + _channel.invokeMethod('setPitch', pitch); + + /// [Future] which invokes the platform specific method for setVoice + /// ***Android, iOS, and macOS supported only*** + Future setVoice(Map voice) async => + _channel.invokeMethod('setVoice', voice); + + /// [Future] which invokes the platform specific method for stop + Future stop() async => _channel.invokeMethod('stop'); + + /// [Future] which invokes the platform specific method for getLanguages + /// Android issues with API 21 & 22 + /// Returns a list of available languages + Future get getLanguages async { + final languages = await _channel.invokeMethod('getLanguages'); + return languages; + } + + /// [Future] which invokes the platform specific method for getEngines + /// Returns a list of installed TTS engines + /// ***Android supported only*** + Future get getEngines async { + final engines = await _channel.invokeMethod('getEngines'); + return engines; + } + + /// [Future] which invokes the platform specific method for getVoices + /// Returns a `List` of `Maps` containing a voice name and locale + /// ***Android, iOS, and macOS supported only*** + Future get getVoices async { + final voices = await _channel.invokeMethod('getVoices'); + return voices; + } + + /// [Future] which invokes the platform specific method for isLanguageAvailable + /// Returns `true` or `false` + Future isLanguageAvailable(String language) async => + _channel.invokeMethod('isLanguageAvailable', language); + + Future get getSpeechRateValidRange async { + final validRange = await _channel.invokeMethod('getSpeechRateValidRange') + as Map; + final min = double.parse(validRange['min'].toString()); + final normal = double.parse(validRange['normal'].toString()); + final max = double.parse(validRange['max'].toString()); + final platformStr = validRange['platform'].toString(); + final platform = TextToSpeechPlatform.values + .firstWhere((e) => describeEnum(e) == platformStr); + + return SpeechRateValidRange(min, normal, max, platform); + } + + /// [Future] which invokes the platform specific method for setSilence + /// 0 means start the utterance immediately. If the value is greater than zero a silence period in milliseconds is set according to the parameter + /// ***Android supported only*** + Future setSilence(int timems) async => + _channel.invokeMethod('setSilence', timems ?? 0); + + void setStartHandler(VoidCallback callback) { + startHandler = callback; + } + + void setCompletionHandler(VoidCallback callback) { + completionHandler = callback; + } + + void setContinueHandler(VoidCallback callback) { + continueHandler = callback; + } + + void setPauseHandler(VoidCallback callback) { + pauseHandler = callback; + } + + void setCancelHandler(VoidCallback callback) { + cancelHandler = callback; + } + + void setProgressHandler(ProgressHandler callback) { + progressHandler = callback; + } + + void setErrorHandler(ErrorHandler handler) { + errorHandler = handler; + } + + /// Platform listeners + Future platformCallHandler(MethodCall call) async { + switch (call.method) { + case "speak.onStart": + if (startHandler != null) { + startHandler(); + } + break; + case "synth.onStart": + if (startHandler != null) { + startHandler(); + } + break; + case "speak.onComplete": + if (completionHandler != null) { + completionHandler(); + } + break; + case "synth.onComplete": + if (completionHandler != null) { + completionHandler(); + } + break; + case "speak.onPause": + if (pauseHandler != null) { + pauseHandler(); + } + break; + case "speak.onContinue": + if (continueHandler != null) { + continueHandler(); + } + break; + case "speak.onCancel": + if (cancelHandler != null) { + cancelHandler(); + } + break; + case "speak.onError": + if (errorHandler != null) { + errorHandler(call.arguments); + } + break; + case 'speak.onProgress': + if (progressHandler != null) { + final args = call.arguments as Map; + progressHandler( + args['text'].toString(), + int.parse(args['start'].toString()), + int.parse(args['end'].toString()), + args['word'].toString(), + ); + } + break; + case "synth.onError": + if (errorHandler != null) { + errorHandler(call.arguments); + } + break; + default: + print('Unknowm method ${call.method}'); + } + } +} diff --git a/flutter_tts-voice_enhancement/lib/flutter_tts_web.dart b/flutter_tts-voice_enhancement/lib/flutter_tts_web.dart new file mode 100644 index 00000000..182e9dfa --- /dev/null +++ b/flutter_tts-voice_enhancement/lib/flutter_tts_web.dart @@ -0,0 +1,184 @@ +import 'dart:async'; +import 'dart:html' as html; +import 'dart:js'; + +import 'package:flutter/services.dart'; +import 'package:flutter_web_plugins/flutter_web_plugins.dart'; + +enum TtsState { playing, stopped, paused, continued } + +class FlutterTtsPlugin { + static const String PLATFORM_CHANNEL = "flutter_tts"; + static MethodChannel channel; + bool awaitSpeakCompletion = false; + + TtsState ttsState = TtsState.stopped; + + get isPlaying => ttsState == TtsState.playing; + + get isStopped => ttsState == TtsState.stopped; + + get isPaused => ttsState == TtsState.paused; + + get isContinued => ttsState == TtsState.continued; + + static void registerWith(Registrar registrar) { + channel = MethodChannel( + PLATFORM_CHANNEL, const StandardMethodCodec(), registrar.messenger); + final instance = FlutterTtsPlugin(); + channel.setMethodCallHandler(instance.handleMethodCall); + } + + html.SpeechSynthesis synth; + html.SpeechSynthesisUtterance utterance; + List voices; + List languages; + + FlutterTtsPlugin() { + utterance = html.SpeechSynthesisUtterance(); + synth = html.window.speechSynthesis; + + _listeners(); + } + + void _listeners() { + utterance.onStart.listen((e) { + ttsState = TtsState.playing; + channel.invokeMethod("speak.onStart", null); + }); + utterance.onEnd.listen((e) { + ttsState = TtsState.stopped; + channel.invokeMethod("speak.onComplete", null); + if (awaitSpeakCompletion) { + return 1; + } + }); + utterance.onPause.listen((e) { + ttsState = TtsState.paused; + channel.invokeMethod("speak.onPause", null); + }); + utterance.onResume.listen((e) { + ttsState = TtsState.continued; + channel.invokeMethod("speak.onContinue", null); + }); + utterance.onError.listen((e) { + channel.invokeMethod("speak.onError", e); + if (awaitSpeakCompletion) { + return 0; + } + }); + } + + Future handleMethodCall(MethodCall call) async { + switch (call.method) { + case 'speak': + final text = call.arguments as String; + _speak(text); + if (!awaitSpeakCompletion) { + return 1; + } + break; + case 'awaitSpeakCompletion': + awaitSpeakCompletion = call.arguments as bool; + return 1; + break; + case 'stop': + _stop(); + return 1; + break; + case 'pause': + _pause(); + return 1; + break; + case 'setLanguage': + final language = call.arguments as String; + _setLanguage(language); + return 1; + break; + case 'getLanguages': + return _getLanguages(); + break; + case 'setSpeechRate': + final rate = call.arguments as num; + _setRate(rate); + return 1; + break; + case 'setVolume': + final volume = call.arguments as num; + _setVolume(volume); + return 1; + break; + case 'setPitch': + final pitch = call.arguments as num; + _setPitch(pitch); + return 1; + break; + case 'isLanguageAvailable': + final lang = call.arguments as String; + return _isLanguageAvailable(lang); + break; + default: + throw PlatformException( + code: 'Unimplemented', + details: "The flutter_tts plugin for web doesn't implement " + "the method '${call.method}'"); + } + } + + void _speak(String text) { + if (ttsState == TtsState.stopped || ttsState == TtsState.paused) { + utterance.text = text; + if (ttsState == TtsState.paused) { + synth.resume(); + } else { + synth.speak(utterance); + } + } + } + + void _stop() { + if (ttsState != TtsState.stopped) { + synth.cancel(); + } + } + + void _pause() { + if (ttsState == TtsState.playing || ttsState == TtsState.continued) { + synth.pause(); + } + } + + void _setRate(num rate) => utterance.rate = rate * 2.0; + void _setVolume(num volume) => utterance.volume = volume; + void _setPitch(num pitch) => utterance.pitch = pitch; + void _setLanguage(String language) => utterance.lang = language; + + bool _isLanguageAvailable(String language) { + if (voices?.isEmpty ?? true) _setVoices(); + if (languages?.isEmpty ?? true) _setLanguages(); + for (var lang in languages) { + if (lang.toLowerCase() == language.toLowerCase()) return true; + } + return false; + } + + List _getLanguages() { + if (voices?.isEmpty ?? true) _setVoices(); + if (languages?.isEmpty ?? true) _setLanguages(); + return languages; + } + + void _setVoices() { + voices = + context['speechSynthesis'].callMethod('getVoices') as JsArray; + } + + void _setLanguages() { + var langs = Set(); + for (var v in voices) { + langs.add(v['lang'] as String); + } + + languages = langs.toList(); + } +} diff --git a/flutter_tts-voice_enhancement/macos/Classes/FlutterTtsPlugin.swift b/flutter_tts-voice_enhancement/macos/Classes/FlutterTtsPlugin.swift new file mode 100644 index 00000000..ec4bffa1 --- /dev/null +++ b/flutter_tts-voice_enhancement/macos/Classes/FlutterTtsPlugin.swift @@ -0,0 +1,315 @@ +import FlutterMacOS +import Foundation +import AVFoundation + +public class FlutterTtsPlugin: NSObject, FlutterPlugin, AVSpeechSynthesizerDelegate { + final var iosAudioCategoryKey = "iosAudioCategoryKey" + final var iosAudioCategoryOptionsKey = "iosAudioCategoryOptionsKey" + + let synthesizer = AVSpeechSynthesizer() + var language: String = AVSpeechSynthesisVoice.currentLanguageCode() + var rate: Float = AVSpeechUtteranceDefaultSpeechRate + var languages = Set() + var volume: Float = 1.0 + var pitch: Float = 1.0 + var voice: AVSpeechSynthesisVoice? + var awaitSpeakCompletion: Bool = false + var speakResult: FlutterResult! + + var channel = FlutterMethodChannel() + init(channel: FlutterMethodChannel) { + super.init() + self.channel = channel + synthesizer.delegate = self + setLanguages() + } + + private func setLanguages() { + for voice in AVSpeechSynthesisVoice.speechVoices(){ + self.languages.insert(voice.language) + } + } + + public static func register(with registrar: FlutterPluginRegistrar) { + let channel = FlutterMethodChannel(name: "flutter_tts", binaryMessenger: registrar.messenger) + let instance = FlutterTtsPlugin(channel: channel) + registrar.addMethodCallDelegate(instance, channel: channel) + } + + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + switch call.method { + case "speak": + let text: String = call.arguments as! String + self.speak(text: text, result: result) + break + case "awaitSpeakCompletion": + self.awaitSpeakCompletion = call.arguments as! Bool + result(1) + break + case "synthesizeToFile": + guard let args = call.arguments as? [String: Any] else { + result("iOS could not recognize flutter arguments in method: (sendParams)") + return + } + let text = args["text"] as! String + let fileName = args["fileName"] as! String + self.synthesizeToFile(text: text, fileName: fileName, result: result) + break + case "pause": + self.pause(result: result) + break + case "setLanguage": + let language: String = call.arguments as! String + self.setLanguage(language: language, result: result) + break + case "setSpeechRate": + let rate: Double = call.arguments as! Double + self.setRate(rate: Float(rate)) + result(1) + break + case "setVolume": + let volume: Double = call.arguments as! Double + self.setVolume(volume: Float(volume), result: result) + break + case "setPitch": + let pitch: Double = call.arguments as! Double + self.setPitch(pitch: Float(pitch), result: result) + break + case "stop": + self.stop() + result(1) + break + case "getLanguages": + self.getLanguages(result: result) + break + case "getSpeechRateValidRange": + self.getSpeechRateValidRange(result: result) + break + case "isLanguageAvailable": + let language: String = call.arguments as! String + self.isLanguageAvailable(language: language, result: result) + break + case "getVoices": + self.getVoices(result: result) + break + case "setVoice": + guard let args = call.arguments as? [String: String] else { + result("iOS could not recognize flutter arguments in method: (sendParams)") + return + } + self.setVoice(voice: args, result: result) + break + default: + result(FlutterMethodNotImplemented) + } + } + + private func speak(text: String, result: @escaping FlutterResult) { + if (self.synthesizer.isPaused) { + if (self.synthesizer.continueSpeaking()) { + if self.awaitSpeakCompletion { + self.speakResult = result + } else { + result(1) + } + } else { + result(0) + } + } else { + let utterance = AVSpeechUtterance(string: text) + if self.voice != nil { + utterance.voice = self.voice! + } else { + utterance.voice = AVSpeechSynthesisVoice(language: self.language) + } + utterance.rate = self.rate + utterance.volume = self.volume + utterance.pitchMultiplier = self.pitch + + self.synthesizer.speak(utterance) + if self.awaitSpeakCompletion { + self.speakResult = result + } else { + result(1) + } + } + } + + private func synthesizeToFile(text: String, fileName: String, result: FlutterResult) { + var output: AVAudioFile? + var failed = false + let utterance = AVSpeechUtterance(string: text) + + if #available(iOS 13.0, *) { + self.synthesizer.write(utterance) { (buffer: AVAudioBuffer) in + guard let pcmBuffer = buffer as? AVAudioPCMBuffer else { + NSLog("unknow buffer type: \(buffer)") + failed = true + return + } + print(pcmBuffer.format) + if pcmBuffer.frameLength == 0 { + // finished + } else { + // append buffer to file + let fileURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent(fileName) + NSLog("Saving utterance to file: \(fileURL.absoluteString)") + + if output == nil { + do { + output = try AVAudioFile( + forWriting: fileURL, + settings: pcmBuffer.format.settings, + commonFormat: .pcmFormatInt16, + interleaved: false) + } catch { + NSLog(error.localizedDescription) + failed = true + return + } + } + + try! output!.write(from: pcmBuffer) + } + } + } else { + result("Unsupported iOS version") + } + if failed { + result(0) + } + result(1) + } + + private func pause(result: FlutterResult) { + if (self.synthesizer.pauseSpeaking(at: AVSpeechBoundary.word)) { + result(1) + } else { + result(0) + } + } + + private func setLanguage(language: String, result: FlutterResult) { + if !(self.languages.contains(where: {$0.range(of: language, options: [.caseInsensitive, .anchored]) != nil})) { + result(0) + } else { + self.language = language + self.voice = nil + result(1) + } + } + + private func setRate(rate: Float) { + self.rate = rate + } + + private func setVolume(volume: Float, result: FlutterResult) { + if (volume >= 0.0 && volume <= 1.0) { + self.volume = volume + result(1) + } else { + result(0) + } + } + + private func setPitch(pitch: Float, result: FlutterResult) { + if (volume >= 0.5 && volume <= 2.0) { + self.pitch = pitch + result(1) + } else { + result(0) + } + } + + private func stop() { + self.synthesizer.stopSpeaking(at: AVSpeechBoundary.immediate) + } + + private func getLanguages(result: FlutterResult) { + result(Array(self.languages)) + } + + private func getSpeechRateValidRange(result: FlutterResult) { + let validSpeechRateRange: [String:String] = [ + "min": String(AVSpeechUtteranceMinimumSpeechRate), + "normal": String(AVSpeechUtteranceDefaultSpeechRate), + "max": String(AVSpeechUtteranceMaximumSpeechRate), + "platform": "ios" + ] + result(validSpeechRateRange) + } + + private func isLanguageAvailable(language: String, result: FlutterResult) { + var isAvailable: Bool = false + if (self.languages.contains(where: {$0.range(of: language, options: [.caseInsensitive, .anchored]) != nil})) { + isAvailable = true + } + result(isAvailable); + } + + private func getVoices(result: FlutterResult) { + if #available(iOS 9.0, *) { + let voices = NSMutableArray() + var voiceDict: [String: String] = [:] + for voice in AVSpeechSynthesisVoice.speechVoices() { + voiceDict["name"] = voice.name + voiceDict["locale"] = voice.language + voices.add(voiceDict) + } + result(voices) + } else { + // Since voice selection is not supported below iOS 9, make voice getter and setter + // have the same bahavior as language selection. + getLanguages(result: result) + } + } + + private func setVoice(voice: [String:String], result: FlutterResult) { + if #available(iOS 9.0, *) { + if let voice = AVSpeechSynthesisVoice.speechVoices().first(where: { $0.name == voice["name"]! && $0.language == voice["locale"]! }) { + self.voice = voice + self.language = voice.language + result(1) + return + } + result(0) + } else { + setLanguage(language: voice["name"]!, result: result) + } + } + + public func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) { + if self.awaitSpeakCompletion { + self.speakResult(1) + } + self.channel.invokeMethod("speak.onComplete", arguments: nil) + } + + public func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didStart utterance: AVSpeechUtterance) { + self.channel.invokeMethod("speak.onStart", arguments: nil) + } + + public func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didPause utterance: AVSpeechUtterance) { + self.channel.invokeMethod("speak.onPause", arguments: nil) + } + + public func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didContinue utterance: AVSpeechUtterance) { + self.channel.invokeMethod("speak.onContinue", arguments: nil) + } + + public func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didCancel utterance: AVSpeechUtterance) { + self.channel.invokeMethod("speak.onCancel", arguments: nil) + } + + public func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, willSpeakRangeOfSpeechString characterRange: NSRange, utterance: AVSpeechUtterance) { + let nsWord = utterance.speechString as NSString + let data: [String:String] = [ + "text": utterance.speechString, + "start": String(characterRange.location), + "end": String(characterRange.location + characterRange.length), + "word": nsWord.substring(with: characterRange) + ] + self.channel.invokeMethod("speak.onProgress", arguments: data) + } + +} diff --git a/flutter_tts-voice_enhancement/macos/flutter_tts.podspec b/flutter_tts-voice_enhancement/macos/flutter_tts.podspec new file mode 100644 index 00000000..2838eb07 --- /dev/null +++ b/flutter_tts-voice_enhancement/macos/flutter_tts.podspec @@ -0,0 +1,22 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html +# +Pod::Spec.new do |s| + s.name = 'flutter_tts' + s.version = '0.0.1' + s.summary = 'macOS implementation of the flutter_tts plugin.' + s.description = <<-DESC + A flutter text to speech plugin + DESC + s.homepage = 'https://github.com/dlutton/flutter_tts' + s.license = { :file => '../LICENSE' } + s.author = { 'Daniel Lutton' => 'eyedea32@gmail.com' } + s.source = { :path => '.' } + s.source_files = 'Classes/**/*' + s.dependency 'FlutterMacOS' + + s.platform = :osx, '10.15' + s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } + s.swift_version = '5.0' + + end \ No newline at end of file diff --git a/flutter_tts-voice_enhancement/pubspec.yaml b/flutter_tts-voice_enhancement/pubspec.yaml new file mode 100644 index 00000000..06e93f33 --- /dev/null +++ b/flutter_tts-voice_enhancement/pubspec.yaml @@ -0,0 +1,28 @@ +name: flutter_tts +description: A flutter plugin for Text to Speech. This plugin is supported on iOS, Android, Web, & macOS. +version: 1.3.0 +homepage: https://github.com/dlutton/flutter_tts + +dependencies: + flutter: + sdk: flutter + flutter_web_plugins: + sdk: flutter + +flutter: + plugin: + platforms: + android: + package: com.tundralabs.fluttertts + pluginClass: FlutterTtsPlugin + ios: + pluginClass: FlutterTtsPlugin + macos: + pluginClass: FlutterTtsPlugin + web: + pluginClass: FlutterTtsPlugin + fileName: flutter_tts_web.dart + +environment: + sdk: ">=2.1.0 <3.0.0" + flutter: ">=1.12.13+hotfix.5 <2.0.0" diff --git a/lib/core/model/ImagesInfo.dart b/lib/core/model/ImagesInfo.dart new file mode 100644 index 00000000..5ab48fb3 --- /dev/null +++ b/lib/core/model/ImagesInfo.dart @@ -0,0 +1,6 @@ +class ImagesInfo { + final String imageAr; + final String imageEn; + + ImagesInfo({this.imageAr, this.imageEn}); +} From a3e01ff9387ad8a61ce9d14f4fd078e2f6fa8df3 Mon Sep 17 00:00:00 2001 From: Sultan Khan Date: Fri, 4 Dec 2020 12:12:52 +0300 Subject: [PATCH 12/71] flutter tts --- lib/pages/DrawerPages/family/my-family.dart | 398 +++++++++--------- .../others/floating_button_search.dart | 18 +- 2 files changed, 218 insertions(+), 198 deletions(-) diff --git a/lib/pages/DrawerPages/family/my-family.dart b/lib/pages/DrawerPages/family/my-family.dart index 80de8ecd..57632c46 100644 --- a/lib/pages/DrawerPages/family/my-family.dart +++ b/lib/pages/DrawerPages/family/my-family.dart @@ -7,7 +7,8 @@ import 'package:diplomaticquarterapp/core/viewModels/appointment_rate_view_model import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/locator.dart'; import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; -import 'package:diplomaticquarterapp/models/Authentication/check_activation_code_response.dart' as list; +import 'package:diplomaticquarterapp/models/Authentication/check_activation_code_response.dart' + as list; import 'package:diplomaticquarterapp/models/FamilyFiles/GetAllSharedRecordByStatusResponse.dart'; import 'package:diplomaticquarterapp/pages/BookAppointment/widgets/BranchView.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; @@ -29,9 +30,10 @@ import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart'; import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/routes.dart'; import 'package:provider/provider.dart'; + class MyFamily extends StatefulWidget { final bool isAppbarVisible; - MyFamily({this.isAppbarVisible =true}); + MyFamily({this.isAppbarVisible = true}); @override _MyFamily createState() => _MyFamily(); } @@ -44,9 +46,9 @@ class _MyFamily extends State with TickerProviderStateMixin { TabController _tabController; int _tabIndex = 0; AuthenticatedUserObject authenticatedUserObject = - locator(); + locator(); AppointmentRateViewModel appointmentRateViewModel = - locator(); + locator(); ProjectViewModel projectViewModel; AuthenticatedUser user; @override @@ -59,118 +61,118 @@ class _MyFamily extends State with TickerProviderStateMixin { bool expandFlag = false; Widget build(BuildContext context) { - imagesInfo.add(ImagesInfo( - imageEn: - 'https://hmgwebservices.com/Images/MobileApp/images-info-home/family-file/en/0.png', - imageAr: - 'https://hmgwebservices.com/Images/MobileApp/images-info-home/family-file/ar/0.png'), + imagesInfo.add( + ImagesInfo( + imageEn: + 'https://hmgwebservices.com/Images/MobileApp/images-info-home/family-file/en/0.png', + imageAr: + 'https://hmgwebservices.com/Images/MobileApp/images-info-home/family-file/ar/0.png'), ); - imagesInfo.add(ImagesInfo( - 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'), + imagesInfo.add( + ImagesInfo( + 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 = Provider.of(context); - return AppScaffold( - appBarTitle: TranslationBase.of(context).myFamilyFiles, - isShowAppBar: widget.isAppbarVisible, - imagesInfo: imagesInfo, + return AppScaffold( + appBarTitle: TranslationBase.of(context).myFamilyFiles, + isShowAppBar: widget.isAppbarVisible, + // imagesInfo: imagesInfo, description: TranslationBase.of(context).familyInfo, - body: Scaffold( - extendBodyBehindAppBar: true, - appBar: PreferredSize( - preferredSize: Size.fromHeight(65.0), - child: Stack( - children: [ - Positioned( - bottom: 1, - left: 0, - right: 0, - child: BackdropFilter( - filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10), - child: Container( - color: Theme.of(context) - .scaffoldBackgroundColor - .withOpacity(0.8), - height: 70.0, - ), + body: Scaffold( + extendBodyBehindAppBar: true, + appBar: PreferredSize( + preferredSize: Size.fromHeight(65.0), + child: Stack( + children: [ + Positioned( + bottom: 1, + left: 0, + right: 0, + child: BackdropFilter( + filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10), + child: Container( + color: Theme.of(context) + .scaffoldBackgroundColor + .withOpacity(0.8), + height: 70.0, ), ), - Center( - child: Container( - height: 60.0, - margin: EdgeInsets.only(top: 10.0), - width: MediaQuery.of(context).size.width * 0.92, // 0.9, - decoration: BoxDecoration( - border: Border( - bottom: BorderSide( - color: Theme.of(context).dividerColor, - width: 0.9), //width: 0.7 - ), - color: Colors.white), - child: Center( - child: TabBar( - isScrollable: true, - controller: _tabController, - indicatorWeight: 5.0, - //indicatorSize: TabBarIndicatorSize.label, - indicatorSize: TabBarIndicatorSize.tab, - - indicatorColor: Theme.of(context).primaryColor, - labelColor: Theme.of(context).primaryColor, - labelPadding: - EdgeInsets.only(top: 4.0, left: 35.0, right: 35.0), - unselectedLabelColor: Colors.grey[800], - tabs: [ + ), + Center( + child: Container( + height: 60.0, + margin: EdgeInsets.only(top: 10.0), + width: MediaQuery.of(context).size.width * 0.92, // 0.9, + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: Theme.of(context).dividerColor, + width: 0.9), //width: 0.7 + ), + color: Colors.white), + child: Center( + child: TabBar( + isScrollable: true, + controller: _tabController, + indicatorWeight: 5.0, + //indicatorSize: TabBarIndicatorSize.label, + indicatorSize: TabBarIndicatorSize.tab, - Container( - width: MediaQuery.of(context).size.width * 0.30, - child: Center( - child: AppText(TranslationBase.of(context).family), - ), + indicatorColor: Theme.of(context).primaryColor, + labelColor: Theme.of(context).primaryColor, + labelPadding: + EdgeInsets.only(top: 4.0, left: 35.0, right: 35.0), + unselectedLabelColor: Colors.grey[800], + tabs: [ + Container( + width: MediaQuery.of(context).size.width * 0.30, + child: Center( + child: AppText(TranslationBase.of(context).family), ), - Container( - width: MediaQuery.of(context).size.width * 0.30, - child: Center( - child: AppText(TranslationBase.of(context).request), - ), + ), + Container( + width: MediaQuery.of(context).size.width * 0.30, + child: Center( + child: AppText(TranslationBase.of(context).request), ), - ], - ), + ), + ], ), ), ), - ], - ), - ), - body: Column( - children: [ - Expanded( - child: (user != null && projectViewModel.isLogin) ? TabBarView( - physics: BouncingScrollPhysics(), - controller: _tabController, - children: [ - myFamilyDetails(context), - myFamilyRequest(context) - ], - ) : Container(child:AppText('Loading..')), - ) + ), ], ), ), - ); - - - + body: Column( + children: [ + Expanded( + child: (user != null && projectViewModel.isLogin) + ? TabBarView( + physics: BouncingScrollPhysics(), + controller: _tabController, + children: [ + myFamilyDetails(context), + myFamilyRequest(context) + ], + ) + : Container(child: AppText('Loading..')), + ) + ], + ), + ), + ); return AppScaffold( appBarTitle: TranslationBase.of(context).myFamilyFiles, isShowAppBar: widget.isAppbarVisible, body: SingleChildScrollView( child: Container( - height: SizeConfig.screenHeight *.9, + height: SizeConfig.screenHeight * .9, width: SizeConfig.realScreenWidth, padding: EdgeInsets.all(20), child: Stack( @@ -179,11 +181,13 @@ class _MyFamily extends State with TickerProviderStateMixin { controller: _tabController, indicatorColor: Colors.red, tabs: [ - Tab( // padding: EdgeInsets.all(6), - child:AppText(TranslationBase.of(context).family)), Tab( // padding: EdgeInsets.all(6), - child:AppText(TranslationBase.of(context).request)), + child: AppText(TranslationBase.of(context).family)), + Tab( + // padding: EdgeInsets.all(6), + child: + AppText(TranslationBase.of(context).request)), ], ), TabBarView( @@ -317,13 +321,13 @@ class _MyFamily extends State with TickerProviderStateMixin { Widget myFamilyRequest(context) { return //Padding( - // padding: const EdgeInsets.symmetric(horizontal: 10.0), - // child: - SingleChildScrollView( - child: Container( + // padding: const EdgeInsets.symmetric(horizontal: 10.0), + // child: + SingleChildScrollView( + child: Container( height: MediaQuery.of(context).size.height, - margin: EdgeInsets.only(top:65), - child: Column( + margin: EdgeInsets.only(top: 65), + child: Column( children: [ RoundedContainer( child: ExpansionTile( @@ -375,13 +379,21 @@ class _MyFamily extends State with TickerProviderStateMixin { // )), Column(children: [ Padding( - padding: EdgeInsets.only(left:10, right:10), child:Row(children: [ - Expanded(flex: 3, child: AppText('Name')), - Expanded(flex: 1, child: AppText('Allow')), - Expanded(flex: 1, child: AppText('Reject')), - ])), + padding: EdgeInsets.only( + left: 10, right: 10), + child: Row(children: [ + Expanded( + flex: 3, child: AppText('Name')), + Expanded( + flex: 1, child: AppText('Allow')), + Expanded( + flex: 1, + child: AppText('Reject')), + ])), Column( - children:familyFileProvider.allSharedRecordsByStatusResponse.getAllSharedRecordsByStatusList + children: familyFileProvider + .allSharedRecordsByStatusResponse + .getAllSharedRecordsByStatusList .map((result) { return Padding( padding: EdgeInsets.all(10), @@ -400,7 +412,9 @@ class _MyFamily extends State with TickerProviderStateMixin { ), onPressed: () { acceptRemoveRequest( - result.iD, 3, context); + result.iD, + 3, + context); }, )), Expanded( @@ -412,7 +426,9 @@ class _MyFamily extends State with TickerProviderStateMixin { ), onPressed: () { acceptRemoveRequest( - result.iD,4, context); + result.iD, + 4, + context); }, )) ], @@ -462,13 +478,15 @@ class _MyFamily extends State with TickerProviderStateMixin { children: [ Expanded( flex: 3, - child: - Text(result.patientName)), + child: Text( + result.patientName)), Expanded( flex: 2, child: AppText( result.statusDescription, - color: result.status==3 ? Colors.green: Colors.red, + color: result.status == 3 + ? Colors.green + : Colors.red, )), ], )); @@ -487,8 +505,8 @@ class _MyFamily extends State with TickerProviderStateMixin { children: [ FutureBuilder( future: getUserViewRequest(), // async work - builder: - (BuildContext context, AsyncSnapshot snapshot) { + builder: (BuildContext context, + AsyncSnapshot snapshot) { switch (snapshot.connectionState) { case ConnectionState.waiting: return Padding( @@ -502,38 +520,43 @@ class _MyFamily extends State with TickerProviderStateMixin { else return Column( children: [ - // Padding( - // padding:EdgeInsets.only(left:10, right:10), - // child: Row( - // mainAxisAlignment: - // MainAxisAlignment.spaceBetween, - // children: [ - // Expanded( - // flex: 3, - // child: AppText( - // TranslationBase.of(context).request), - // ), - // Expanded( - // flex: 2, - // child: AppText( - // TranslationBase.of(context).switchUser, - // )), - // Expanded( - // flex: 1, - // child: AppText( - // TranslationBase.of(context).deleteView, - // )), - // ], - // )), + // Padding( + // padding:EdgeInsets.only(left:10, right:10), + // child: Row( + // mainAxisAlignment: + // MainAxisAlignment.spaceBetween, + // children: [ + // Expanded( + // flex: 3, + // child: AppText( + // TranslationBase.of(context).request), + // ), + // Expanded( + // flex: 2, + // child: AppText( + // TranslationBase.of(context).switchUser, + // )), + // Expanded( + // flex: 1, + // child: AppText( + // TranslationBase.of(context).deleteView, + // )), + // ], + // )), Column(children: [ - Padding( - padding:EdgeInsets.only(left:10, right:10), - child: Row(children: [ - Expanded(flex: 3, child: AppText('Name')), - Expanded(flex: 1, child: AppText('Delete')), - ])), + Padding( + padding: + EdgeInsets.only(left: 10, right: 10), + child: Row(children: [ + Expanded( + flex: 3, child: AppText('Name')), + Expanded( + flex: 1, child: AppText('Delete')), + ])), Column( - children: familyFileProvider.allSharedRecordsByStatusResponse.getAllSharedRecordsByStatusList + children: familyFileProvider + .allSharedRecordsByStatusResponse + .getAllSharedRecordsByStatusList .map((result) { return Padding( padding: EdgeInsets.all(10), @@ -541,7 +564,8 @@ class _MyFamily extends State with TickerProviderStateMixin { children: [ Expanded( flex: 3, - child: AppText(result.patientName)), + child: AppText( + result.patientName)), Expanded( flex: 1, child: IconButton( @@ -550,8 +574,8 @@ class _MyFamily extends State with TickerProviderStateMixin { color: Colors.black, ), onPressed: () { - deactivateRequest(result.iD, - 5, context); + deactivateRequest( + result.iD, 5, context); }, )), ], @@ -625,17 +649,17 @@ class _MyFamily extends State with TickerProviderStateMixin { } switchUser(user, context) { - GifLoaderDialogUtils.showMyDialog(context); + GifLoaderDialogUtils.showMyDialog(context); // this // .familyFileProvider // .silentLoggin(user) // .then((value) => loginAfter(value, context)); - // Utils.showProgressDialog(context); + // Utils.showProgressDialog(context); this .familyFileProvider .silentLoggin(user is AuthenticatedUser ? null : user, - mainUser: user is AuthenticatedUser) + mainUser: user is AuthenticatedUser) .then((value) => loginAfter(value, context)) .catchError((err) { print(err); @@ -644,26 +668,26 @@ class _MyFamily extends State with TickerProviderStateMixin { }); } - loginAfter(result, context) async{ + loginAfter(result, context) async { GifLoaderDialogUtils.hideDialog(context); - // var familyFile = await sharedPref.getObject(FAMILY_FILE); - // var mainUser = await sharedPref.getObject(MAIN_USER); - // result = CheckActivationCode.fromJson(result); - // this.sharedPref.clear(); - // this.sharedPref.setObject(FAMILY_FILE, familyFile); - // this.sharedPref.setObject(MAIN_USER, mainUser); - // result.list.isFamily = true; - // this.sharedPref.setObject(USER_PROFILE, result.list); - // this.sharedPref.setObject(LOGIN_TOKEN_ID, result.logInTokenID); - // this.sharedPref.setString(TOKEN, result.authenticationTokenID); - // - // authenticatedUserObject.isLogin = true; - // appointmentRateViewModel.isLogin = true; - // projectViewModel.isLogin = true; - // //this.checkIfUserAgreedBefore(result), - // Navigator.of(context).pushNamed( - // HOME, - // ); + // var familyFile = await sharedPref.getObject(FAMILY_FILE); + // var mainUser = await sharedPref.getObject(MAIN_USER); + // result = CheckActivationCode.fromJson(result); + // this.sharedPref.clear(); + // this.sharedPref.setObject(FAMILY_FILE, familyFile); + // this.sharedPref.setObject(MAIN_USER, mainUser); + // result.list.isFamily = true; + // this.sharedPref.setObject(USER_PROFILE, result.list); + // this.sharedPref.setObject(LOGIN_TOKEN_ID, result.logInTokenID); + // this.sharedPref.setString(TOKEN, result.authenticationTokenID); + // + // authenticatedUserObject.isLogin = true; + // appointmentRateViewModel.isLogin = true; + // projectViewModel.isLogin = true; + // //this.checkIfUserAgreedBefore(result), + // Navigator.of(context).pushNamed( + // HOME, + // ); result = list.CheckActivationCode.fromJson(result); var familyFile = await sharedPref.getObject(FAMILY_FILE); var mainUser = await sharedPref.getObject(MAIN_USER); @@ -687,32 +711,30 @@ class _MyFamily extends State with TickerProviderStateMixin { Map request = {}; request["ID"] = ID; request["Status"] = status; - this.familyFileProvider.deactivateFamily(request).then((value) => { - GifLoaderDialogUtils.hideDialog(context), - refreshFamily(context) - }); + this.familyFileProvider.deactivateFamily(request).then((value) => + {GifLoaderDialogUtils.hideDialog(context), refreshFamily(context)}); } + acceptRemoveRequest(ID, status, context) { GifLoaderDialogUtils.showMyDialog(context); Map request = {}; request["ID"] = ID; request["Status"] = status; - this.familyFileProvider.acceptRejectFamily(request).then((value) => { - GifLoaderDialogUtils.hideDialog(context), - refreshFamily(context) - }); + this.familyFileProvider.acceptRejectFamily(request).then((value) => + {GifLoaderDialogUtils.hideDialog(context), refreshFamily(context)}); } - checkUserData() async{ + + checkUserData() async { if (await this.sharedPref.getObject(USER_PROFILE) != null) { - var data = AuthenticatedUser.fromJson( - await this.sharedPref.getObject(USER_PROFILE)); + var data = AuthenticatedUser.fromJson( + await this.sharedPref.getObject(USER_PROFILE)); - var data2 = AuthenticatedUser.fromJson( - await this.sharedPref.getObject(MAIN_USER)); - print(data2); - setState(() { - this.user = data; - }); + var data2 = AuthenticatedUser.fromJson( + await this.sharedPref.getObject(MAIN_USER)); + print(data2); + setState(() { + this.user = data; + }); } } } diff --git a/lib/widgets/others/floating_button_search.dart b/lib/widgets/others/floating_button_search.dart index e8900040..b6f7e89d 100644 --- a/lib/widgets/others/floating_button_search.dart +++ b/lib/widgets/others/floating_button_search.dart @@ -107,7 +107,6 @@ class _FloatingSearchButton extends State // }); Future.delayed(const Duration(seconds: 2), () { - requestPermissions(); getUserData(); @@ -119,9 +118,8 @@ class _FloatingSearchButton extends State @override Widget build(BuildContext context) { projectProvider = Provider.of(context); - return Container(child: - isShow ? getStack() - : Stack(children: [Container()])); + return Container( + child: isShow ? getStack() : Stack(children: [Container()])); } Widget getStack() { @@ -134,7 +132,7 @@ class _FloatingSearchButton extends State // mainAxisSize: MainAxisSize.min, // crossAxisAlignment: CrossAxisAlignment.stretch, // children: [ - GestureDetector( + GestureDetector( child: Container( child: Image.asset('assets/images/gif/robot-idle.gif'), ), @@ -151,7 +149,7 @@ class _FloatingSearchButton extends State onTap: () { setState(() { if (this.mounted) { - isShow =false; + isShow = false; } }); }, @@ -780,14 +778,14 @@ class _FloatingSearchButton extends State speak() async { var voice = await flutterTts.getVoices; + await flutterTts.setVoice({"name": "es-us-x-sfb-local", "locale": "es-US"}); print(voice); if (_currentLocaleId == 'en' && results['ReturnMessage'] != null) { - await flutterTts.setVoice("en-us-x-sfg#male_1-local" ); - await flutterTts.setLanguage("en-US"); + //await flutterTts.setLanguage("en-US"); await flutterTts.speak(results['ReturnMessage']); } else if (results['ReturnMessage_Ar'] != null) { await flutterTts.setLanguage("ar-SA"); - await flutterTts.setVoice("ar-xa-x-arc-local"); + // await flutterTts.setVoice("ar-xa-x-arc-local"); await flutterTts.speak(results['ReturnMessage_Ar']); } // Future.delayed(const Duration(seconds: 10), () { @@ -815,6 +813,6 @@ class _FloatingSearchButton extends State user = AuthenticatedUser.fromJson( await this.sharedPref.getObject(USER_PROFILE)); } - await flutterTts.setVoice("en-us-x-sfg#male_1-local" ); + //await flutterTts.setVoice("en-us-x-sfg#male_1-local"); } } From 4669252d1f98554d2f3000bb2711ce53cb87a91c Mon Sep 17 00:00:00 2001 From: Sultan Khan Date: Fri, 4 Dec 2020 12:13:01 +0300 Subject: [PATCH 13/71] flutter tts --- pubspec.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index f375d63d..ae514553 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -151,7 +151,8 @@ dependencies: wakelock: ^0.1.4 after_layout: ^1.0.7 twilio_programmable_video: ^0.5.0+3 - flutter_tts: ^1.3.0 + flutter_tts: + path: flutter_tts-voice_enhancement vibration: ^1.7.2 speech_to_text: path: speech_to_text From 92b0b6d6ea31e1afa4e14c5883fd99c6902719ba Mon Sep 17 00:00:00 2001 From: Sultan Khan Date: Sun, 6 Dec 2020 08:29:05 +0300 Subject: [PATCH 14/71] Merge branch 'master' of https://gitlab.com/Cloud_Solution/diplomatic-quarter into sultan-patientapp # Conflicts: # lib/uitl/translations_delegate_base.dart --- lib/widgets/others/floating_button_search.dart | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/widgets/others/floating_button_search.dart b/lib/widgets/others/floating_button_search.dart index b6f7e89d..dc987e99 100644 --- a/lib/widgets/others/floating_button_search.dart +++ b/lib/widgets/others/floating_button_search.dart @@ -777,15 +777,12 @@ class _FloatingSearchButton extends State } speak() async { - var voice = await flutterTts.getVoices; - await flutterTts.setVoice({"name": "es-us-x-sfb-local", "locale": "es-US"}); - print(voice); + // var voice = await flutterTts.getVoices; if (_currentLocaleId == 'en' && results['ReturnMessage'] != null) { - //await flutterTts.setLanguage("en-US"); + await flutterTts.setVoice({"name":"en-au-x-aub-network", "locale":"en-AU"}); await flutterTts.speak(results['ReturnMessage']); } else if (results['ReturnMessage_Ar'] != null) { - await flutterTts.setLanguage("ar-SA"); - // await flutterTts.setVoice("ar-xa-x-arc-local"); + await flutterTts.setVoice({"name":"ar-xa-x-ard-network", "locale":"ar"}); await flutterTts.speak(results['ReturnMessage_Ar']); } // Future.delayed(const Duration(seconds: 10), () { From 83ac5b7031518f58824d7d0d083036ee8a9b0dc0 Mon Sep 17 00:00:00 2001 From: Sultan Khan Date: Mon, 7 Dec 2020 09:06:34 +0300 Subject: [PATCH 15/71] voice command updated --- assets/app_icons/d_q_icons_icons.dart | 43 +++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 assets/app_icons/d_q_icons_icons.dart diff --git a/assets/app_icons/d_q_icons_icons.dart b/assets/app_icons/d_q_icons_icons.dart new file mode 100644 index 00000000..5d1ff3c6 --- /dev/null +++ b/assets/app_icons/d_q_icons_icons.dart @@ -0,0 +1,43 @@ +/// Flutter icons DQIcons +/// Copyright (C) 2020 by original authors @ fluttericon.com, fontello.com +/// This font was generated by FlutterIcon.com, which is derived from Fontello. +/// +/// To use this font, place it in your fonts/ directory and include the +/// following in your pubspec.yaml +/// +/// flutter: +/// fonts: +/// - family: DQIcons +/// fonts: +/// - asset: fonts/DQIcons.ttf +/// +/// +/// +import 'package:flutter/widgets.dart'; + +class DQIcons { + DQIcons._(); + + static const _kFontFam = 'DQIcons'; + static const _kFontPkg = null; + + static const IconData blood_pressure = IconData(0xe800, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData blood = IconData(0xe801, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData bmi = IconData(0xe802, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData heart = IconData(0xe803, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData height = IconData(0xe804, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData outline = IconData(0xe805, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData thermometer = IconData(0xe806, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData weight_scale = IconData(0xe807, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData parking_icon = IconData(0xe808, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData blood_type_icon = IconData(0xe809, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData height_icon = IconData(0xe80a, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData online_payment_icon = IconData(0xe80b, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData search_medicine_icon = IconData(0xe80c, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData vital_sign_icon = IconData(0xe80d, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData weight_icon = IconData(0xe80e, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData my_medical_file = IconData(0xe80f, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData family = IconData(0xe810, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData calendar__2_ = IconData(0xe811, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData roboticon = IconData(0xe812, fontFamily: _kFontFam, fontPackage: _kFontPkg); +} From 496163a61ae63c6e7ba59f43745382b3bac71999 Mon Sep 17 00:00:00 2001 From: Sultan Khan Date: Mon, 7 Dec 2020 09:06:56 +0300 Subject: [PATCH 16/71] voice command updated --- assets/app_icons/config.json | 14 ++++ assets/app_icons/d_q_icons_icons.dart | 43 ----------- assets/app_icons/fonts/DQIcons.ttf | Bin 15048 -> 28064 bytes lib/config/localized_values.dart | 6 +- lib/d_q_icons_icons.dart | 1 + .../all_habib_medical_service_page.dart | 1 + lib/uitl/translations_delegate_base.dart | 1 + .../bottom_navigation/bottom_nav_bar.dart | 69 ++++++++++-------- lib/widgets/others/app_scaffold_widget.dart | 67 +++++++++++++++-- lib/widgets/others/bottom_bar.dart | 2 +- .../others/floating_button_search.dart | 48 ++++++------ .../weather_slider/weather_slider.dart | 26 +++++-- pubspec.yaml | 2 +- 13 files changed, 167 insertions(+), 113 deletions(-) delete mode 100644 assets/app_icons/d_q_icons_icons.dart diff --git a/assets/app_icons/config.json b/assets/app_icons/config.json index 0bedcb06..e2e1afdb 100644 --- a/assets/app_icons/config.json +++ b/assets/app_icons/config.json @@ -257,6 +257,20 @@ "search": [ "calendar-(2)" ] + }, + { + "uid": "ad42aa33b55d1a7b2edcf4ed976435d9", + "css": "roboticon", + "code": 59410, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M546.9 33.2C546.1 35.3 544.8 37.2 544.1 37.7 542.9 38.3 542.9 38.9 543.8 40.6 544.5 42.2 546.7 43.5 550.4 44.7L555.8 46.6 557.5 44.4C560.3 40.7 562.1 36.4 561.5 34.8 561.2 34 559.3 32.9 557.3 32.3 555.4 31.7 553.7 30.8 553.7 30.4 553.7 30 552.5 29.6 551 29.6 548.8 29.6 548.1 30.2 546.9 33.2ZM453.8 33.9C452.7 35.3 451.9 37.6 451.9 39 451.9 41 451.4 41.7 450 41.7 447.2 41.7 447.8 43.1 452 46.8 458.9 52.5 461.7 52.1 464.4 45 466.7 39.1 466 36.9 461.7 35.6 459.7 35.1 457.6 33.9 456.9 33.1 455.8 31.5 455.6 31.6 453.8 33.9ZM500.2 34.4C499.4 36 498 38.1 497.1 39 495.6 40.5 495.7 40.7 499 43.8 503.9 48.7 506.6 49 509.6 45.2 510.9 43.5 512.8 41.4 513.6 40.6 515 39 514.9 38.7 511.2 35.2 506.2 30.4 502.5 30.1 500.2 34.4ZM523.1 36L518.8 40.5 523.3 45.2C525.7 47.8 527.8 50.6 527.8 51.7 527.8 52.7 525.9 55.6 523.6 58.1L519.4 62.9 523 66.6C528 71.9 530.9 71.8 536.2 66 539.9 62 540 61.7 538.4 60.7 534.1 58.3 531.5 54.8 531.5 51.5 531.5 47.3 535.7 38.9 537.9 38.9 538.9 38.9 538.1 37.7 535.5 35.2 530.3 30.3 528.3 30.5 523.1 36ZM477.4 34.4C476.7 35.6 475.4 38.2 474.5 40.3 473 43.8 473.1 44 475 45.6 476.1 46.5 477.9 47.2 478.8 47.2 479.7 47.2 481 48.1 481.7 49.1 482.3 50.1 483.1 50.9 483.6 50.9 484.8 50.9 488 45 488 42.8 488 41.3 488.5 40.7 490 40.7 491.9 40.7 491.9 40.6 489.3 37.9 486.3 34.8 482.4 32.4 480.2 32.4 479.4 32.4 478.1 33.3 477.4 34.4ZM568.7 36.6L566.8 39.7 569.5 42C575.1 46.8 581.6 46.9 583.2 42.3 585.6 36 585.8 36.4 578.8 34.8 570.4 32.9 570.8 32.8 568.7 36.6ZM428.6 38C428 40.2 426.8 41.9 425.6 42.2 424.1 42.7 424.2 43.1 426.9 46 433.4 52.7 436.5 52.8 439.8 46.2 440.8 44.3 442.3 42.6 443.1 42.6 446.6 42.6 442.2 37.5 437.9 36.6 436.4 36.2 435 35.6 434.7 35.1 434.4 34.6 433.1 34.3 431.9 34.3 430.1 34.3 429.4 35 428.6 38ZM408.4 38.8C404 40.2 403.2 40.7 402.5 43.4 401.4 47.9 402 48.8 407.7 50.6 413.7 52.4 415.6 51.9 416.4 48.1 416.7 46.6 417.9 44.5 419.1 43.6L421.3 41.9 419.4 39.4C417.2 36.7 415.5 36.6 408.4 38.8ZM619.7 52C617 54.9 615.3 61.8 616.8 63.5 617.3 64.3 618.3 64.8 618.9 64.8 619.5 64.8 621.5 65.6 623.4 66.6 626.8 68.2 626.9 68.2 629.1 66.6 631.3 64.8 633.9 57.2 632.9 55.6 632.3 54.7 623.1 50 622 50 621.9 50 620.7 50.9 619.7 52ZM572.2 54.3C571.7 55.6 571.3 56.9 571.3 57.3 571.3 57.8 570.5 59.2 569.4 60.5 567.6 62.8 567.6 62.8 569.5 65.2 571.6 67.8 577 69.8 580.6 69.3 582.4 69.1 583.1 68.1 584.5 64 585.5 61.3 585.9 58.2 585.6 57.2 585 55.3 581.2 53.4 576.1 52.5 573.5 51.9 573 52.2 572.2 54.3ZM595.2 53.4C594.4 54.4 593.2 56.9 592.8 59.1 591.6 64.3 593.2 66.4 599.4 67.5 605.4 68.6 606.3 68.1 607 64.1 607.4 62.1 608.1 59.9 608.5 58.9 610.9 54.4 598.8 49.4 595.2 53.4ZM548.7 54.7C547.9 55.9 547.2 57.4 547.2 58 547.2 58.5 546.6 59.5 545.8 60.2 545.1 60.8 544.4 62.3 544.4 63.6 544.4 65.5 545.3 66.2 549.1 67.8 551.7 68.8 553.7 70.1 553.7 70.5 553.7 72 556.2 71.3 558.1 69.2 560.4 66.8 562.5 60 561.7 57.9 561.1 56.4 557.2 54.4 552.6 53.2 550.7 52.8 549.9 53.1 548.7 54.7ZM480 55.4C479.4 55.7 477.8 58.1 476.4 60.8 473.3 66.3 473.7 67.3 479.7 70.5 485.6 73.3 487.9 72.7 489.4 67.6 489.7 66.3 490.6 64.5 491.5 63.6 493.2 61.7 492.5 60.8 487.7 59.3 485.7 58.7 483.7 57.4 483.1 56.4 481.9 54.4 481.5 54.4 480 55.4ZM500.1 57C499 58.4 497.9 60.6 497.6 61.8 496.5 65.8 502.6 72 506.6 70.8 509 70 515.7 64.1 515.7 62.6 515.7 61.3 507.7 55.8 504.5 55.1 502.6 54.6 501.7 55 500.1 57ZM429.7 59.8C427.7 62.3 426.5 67.1 427 70 427.7 73.6 438.2 76.1 439.8 73.1 444.9 63.8 444.7 62 438.5 59.2 433.4 56.9 431.9 56.9 429.7 59.8ZM453.2 59.5C452.5 60.7 451.6 63.6 451.3 65.8 450.7 70 450.8 70.1 453.8 71.3 455.6 71.9 457.7 73.1 458.5 73.9 460.7 75.8 462.9 74.6 464.4 70.6 465.2 68.7 466.3 66.2 466.9 65.1 468.2 62.4 465.9 59.6 461.2 58.3 456.2 56.9 454.8 57.2 453.2 59.5ZM407.2 59.9C405 62.5 401.8 69.4 402.3 70.4 402.6 70.8 404.4 71.5 406.3 71.9 408.1 72.1 410.8 73.2 412.2 74.2L414.8 75.9 417.1 71.3C418.4 68.8 419.4 65.7 419.4 64.4 419.4 59.5 410.5 56.3 407.2 59.9ZM382.4 60.6C380.8 62.5 378.7 70.2 379.3 71.8 379.5 72.5 381.3 73.5 383.1 74.2 385.1 74.7 386.9 75.6 387.5 76 390.3 78.7 394.8 74.6 395.8 68.4 396.7 63.6 394.9 61.6 388.8 60.3 383.1 59.1 383.8 59 382.4 60.6ZM358.9 61.9C357.3 63.7 355.6 68.7 355.6 71.5 355.6 73.8 358 75.7 362.1 76.9 367.1 78.2 369 77.4 370.7 73.1 373.4 66.5 372.9 65.1 367 62.5 360.7 59.7 360.8 59.7 358.9 61.9ZM339.3 65.2C332 69 331 70.1 332 72.9 333.1 75.8 336 77.5 341.2 78 344.4 78.2 345 78 346 75.9 346.7 74.6 347.4 71.9 347.8 69.7 348.3 66.2 348.1 65.8 345.7 64.5 343.2 63.2 342.8 63.3 339.3 65.2ZM645.2 73.8C644.4 74.7 643 77.7 642 80.4 640.4 85.3 640.4 85.4 642.1 86.7 643.1 87.4 644.5 88 645.5 88 646.3 88 647.5 88.6 648.1 89.4 650.7 92.5 655.6 89 657 83.1 657.6 80.8 657 79.9 653.3 76.3 648.6 71.9 647.3 71.4 645.2 73.8ZM666.4 77.7C663.8 85 664.4 87 669.5 87 670.5 87 672.1 87.9 673.2 89 675.5 91.2 677.2 90.3 678.2 86.3 678.6 84.9 679.4 83.1 680.2 82.3 681.4 81 681 80.5 676.6 77.6 668.8 72.4 668.2 72.4 666.4 77.7ZM622.2 75C621.4 75.5 619.7 78 618.5 80.6L616.3 85.4 618.8 87.6C621.2 89.6 623.3 90.3 626.9 89.9 628.5 89.7 635.2 82.7 635.2 81.1 635.1 80 626.1 74.1 624.5 74.1 624.1 74.1 623 74.5 622.2 75ZM597.8 76.4C595.7 78.5 592.6 85.9 593.1 87.5 593.7 88.8 599.9 91.7 602.2 91.7 604.1 91.7 608.5 87.8 610.4 84.4L611.9 81.8 607 78.3C601.7 74.6 599.9 74.3 597.8 76.4ZM550.1 78.3C547.8 81.3 545.8 87.3 546.6 89.3 547.2 90.9 556.7 94 558.7 93.2 559.5 92.9 560.2 91.9 560.2 90.9 560.2 90 561.2 87.9 562.5 86.1 563.8 84.4 564.8 82.9 564.8 82.7 564.8 82.5 562.9 81.5 560.5 80.5 558 79.4 555.6 78 555.3 77.2 554.2 75.3 552.2 75.6 550.1 78.3ZM574.4 77C573 78.8 569.4 86.6 569.4 87.7 569.4 89.4 575.5 92.6 578.4 92.6 581.4 92.6 584.1 90.3 586.4 85.6L587.9 82.7 583.4 79.4C578.8 75.8 575.8 75.1 574.4 77ZM525.5 79.3C524.7 80 523.9 81.7 523.6 83 523.3 84.2 523 86.1 522.7 87.3 522.1 90.1 523.1 91.2 526.4 92 528 92.4 529.9 93.3 530.7 94.2 534.2 97.2 538.9 91.9 538.9 84.7 538.9 81.9 538.5 81.2 535.9 80.2 530.6 78.1 527 77.7 525.5 79.3ZM501.7 80.3C499.5 82.6 498.1 89.7 499.2 91.9 499.6 92.7 502.1 94.1 504.7 94.8 509.4 96.2 512 96 512 94.2 512 93.6 512.9 91.4 514 89.2 516.2 84.5 515.9 83.1 512.3 81.1 507.6 78.7 503.3 78.3 501.7 80.3ZM478.5 80.6C476.9 81.6 475 86.9 475 90.6 475 91.9 475.8 93 477.6 93.6 479 94.2 481.4 95.2 482.9 95.9 484.4 96.7 486.4 97 487.2 96.8 489.4 95.9 491.7 90.6 491.7 86.7 491.7 84 491.2 83.1 489.2 82.1 485.5 80.3 480.4 79.5 478.5 80.6ZM455.1 82.1C454.4 82.9 453.7 84.4 453.7 85.6 453.7 86.8 453.1 88.2 452.3 88.9 448.9 91.8 451.7 95.6 458.5 97.3 462.4 98.4 463.1 98.3 464.7 96.9 466.9 94.8 468.7 87.3 467.5 85.1 466.8 83.6 463.9 82.4 458.5 81.2 457.3 80.9 455.8 81.3 455.1 82.1ZM430.8 82.6C429.4 84.4 427.8 89.7 427.8 92.3 427.8 93.6 428.4 94.7 429.4 95.1 430.3 95.4 432.8 96.4 434.9 97.4 437 98.4 439.4 98.9 439.9 98.6 441.5 97.6 444.4 90.6 444.4 87.7 444.4 85.6 443.8 84.8 441.5 83.8 436.4 81.8 431.9 81.2 430.8 82.6ZM407.6 83.5C406.9 84.2 406.5 85.4 406.5 86.3 406.5 87.3 405.5 89.1 404.2 90.4 401.9 92.6 401.9 92.7 403.7 94.4 404.7 95.5 406.1 96.3 406.9 96.3 407.5 96.3 409.2 97.1 410.5 98.1 413.1 100.3 416 100.6 417.5 98.7 419 96.9 421.5 88.1 420.8 87 420.4 86.3 410.9 82.4 409.4 82.4 409 82.4 408.2 82.9 407.6 83.5ZM386.6 84.3C385.6 84.6 383.3 86.8 381.6 88.9L378.5 92.8 382.4 96.8C387.1 101.6 389.1 102.2 392 99.9 394.6 97.9 397.5 91.2 396.8 88.9 395.7 85.6 389.7 83 386.6 84.3ZM360.3 86.7C359.2 88.1 357.9 90.8 357.2 92.9 356.2 96.1 356.3 96.7 357.9 97.8 358.8 98.5 360.6 99.1 361.7 99.1 362.9 99.1 364.4 99.9 365.1 100.9 366.3 102.7 366.4 102.7 368.9 100.1 370.3 98.7 371.3 97.1 371.2 96.7 370.8 94.6 371.4 93.5 372.7 93.5 375.6 93.5 373 89.2 368.1 86.2 364.1 83.6 362.6 83.8 360.3 86.7ZM336.9 85.9C334.5 86.4 332.9 91.8 333.2 97.5 333.3 99.5 338.5 101.9 343 101.9 345.8 101.9 346.3 101.5 347.2 98.3 347.9 96.5 348.7 94.5 349.2 94 350.6 92.5 350.1 89.9 348 88.5 345.5 86.9 339.1 85.4 336.9 85.9ZM311.6 88.2C310.8 89.4 309.9 92.3 309.6 94.7 309 99.4 308.7 99.2 317 101.9 320.6 103 320.8 102.9 322.8 100.6 325.8 97.1 326.6 92.1 324.5 89.8 322.9 88.1 317.8 86.1 314.6 86.1 313.7 86.1 312.4 87 311.6 88.2ZM671.6 95.5C670.5 95.8 668.5 98.4 666.9 101.8L664.3 107.3 668.1 110.2C670.3 111.7 673.1 113 674.4 113 676.9 113 680.8 109 681.9 105.5 683.6 100.3 676.7 93.5 671.6 95.5ZM691.9 96.5C690.8 97.8 688.9 104.3 688.9 106.5 688.9 107.4 691.2 109 694.5 110.6 699.8 113 700.3 113.1 701.9 111.6 702.8 110.7 704.2 108.1 705 105.7L706.5 101.4 703 98.4C699.3 95.2 693.7 94.3 691.9 96.5ZM647.5 98.9C645.9 99.7 643.5 101.8 642.2 103.3L639.8 106.3 644.4 110.6C646.9 112.9 649.5 114.8 650.3 114.8 652.8 114.8 658.3 106.7 658.3 103.1 658.2 101.3 655.5 98.8 652.3 97.8 651.2 97.5 649.2 97.9 647.5 98.9ZM596.4 103.2C592.5 109.6 593.1 112 599 113.8 601.1 114.4 603.1 115.5 603.3 116.2 604.3 118.5 606.7 116.5 608.9 111.4 611.9 104.6 611.8 102.9 608.4 102.2 606.9 101.9 604.9 100.8 604.1 99.9 601.5 97 599.6 97.9 596.4 103.2ZM622.4 99.3C621.9 99.9 620.5 102.4 619.2 104.8 617 108.8 616.9 109.3 618.4 110.5 623.5 115 628.6 115.1 633 110.7 634.7 109 636.1 106.9 636.1 106.2 636.1 105.4 634.4 103.2 632.2 101.5 628.2 98.1 624.2 97.1 622.4 99.3ZM574.6 101.1C571.9 105.4 570.1 110.1 570.6 111.5 571 112.3 573.1 113.8 575.5 114.8 578.6 116.2 579.6 117.1 579.6 118.7 579.6 120.5 579.8 120.6 580.9 119.4 582.8 117.5 588 107.6 588 106 588 105.3 586.6 104.1 585 103.4 583.3 102.7 581.4 101.5 580.6 100.6 578.9 98.4 576.2 98.7 574.6 101.1ZM549.3 103C546.1 108.9 546.2 114.8 549.4 114.8 550 114.8 552 115.6 553.9 116.5 558.7 119 560.7 117.9 562.5 111.6 564.4 105.4 564 104.1 559.7 102.3 554.8 100.2 550.6 100.6 549.3 103ZM502.9 104.3C500.2 107.7 498.6 113.6 500.1 115.4 500.6 116.1 501.7 116.7 502.2 116.7 502.9 116.7 504.9 117.5 506.9 118.5L510.6 120.4 512.6 118.4C516.6 114.7 517.1 105.6 513.5 105.6 512.9 105.6 510.8 104.7 508.8 103.7 506.8 102.7 505.1 101.9 505 101.9 504.8 101.9 503.9 103 502.9 104.3ZM525.9 105.3C525.3 107.2 524.2 109.5 523.4 110.4 520.6 113.5 526.8 118.5 533.2 118.5 535.6 118.5 536.4 118 537.1 115.9 537.7 114.5 538.7 112.1 539.4 110.6 540.9 106.9 539.9 105.3 535 103.2 529.2 100.9 527.1 101.3 525.9 105.3ZM480.3 103.8C478.1 105.1 475.9 110.2 475.9 113.8 475.9 117.3 478.6 119.2 484.4 120L488.7 120.6 490.3 115.8C491.1 113.2 492.2 110.9 492.7 110.6 494 109.7 491.9 106.6 488.6 104.6 485.3 102.6 482.8 102.3 480.3 103.8ZM408.3 108.4C404.9 113.2 404.4 114.9 405.5 117.8 406.7 120.9 414 124.5 416.5 123.2 418.4 122.2 421.3 116.9 421.3 114.3 421.3 112.6 413.6 104.6 412 104.6 411.6 104.6 409.9 106.3 408.3 108.4ZM433.1 107.4C431.8 108.9 430.2 111.7 429.5 113.6 428.5 116.8 428.6 117.1 430.6 118.7 431.7 119.6 433.4 120.4 434.4 120.4 435.4 120.4 436.4 121 436.7 121.8 438 125.1 442.6 121.5 442.6 117.2 442.6 115.5 443.1 114.5 444.4 114.2 445.5 113.9 446.3 113.3 446.3 113 446.3 111.8 438.1 104.6 436.7 104.6 435.9 104.6 434.4 105.8 433.1 107.4ZM455.7 106.2C455.3 107.1 454.6 109 454.3 110.4 453.9 111.9 453 113 451.6 113.1L449.5 113.4 451.9 115.7C456.3 119.8 461.2 122.4 463.6 121.8 466.2 121.1 468.2 117 468.7 111.6L469 108.1 463.4 106.3C456.6 104.3 456.8 104.3 455.7 106.2ZM363.6 107.5C362.8 108.1 361 110.5 359.7 113 358.4 115.5 357 117.7 356.5 118.1 355.9 118.3 357.7 120.1 360.2 121.9 366.6 126.2 369.1 125.9 371.9 120.4 373.1 118.1 374.1 115.3 374.1 114.2 374.1 111.9 371.7 110.2 368.5 110.2 367.5 110.2 366.3 109.4 365.9 108.4 365.5 107 364.9 106.9 363.6 107.5ZM384.2 109.8C383.6 111.3 382.5 113.9 381.7 115.5 380.4 118.2 380.4 118.6 381.9 120.3 384.2 122.8 388.1 124.3 391.8 123.9 395.3 123.6 397 120.9 397.9 114.8 398.3 111.8 398.1 111.1 395.9 109.7 394.6 108.8 391.7 107.9 389.4 107.6 385.6 107.2 385.2 107.3 384.2 109.8ZM313.7 110.8C311.7 113.1 310.2 117.1 310.2 120.5 310.2 122.6 310.7 123.4 312.8 124.1 314.2 124.5 316.5 125.6 318.1 126.5 320.7 127.9 320.8 127.9 323.2 125.2 324.6 123.6 326 120.6 326.4 118.6 327.3 113.2 325.6 111.5 318 109.8 315.9 109.4 314.8 109.6 313.7 110.8ZM336.1 112.2C335.1 113.9 334.3 116.9 334.3 118.8 334.3 122 334.5 122.4 338.2 124.1 344.7 127 346 126.7 348.7 120.6 350.2 117.3 350.7 114.8 350.3 114 349.5 112.8 341.3 109.3 339.1 109.3 338.4 109.3 337.1 110.6 336.1 112.2ZM291 111.3C288.7 112.4 286.9 116.2 286.8 120.6 286.6 123.4 286.9 123.8 291.7 126 295.2 127.7 297.2 128.2 298.3 127.7 299.9 126.9 303.9 115.9 303.1 114.6 302.4 113.5 295.6 110.2 294.3 110.3 293.6 110.3 292.1 110.7 291 111.3ZM268 117.7L262.5 123.3 266.1 126.5C268.1 128.2 270.2 129.6 270.6 129.6 271.1 129.6 273.1 128 275.2 125.9 279.3 121.9 279.3 120.6 275.5 115.1L273.5 112.1 268 117.7ZM718.3 118.1C717.4 119.3 716.7 120.6 716.7 121 716.7 121.5 715.8 122.8 714.8 123.9 711.4 127.5 714.1 132.3 720.4 134.1 723.1 134.8 721.8 135 713.2 135.1L702.8 135.2 704.7 131.6C705.7 129.6 706.7 126.8 706.8 125.4 706.9 123.1 706.5 122.6 702.1 121 698 119.5 697 119.4 694.7 120.6 693.3 121.2 691.4 123.3 690.5 125.3 688.9 128.4 688.9 129 690.1 130.9 690.8 132 692.9 133.4 694.6 134 697.2 134.8 696.3 135 688.2 135.1L678.7 135.2 680.6 132.1C683.1 128.1 682.9 126.9 679.5 122.9 675.5 118 672.2 118.1 669.1 123.5 667.8 125.7 666 127.8 665.2 128.1 664.3 128.5 661.6 127.3 658.1 125 651.6 120.6 648 120.4 645.3 124.1 642.8 127.6 642.2 131.9 644 133.7 645.4 135.1 645 135.2 639.4 135.2 636.1 135.2 633.3 134.9 633.3 134.6 633.3 133.6 635.5 130.1 636.5 129.4 638.1 128.4 632.5 123.2 628.5 122 623.6 120.6 620.9 122.5 619.4 128.6 618.9 131.2 618.6 133.7 619 134.3 619.4 134.8 617.8 135.2 614.5 135.2L609.4 135.2 610.4 132C611.7 127.9 610.9 126.3 606.9 124.6 605.2 123.9 603.7 122.8 603.7 122.3 603.7 120.2 600.7 121.5 599.3 124.2 598.4 125.7 596.8 128.4 595.6 130.2 593.8 133.1 593.7 133.3 595.2 134.2 596.4 134.9 595.6 135.1 591.8 135.2 587.6 135.2 586.9 135 588 133.9 590 131.4 588.7 128.3 584.6 126.4 582.5 125.4 580.2 124 579.4 123.4 577.2 121.5 572.7 126.9 572.7 131.5L572.7 135.2 567.9 135.2C564 135.2 563.1 134.9 563.5 133.8 563.9 133.1 564.4 132.4 564.8 132.4 566.2 132.4 564.5 128.6 562.6 127.3 561.6 126.6 558.8 125.6 556.7 125.1 551.7 124 549.6 125.6 548.6 131.4L548 135.2 543.4 135.2C539.1 135.2 538.9 135.1 539.8 133.2 541.1 130.9 539.4 128.7 534.7 126.5 530.4 124.4 529.9 124.5 527.3 128.7 526 130.8 524.3 132.8 523.4 133.1 521.9 133.7 512.7 129.4 509.5 126.6 507.8 125 507.2 124.9 505.9 126 505.1 126.7 503.6 129.1 502.7 131.2 501 135.1 500.9 135.2 496.4 135.2 492.4 135.2 491.9 135 492.3 133.4 493 131 489.7 128.1 485.6 127.2 481.8 126.6 480.6 127.3 479.1 131.8 478.2 134.4 477.7 134.7 474.2 135 471.1 135.3 469.9 134.9 469 133.6 468.2 132.6 466 130.6 463.9 129.2L460.1 126.6 457.4 129.2C455.9 130.6 454.4 132.6 454.1 133.5 453.3 136 447.9 135.7 443.7 132.9 441.9 131.6 439.8 130.6 439.3 130.6 438.7 130.6 438 129.7 437.7 128.7 436.9 126 434.8 127.3 432.9 131.6 431.2 135.1 431.1 135.2 426.2 135.2 423.5 135.2 421.3 134.8 421.3 134.4 421.3 133.9 419.5 132.9 417.4 131.9 415.2 131.1 413.1 129.9 412.9 129.4 412.5 128.8 411 129.8 409.3 131.9 406.8 134.7 405.7 135.2 402.4 135.2 400.3 135.2 396.6 134.2 394 133 389.3 130.6 387.7 130.8 385.2 133.7 383.6 135.6 373 135.7 371.4 133.9 369.4 131.4 365.6 131.2 362.7 133.3 360.4 135.1 359.2 135.3 353.3 134.8 349.7 134.5 345.2 134.1 343.2 133.7 341 133.3 339.3 133.5 338.4 134.3 337.4 135.1 321.6 135.3 268.3 135.1L199.5 134.7 193.5 137.6C178.4 144.7 170.9 160.9 175.4 176.3 177.2 182.6 178.8 185.3 183.1 189.9L186.3 193.3 181.6 194.4C171.5 196.5 163 203.3 158.5 212.8 156.4 217.3 156 219.3 156 226.4 156 233.6 156.4 235.5 158.7 240.5 161.8 247.2 168.3 253.8 174.8 256.8 178.1 258.2 181.6 258.8 189 259.1L198.8 259.4 198.3 263.4C198 267.1 198.2 267.8 201.8 271.5L205.6 275.5 209.3 271.6C213.4 267.1 213.9 264.5 210.9 261.4L209 259.3 215.5 259.3 221.9 259.3 221.5 264.3C221.1 269.1 221.2 269.4 223.9 270.7 227.3 272.5 232.8 272.7 234 271 235.2 269.5 237.4 261.9 237.1 260.4 237 259.6 238.3 259.3 241.1 259.3L245.4 259.3 244.8 263.2C244.4 266.3 244.6 267.6 245.7 268.8 247.6 270.6 254.3 272.6 256.1 271.9 257.7 271.3 262.2 261.3 261.5 260.1 261.2 259.6 263.1 259.3 265.8 259.3L270.6 259.3 269 261.7C267.6 263.8 267.6 264.2 269 266.3 270.7 269 273.9 270.4 278.3 270.4 281.1 270.4 281.8 269.9 283 267.1 283.6 265.4 284.3 262.9 284.3 261.6 284.3 259.4 284.6 259.3 288.2 259.3 292.1 259.3 292.1 259.3 292.1 262.7 292.1 265.9 292.3 266.1 297.6 268.2 302.8 270.2 303.2 270.3 304.8 268.8 305.7 268 307 265.5 307.6 263.2 308.5 259.3 308.6 259.3 312.7 259.3 316.2 259.3 316.7 259.4 315.9 260.8 314.5 263.5 315.6 264.8 320.9 267.1 326.7 269.7 328.6 269.4 329.4 265.6 330.1 262 333 259.3 336.1 259.3 338.1 259.3 338.8 259.7 339.1 261.2 339.4 264 343.8 266.9 347.3 266.9 349.6 266.9 351.1 266.1 353.9 263.1 358.4 258.2 361.1 258.1 364.9 262.5 366.9 264.7 368.6 265.7 370.3 265.7 371.9 265.7 374.3 264.4 376.6 262.5 380.6 259.1 386.1 258 386.1 260.6 386.1 262.3 390.1 264.4 395.3 265.6 398.7 266.4 399.3 266.3 400.5 264.5 401.2 263.4 401.9 261.9 401.9 260.9 401.9 259.5 402.7 259.3 406.5 259.3 409.1 259.3 411.1 259.7 411.1 260.3 411.1 260.7 412.9 261.9 415.1 262.9 422.4 266.1 422.7 266.1 424 262.5 425.1 259.4 425.3 259.3 429.7 259.3 432.2 259.3 434.3 259.6 434.3 260.1 434.3 260.6 435.8 261.5 437.8 262 439.6 262.7 441.9 263.8 442.9 264.6 444.3 265.9 444.6 265.8 446.3 264.4 447.3 263.4 448.3 261.9 448.6 261 449.5 258.2 457.3 258.6 461.7 261.6 463.5 262.9 465.8 263.9 466.9 263.9 467.8 263.9 469.6 262.9 470.9 261.6 472.9 259.6 474.2 259.3 478.3 259.3 481.6 259.3 484.7 259.9 487 261.1 491.7 263.4 493.1 263.4 494.7 261 496 259.3 496.8 259.2 503.4 259.6 512 260.3 512.5 260.3 525.2 259.6 530.6 259.4 536.6 259.5 538.3 260.1 540.4 260.6 541.7 260.6 541.7 260.1 541.7 259.6 578.1 259.3 632.9 259.3L724.2 259.3 722.7 262C721.9 263.5 721.3 265.6 721.3 266.7 721.3 267.9 720.6 268.9 719.4 269.2 716.8 269.9 717.1 270.9 721.5 274.1 726.1 277.5 729.8 277.7 732.9 274.6 737.4 270.1 736.7 264.2 731.3 261.9 726.3 259.9 727.7 259.3 737.6 259.3 745.4 259.3 747.2 259.5 746.6 260.4 746 261 744.9 263.7 744 266.4 741.9 272.3 742.6 273.5 749.7 275.6 755.8 277.3 756.9 276.8 758.9 269.7 760.3 265 760.3 264.5 758.7 262.9 757.9 261.9 755.8 260.7 754.3 260.3 752 259.6 753.6 259.4 760.8 259.4L770.2 259.3 769.2 262.7C768.6 264.6 767.6 266.9 766.8 267.9 765.6 269.4 765.6 269.7 767.7 271.8 770.6 274.7 777 276.2 779.4 274.4 781.4 273.1 783.9 264.7 783 262.5 782.7 261.7 781.5 260.6 780.4 260.2 778.7 259.5 779.2 259.4 783.1 259.4 788.3 259.3 788.2 259.2 789.4 266.4 790.1 271.3 791 271.4 799.7 267.2 807.2 263.6 813.9 258 817.8 251.9 821.4 246.2 821.2 245.4 816.1 245.4 813.8 245.4 812 245.1 812.2 244.6 820.6 228.4 818.3 213.3 806 201.9 801.8 198.1 799.4 196.8 794 195.2L787.2 193.2 791.2 188.3C804.6 171.9 799.2 147.2 779.8 137.8L773.6 134.7 750.3 134.7C737.4 134.7 726.9 134.5 726.9 134.4 726.9 134.2 727.8 132.4 728.9 130.5L730.8 126.9 726.3 121.6C723.7 118.7 721.3 116.2 720.7 116 720.3 115.9 719.2 116.8 718.3 118.1ZM675.6 263.1C674.4 264.4 672.9 267.2 672.2 269.9 671.3 273.9 671.4 274.6 672.8 275.6 674.7 277 684.1 279.3 684.8 278.4 685.2 278.1 685.6 276.5 686 274.8 686.4 273 687.4 271.4 688.7 270.8 689.8 270.4 690.7 269.7 690.7 269.4 690.7 268.1 686.8 264.8 685.2 264.8 684.2 264.8 682.6 264 681.8 263 679.7 260.6 678.4 260.6 675.6 263.1ZM699.9 263.8C698.4 265.3 697.2 267.1 697.2 267.9 697.2 268.6 696.3 269.4 695.2 269.7L693.1 270.3 695.4 272.7C696.9 274.3 698.2 274.9 699.5 274.6 700.6 274.4 702.5 273.9 704 273.6 705.9 273.1 706.5 273.2 706.5 274.4 706.5 276.7 707.7 276.3 710.6 273.1 713.2 270.5 713.3 270.2 712 267.8 710.6 265.4 705.2 261.1 703.5 261.1 703.1 261.1 701.4 262.3 699.9 263.8ZM605.2 265.1C604.4 266.2 602.9 269.1 601.8 271.5 599.4 276.5 600 278.1 604.8 279.2 606.3 279.5 608.4 280.6 609.4 281.7 611.7 283.9 613.4 282.8 614.4 278.6 614.7 277.1 616 275.1 617.3 274.1L619.7 272.2 617.6 269.9C616.4 268.6 614.9 267.6 614.4 267.6 613.7 267.6 611.7 266.6 609.8 265.3L606.5 263.1 605.2 265.1ZM650.9 266.3C650.3 268.3 649.2 270.9 648.3 272.1 647 274.3 647.1 274.5 649.4 276.5 650.7 277.7 653.4 279.1 655.3 279.5 659.8 280.8 662.5 279.1 663.9 274 665.7 267.1 663.7 264.4 656.1 263.3 652 262.8 652 262.8 650.9 266.3ZM627.8 266.3C627.2 267.6 626.9 269.1 626.9 269.5 626.9 270 626 271.2 624.9 272.3 623.1 274.2 623.1 274.3 624.7 276.1 628.6 280.5 634.7 281.8 637.3 278.9 639.6 276.4 641.9 270.5 641.2 268.4 640.8 267.3 639 266.2 635.9 265.3 629.5 263.4 628.8 263.5 627.8 266.3ZM580.6 268.1C579.6 269.5 578.3 272.1 577.8 274 576.9 276.9 577 277.5 578.8 278.9 579.9 279.8 581.6 280.6 582.5 280.6 583.4 280.6 584.7 281.4 585.4 282.3 587 285 589.3 283.3 592.3 276.9L594.9 271.6 590.6 268.7C585.6 265.1 583.1 265 580.6 268.1ZM555.6 268.4C552.8 273.6 553 280.6 555.8 280.6 556.5 280.6 558.7 281.4 560.6 282.4L564.4 284.4 566.8 281.6C569.3 278.9 571.1 272.2 569.9 270.3 567.8 266.9 557.2 265.5 555.6 268.4ZM487.1 268.9C486.7 269.4 485.6 271.7 484.7 273.8 483.9 275.9 482.6 277.9 481.9 278.1 479.6 279 481.9 282.1 485.6 283.3 487.4 283.9 489.6 285.4 490.6 286.7 492.2 288.7 492.6 288.8 493.8 287.5 494.6 286.8 495.5 284.9 495.8 283.3 496.2 281.9 497.5 279.7 498.8 278.7 501.1 276.9 501.1 276.8 499.5 275 496.7 271.9 488.1 267.6 487.1 268.9ZM532.3 271.4C531.7 273.4 530.3 275.7 529.3 276.5 527.3 277.9 527.3 277.9 529.9 280.1 532.5 282.4 538.8 284.6 541.5 284.1 543.3 283.7 547.2 277.1 547.2 274.4 547.2 272.8 546.1 271.7 542.6 269.9 535.8 266.5 533.7 266.8 532.3 271.4ZM511.2 271.2C504 279 504.2 278.5 506.1 280.7 507.1 281.8 509.3 283.2 510.9 284 513.4 285 514.4 285 517 283.9 518.7 283.2 521 281.3 522.1 279.8L524.2 276.9 520.8 273.3C516.5 268.4 514.3 268 511.2 271.2ZM439.4 271.5C435.9 273.4 433.4 282.9 436.1 284.3 436.9 284.7 439.4 285.9 441.7 286.9L445.7 288.9 447.9 286.9C449.9 284.9 451.9 280 451.9 276.7 451.9 273.5 442.7 269.6 439.4 271.5ZM460.2 276.4C459.1 279.8 458.5 282.9 458.9 283.3 459.4 283.7 461.3 284.5 463.2 285.2 465.1 285.7 466.7 286.9 466.7 287.6 466.7 288.3 467.2 288.9 467.9 288.9 469.5 288.9 471.7 286.4 473.1 282.6 473.8 281 474.7 279.6 475.2 279.6 475.6 279.6 475.9 278.5 475.7 277.1 475.4 274 471.9 271.6 466.6 270.8L462.2 270.2 460.2 276.4ZM414.5 273.9C412.5 276.1 411 280.6 411.6 282.5 411.9 283.4 414.2 285.6 416.7 287.4L421.2 290.6 424.9 286.4C429.2 281.6 429.6 279 426.7 276.1 422.5 272.2 416.9 271.2 414.5 273.9ZM278.4 273.8C277.9 274.7 266.1 322.5 265.2 327.1 264.6 330.3 264.4 330.5 263.1 329.3 262.2 328.5 259.2 327.2 256.1 326.4 251.6 325.1 250.6 325 249.5 326 248.1 327.5 246.3 336.5 247.1 337.8 247.4 338.2 249.6 339.5 252.1 340.6 254.5 341.7 256.5 343.1 256.5 343.9 256.5 346.4 259 344.4 260.6 340.6 261.6 338.7 262.4 337.1 262.6 337.3 263.2 337.9 259.9 350.6 258.9 351.1 258.3 351.5 257.5 350.9 256.9 349.9 256 348.2 255.8 348.2 253.1 351.1 248.6 355.9 247.8 358.1 249.4 360.6 250.3 361.9 252.1 363.6 253.7 364.5 256.2 365.9 256.6 366.6 256.1 369 255.7 370.5 254.7 372.6 253.7 373.6 252.7 374.7 251.9 376 251.9 376.5 251.9 376.9 250.8 378.9 249.5 380.7L247.2 384.2 250 385.6C251.9 386.7 252.7 387.6 252.4 388.7 252.1 389.5 251.3 394.3 250.5 399.1 249.6 403.9 248.6 408.7 248.1 409.7 247.7 410.7 247 413.9 246.8 416.7 246.5 419.4 245.4 427.5 244.3 434.4L242.4 447.1 237.9 446.6C233.5 446.1 233.2 446.2 229.6 449.8 226.2 453.2 226 453.7 226.9 455.9 228.4 459.1 231.4 460.9 236 461.7 239.2 462.1 239.8 462.6 239.8 464.4 239.8 468.1 238.9 469.4 236.5 468.9 233.5 468.1 230 471.9 229.2 476.8 228.4 481.5 229.3 482.8 234.6 484.3 238.5 485.4 238.8 485.6 240.2 490.6 243.2 501.7 244.3 509.3 247.2 544 249.6 572.4 255.3 618.1 257.1 624.4 257.5 625.9 257.2 626.1 255 625.6 250.6 624.4 242.8 618.8 234.5 610.6 230.4 606.5 226.7 603.3 226.4 603.5 226.1 603.8 225.9 606.5 225.9 609.4 225.9 615.6 225.5 615.8 220 613 218 612 216.1 611.4 215.6 611.6 214.4 612.4 211.1 620 211.1 622.3 211.1 624.2 212 625.1 216.3 627.1 219.2 628.6 221.6 629.6 221.8 629.4 221.9 629.3 222.6 628.1 223.4 626.9 225 624.6 225 624.7 225 631.3 225 634.9 224.8 638 224.5 638 224.3 638 222.5 637.3 220.6 636.6 216.7 634.9 214.8 635.3 214.8 637.9 214.8 638.9 213.6 641.2 212 642.9L209.3 646 214.7 649.4C217.8 651.3 221 652.8 222.1 652.8 223.8 652.8 224.1 653.3 224.1 656.6 224.1 659.9 223.9 660.3 222.2 659.7 221.2 659.4 219.5 659.4 218.5 659.7 216.2 660.5 213 666.6 213 670.3 213 672.6 213.4 673.2 215.6 673.7 220.6 674.8 221.3 675.2 221.3 676.6 221.3 677.4 221.9 677.8 222.6 677.5 224 676.9 225 679.4 225 683.1 225 685.6 223.6 685.7 221.6 683.3 219.3 680.6 218.7 680.9 216.6 685.8 215.6 688.3 214 690.8 213.1 691.5 211.8 692.6 211.9 693.1 215.7 696.4 219.1 699.4 220.5 700 223 699.7 225.6 699.4 225.9 699.7 225.9 701.9 225.9 703.1 226.2 705.2 226.6 706.4 227 708.1 226.9 708.4 225.4 708.1 219.4 706.3 218.7 706.3 217.2 708.5 216.5 709.6 215.6 712.8 215.2 715.4L214.6 720.2 219.4 721.8C222 722.6 224.4 724 224.7 724.7 225.2 726 225.5 725.9 226.5 724.5 228 722.6 228.3 723.2 229 729.4 229.5 734 228.3 734.5 223.9 731.4 220.6 729 219.6 729.7 217.2 735.9 215.1 741.5 215.3 744.4 217.7 744.4 218.7 744.4 220.8 745.3 222.3 746.4 225.6 748.7 227.5 748.1 228.9 744.4 229.4 742.9 230 741.8 230.3 742 230.6 742.2 231.1 745.5 231.6 749.3 232 753 232.6 756.9 232.9 758.1 233.3 760.2 233.2 760.1 229.5 757.4 227.4 755.9 224.7 754.6 223.5 754.6 221.2 754.6 218.5 757.8 218.5 760.4 218.5 761.4 217.8 762 216.7 762 214.1 762 214.4 763 218.1 766.9 222.6 771.5 225.6 771.5 230 767.1 231.9 765.4 233.4 763.9 233.6 763.9 233.8 763.9 234.3 766.3 234.6 769.2 235 772 237.3 786.2 239.8 800.6 244 824.3 244.4 827.1 243.3 831.4 242.2 836.2 243.1 838.9 245.8 838.9 246.5 838.9 247.3 840.6 247.6 843.1 248.1 846.4 247.9 847.7 246.4 849.7 245.4 851.1 244.4 854.2 244.3 856.5 244 860.7 244.6 861.5 251 864.1 251.3 864.3 251.9 865.9 252.2 867.8 252.8 871.1 252.7 871.3 250.6 871.3 247.7 871.3 245.8 873.9 244.5 879.6 243.3 884.9 244.5 886.4 251.3 887.9 256.4 889 257.3 890.1 257.4 894.7 257.4 896.1 256.8 896.4 253.1 896.1 249.2 895.8 248.5 896.1 247.5 898.2 246.9 899.5 246.3 902.4 246.1 904.6 245.8 908.7 245.9 908.8 249.5 910 251.6 910.6 253.8 911.9 254.4 912.7 255.5 914.1 255.6 914.1 257.4 912.5 258.4 911.6 259.3 910.2 259.3 909.4 259.3 906.3 260.3 909.4 261.5 916L262.7 923 260.1 922C258.7 921.6 257 920.6 256.4 919.8 255.8 919.1 254.4 918.5 253.1 918.5 251.3 918.5 250.5 919.4 249.1 922.4 248.1 924.5 246.5 926.9 245.4 927.8 243.3 929.4 243.3 929.4 247.8 931.9 250.3 933.3 253.8 935.4 255.6 936.4 257.3 937.4 258.5 938 258.1 937.6 257.8 937.1 258.1 936.2 258.8 935.5 259.5 934.8 260.6 932.5 261.1 930.6 261.7 928.5 262.5 926.9 262.9 926.9 263.3 926.9 264.3 930.4 264.8 934.5L266 942.3 272.8 945.6C276.6 947.5 279.5 948.6 279.4 948.1 279.3 947.7 281.5 945.8 284.3 944.2 288.7 941.5 293 936.4 319.3 902.8 335.6 881.7 349.7 863.8 350.5 863.1 351.5 862 352 861.9 353.1 862.9 353.9 863.5 354.6 863.6 354.9 863.2 355.8 861.9 360.2 833.9 361.4 822.5L362.5 811.3 372.7 818.6C400.6 838.7 426.3 851 452 856.7 463 859.1 504.3 860.1 518.2 858.3 549.7 854.4 579.4 840.8 614.2 814.6 621.4 809.3 627.6 805.1 627.9 805.4 628.1 805.7 628.9 809.7 629.5 814.4 631.9 832.5 636.4 854.7 637.6 854.3 638.2 854 649.4 870.2 666.2 895.6 681.3 918.5 693.9 937.8 694.1 938.3 694.4 938.9 698.7 941.6 703.8 944.4 711 948.3 713 949.8 712.7 951 712 953.3 727.6 945.6 728.3 943.2 728.7 942 729.5 941.6 731 941.9 732.8 942.2 733.5 941.6 735 938.5 738 932.5 738.3 930.2 736.4 928.5 735.5 927.7 733.9 926.9 732.9 926.7 731.3 926.4 731.1 925.7 731.3 922.2 731.5 920 732.4 917.1 733.4 915.9 734.4 914.6 735.2 912.9 735.2 912 735.2 911.1 735.8 909.9 736.6 909.3 738.5 907.7 738.3 905.8 736.1 905.1 733.8 904.4 733.8 902.9 736 887.5 737 880.8 738.1 872.7 738.4 869.2 738.8 865.7 739.4 863 739.7 863 740 863 742.1 864.4 744.4 866.2 751.6 871.9 754.3 871.6 756.9 864.4 759.3 858.3 758.6 856.3 753.8 854.5 751.5 853.7 749.4 852.3 749.1 851.4 748.5 849.9 748.4 849.9 746.9 851.3 746.1 852.1 745 854.5 744.4 856.6 743.5 859.9 741.4 862 740.2 860.8 739.7 860.5 741.4 845.2 742.1 842.9 742.3 842.2 743.6 842.8 745.5 844.5 747 846 748.6 847.2 749 847.2 749.4 847.2 751.4 845.7 753.5 843.9 759.3 839 758.9 835.3 752 830 747.9 826.9 747.9 826.9 745.9 828.6L744 830.5 744.3 825.8C744.6 821.2 745.2 820.6 746.9 822.3 749.2 824.5 752.8 822.4 754.7 817.8 755.7 815.5 757 813.1 757.6 812.8 759.3 811.9 756.9 809.4 751.7 806.9 747.7 804.8 747.2 804.3 747.2 801.5 747.2 798.9 747.5 798.4 749 798.8 751.2 799.4 754.4 796 755.6 791.8 756.9 786.6 756.7 785.4 753.8 783.8L751.1 782.4 752.9 777.8C754.5 773.2 756.6 753.6 756.4 742.6L756.3 738.4 755.1 741.7 753.9 744.9 753.8 742.1C753.7 740.6 754.2 733.3 754.7 725.9 755.2 718.6 755.9 704.4 756.4 694.3 756.8 684.2 757.3 675.7 757.6 675.5 758.1 674.8 764.9 677.6 766.7 679.3 767.9 680.3 768.6 679.9 771.6 676.2 776.1 670.6 775.9 668 770.8 665.1 765.4 661.9 762.2 662.2 760.7 665.9 758 673 757.9 672.9 757.4 662.5 757.1 656.9 756.9 652.2 757 652 757 651.9 759.7 652.7 763 653.8 766.1 654.8 769.3 655.5 769.9 655.2 770.6 655 771.4 653.2 771.7 651.4 772.1 649.1 773 647.8 774.2 647.5 777.8 646.6 775.5 643.1 769.7 640.8 768.1 640.2 766.6 639.1 766.3 638.4 765.7 636.9 762.7 637.6 760.7 639.7 759.9 640.6 758.7 643 758 645 756.7 648.5 756.6 648.4 756.5 638.4 756.3 627.5 755.4 612.2 753.8 593.5 753.2 587.1 751.9 571.3 750.8 558.3 749.8 545.4 748.6 533.5 748.2 532L747.6 529.4 743.7 534.4C741.6 537.2 738.4 542.6 736.7 546.4L733.4 553.2 734 542.6C734.3 536.5 735 530.8 735.7 529.3 736.5 527.7 737.7 520.6 738.4 513.5 739.3 506.3 740.6 497.5 741.4 494 742.2 490.4 743 484 743.1 479.7 743.1 475.3 743.6 471.8 744.1 471.6 745 471.3 744.8 421.6 744 418.7 743.7 418.1 742.7 417.6 741.6 417.6 740.2 417.6 739.8 417.2 740.2 416.1 742.8 409.3 741.9 405.9 737 404.6 735 404.1 732.9 403.9 732.4 404.2 731.9 404.4 731.5 403.9 731.5 402.9 731.5 397 718.8 337.1 709.6 299.8L703.5 275 701.1 275.6C699.7 275.8 698.1 276.2 697.6 276.4 696.9 276.6 697 278.6 698.3 283.1 701.4 293.8 702.6 301.6 704.6 323.1 706.8 345.6 707.7 350.9 714.2 376 718 390.6 722.2 411.6 722.2 415.6 722.2 417.1 718.1 417.2 667.4 416.9 637.2 416.8 603 416.9 591.2 417.5 572.3 418.2 569.1 418.6 562.3 420.7 553.1 423.7 544.4 429.4 540 435.3L536.7 439.7 520.9 439.3C506.9 438.8 494.4 439.4 475.5 441.3L469.9 441.9 467.2 436.7C462.1 426.7 449.6 418.2 435.5 415.3 423.2 412.8 381.6 411 323.1 410.5 292.3 410.2 266.9 409.8 266.8 409.6 266 408.9 287.1 285.8 289 280.2 290.4 275.8 290.5 274.4 289.5 273.9 288.1 273 279 273 278.4 273.8ZM360.2 425.9C395.7 427 421.9 428.5 429.6 429.7 441.2 431.6 449.9 436.9 454.3 444.6 456.9 449.4 456.9 449.8 456.9 463 456.8 474.8 456.4 477.7 453.9 487 445.2 520.2 433 538.3 411.2 550.6 398.9 557.6 386.2 561 369 561.8 326.8 563.7 291.5 544.1 280.5 512.4 276.1 499.8 274.4 469.8 277.2 456.4 278.7 449.4 282.1 442.1 285.4 439.2 292.4 432.7 305.6 427.2 317.9 425.9 327.5 424.9 329.1 424.9 360.2 425.9ZM679.9 434.5C694 438.6 702.2 445.2 705.4 454.7 711.5 473.2 709.9 504.4 702.2 520.2 685.6 554.4 631.8 569.7 594 550.9 575 541.6 562.6 525.9 554.4 500.8 549.4 485.7 547.8 476.9 547.7 464.4 547.7 454.2 547.9 452.8 550.1 448.6 553 443 559.3 438 566.5 435.6 574 433.2 589.4 432.6 635.2 432.9 668.9 433 675.3 433.2 679.9 434.5ZM528.4 455.2L531.2 455.7 531.8 466C533.4 498.9 548.1 534.4 566.9 551.5 590.3 572.4 623.7 579.7 657.5 571.2 692.3 562.4 716.9 538.3 722.7 507.3 723.4 503 724.3 493.4 724.4 486.3 724.5 475.7 724.8 473.1 725.8 473.1 726.9 473.1 727 477.2 726.5 499.7L725.9 526.4 717.7 543.1C698.8 581.8 680.4 608.8 657 631.9 639.3 649.6 622.8 660.6 604 667.6L596.9 670.2 589.4 663.9C550.6 631.5 501.6 619.6 455 631.5 432 637.4 408.7 649.5 391.8 664.4 384.7 670.6 384.4 670.6 371.6 665 333.1 648.4 296.2 605.8 264.9 541.7L256.9 525.5 256.6 516.2C256.2 506.3 258.1 471.9 259.2 467.8 259.6 466.3 260.1 470.8 260.5 479.6 261.9 514.2 268.7 532.1 286.9 549.2 294.7 556.7 299.2 559.7 309 564.7 344.5 582.5 390.5 581.4 422.2 561.9 431.2 556.4 444.8 543.3 450.4 534.9 462 517 470.9 489.4 472.8 465.1L473.4 456.7 481.9 455.7C491.5 454.8 524.4 454.4 528.4 455.2ZM740.5 604.6L744.4 614.4 740.6 618C736.8 621.3 730.6 625 726.3 626.3 724.4 626.9 724.4 626.9 725.5 620.2 726.1 616.5 727.3 607.8 728.2 600.9 730.6 582.2 730.2 582.8 733.6 589.4 735.2 592.4 738.2 599.3 740.5 604.6ZM555.6 685.7C555.6 686 554 689.3 552.1 693 545.4 705.9 532.8 715.7 517.5 720.1 508.8 722.5 476.4 722.5 467.1 720.1 456.7 717.3 444.8 711.1 438 704.8 432.7 700 425 689.2 425 686.6 425 685.9 446.6 685.6 490.3 685.4 526.2 685.2 555.6 685.4 555.6 685.7ZM602.7 692.1C612.2 694.4 620.8 699.5 629.3 707.9 637.6 716.1 639.8 720.2 642 730.9 644.6 743.6 643.7 749.6 638.1 755.7 630.7 764 619.2 768.1 605.6 767.4 598.7 767.1 596.6 766.6 590.4 763.6 571.3 754.5 559.9 739.1 559.9 722.2 559.9 699.6 578.6 686.5 602.7 692.1ZM363 462.2C355.6 465.9 351.6 471 349.9 478.2 347.7 488.3 352.1 498.3 361.5 504.2 365 506.3 367.3 506.9 372.2 507.2 380.1 507.7 383.9 506.5 389.2 501.8 399.1 493.1 400.8 479.2 393.2 469.3 388.6 463.1 382.8 460 375.3 459.5 369.5 459.2 368.4 459.4 363 462.2ZM389.3 466.8C394.2 470.6 391.4 478.1 385 478.1 379.1 478.1 376.5 470.4 381.1 466.8 382.5 465.6 384.3 464.8 385.2 464.8 386.1 464.8 387.9 465.6 389.3 466.8ZM602.5 460.6C594.4 463.6 587.8 471.9 586.6 480.6 584.6 494.4 596.3 507.4 610.6 507.4 620.3 507.3 627.8 502.4 632 493.1 637.4 481.7 632.4 467.8 620.8 461.9 616.2 459.4 607.2 458.8 602.5 460.6ZM626.3 466.8C631.2 470.6 628.4 478.1 622 478.1 616.3 478.1 613.8 471.3 618.1 467.1 620.8 464.4 623.1 464.3 626.3 466.8ZM390.1 274.3C389.4 275 388.5 277.5 388 279.9 386.8 285.6 387.8 287.6 392.4 288.8 399.4 290.6 399.4 290.6 402.1 285 403.6 282 404.6 279.1 404.4 278.3 403 274.6 392.2 271.7 390.1 274.3ZM366.2 276.3C365.3 277.6 364.4 280.6 364.2 282.8L363.7 286.9 368.4 288.4C371 289.3 373.3 290.4 373.6 290.8 374.5 292.2 377.6 290.1 379.2 287 379.9 285.6 380.6 282.9 380.6 281.1 380.6 277.1 377.9 275 371.9 274.4 368.2 273.9 367.6 274.2 366.2 276.3ZM342.6 278.4C341.9 280.4 340.9 282.9 340.2 283.9 339.2 285.6 339.3 286.1 341.1 287.9 343.5 290.1 348.7 291.3 352.2 290.4 353.8 290 354.9 288.6 356 285.6 357.5 281.8 357.6 281.4 356.1 279.2 354.3 276.4 351.2 275 346.8 275 344 275 343.5 275.4 342.6 278.4ZM202.1 281.7C198.6 285.6 198 287.3 199.2 290.6 200.3 293.5 204.5 298.1 206.1 298.1 207.6 298.1 213 292.8 213.9 290.4 214.8 287.8 213 284.4 208.9 281.2 207.1 279.8 205.5 278.7 205.3 278.7 205.2 278.7 203.7 280.1 202.1 281.7ZM249.2 281.1C248.1 282.4 246.9 284.9 246.3 286.7 245 290.5 245.9 292 249.7 293.1 251.1 293.3 253.2 294.4 254.4 295.5L256.8 297.2 258.5 294.7C259.4 293.2 260.2 291.3 260.2 290.2 260.2 289.1 261 287.9 262 287.4 263.8 286.6 263.9 286.5 262.4 284.4 260.9 282.3 254.5 278.8 252.1 278.7 251.6 278.7 250.2 279.8 249.2 281.1ZM224.3 280.8C222.6 282.8 221.3 290 222.3 291.8 222.8 292.7 224.4 293.6 226.1 294 227.8 294.4 229.9 295.3 230.8 296.1 232.3 297.4 232.6 297.3 234.6 295.5 237.4 292.9 239.4 285.9 238 283.4 236.3 280.1 226.4 278.2 224.3 280.8ZM770 284C769.4 285.5 768.2 288.1 767.8 290.1 766.9 293.3 766.9 293.9 768.9 295.8 771.4 298.3 777.4 299.8 779.5 298.4 780.3 298 781.3 296.3 781.8 294.8 782.2 293.3 783.2 291.4 784.1 290.6 786.3 288 783.5 284.7 777.4 283 771.1 281.1 771.6 281 770 284ZM748.5 283.1C746.9 284.2 743.2 293.3 743.8 294.8 744.7 297.1 749.1 299.4 752.9 299.4 756.5 299.5 756.6 299.4 758.8 294.1 760.6 289.8 760.8 288.2 760 287.2 757.8 284.6 750.4 281.9 748.5 283.1ZM723.1 285.5C723.1 286.1 722.3 288.2 721.3 290.3 720.3 292.3 719.4 294.4 719.4 295 719.4 298.1 730.1 302.3 733.1 300.4 735.2 299.1 737.2 290.1 736 287.9 734.5 285 723.1 282.9 723.1 285.5ZM606.6 289.9C604.5 291.5 602.5 293.8 602.2 295.1 601.6 297.5 603.2 301.5 605.1 302.2 606.5 302.8 616.9 299.1 617.8 297.7 618.8 296.4 617.7 293.4 615.4 290.9 611.9 287 610.7 286.9 606.6 289.9ZM582.1 290.6C580.7 291.9 579.2 294.4 578.6 296.2 577.7 298.8 577.8 299.5 579.4 301.7 580.3 303 582.8 304.5 584.7 305.3 591 307.5 593.6 305 593.9 296.5 594 293.5 593.7 293.1 590.3 292 588.2 291.3 586.1 290.1 585.6 289.4 584.7 288.2 584.2 288.4 582.1 290.6ZM535 293.2C533.7 294.7 532.4 296.7 532.2 297.7 532 298.7 531.3 299.5 530.6 299.5 528.1 299.5 528.7 301.7 532.1 304.4 538.1 309.2 539.2 309.1 544.7 303.8L549.5 299.1 545.2 294.9C542.8 292.6 540.1 290.7 539.1 290.7 538.1 290.7 536.3 291.9 535 293.2ZM557.5 293.1C552.6 297.2 552.4 298.3 556.1 302.7 560.9 308.2 563.9 307.9 569.1 300.8 570.8 298.3 572 295.8 571.7 295.3 570.9 294 564 290.8 561.9 290.7 561 290.7 559.1 291.9 557.5 293.1ZM488.2 293.1C486.3 294.4 485 297.5 483.8 303.3 483.3 305.9 483.5 306.3 486.9 307.8 492.3 310.3 495.4 309.5 497.9 305.1 501 299.6 500.5 297 495.6 295.6 493.4 294.8 491.7 293.7 491.7 293 491.7 291.3 490.7 291.3 488.2 293.1ZM509.2 295.8C508.1 298.1 507.4 301.4 507.6 303.1 507.9 305.6 508.4 306.2 512.1 307.6 517.6 309.5 519.9 309 521.3 305.3 521.9 303.6 522.9 301.2 523.6 299.8 524.9 297.2 524.9 297.2 519.3 294.4 516.2 293 513.1 291.7 512.3 291.7 511.6 291.7 510.2 293.5 509.2 295.8ZM464.1 293.8C463.5 294.4 462.8 296.1 462.5 297.5 462.1 298.9 460.7 300.8 459.5 301.9 456.6 304.2 457.4 305.4 464.7 309.3L469.9 312.1 471.9 309.6C473.1 308.2 474.6 305.5 475.6 303.5 477.5 299.3 476.6 297.7 471.3 296.3 469.4 295.7 467.5 294.7 467.2 294 466.6 292.3 465.4 292.2 464.1 293.8ZM417.9 295.4C414.6 296.7 411.3 305.3 412.6 308.8 413 309.5 415.5 310.8 418.3 311.7 423.4 313.1 423.5 313.1 425.2 311.1 426.1 310 426.9 308.3 426.9 307.3 426.9 306.4 427.7 305.1 428.7 304.4 431.3 302.6 430.4 300.6 425.2 297.2 420.6 294.2 420.7 294.3 417.9 295.4ZM439.4 296.5C438.6 297.6 438 299.3 438 300.2 438 301 437.2 302.1 436.4 302.6 434.9 303.4 434.9 303.6 436.4 305.9 438.7 309.4 442.2 311.4 444.8 310.7 446.8 310.3 454.5 301.3 453.6 300.6 449.4 297.6 443.8 294.4 442.5 294.4 441.6 294.4 440.2 295.4 439.4 296.5ZM391.2 298.5C389.9 300.6 388 305.9 388 307.7 388 308.1 390.7 309.6 394.1 311.2 399.7 313.7 400.4 313.8 401.9 312.5 402.8 311.7 404 309.2 404.6 307 406.1 301.5 404.9 299.5 398.9 297.7 392.8 295.9 392.9 295.9 391.2 298.5ZM251.4 300.8C247.7 302.4 245.9 305.5 245.8 310.4L245.8 315.2 251.8 317.3C258.5 319.7 259.4 319.4 261 313.9 261.7 311.5 262.7 310.2 263.6 310.2 265.8 310.2 260.6 304.8 258 304.4 256.9 304.3 255.6 303.2 255.1 302 254.1 299.8 254.1 299.8 251.4 300.8ZM203.3 305.6C198.1 311.8 198.5 315.7 204.5 320.1L207.3 322.2 211.1 318.7C216 314 216 311.2 211.4 307.7 209.4 306.3 207.4 304.5 206.9 303.8 206.1 302.8 205.4 303.1 203.3 305.6ZM226 304.4C225 305.3 223.6 308 223 310.5 221.6 315.7 222.2 316.6 229.1 318.9 233.5 320.4 233.7 320.3 235.7 318.4 238.1 316.3 239.9 310.2 239.2 307.3 238.1 303.2 229.6 301.4 226 304.4ZM181.6 310.9C181 313.8 180.3 317.1 180 318.2 179.2 321.3 183.5 322.9 186.8 320.7 189.3 319.2 191.7 314.3 191.7 310.7 191.7 308.8 191 308.2 187.8 307.3 185.6 306.8 183.5 306.1 183.2 305.9 182.9 305.7 182.1 308 181.6 310.9ZM748.4 307C747.8 307.3 746.6 309.8 745.7 312.6 743.8 319.4 745.1 321.6 751.9 323.1 754.6 323.6 756.9 324 756.9 323.9 757 323.7 758.3 321.1 759.7 318.1 762.5 312.2 762.3 310.6 758.2 308.6 755.5 307.3 749.9 306.4 748.4 307ZM770.8 308.3C770 309.3 769 311.9 768.8 314.3L768.2 318.4 773.7 320.8C776.7 322.1 779.6 323 780.2 322.8 782.2 321.9 784.3 318.1 784.8 313.6 785.5 309.4 785.4 309.3 782.1 307.9 777.4 305.9 772.9 306.1 770.8 308.3ZM723.6 310.4C723.2 311.6 722.3 313.9 721.6 315.6 720.1 318.8 721 321.3 723.8 321.3 724.5 321.3 726.2 322.4 727.5 323.7 730.7 326.9 732.4 325.8 734.3 319.6 735 317 735.9 314.6 736.4 314.3 737.8 312.9 736.9 311.9 732.8 310.2 727.1 307.7 724.4 307.8 723.6 310.4ZM513 314.8C513 315.5 511.9 317.4 510.6 319.2 509.3 320.9 507.9 323.4 507.5 324.8L506.9 327.2 501.1 321.9C495.8 317.1 494.4 316 494.4 317 494.4 317.9 510.6 330.9 511.9 331.2 521.3 332.9 522.2 332.6 522.2 328 522.2 326.9 522.9 325.6 523.6 325.4 524.4 325 525 323.8 525 322.5 525 320.7 524.2 319.9 520.6 318.3 518.1 317.3 515.5 315.8 514.6 315 513.3 314 513 313.9 513 314.8ZM534.3 318.1C533.7 319.4 533.3 320.8 533.3 321.3 533.3 321.8 532.7 322.8 531.9 323.6 530.5 325 530.5 325.3 532.5 327.4 538.5 333.9 543.8 333.4 547.3 326.1 549.2 322.3 549.3 321.7 548.1 319.5 546.6 317 544.1 316 538.6 315.8 535.6 315.7 535 316.1 534.3 318.1ZM464.5 319C463.7 319.7 462.9 321.6 462.5 323.1 462.2 324.5 461.3 326.3 460.6 326.9 458.5 328.6 459 329.6 462.8 331.2 464.6 331.9 466.9 333.1 467.7 333.9 468.9 335 469.4 334.8 471.5 332.6 472.8 331.2 474.1 328.8 474.4 327.3 474.8 325.7 475.3 323.9 475.6 323.1 475.8 321.9 474.7 321 471.4 319.5 465.9 317.2 466.2 317.2 464.5 319ZM440.2 322.9C438.7 324.8 436.9 326.9 436.2 327.6 434.9 328.7 435.1 329.2 437.8 331.6 441.4 334.8 446.1 335.2 450.1 332.3 454.9 328.9 455.1 327.4 451.3 323.1 446.8 318.1 443.7 318.1 440.2 322.9ZM228.5 326.6C227.1 326.9 223.1 335.4 223.1 337.9 223.1 339 235 343.5 236.5 343 239.3 341.9 241.5 332.9 239.6 330.3 238.3 328.5 231 326 228.5 326.6ZM203.3 329.5C199.2 333.9 199.8 338.6 205.6 344L208.4 346.8 212.1 342.9C217 337.6 216.9 334.6 212 330.2 210 328.3 207.8 326.9 207.1 326.9 206.5 326.9 204.7 328.1 203.3 329.5ZM178.2 331.9C177.4 333.7 176.7 336.8 176.6 338.6 176.4 341.9 176.5 342 180.8 343.2 183.2 344 185.2 344.9 185.2 345.5 185.2 347 187.6 346.3 189.6 344.2 191.6 342 193.7 334.9 193 332.9 192.3 331.3 188.4 329.6 183.7 329 179.7 328.4 179.6 328.5 178.2 331.9ZM773.1 330.6C772.7 331.5 772.2 333 772.2 333.8 772.2 334.6 771.2 336.2 769.9 337.4L767.6 339.6 770.8 342.4C774 345.3 779.5 347 781.4 345.8 783.1 344.8 786.2 338 785.9 335.9 785.7 334.6 783.9 333.2 779.9 331.5 774.4 328.9 774.1 328.9 773.1 330.6ZM725 333.9C721.1 340.1 721.5 343.2 726.4 346 732.6 349.5 735.5 348.6 736.7 342.8 737.1 340.7 737.8 339.8 739 339.8 742.6 339.8 740.6 336.7 735.6 334.6 733.6 333.8 731 332.3 729.9 331.3L727.9 329.4 725 333.9ZM796.8 331.3C795.3 332.2 793.3 334.2 792.6 335.6 791.3 338.1 791.3 338.2 794.4 340.9 799.2 344.9 801.7 345.7 804.3 344 806.7 342.4 806.8 341.5 805.3 334.7 804.4 330.8 803.8 330.1 801.9 329.8 800.6 329.7 798.3 330.4 796.8 331.3ZM747.1 335.3L743.3 339.1 745.6 341.5C749.3 345.7 751.3 347.2 753.7 347.2 757.1 347.2 760.2 344.7 760.2 341.9 760.2 340.5 760.8 339.4 762 339.2 764.5 338.5 764.4 337.9 760.8 334.4 756.3 330 752.1 330.3 747.1 335.3ZM205.3 351.7C204.4 352.6 203.4 354.6 203.1 356.2 202.8 358.2 201.9 359.3 200.4 359.6 198.2 360.2 198.1 360.3 199.6 362.5 200.5 363.8 201.9 364.8 202.7 364.8 203.5 364.8 205.2 365.6 206.5 366.7 209.9 369.4 212.5 369.1 213.9 365.7 214.5 364.2 216.1 362 217.4 361 220.5 358.6 219.4 356.7 214.3 354.9 212.3 354.3 210 352.9 209.1 351.9 207.2 349.6 207.1 349.6 205.3 351.7ZM227.8 351.8C227.3 352.8 226.9 354.2 226.9 354.9 226.9 355.6 225.8 357.1 224.5 358.3L222.3 360.5 226.7 364.1C230.4 367.1 231.6 367.6 234.7 367.4 238.1 367.1 238.5 366.9 239.6 363.5 240.3 361.6 240.8 358.8 241 357.3 241.2 354.8 240.7 354.4 235.6 352.3 229 349.5 229 349.5 227.8 351.8ZM181.7 353.7C178.9 356.3 176.7 360.8 177 363.2 177.2 364.7 178.4 365.6 180.9 366.5 183 367.1 185 368.2 185.6 369.1 186.5 370.3 186.9 370.3 189.2 368.5 190.6 367.4 191.7 365.6 191.7 364.6 191.7 363.5 192.3 361.9 193.1 361.1 194.4 359.6 194.1 359.2 190.3 355.6 185.6 351.3 184.5 351.1 181.7 353.7ZM796.9 353.9C796.1 355.1 795.2 358.1 794.9 360.6L794.3 365.3 799.4 367.4C806.7 370.5 808.2 369.5 809.7 361 810.6 356 809.2 354.1 803.7 352.9 801.1 352.3 798.8 351.9 798.6 351.9 798.3 351.9 797.6 352.8 796.9 353.9ZM774.2 354C773.7 354.6 773 356.3 772.7 357.7 772.3 359.1 771.2 360.8 770.1 361.6 768.4 362.7 768.4 363.1 769.5 364.4 770.3 365.3 772.1 366.6 773.6 367.3 775.2 368 777.1 369.1 778.1 369.7 780.4 371.4 782.6 369.5 784 364.8 784.6 362.7 785.6 360.3 786.2 359.5 787.7 357.8 786.7 356.9 780.4 354.7 776.4 353.3 774.9 353.1 774.2 354ZM726 356.7C725.5 358.3 725.3 361.5 725.6 364.2 726.1 368.1 726.7 369 729.7 370.9 731.7 372.1 733.5 373.1 733.7 373.1 735 373.1 738.9 365.8 738.9 363.4 738.9 360 737.6 358.1 733.3 355.6 728.8 353 727.2 353.1 726 356.7ZM749.1 357.4C748 358.9 746.9 361.7 746.6 363.4 746 366.6 746.1 366.7 751.4 369 754.4 370.3 757.4 371.3 758.1 371.1 758.9 370.9 760.2 369.1 760.9 366.9 761.7 364.6 762.8 362.6 763.5 362.3 765.7 361.5 765 360.3 760.5 357.4 754.8 353.8 751.7 353.8 749.1 357.4ZM591.7 373.2C576.1 374.3 558.8 377.6 554.8 380.2 546.9 385.4 547.4 397.6 555.7 402.9 559.3 405 563.5 404.9 575 402.3 596 397.6 623.9 399.2 647 406.3 651.5 407.6 656.9 408.8 659.3 408.8 669.7 408.8 675.7 396.8 669.5 388.1 666.9 384.4 661.2 381.9 646.9 378.2 628.7 373.6 610 371.9 591.7 373.2ZM227.5 378.2C225.6 381.2 224.4 384.2 224.7 385.1 225.2 386.8 228.6 388.9 230.7 388.9 231.4 388.9 232.8 389.7 233.9 390.8L235.9 392.7 237.7 390.5C238.6 389.2 240 386.4 240.7 384.3 242.2 379.7 241.5 377.9 237.4 376.6 235.9 376.1 234.1 375.1 233.2 374.4 232.5 373.7 231.6 373.1 231.2 373.1 230.9 373.1 229.3 375.5 227.5 378.2ZM362 373.8C332.4 378.2 318.1 382.8 314.5 388.8 312.1 393 312.4 399.6 315.4 403.4 318.1 407 322 409.3 325.7 409.3 327.2 409.3 331.4 408.2 335.1 406.9 358 399.2 388.1 397.5 412 402.7 416.9 403.8 421.8 404.6 423 404.6 426.4 404.6 431.3 401.9 433.4 398.9 437.2 393.6 435.3 383.2 429.7 379.9 427.3 378.4 417.3 376.1 406 374.5 397.6 373.3 368.2 372.8 362 373.8ZM182.6 376.4C179.7 378.8 177.1 385.8 178.1 388.4 178.7 390.1 181.9 391.4 187 392.2 190.6 392.8 190.7 392.8 192.5 388.6 193.5 386.3 195 384 195.9 383.5 197.4 382.7 197.2 382.4 194.4 380.6 192.6 379.6 190.7 378.7 190.1 378.7 189.5 378.7 188.2 377.7 187.2 376.4L185.4 374.1 182.6 376.4ZM776.1 375.2C775.6 375.8 774.7 378.1 774.2 380.3 773.5 382.4 772.2 384.8 771.1 385.6 768.4 387.4 769.4 389.3 774 390.6 776 391.2 778.3 392.6 779.1 393.7 780.9 396.3 783 395.4 784.7 391 785.6 389.1 786.9 386.9 787.7 386.4 790 384.6 788 381 783.3 378.7 781.2 377.6 779.4 376.2 779 375.5 778.4 373.8 777.4 373.7 776.1 375.2ZM797.7 376.6C797.4 378.1 796.4 380.7 795.5 382.6 794 385.6 793.9 386.2 795 387.9 795.7 388.9 797.5 389.9 799 390.3 800.5 390.6 802.2 391.5 802.9 392.2 804.7 394.4 806.1 393.7 809.6 388.2 814.6 380.3 814.4 379.4 805.6 376 799 373.5 798.2 373.6 797.7 376.6ZM206 377.7C204.5 378.6 202.4 380.3 201.5 381.4 199.6 383.3 199.7 383.4 203.2 387 208.1 392 210.8 391.9 216.5 386.7L220.8 382.6 219 380.6C216.8 378.1 212.8 375.9 210.5 375.9 209.5 375.9 207.6 376.7 206 377.7ZM750.3 381.3C748.6 383.7 747.2 386.6 747.2 387.7 747.2 390.3 752.9 393.8 757.2 393.9 760.5 394 760.7 393.8 761.9 390 762.6 387.9 763.7 386.1 764.4 386.1 765.8 386.1 766.1 385.3 765 383.6 764.5 383 754 376.8 753.2 376.9 753.2 376.9 751.9 378.8 750.3 381.3ZM728.8 380.7C728.8 381.9 729.4 385.6 730 388.9 731.1 394.6 731.3 394.9 733.7 394.7 736.9 394.4 738.9 392.9 740.5 389.1 742.3 384.6 741.3 382.9 735.9 380.6 730 378.1 728.7 378.1 728.8 380.7ZM230.2 398.7C229.4 399.4 228.7 400.9 228.7 401.8 228.7 402.7 227.9 404.5 226.8 405.9 224.9 408.3 224.9 408.5 226.4 410.2 227.2 411.1 229.3 412.2 230.9 412.6 232.5 412.9 234.4 413.6 234.9 414.1 236.6 415.4 240.3 412.8 242.2 409.2 244.2 405.3 242.7 401.9 238.1 399.3 233.8 396.9 232.1 396.8 230.2 398.7ZM181.9 400.2C181.5 400.7 180.6 403.6 180 406.4 178.6 412.2 179.2 413.3 183.5 414.3 185.1 414.5 187.1 415.5 188 416.2 190.5 418.4 194 415.1 195.4 409.3 196.8 403.5 196 402.4 189.5 400.5 183.9 398.8 182.7 398.7 181.9 400.2ZM205.6 401.1C201.9 411.1 202 413 206 413 207.4 413 209.4 414 210.6 415.4 213.2 418.1 214.2 417.9 215.7 413.7 216.4 412 217.8 409.7 218.8 408.6 221.4 405.6 220.2 403.3 214.6 401 208.6 398.5 206.7 398.5 205.6 401.1ZM775.2 403.4C773.1 405.5 771.3 408.1 771.3 409.1 771.3 411 776.2 415.7 778.2 415.7 778.9 415.7 779.7 416.5 780 417.3 780.6 418.6 781.2 418.2 784.3 415.3 788.6 411 789 408.2 785.5 405.3 784.1 404.2 782.1 402.4 781.1 401.4L779.2 399.5 775.2 403.4ZM799.5 402.3C796.7 405 796.2 405.9 796.7 408.1 797.5 411.5 804 418.1 805.9 417.3 808.1 416.5 812.3 409.5 812.3 406.8 812.3 403.9 807.5 399.1 804.7 399.1 803.7 399.1 801.4 400.6 799.5 402.3ZM162.5 404C162.2 405.6 161.7 409 161.2 411.4 160.5 415.5 160.6 415.9 162.5 417.2 166 419.5 169 417.6 171.2 411.5 172.3 408.6 172.9 405.8 172.5 405.5 172.1 405.1 169.8 403.9 167.4 402.9L163.1 401 162.5 404ZM751.1 403.2C749.1 405.8 747.8 410.6 748.3 413.5 748.7 415.8 752.8 417.7 757.6 417.9 761.4 418.1 761.5 418 762.7 414 763.3 411.7 764.4 409.5 765 409.1 767.6 407.5 762 403 755.5 401.4 753.5 400.9 752.6 401.3 751.1 403.2ZM231.5 422.1C229.3 425.4 226.9 430.8 226.9 432.9 226.9 434.6 233.6 437.9 237.1 438 240.1 438 241.7 436.2 241.9 432.9 242 431.6 242.7 430.1 243.4 429.7 245.5 428.4 244.2 425.6 241 424.6 239.4 424.1 237.2 422.7 236.1 421.5 235.1 420.4 234 419.4 233.8 419.4 233.6 419.4 232.6 420.6 231.5 422.1ZM208.1 422.4C206.7 423.5 203.8 430.2 203.4 433.3 203.3 434.1 204.8 435.5 206.9 436.4 209 437.4 211.4 438.8 212.3 439.6 213.1 440.4 214 440.8 214.2 440.6 216.9 437 220.4 430.5 220.4 429 220.4 426.7 218.1 424.5 213.6 422.7 209.5 421 210 421 208.1 422.4ZM777.3 424.6C776.1 425.9 774.6 429 774.1 431.6 772.8 436.9 773.2 437.9 778.1 440.2 783.5 442.7 784.9 442.2 787.5 436.8 788.8 434 789.8 431.2 789.8 430.5 789.8 428.5 788 426.9 785.9 426.9 784.9 426.9 783.1 425.8 781.9 424.5L779.5 422.2 777.3 424.6ZM801.1 424.3C799.2 426.4 798 429 796.9 433.4 796.4 435.5 796.9 436 801.4 438.4L806.4 441.2 808.6 439.1C813.4 434.5 813.7 426.9 809.1 423.7 806.2 421.7 803.4 421.9 801.1 424.3ZM159.4 425.7C157.9 429.5 157.1 434.8 157.9 436.9 158.1 438 159.8 439.6 161.5 440.7 165.5 443.1 169.1 442 170 438.2 170.4 436.9 171.2 434.4 171.9 433 173.6 429.6 173 428.8 165.6 425.6L160.4 423.3 159.4 425.7ZM181.5 427C179.2 432.1 179.1 436 181.3 436.8 182.1 437 184.6 438.1 186.9 439.1 190.6 440.8 190.9 440.9 192.7 439.3 195.1 437.1 197.5 428.8 196.2 427.2 195.1 425.9 187.6 423.1 185 423.1 183.8 423.1 182.6 424.5 181.5 427ZM751.5 427.2C748.1 432.4 748.7 439.8 752.5 439.8 753.2 439.8 755.4 440.5 757.1 441.4 760.3 442.9 760.4 442.8 762.5 440.6 765.1 438.1 766.9 431.6 765.6 429.2 764.4 427.2 759.3 425 755.6 425 753.9 425 752.5 425.7 751.5 427.2ZM160.2 449.7C155.8 458.9 156 459.9 162.1 463.1 167.7 465.8 169.3 465.2 171.8 459.3 174.4 453.2 173.8 451.8 168.5 449.6 166.5 448.8 164.5 447.5 164.3 446.8 163.3 444.4 162.3 445.2 160.2 449.7ZM207.9 448.8C207.6 450.2 206.5 452.4 205.5 453.8 203.2 457 203.8 458.4 208.4 461 213.3 463.8 215.5 463.1 219.6 457.5L223 453 221 451.1C218.7 449 212.6 446.3 210.2 446.3 209.2 446.3 208.3 447.2 207.9 448.8ZM801.7 447.9C800.9 448.8 799.6 451.4 798.8 453.6 796.9 458.5 797.8 460.6 801.9 461.6 803.5 461.9 805.6 463 806.4 463.8 807.9 465.3 808.2 465 812.8 458.1 816.2 453.1 817.2 450.9 816.2 450.9 815.4 450.9 812.8 449.9 810.4 448.6 805.3 445.8 803.5 445.7 801.7 447.9ZM182.9 449.4C182 450.6 181.3 453.7 181.2 456L181 460.3 186.2 462.4C192.3 464.9 194 464.4 195.9 459.6 199 452.3 196.8 448.4 189.1 447.5 184.8 447 184.4 447.2 182.9 449.4ZM779.4 448.2C776.9 449.6 773.1 458.3 774.1 460.2 775.4 462.6 781.3 465.1 783.9 464.4 785.8 463.9 791.7 456.6 791.7 454.5 791.7 453.9 782.3 447.2 781.5 447.2 781.2 447.2 780.3 447.7 779.4 448.2ZM754.4 449.7C751.9 452.7 749.9 457.5 750.2 460 750.4 461.9 751.2 462.7 753.2 463.2 754.8 463.7 757.2 464.6 758.7 465.4 761.7 466.9 763.9 465.8 763.9 463 763.9 462 765 459.9 766.3 458.3 767.7 456.8 768.6 455.4 768.4 455.2 766 453.1 757.9 448.1 756.9 448.1 756.4 448.1 755.2 448.9 754.4 449.7ZM803 470.8C800.7 472.5 797.5 482.1 798.8 483.4 799.3 483.9 801.9 485 804.9 486 809.6 487.7 810.3 487.7 811.6 486.5 812.3 485.6 813 484.3 813 483.4 813 482.5 813.8 480.6 814.9 479.3 817.1 476.4 816.9 475.9 811.6 472.2 806.9 469.1 805.8 468.9 803 470.8ZM185.5 471.5C184.9 472.1 183.8 474.8 182.9 477.5 180.8 483.1 181.6 484.6 186.6 485.6 188.3 485.9 190.2 486.9 190.6 487.8 191.5 489.2 191.8 489.2 193.9 487.1 195.2 485.8 196.3 483.9 196.3 482.6 196.3 481.2 196.9 480.2 198.1 479.9 200.5 479.3 200.5 478.6 198.1 475.6 196.9 474.2 194.3 472.6 191.5 471.8 185.7 470.1 186.5 470.1 185.5 471.5ZM208.4 472C207.9 473.1 207.4 474.6 207.4 475.4 207.4 476.2 206.5 477.8 205.4 478.9 203.5 480.7 203.5 480.9 205.1 482.1 206.1 482.8 207.3 483.3 208 483.3 208.6 483.3 210.5 484.4 212 485.8 214.4 487.7 215.4 488.1 216.6 487.3 218.7 486 221 481.6 221.8 477.5 222.4 474.2 222.3 474 218.9 472.6 212.9 470.1 209.5 469.9 208.4 472ZM161.4 472.7C159.8 473.8 157.4 480.1 157.4 483.3 157.4 484.3 166.9 488.9 169 488.9 170.9 488.9 173 485.8 174.2 481.2 175.1 477.3 175 476.6 173.6 475 172.8 474.1 170.7 473 169.1 472.7 167.5 472.3 165.6 471.9 164.8 471.7 164 471.5 162.5 471.9 161.4 472.7ZM756.3 473.1C753.5 475.3 750.6 481.9 751.4 484.4 751.8 485.4 753.4 486.5 755.6 487 757.6 487.6 759.5 488.6 760 489.4 761.6 492.3 765.7 488 765.7 483.4 765.7 482.4 766.7 481.5 767.9 481.1 769.8 480.6 769.6 480.3 765.1 475.9 762.5 473.3 759.9 471.3 759.4 471.3 759 471.3 757.5 472.1 756.3 473.1ZM778.9 472.5C778.3 473.1 777.6 474.8 777.3 476.2 776.9 477.6 775.7 479.4 774.7 480.1 772.9 481.4 772.9 481.5 774.5 483.2 775.4 484.3 777 485.4 778.1 485.7 779.2 486 781 487.1 782.1 488.2 784.1 489.9 784.4 490 786.5 488.6 788.9 487 792.4 477.1 791 475.9 790.6 475.6 787.9 474.4 785 473.3 781 471.9 779.5 471.7 778.9 472.5ZM210.7 493.7C209.9 494.8 209.3 496.3 209.3 497 209.3 497.7 208.2 499.3 206.9 500.6 205.7 501.8 204.9 503.3 205.2 504 205.4 504.6 208.1 506.5 211.3 508.1 216.8 511 217.1 511 218.6 509.5 219.4 508.6 220.8 505.8 221.7 503.3 223.4 498 222.8 496.8 218 495.8 215.7 495.5 214.4 494.6 214.2 493.4 213.5 491.1 212.5 491.2 210.7 493.7ZM185.8 496.3C183.5 499 181.8 505.6 182.8 507.3 183.6 508.6 193.2 511.4 194.8 510.8 195.6 510.6 196.5 508.8 196.9 506.9 197.1 505.2 198.3 503.1 199.4 502.3 200.8 501.3 201 500.7 200.1 499.6 199.4 498.9 197.8 498 196.3 497.7 194.9 497.4 193 496.3 192 495.3 189.8 492.9 188.5 493.1 185.8 496.3ZM804 494.6C803.4 495.3 802.3 497.5 801.5 499.5 800.6 501.5 799.5 503.4 799 503.7 797 504.9 799.4 507.4 804.4 509.3 811.8 512 811.9 511.9 815.2 504.7 817.3 500.3 817.1 499.7 812.9 496.9 808.1 493.8 805.3 493.1 804 494.6ZM827 494.6C826.6 495.3 825.8 496.9 825.5 498.1 825.1 499.4 824.3 501.4 823.5 502.5 822.4 504.2 822.5 504.7 824.1 506.8 825.1 508.1 827 509.4 828.4 509.6 829.9 510 831.8 510.5 832.8 510.8 834.4 511.3 834.4 510.9 833.9 505 832.9 494.5 832.5 493.5 830.1 493.5 829 493.5 827.6 494.1 827 494.6ZM161.8 496C160.2 497.8 158 506.1 158.8 507.3 159 507.8 161.6 509.3 164.4 510.6L169.6 513.1 171.9 510.8C173.5 509.4 174.4 507.1 174.7 504.3 175.5 498.4 173.8 496.7 166.1 495 164.1 494.5 163 494.8 161.8 496ZM757.8 495.2C757.2 495.6 755.6 498.1 754.3 500.6 753 503.3 751.4 505.6 750.9 505.6 748.9 505.6 751.4 508.3 755.6 510.6 761.9 514.1 763.6 513.5 767 507.3 769.4 502.9 769.7 501.9 768.6 500.6 768 499.7 766.6 499.1 765.6 499.1 764.6 499.1 762.8 498.1 761.5 496.8 758.9 494.2 759.2 494.3 757.8 495.2ZM779.4 498.1C775.4 502.8 774.8 504.8 776.6 507.4 778.2 509.7 783.1 512 786.5 512 788.1 512 789 511.3 789.7 509.1 790.3 507.5 791.4 505.4 792.2 504.5 794.4 502.2 793.2 500.2 789.2 498.5 787.2 497.7 785 496.4 784.2 495.7 782.8 494.5 782.3 494.7 779.4 498.1ZM210.7 518.7C209.9 519.8 209.3 521.4 209.3 522.2 209.3 523 208.6 524.7 207.9 526.2 206.4 529 205.8 528.3 214.4 533.6L218.1 535.9 220.7 531.9C225.6 524 224.9 520.1 217.7 517.7 213.2 516.2 212.3 516.4 210.7 518.7ZM804.4 518.7C801.9 522.8 799.8 528.6 800.3 530 800.6 530.7 802.5 531.9 804.6 532.5 806.8 533.1 809 534.4 809.6 535.4 810.7 536.9 810.9 536.9 812.2 535.5 813.9 533.5 817.6 525.8 817.6 524.4 817.6 523.5 810.4 518.7 806.4 516.9 806.1 516.8 805.2 517.6 804.4 518.7ZM187.8 519.7C186.6 521 184.7 523.5 183.6 525.3L181.7 528.5 183.6 530.4C186 532.5 192 535.2 194.6 535.2 195.6 535.2 196.6 534.4 196.9 533.5 197.2 532.7 198.2 530.2 199.3 528 200.3 525.7 201 523.8 200.7 523.6 200.6 523.4 198.9 522.2 197 521 191.8 517.4 190.1 517.1 187.8 519.7ZM829.3 519.5C828 520.6 826 522.9 824.9 524.6L822.9 528.1 825.1 529.7C832.8 535.6 836.1 535.5 836.1 529.4 836.1 519.1 833.9 515.9 829.3 519.5ZM780.5 520.6C779.9 521.7 779.1 523.6 778.7 524.9 778.4 526.2 777.6 527.3 776.9 527.3 774.4 527.3 775.2 529.3 778.9 532.1 784.2 536.5 787.1 536.2 790.6 531.2 792 529.1 793.5 526.9 793.8 526.3 794.5 525 785.6 518.5 783.1 518.5 782.2 518.5 781 519.4 780.5 520.6ZM163.1 520.6C162.7 521.2 161.9 523.1 161.6 524.8 161.2 526.5 160.4 528.1 159.6 528.4 158.5 528.8 158.6 529.4 160.4 531.3 163.5 534.6 167.9 536.3 170.8 535.2 175.3 533.5 178.6 524.8 175.7 522.5 174.6 521.7 166.9 519.4 165 519.4 164.5 519.4 163.7 520 163.1 520.6ZM755.2 524.1C753.3 526.1 751.9 528.3 751.9 529.1 751.9 529.8 753.1 531.7 754.7 533.2 758.8 537.3 762.5 537.1 767.6 532.6 772.3 528.4 772.2 527.2 766.6 523.1 761.4 519.4 759.3 519.6 755.2 524.1ZM187 545.5C185.1 548.7 184.3 551.1 184.4 553.1 184.7 555.8 185.1 556.1 190.6 557.5 197 559.2 196.7 559.4 199.6 552.1 201.6 547.4 201.3 545.4 198.6 545.4 198.1 545.4 196.1 544.4 194.3 543.1 192.4 541.8 190.6 540.7 190.4 540.7 190.2 540.7 188.7 542.9 187 545.5ZM211.1 543.1C210.6 544.4 210.2 546 210.2 546.6 210.2 547.2 209.5 548.7 208.7 549.8 207.5 551.6 207.5 552.2 208.4 553.3 209.9 555.2 213.6 557 217.3 557.8 220.1 558.4 220.3 558.3 223 552.7L225.7 546.9 223.6 544.8C221.8 543 216.2 540.7 213.1 540.7 212.5 540.7 211.6 541.9 211.1 543.1ZM805.7 542.1C803.6 543.7 800.4 553 801.4 554.5 802.2 555.9 811.7 558.7 813.2 558.1 814.1 557.8 815.2 555.8 815.7 553.7 816.3 551.6 817.3 549.7 818.1 549.4 820 548.6 818.3 545.9 814.1 543.1 810.1 540.4 808.6 540.2 805.7 542.1ZM827.6 542.3C823.3 547.2 823.4 550 827.7 554.1 830.6 556.9 834.3 557.5 836.6 555.6 838.8 553.7 838.4 544.9 836.1 542.6 833.8 540.3 829.4 540.2 827.6 542.3ZM164.5 544.2C163.8 545.1 162.9 546.9 162.5 548.2 162.1 549.6 161.1 551.1 160.1 551.5 158.4 552.2 158.6 552.6 162.2 555.4 166.9 559 169.9 559.9 171.9 558.2 173.5 556.9 179.1 549.1 178.5 548.8 178.4 548.7 176.3 547.2 173.9 545.6 169.1 542.2 166.7 541.9 164.5 544.2ZM780.3 544.3C779.4 545.3 778.4 548.1 778.1 550.6 777.4 556.3 779.4 558.4 785.8 559L790.3 559.4 792.7 554.2C795 549.1 795 548.9 793.4 546.9 792.5 545.6 790.5 544.4 789 544.2 787.5 543.9 785.3 543.3 784.1 543.1 782.6 542.7 781.4 543.1 780.3 544.3ZM757.7 544.6C755.4 547.5 753.1 554.4 753.9 555.8 755.2 558.2 759.7 560.2 763.8 560.2 766.9 560.2 767.8 559.8 768.9 557.6 769.6 556.1 770.4 553.3 770.6 551.5 770.7 548.6 770.4 547.6 768.5 546.2 765.4 543.9 759.1 543 757.7 544.6ZM211.9 567.2C211.4 568.7 210.3 571.3 209.5 572.9 207.8 576.5 208.8 578.2 213.6 580.3 220.8 583.2 224.4 581.1 225.6 573 226.1 569.2 225.9 568.5 223.9 567.2 222.7 566.4 219.7 565.5 217.3 565.2 213.2 564.6 213 564.7 211.9 567.2ZM828.1 567.1C827.2 568.6 826.5 571.5 826.5 573.9 826.4 578 826.5 578.1 829.6 579 831.4 579.4 833.6 580.5 834.5 581.3 835.8 582.4 836.6 582.6 837.8 581.8 839.1 580.9 839.4 579.4 839.3 573.7 839.2 569.8 838.9 566.4 838.7 566.2 838.4 565.9 836.4 565.5 834.1 565.2 830.2 564.6 829.7 564.8 828.1 567.1ZM164.9 567.8C164.4 569 163.3 571.7 162.5 573.9 160.9 577.6 160.9 577.9 162.4 579.5 164.4 581.7 171.4 583.7 173.9 583 176.3 582.1 178.2 576.5 177.9 571 177.8 570 176.2 568.6 173.9 567.6 168.5 565.2 165.9 565.3 164.9 567.8ZM187.5 567.9C186.8 569.1 185.8 571.9 185.6 574.3L184.9 578.5 188.8 579.7C190.9 580.4 193.1 581.4 193.6 582.1 196.1 585 199.4 582.2 201.5 575.5 203.1 570 202.1 568.1 197.4 566.7 191.9 565.2 189.1 565.5 187.5 567.9ZM804.6 567.1C803 569.1 801.9 576 802.9 578 803.5 579.2 810.6 581.5 813.9 581.5 815.5 581.5 817.5 578.6 818.4 575.3 819.7 570.8 818 568.1 813.2 566.8 808.4 565.4 806 565.5 804.6 567.1ZM780.2 569.2C778.2 573.1 777.6 577.5 778.6 579.4 779.7 581.6 784.2 583.3 788.4 583.3 791.2 583.3 791.6 583 793.4 577.7 795.1 573.1 795.3 571.9 794.4 570.7 792.5 568.4 788.2 566.7 784.8 566.7 782.1 566.7 781.3 567.1 780.2 569.2ZM756.9 569.7C756.1 571 755.4 574.1 755.3 576.5L755.1 580.7 759.1 581.9C761.2 582.6 763.7 583.7 764.4 584.4 765.7 585.4 766.3 585.2 768.1 583.1 769.3 581.7 770.6 578.7 770.9 576.3 771.8 570.7 769.6 568.4 763.1 567.8 759 567.4 758.3 567.6 756.9 569.7ZM212.6 590C211.9 591.2 210.7 594 210.2 596.2 209.3 599.9 209.3 600.5 210.7 601.6 211.7 602.2 213.1 602.8 214 602.8 214.8 602.8 216.6 603.6 218 604.7L220.4 606.6 223.1 603.9C226 600.9 227.7 595.1 226.2 592.7 225.1 590.8 221.8 589.3 217.4 588.5 214.4 588 213.8 588.2 212.6 590ZM829 590.4C828.1 591.8 827.4 594.7 827.4 597 827.3 601.2 827.4 601.3 831.2 602.8 833.4 603.6 835.6 604.7 836.3 605.4 837.1 606.2 837.8 606.1 839.1 604.9 840.4 603.7 840.7 602 840.7 596.8L840.7 590 836.7 589C831 587.6 830.8 587.6 829 590.4ZM189.4 590.9C188.6 592 188 593.4 188 594 188 594.4 187.3 596.1 186.6 597.6 185.3 600.1 185.3 600.5 187.1 602.4 188.8 604.2 195 606.5 198.1 606.5 199.8 606.5 202.8 600.6 202.8 597 202.8 593.1 201.1 591.1 196.5 589.8 191.7 588.5 191 588.6 189.4 590.9ZM806.1 590.3C804.6 591.8 802.8 597.3 802.8 600.3 802.8 601.2 803.9 602.3 805.4 602.9 806.8 603.4 809.1 604.4 810.5 605.2 811.9 605.9 813.7 606.5 814.4 606.5 817.4 606.5 821.1 596.6 819.4 593.3 817.6 590.1 808.4 588 806.1 590.3ZM782.4 592.2C781.9 593.5 781.5 595.2 781.5 595.9 781.5 596.6 780.6 597.7 779.6 598.3 778.6 599 777.8 599.8 777.8 600.2 777.8 601.7 781.9 604.6 784.1 604.6 785.5 604.6 786.5 605.3 786.8 606.5 787.4 608.8 790 608.9 791.9 606.7 792.7 605.8 794.2 602.9 795.3 600.2L797.1 595.2 791.2 592.5C783.9 589.3 783.5 589.2 782.4 592.2ZM164.4 594.6C163.5 596.8 162.1 599 161.4 599.6 160 600.6 160.2 600.8 162.6 602.3 164.1 603.2 166.4 604.7 167.8 605.6 173.1 609.4 176.8 607.2 178.5 599.4 179.6 594.6 179.2 593.9 174.2 592.1 167.6 589.8 166.1 590.2 164.4 594.6ZM760 592.3C757.6 595.1 755.5 600 755.7 602.1 755.9 603.6 757.1 604.5 759.7 605.4 761.8 606 763.9 607.1 764.4 608 766.5 610.6 770.4 606.6 770.4 601.9 770.4 600.6 771 600 772.2 600 775.1 600 774.4 598.6 769.8 594.5 765.2 590.5 762.2 589.8 760 592.3ZM168.3 613.6C166.4 615.8 163 622.8 163 624.4 163 625.3 165.4 627.1 168.4 628.6 174.6 631.9 175.5 631.6 178.7 625.3 181 620.6 180.3 618.4 175.6 616.1 174 615.3 172 614 171.2 613.3 169.9 612.2 169.5 612.2 168.3 613.6ZM784.4 614.2C783.3 615.4 781.9 617.6 781.4 619.2 780.2 622.9 782.2 627.8 786.4 630.7L789.2 632.8 792.8 628.8C796.7 624.4 797.2 621.2 794.5 618.7 792.3 616.7 786.9 612 786.7 612 786.5 612 785.6 613 784.4 614.2ZM830 614.4C829.2 615.6 828.2 618.5 828 620.8 827.6 624.7 827.7 625 830.2 625.9 831.7 626.4 834.1 627.4 835.5 628.2 837.4 629.3 838.6 629.4 839.9 628.7 841.4 627.9 841.7 626.7 841.7 620.5 841.7 613.7 841.5 613.1 839.6 612.6 834.9 611.4 831.6 611.9 830 614.4ZM189.8 615.4C189.4 616.9 188.2 619.3 187.5 620.7 186.1 623.2 186.1 623.6 187.7 625.1 188.6 625.9 191.3 627.5 193.7 628.5L198.1 630.5 201.4 626.1C205.3 621.1 205.4 618.1 201.8 615.5 200.4 614.5 197.4 613.4 195 613.2 191 612.8 190.7 612.9 189.8 615.4ZM760.8 616.5C756.1 621.3 756.2 624.2 761.3 629.4 763.4 631.6 765.7 633.3 766.3 633.3 766.9 633.3 768.5 632 769.8 630.5 773.4 626.2 773.1 621.4 768.9 616.7 767 614.6 765.3 613 764.9 613 764.5 613 762.7 614.5 760.8 616.5ZM807.8 614.1C807.3 614.7 806 617.1 804.9 619.4L802.8 623.6 804.7 625.3C805.8 626.1 807.8 627.1 809.2 627.4 810.5 627.7 812.6 628.3 813.8 628.8 815.3 629.4 816.4 629.4 817.1 628.7 818.3 627.8 820.4 620.2 820.4 617.1 820.4 614 809.4 611.4 807.8 614.1ZM146.5 622.9C146.8 630.9 146.8 631 149.2 631.3 151.3 631.6 152 630.9 154.5 626.3 156.1 623.3 157.4 620.6 157.4 620.4 157.4 619.7 148.1 614.8 146.9 614.8 146.6 614.8 146.4 618.4 146.5 622.9ZM191.4 637.8C189.7 639.7 188 644.9 188 647.8 188 649.4 188.7 650.2 191.8 651.1 193.9 651.7 196 653 196.6 653.8 198.1 656.1 200 654.9 201.9 650.4 202.9 648.1 204.1 646.3 204.6 646.3 206.1 646.3 205.7 641.9 204.2 640.4 203.3 639.5 200.9 638.5 198.8 638 196.7 637.4 194.4 636.8 193.8 636.6 193.2 636.4 192.1 636.9 191.4 637.8ZM785.3 638.5C783.5 640.7 783.1 641.9 783.4 644.2 783.4 644.5 782.6 645.2 781.5 645.6 778.3 646.8 779.6 649.2 784.8 651.8 787.4 653.1 790.3 654.7 791.1 655.5 792.4 656.6 792.8 656.2 794.5 652.2 795.6 649.7 797 647.3 797.8 646.9 800.7 645.3 799.2 642.5 794 640.3 791.2 639 788.9 637.6 788.9 637 788.9 635.4 787.2 636 785.3 638.5ZM834.5 637.5C833.4 638.2 831.3 640.9 829.7 643.4L826.9 648.1 830.9 649.9C835.3 652 838.1 652.3 840.8 650.9 842.2 650.1 842.6 648.9 842.6 644.4 842.6 639.3 842.4 638.9 839.8 637.5 836.6 635.8 836.9 635.8 834.5 637.5ZM168.1 638.5C167.3 639.3 166.7 640.4 166.7 640.9 166.7 641.4 165.9 643.3 165.1 645.1 162.8 650 165.3 652.7 173.2 654.2 177.5 654.9 179.3 653.2 180.1 647.8 180.9 642.5 180.1 640.2 177 639.1 172 637.1 169.6 637 168.1 638.5ZM807.2 640.9C805.3 643.1 803.7 645 803.7 645.4 803.7 645.6 805.6 647.7 807.8 649.9 813.1 655.1 816.3 655 819 649.5 820 647.5 821.4 645.5 822 645.1 824.4 643.6 816.5 637 812.4 637 811.6 637 809.3 638.8 807.2 640.9ZM147 647.1L147.3 655.6 150.5 655.6C154.1 655.6 155.8 653.1 156.9 646.8 157.7 642.1 155.9 640.2 150.5 639.4L146.8 638.7 147 647.1ZM193.1 662.3C188.1 666.6 188.3 669.4 193.8 674.8 197.9 678.9 198.1 679 200.3 677.5 202.6 676 205.6 670.7 205.6 668 205.6 666.5 198.8 659.3 197.4 659.3 197 659.3 195.2 660.6 193.1 662.3ZM833.1 660.9C832.1 661.9 831.5 663.7 831.5 665 831.5 666.7 830.8 667.5 829.5 667.9 826.6 668.6 828.8 671.8 833.8 674 836.1 675 838 676.3 838 676.8 838 677.3 838.7 677.8 839.6 677.8 842 677.8 843.5 674 843.5 667.7L843.5 662.2 839.8 660.7C835.1 658.9 834.9 658.9 833.1 660.9ZM807.9 665.4C804.9 671.9 805 673 808.1 674.3 813.9 676.8 815.6 678.6 815.6 681.9 815.5 684.7 815.3 685 813.7 684.2 811.6 683.1 809.6 684.3 808.7 687.3 808.4 688.4 807.5 690.1 806.8 690.9 805.6 692.2 805.6 692.9 806.7 695 807.6 696.9 809.3 698.1 813.6 699.5L819.3 701.6 820.4 697.3C820.9 695 821.8 692.4 822.1 691.7 822.7 690.7 821.9 689.2 819.8 686.8 818 684.8 816.7 682.3 816.7 681 816.7 677.8 820.3 670 822.6 668.4 823.1 668.1 823.1 666.8 822.8 665.4 822.3 663.5 821.2 662.8 817.4 661.6 814.8 660.8 812 660.2 811.4 660.2 810.7 660.2 809.2 662.5 807.9 665.4ZM168.2 662.8C166.2 665 164.7 672.1 165.8 674.3 166.3 675.2 166.9 675.9 167 675.9 167.2 675.9 169.5 676.3 172.1 676.9 178 678 180 677.1 181.4 673.1 183.4 667.2 182.9 665.9 177.2 663.4 171 660.6 170.2 660.6 168.2 662.8ZM784.4 664.3C781.8 668.3 781.9 672.3 784.5 674.7 787.6 677.6 792.9 680.1 793.3 678.9 793.5 678.3 794.9 676.4 796.4 674.4 797.9 672.5 799.1 669.9 799.1 668.4 799.1 666.2 798.3 665.6 794.1 663.5 787.5 660.5 786.7 660.5 784.4 664.3ZM147.9 669.6C148.3 675 148.9 677.6 150.1 678.8 151.6 680.3 151.8 680.3 154 678 156.7 675.1 158.3 671.3 158.3 668 158.3 665.6 155.8 664.1 149.8 662.6L147.4 662 147.9 669.6ZM194.5 683.9C192 685.7 189.8 690.6 189.8 694.4 189.8 697.5 191.2 698.5 197 699.8 201.9 700.9 204.2 699.4 205 694.4 205.4 692.2 206.2 690.5 207.1 690.1 208.4 689.5 208.4 689.4 206.9 688.2 205.9 687.6 204.4 687 203.5 687 202.5 687 200.7 686 199.4 684.7 196.7 681.9 197.2 682 194.5 683.9ZM833.7 686.5C829.8 690.4 829.6 693.5 833 696.2 834.4 697.3 836 698.1 836.7 698.1 837.3 698.1 838.2 698.8 838.7 699.6 839.2 700.5 840.4 700.9 841.3 700.7 842.8 700.5 843.1 699.4 843.3 693.3L843.6 686.3 840.6 684.8C839 684 837.5 683.3 837.2 683.3 837 683.3 835.5 684.7 833.7 686.5ZM169.9 685.7C169.2 686.6 168.5 687.8 168.5 688.5 168.5 689.3 167.5 690.9 166.2 692.2 165 693.4 164.2 695 164.4 695.6 164.9 697 174.5 702.8 176.3 702.8 178.7 702.8 180.8 700.2 182 695.6 183.8 688.5 183.6 688.2 174.4 685.3 171.9 684.5 171 684.6 169.9 685.7ZM764.1 686.7C761.7 688.3 759.3 692.6 759.3 695.2 759.3 696.2 760.3 697.7 761.6 698.5 765.8 701.3 766.1 704 763 711.8 758.9 721.9 759.1 722.8 765.3 724.5 771.8 726.5 773.3 726.1 774.3 722.6 774.6 721 775.6 719.2 776.4 718.5 779.1 716.3 778 714.3 773.1 712.2 767.7 709.9 767.3 708.2 771.2 703.4 777 695.9 777.1 691.2 771.4 687.3 767.7 684.8 766.9 684.7 764.1 686.7ZM786.4 686.3C785.7 687.4 783.8 692.2 782.8 695.4 782.2 696.9 790.3 702.8 792.8 702.8 794.4 702.8 797.2 699.9 797.2 698.4 797.2 697.9 798.2 696 799.4 694.2 802 690.4 801.9 690.1 795.3 687.1 790.6 684.9 787.5 684.7 786.4 686.3ZM148.5 690.9C148.8 693.6 149.1 697.2 149.1 698.8 149.1 701.5 149.4 701.9 151.6 701.9 153.2 701.9 155.2 700.6 157.7 698L161.4 694.1 157.1 690.1C154.3 687.4 152 686.1 150.4 686.1 148 686.1 147.9 686.2 148.5 690.9ZM811.8 708.1C810.8 709.1 810.2 710.4 810.2 711.1 810.2 711.8 809.4 713.7 808.2 715.5 805.7 719.4 806.7 720.6 813.6 722.9 819.2 724.6 821.6 724 822 720.5 822.2 719.4 823.3 717.9 824.5 717 827.3 715.2 826.7 713.3 822.3 711.1 820.4 710.2 818.3 708.7 817.7 708 816 706 813.6 706.1 811.8 708.1ZM835.4 707.7C834.7 708.4 834 710.3 833.7 711.9 833.3 713.5 832.6 714.8 831.9 714.8 827.6 714.8 830.6 719.6 836 721.4 837.9 721.9 840.1 723.1 840.9 723.8 843.4 726 844.8 722.3 844.1 715.4 843.5 710.5 843.1 709.5 840.9 708.5 836.7 706.4 836.5 706.4 835.4 707.7ZM169.6 711.9C166.2 715.5 165.4 715.9 162.7 715.5 160.9 715.2 157.6 713.7 155.1 712.1 152.6 710.6 150.2 709.3 149.8 709.3 149.4 709.3 149.1 712.8 149.1 717 149.1 725.4 150 727.2 153.8 726.7 155.8 726.4 156.4 725.7 158.5 720.8 160 717.4 162.8 716.8 164.7 719.4 165.6 720.4 167.9 721.8 169.9 722.4 174.5 723.9 175 726.2 171.9 731.7 167.6 739.2 167.9 743.9 172.9 748.5 175.3 750.7 175.5 750.8 177.8 749.4 186.6 743.8 187.5 739.3 181 733.1 178.7 731 176.9 728.8 176.9 728.4 176.9 728 178.1 726.1 179.6 724.4 183.7 719.7 183.4 715.6 178.8 711 176.9 709 174.8 707.5 174.4 707.5 174 707.6 171.9 709.5 169.6 711.9ZM192.5 712.6C189.3 718.4 189.4 719.7 194 722.2 198.5 724.7 198.8 726.1 195.5 731.1 191.9 736.6 191.3 738.7 192.5 741.9 193.3 744.2 200.9 750 203 750 203.3 750 204.3 748.7 205.1 747.2 205.9 745.6 206.3 744.4 205.9 744.4 205.6 744.4 206.3 743.1 207.3 741.3 209.8 737.3 209.7 736.5 206.9 735.7 203.4 734.8 199.9 731 200.6 729 200.9 728.1 202.9 724.4 204.8 721 206.9 717.5 208.2 714.2 208.1 713.5 207.4 711.9 199.4 707.4 197.1 707.4 196.1 707.4 194.4 709.4 192.5 712.6ZM787.7 709C787.5 709.4 786.8 711.4 786.1 713.4 785.5 715.5 784.5 717.6 784.2 718.1 782.1 720.6 786.3 724 793.2 725.5 796 726 796.2 725.9 798.9 720.3L801.7 714.5 799.5 712.4C796.8 709.6 788.7 707.3 787.7 709ZM811.8 731.9C810.1 733.5 808.3 739 808.3 742.3 808.3 745 811.6 747 816.9 747.8 821 748.3 821.3 748.2 822.3 745.7 822.9 744.3 823.9 741.8 824.5 740.2 825.9 736.9 825.1 734.8 821.5 733 817 730.7 813.3 730.3 811.8 731.9ZM836.8 731.6C834.6 732.9 832.4 738 832.4 741.7 832.4 744.8 833.7 745.6 840.6 746.8L844.6 747.4 844 741.1C842.9 730.8 841.4 728.9 836.8 731.6ZM787.9 734.8C787.3 736.3 786.5 738.4 786 739.5 785.6 740.7 784.8 741.7 784.3 741.7 783.7 741.7 783.7 742.5 784.4 743.9 785.6 746.5 791.1 749.1 795.3 749.1 797.6 749.1 798.1 748.5 799.2 745.6 799.7 743.7 800.6 741.6 801.1 741 801.7 740.4 801.9 738.9 801.5 737.6 800.9 735.3 798.1 733.8 792.4 732.8 789.3 732.2 788.9 732.4 787.9 734.8ZM149.2 735.4C149.2 737.4 149.3 737.4 150 735.6 150.5 734.5 150.6 736.4 150.3 740.6 149.8 746.9 149.9 747.3 152.2 749.5L154.6 751.8 156.9 749.7C158.2 748.6 159.9 745.7 160.6 743.4 162.2 737.9 161 735.8 155.2 734.4 149.5 733 149.1 733.1 149.2 735.4ZM763.6 735C762.8 735.8 761.8 738.4 761.2 740.6 760.5 744.1 760.6 744.8 762.1 746.4 763.1 747.3 764.6 748.1 765.6 748.1 766.5 748.1 768.1 748.8 769.3 749.6 772.6 751.9 775.5 749.5 776.9 743.1 778.3 736.9 777.8 735.6 773.4 734.4 768.3 732.9 765.3 733.1 763.6 735ZM197.4 755.1C195.7 756.5 194 759.4 193.1 762.1 191.1 767.8 191.6 768.4 199 770.8 204 772.5 204.1 772.5 205.7 770.4 206.7 769.3 207.4 767.7 207.4 766.9 207.4 766 208.3 764.4 209.4 763.2 211.9 760.7 211.2 759.8 206 758.1 204 757.3 201.9 755.8 201.3 754.7L200.3 752.7 197.4 755.1ZM172.8 755.7C171.9 756.9 171.3 758.2 171.3 758.8 171.3 759.4 170.5 761.4 169.4 763.3 167.4 766.9 167.5 769.4 169.7 769.4 170.4 769.4 172.5 770.3 174.5 771.3 179.5 773.9 181.2 773.6 183.3 770.1 186.3 765.3 185.7 762.9 180.6 758.1 178.1 755.6 175.6 753.7 175.1 753.7 174.6 753.7 173.5 754.6 172.8 755.7ZM835.6 758.8C833.9 761.7 832.4 764.5 832.4 765.2 832.4 767.3 838.4 770.5 842.8 770.6L846.8 770.8 846.5 764.4C846.1 757.6 845.6 756.6 841.5 754.8 839 753.8 838.8 754 835.6 758.8ZM811.1 757.4C810.6 758.3 809.9 761 809.6 763.1 808.9 768.6 811.2 770.7 817.8 770.8 822.8 770.8 822.8 770.8 825.6 764.5 826.8 761.7 826.9 760.8 825.8 759.6 822.4 755.5 813 754 811.1 757.4ZM150.1 757.3C149.4 757.8 148.7 760.6 148.4 764.4 148 770.1 148.1 771 149.8 772.6 152.9 775.3 155.8 773.9 159.6 767.9L162.9 762.7 158.1 759.6C152.9 756.3 152 756.1 150.1 757.3ZM766.9 758.5C765.2 760.5 761.1 767.8 761.1 769 761.1 770.1 767.6 772.2 770.8 772.2 773.2 772.2 775 771.4 777.5 769.1L780.9 766 778.3 762.9C775.6 759.5 771.5 756.5 769.8 756.5 769.3 756.5 768 757.4 766.9 758.5ZM789.1 757.6C788.6 758.2 787.9 760.2 787.5 761.9 787.1 763.8 786.2 765.2 785.2 765.5 782.6 766.1 784 768.3 787.8 769.4 789.7 770.1 792.1 771.6 793.2 773L795.2 775.3 798 772.5C800.7 769.8 803.3 763 802.5 760.6 802 759.5 794 756.5 791.4 756.5 790.6 756.5 789.6 757 789.1 757.6ZM220.1 779.4C218.4 781.3 216.7 786.2 216.7 789.2 216.7 790.3 218.1 791.5 221.1 792.7 223.5 793.7 226.1 795.2 226.9 795.9 228.1 797 228.7 796.5 231.4 791.3 233.1 788 234.3 784.6 234.1 783.7 233.6 781.4 229.7 778.9 225.5 778.2 222.4 777.8 221.4 778.1 220.1 779.4ZM790.9 781C789.3 782.8 787.9 785 787.9 785.9 787.5 791 789.4 794.4 793.9 796.8 797.8 798.9 799.4 798 801 792.8 801.7 790.9 802.8 788.9 803.5 788.3 805.7 786.8 804.2 784.4 799.6 782.4 797.4 781.5 795.2 780 794.7 779.2 794 777.9 793.4 778.1 790.9 781ZM838.2 778.9C837.7 779.5 836.9 781.1 836.6 782.4 836.2 783.7 835.3 785.5 834.4 786.4 833.1 787.9 833.2 788.2 836.1 791.2 839.8 795 841.9 795.8 844.4 794.5 848.1 792.5 849.1 790.6 849.1 786.1 849.1 782.4 848.7 781.5 846.8 780.2 843.4 778 839.4 777.4 838.2 778.9ZM196.9 780.7C196 781.9 195.4 783.2 195.4 783.7 195.4 784.2 194.4 785.6 193.4 786.8 191.7 788.5 191.6 789.1 192.7 790.4 193.8 791.8 203 796.3 204.6 796.3 205.4 796.3 211.1 785.6 211.1 784.3 211.1 783.2 201.9 778.7 200 778.7 199 778.7 197.6 779.6 196.9 780.7ZM815.6 779.6C814.7 780.2 812.8 782.4 811.2 784.7L808.4 788.8 812.1 792C816.1 795.7 819.5 796.3 823 793.9 824.2 793.1 825 791.5 825 790.1 825 788.5 825.6 787.6 826.9 787.3 829.4 786.7 828.9 785.5 824.9 782.3 821.2 779.4 817.8 778.3 815.6 779.6ZM173.3 780.7C172.9 781.4 171.6 783.7 170.6 785.9L168.7 789.8 171.5 792.6C176.4 797.6 181.9 797.4 185.1 792.2 188.9 786.1 187.1 782.3 179.6 780.6 174.4 779.4 174.4 779.4 173.3 780.7ZM764.8 783.3C764.2 785 763.5 788.1 763.5 790.1 763.4 793.7 763.6 794 766.8 794.9 768.6 795.4 770.7 796.4 771.6 797 775 799.9 778.4 795.9 779.4 787.8 779.8 783.6 779.7 783.3 777.2 782.4 775.7 781.8 772.6 781.1 770.3 780.8 766.2 780.4 766 780.5 764.8 783.3ZM149.1 785.5C144.8 789.4 144.8 792.3 149 795.1 150.7 796.3 153 797.2 154.1 797.2 156.9 797.2 161.4 794.3 162.9 791.3 164.2 789 164.1 788.7 161.1 785.6 156.9 781.4 153.5 781.4 149.1 785.5ZM840.2 800.7C839.6 801.1 838.2 803.3 837.2 805.7 834.7 811.5 832.7 811.5 826.8 806 821.7 801.3 818 800.6 814.7 803.8 813.2 805.3 813 806.6 813.1 810.5 813.4 814.7 813.8 815.5 816.7 817.4 821 820.3 824.1 819.8 825.4 816 825.9 814.4 827.1 812.3 828 811.4 829.5 809.9 829.7 809.9 832.1 811.9 835.4 814.4 844.1 818.5 846.4 818.5 847.4 818.5 848.1 818 848.1 817.3 848.1 816.7 849 814.6 850 812.7 852.3 808.4 852.4 805.6 850.3 805 848.4 804.4 845.8 803.1 843.1 801.3 842 800.6 840.7 800.4 840.2 800.7ZM196.9 806.2C195 809.2 193.5 811.9 193.5 812.3 193.5 815 203.1 820.2 206 819.1 206.8 818.8 208.5 816.2 209.8 813.4 212.3 808 211.9 805.6 208.4 805.6 207.5 805.6 205.5 804.5 203.7 803.2 201.9 801.9 200.5 800.9 200.4 800.9 200.3 800.9 198.6 803.3 196.9 806.2ZM221.5 803.4C220.7 804.8 218.5 813.8 218.5 815.3 218.5 815.6 220.2 816 222.2 816.3 224.4 816.7 225.9 817.4 225.9 818.1 225.9 819.8 229.2 819.8 230.8 818.1 231.6 817.4 232.9 814.6 233.7 811.9 235.6 806.2 235.2 805.6 228.3 803.3 222.6 801.5 222.5 801.5 221.5 803.4ZM792.4 803.4C790.3 805.8 786.8 814.5 787.4 815.6 788.2 816.9 796.1 820.4 798.2 820.4 800.6 820.4 803 816.5 803.4 811.8 804 807.3 803 805.9 798.7 805.2 797.3 804.9 795.6 804.1 795 803.2 794 801.9 793.8 801.9 792.4 803.4ZM172.4 808.3C170.7 811.4 169.4 814.1 169.4 814.4 169.4 814.6 170.8 815.4 172.5 816 174.1 816.8 176.3 818.2 177.2 819.4 179 821.3 179 821.4 176.1 826.9 172.2 834.1 172.2 838.1 175.9 841.8 180 845.8 183.1 845.2 185.8 839.8 188.7 833.9 188.5 831.8 185 829.6 178.8 826 178.6 825.5 181.9 821.6 184.3 818.7 188.1 809.4 187.5 808.3 186.9 807.4 177.4 802.8 176.2 802.8 175.7 802.8 174 805.3 172.4 808.3ZM149.6 805.7C148 808.4 146 815.5 146.8 816.7 147 817 148.8 818 150.7 818.6 152.6 819.2 154.8 820.3 155.6 821 158.8 823.7 162.5 819.4 163.5 811.8 164.1 807.8 164.1 807.7 160.6 806.3 153.4 803.5 151.2 803.3 149.6 805.7ZM766.2 807.8C765.5 809.5 764.4 811.2 763.9 811.6 763.4 811.9 763 813.1 763 814.4 763 816.3 763.8 817.1 767.3 818.6 769.7 819.6 772 821 772.5 821.6 773.4 823.1 780.6 815 780.6 812.4 780.6 810.2 778.7 808.3 774.4 806.1 769.7 803.8 767.7 804.2 766.2 807.8ZM223.7 824.5C223 825.3 222.1 827.1 221.8 828.7 221.4 830.2 220.3 832.1 219.2 832.9 215.1 835.7 220.9 841.3 228.9 841.9 231.8 842.1 231.9 841.9 234 836.4 235.8 831.2 235.9 830.5 234.6 829.2 233.8 828.4 232.4 827.8 231.4 827.8 230.4 827.8 228.5 826.8 227.3 825.6 225.3 823.5 224.8 823.4 223.7 824.5ZM840 826.9C838.9 828 838 829.5 838 830.6 838 831.5 837.3 832.7 836.5 833.1 835.4 833.8 835.1 834.7 835.6 836.4 836 838.2 837 839.1 840.1 839.9 842.2 840.6 844.5 841.5 845.3 842 846.7 843.1 846.9 842.8 851.4 835.8 852.7 833.9 853.7 831.9 853.7 831.5 853.7 830.4 845.4 825 843.5 825 842.7 825 841.1 825.8 840 826.9ZM198.2 828.3C195.9 831.3 194.8 836.8 196 838.8 197.1 840.6 205 843.6 206.9 843 207.6 842.7 209 840.4 210 837.9 211.1 835.4 212.4 833.3 213 833.3 214.8 833.3 212.9 831.5 208.1 828.7 202.1 825.3 200.6 825.3 198.2 828.3ZM814.4 830.7C811.4 837.2 811.5 838.3 815.2 840.6 818.3 842.6 820.9 843.1 823.6 842 825.1 841.5 830.6 834.1 830.6 832.7 830.5 831.2 821.6 825.9 819.1 825.9 816.9 825.9 816.2 826.7 814.4 830.7ZM768.7 830.4C766.6 832.4 764.8 834.6 764.8 835.4 764.8 838.6 771.9 846.3 774.9 846.3 776.6 846.3 781.5 838.8 781.5 836.3 781.5 834.2 775.2 826.9 773.2 826.9 772.9 826.9 770.8 828.4 768.7 830.4ZM793.9 827.6C791.8 828.9 788.9 834.8 788.9 837.7 788.9 840.4 789.3 840.7 792.6 841.7 794.5 842.2 796.7 843.3 797.1 844.3 798 845.7 798.1 845.7 799.9 844 801.6 842.3 806.8 833.1 806.2 832.8 797.8 826.7 796.2 826 793.9 827.6ZM150.7 829.4C149.1 831.2 146.9 839.4 147.7 840.7 148 841.2 149.7 842 151.7 842.7 153.5 843.2 155.8 844.4 156.8 845.2 158.1 846.5 158.5 846.4 160.2 844.9 162.5 842.9 165.1 836.1 164.6 833.2 164.4 830.7 161.6 829.2 156 828.2 153.1 827.8 151.9 828.1 150.7 829.4ZM840.5 849.5C839.6 850.3 838.2 853.2 837.4 856.1 835.6 861.5 836.2 863.3 839.9 864.1 841.9 864.4 853.1 854 852.4 852.3 852.1 851.6 850.3 850.6 848.1 850 846 849.4 843.8 848.8 843.1 848.5 842.4 848.2 841.2 848.7 840.5 849.5ZM198.4 854.5C196.8 857.6 195.4 860.5 195.4 860.9 195.4 861.5 197.7 863.1 200.6 864.8 205 867.3 206.2 867.6 208 866.8 210.2 865.8 210.6 864.9 210.3 861.8 210.1 860.8 211 859.8 212.4 859.3 215.4 858.1 215.4 857.3 212.8 854.9 210.9 853.3 203 849.1 201.8 849.1 201.6 849.1 200 851.6 198.4 854.5ZM223.3 850.2C222.7 850.8 222.2 852.2 222.2 853.3 222.2 855.5 220.5 857.9 218.3 858.5 216.6 859.2 218.4 861.1 222.3 862.7 224.4 863.4 226.6 864.9 227.2 865.9 229.1 868.6 231.4 866.9 234.5 860.7 237.7 854.4 237.1 852.7 230.8 850.6 225.6 848.8 224.8 848.7 223.3 850.2ZM793 852.3C792.3 854.1 791.7 855.9 791.7 856.4 791.7 856.9 790.8 857.9 789.7 858.7 788.3 859.6 788 860.6 788.4 861.9 789.1 864.2 795.8 867.6 799.7 867.6 802.4 867.6 802.7 867.2 804.5 861.9 806.8 855.4 806.4 854.5 801 853 799.1 852.3 797.1 851.2 796.9 850.5 796 848.1 794.4 848.9 793 852.3ZM816.3 851.1C814.4 852.7 813.7 854.4 813.2 858.1L812.7 863 816.3 864.4C818.3 865.2 820.8 866.3 821.9 866.9 824.8 868.2 826.3 866.8 828.7 860.4 830.9 854.5 830.7 853.4 827.1 851.6 821.9 848.9 819 848.8 816.3 851.1ZM770.6 852C768 855.1 765.7 859.7 765.7 862.5 765.7 864.4 766.5 865.2 769.3 866.4 771.1 867.2 774.1 867.9 775.8 868 778.7 868.1 779.1 867.8 779.8 864.8 780.3 863.1 781.5 860.8 782.5 860 784.9 858 784.2 856.8 779.1 854.5 776.8 853.6 774.7 852.2 774.4 851.4 773.7 849.5 772.9 849.6 770.6 852ZM174.6 853C173.8 854.2 172.9 857 172.6 859.4L172 863.4 177.7 866C182.1 868.1 183.7 868.4 185.2 867.6 187.1 866.6 190.2 857.7 189.4 855.5 188.5 853.3 185.4 851.8 180.6 851.2 176.6 850.7 175.9 850.9 174.6 853ZM150.7 854.3C149.6 856.6 149.9 857 155.4 862.1 158.5 865.2 161.5 867.6 161.9 867.6 163.1 867.6 166 860.6 166 857.8 166 855.1 164.9 854.2 160.2 852.8 154.5 851.2 151.9 851.6 150.7 854.3ZM225.2 872.4C224.5 873.1 224.1 874.3 224.1 875.1 224.1 876 223.1 878 221.8 879.4 220.4 881.1 219.6 882.9 220 883.7 220.9 886 230.5 890.3 232.3 889.2 234.3 888 236.1 884.2 236.8 880 237.3 876.4 236.3 875 232.7 875 231.5 875 230.1 874.2 229.4 873.1 228.1 871 226.8 870.8 225.2 872.4ZM176.1 875.2C173.8 877.5 175.1 880.1 181 885 186.7 889.6 186.9 889.7 187.5 887.8 187.9 886.6 189.1 884.7 190.1 883.5L191.9 881.5 189.7 879.1C185.8 874.8 178.6 872.7 176.1 875.2ZM200.1 876.4C198.6 877.7 197 879.5 196.8 880.6 196 882.9 198.6 886.8 201.9 888.5 205 890.1 207.2 889.3 212.9 884.5 215.6 882.2 215.8 881.6 215 879.9 213.5 877.3 208.2 874.1 205.3 874.1 204 874.1 201.7 875.1 200.1 876.4ZM770.2 876.1C768.1 877.7 766.7 881.7 766.7 885.6 766.7 888.5 767 888.9 770.2 889.7 772 890.3 774.5 891.3 775.6 892.1 777.4 893.3 777.8 893.3 780 891.1 784.3 886.8 784.4 879 780.2 877 776.2 875.3 771.9 874.8 770.2 876.1ZM792.2 879.3C791.3 881.8 790.6 884.5 790.5 885.6 790.2 887.9 794.4 890.7 798.8 891.4 801.9 891.8 802.8 891.6 804.4 889.4 805.4 888.1 806.5 885.4 806.9 883.2 807.7 877.9 805.6 875.7 798.8 875.2L793.8 874.8 792.2 879.3ZM745.4 879.3C744.7 880.7 743.7 883.1 743 884.5 741.3 887.9 741.7 888.4 747.2 891.2 749.7 892.5 752 894 752.4 894.5 753.3 896.1 759.3 886.3 759.3 883.1 759.3 879.9 756.1 877.7 750.5 877 746.7 876.7 746.3 876.8 745.4 879.3ZM225.6 897.7C224.8 898.4 223.9 900.4 223.6 902 223.2 903.7 222.5 905.6 221.9 906.3 220.8 907.7 220.6 907.4 226.6 911.1 232 914.4 234.1 914.3 236.3 910.5 238.1 907.3 239.1 901.8 238.1 900.4 236.2 897.4 227.7 895.6 225.6 897.7ZM747.9 900.4C746.2 902.1 743.2 910 743.8 911.4 744.1 912 746.7 913.7 749.5 915.3L754.8 918.1 757 915.5C761.8 910 761.1 904.9 755.3 901.4 750.6 898.7 749.7 898.6 747.9 900.4ZM769.4 901.9C768.2 904.1 767.6 906.3 767.8 908.7 768.1 912 768.3 912.3 772.6 914L777.2 915.6 780.3 913.3C783.4 910.9 784.6 908.2 784.1 904.5 783.8 902 780.3 900 774.9 899.4 771.7 898.9 771.2 899.1 769.4 901.9Z", + "width": 1000 + }, + "search": [ + "roboticon" + ] } ] } \ No newline at end of file diff --git a/assets/app_icons/d_q_icons_icons.dart b/assets/app_icons/d_q_icons_icons.dart deleted file mode 100644 index 5d1ff3c6..00000000 --- a/assets/app_icons/d_q_icons_icons.dart +++ /dev/null @@ -1,43 +0,0 @@ -/// Flutter icons DQIcons -/// Copyright (C) 2020 by original authors @ fluttericon.com, fontello.com -/// This font was generated by FlutterIcon.com, which is derived from Fontello. -/// -/// To use this font, place it in your fonts/ directory and include the -/// following in your pubspec.yaml -/// -/// flutter: -/// fonts: -/// - family: DQIcons -/// fonts: -/// - asset: fonts/DQIcons.ttf -/// -/// -/// -import 'package:flutter/widgets.dart'; - -class DQIcons { - DQIcons._(); - - static const _kFontFam = 'DQIcons'; - static const _kFontPkg = null; - - static const IconData blood_pressure = IconData(0xe800, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData blood = IconData(0xe801, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData bmi = IconData(0xe802, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData heart = IconData(0xe803, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData height = IconData(0xe804, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData outline = IconData(0xe805, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData thermometer = IconData(0xe806, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData weight_scale = IconData(0xe807, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData parking_icon = IconData(0xe808, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData blood_type_icon = IconData(0xe809, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData height_icon = IconData(0xe80a, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData online_payment_icon = IconData(0xe80b, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData search_medicine_icon = IconData(0xe80c, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData vital_sign_icon = IconData(0xe80d, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData weight_icon = IconData(0xe80e, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData my_medical_file = IconData(0xe80f, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData family = IconData(0xe810, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData calendar__2_ = IconData(0xe811, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData roboticon = IconData(0xe812, fontFamily: _kFontFam, fontPackage: _kFontPkg); -} diff --git a/assets/app_icons/fonts/DQIcons.ttf b/assets/app_icons/fonts/DQIcons.ttf index 3cff7aa3aa160db15e3bed25202bd55176c2d0d6..bc92c83de143966170d64f05992da0c9495e33f0 100644 GIT binary patch delta 13481 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 Gpi=-6LRoA8 diff --git a/lib/config/localized_values.dart b/lib/config/localized_values.dart index 6464db31..ecc3cf37 100644 --- a/lib/config/localized_values.dart +++ b/lib/config/localized_values.dart @@ -1079,5 +1079,9 @@ const Map localizedValues = { "Through this service, you will be able to link your family medical files to your medical file so that you can manage their records by login to your medical file.", "ar": "هذه الخدمة تم تصميمها لتتمكن من ربط الملفات الطبية للعائلة بملفك الطبي حتى تتمكن من إدارة سجلاتهم عن طريق تسجيل الدخول إلى ملفك الطبي." - } + }, +"help": { +"en": "Help", +"ar": "مساعدة" +} }; diff --git a/lib/d_q_icons_icons.dart b/lib/d_q_icons_icons.dart index c3b64559..5d1ff3c6 100644 --- a/lib/d_q_icons_icons.dart +++ b/lib/d_q_icons_icons.dart @@ -39,4 +39,5 @@ class DQIcons { static const IconData my_medical_file = IconData(0xe80f, fontFamily: _kFontFam, fontPackage: _kFontPkg); static const IconData family = IconData(0xe810, fontFamily: _kFontFam, fontPackage: _kFontPkg); static const IconData calendar__2_ = IconData(0xe811, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData roboticon = IconData(0xe812, fontFamily: _kFontFam, fontPackage: _kFontPkg); } diff --git a/lib/pages/AlHabibMedicalService/all_habib_medical_service_page.dart b/lib/pages/AlHabibMedicalService/all_habib_medical_service_page.dart index 49c49811..00052db4 100644 --- a/lib/pages/AlHabibMedicalService/all_habib_medical_service_page.dart +++ b/lib/pages/AlHabibMedicalService/all_habib_medical_service_page.dart @@ -65,6 +65,7 @@ class _AllHabibMedicalServiceState extends State { isShowAppBar: true, appBarTitle: TranslationBase.of(context).alhabiServices, isShowDecPage: false, + isHelp:false, body: Column( children: [ Expanded( diff --git a/lib/uitl/translations_delegate_base.dart b/lib/uitl/translations_delegate_base.dart index 57804e4a..d8d29429 100644 --- a/lib/uitl/translations_delegate_base.dart +++ b/lib/uitl/translations_delegate_base.dart @@ -1033,6 +1033,7 @@ class TranslationBase { localizedValues['info-my-appointments'][locale.languageCode]; String get infoTodo => localizedValues['info-todo'][locale.languageCode]; String get familyInfo => localizedValues['family-info'][locale.languageCode]; + String get help => localizedValues['help'][locale.languageCode]; } class TranslationBaseDelegate extends LocalizationsDelegate { diff --git a/lib/widgets/bottom_navigation/bottom_nav_bar.dart b/lib/widgets/bottom_navigation/bottom_nav_bar.dart index 21cbebba..89d892f7 100644 --- a/lib/widgets/bottom_navigation/bottom_nav_bar.dart +++ b/lib/widgets/bottom_navigation/bottom_nav_bar.dart @@ -4,7 +4,7 @@ import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:eva_icons_flutter/eva_icons_flutter.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; - +import 'package:diplomaticquarterapp/services/robo_search/event_provider.dart'; import '../../d_q_icons_icons.dart'; import 'bottom_navigation_item.dart'; @@ -19,9 +19,12 @@ class BottomNavBar extends StatefulWidget { class _BottomNavBarState extends State { int _index = 0; - + var event = RobotProvider(); _changeIndex(int index) { widget.changeIndex(index); + if(_index==0){ + event.setValue({'isRobotVisible':'true'}); + } } @override @@ -36,14 +39,7 @@ class _BottomNavBarState extends State { mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ - BottomNavigationItem( - icon: EvaIcons.home, - activeIcon: EvaIcons.home, - changeIndex: _changeIndex, - index: widget.index, - currentIndex: 0, - name: TranslationBase.of(context).home, - ), + BottomNavigationItem( icon: DQIcons.my_medical_file, activeIcon: DQIcons.my_medical_file, @@ -52,28 +48,6 @@ class _BottomNavBarState extends State { currentIndex: 1, name: TranslationBase.of(context).medicalProfile, ), - if(widget.index == 0) - Expanded( - child: SizedBox( - height: 50, - child: Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - SizedBox(height: 22), - ], - ), - ), - ), - if(widget.index != 0) - BottomNavigationItem( - icon: EvaIcons.calendar, - activeIcon: EvaIcons.calendar, - changeIndex: _changeIndex, - index: _index, - currentIndex: 2, - name: TranslationBase.of(context).bookAppo, - ), BottomNavigationItem( icon: DQIcons.family, @@ -83,6 +57,29 @@ class _BottomNavBarState extends State { currentIndex: 3, name: TranslationBase.of(context).myFamily, ), + if(widget.index == 0) + Expanded( + child: SizedBox( + height: 50, + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox(height: 22), + ], + ), + ), + ), + if(widget.index != 0) + BottomNavigationItem( + icon: EvaIcons.calendar, + activeIcon: EvaIcons.calendar, + changeIndex: _changeIndex, + index: _index, + currentIndex: 2, + name: TranslationBase.of(context).bookAppo, + ), + BottomNavigationItem( icon: EvaIcons.calendar, activeIcon: EvaIcons.calendar, @@ -90,6 +87,14 @@ class _BottomNavBarState extends State { index: widget.index, currentIndex: 4, name: TranslationBase.of(context).todoList, + ), + BottomNavigationItem( + icon: DQIcons.roboticon, + activeIcon: DQIcons.roboticon, + changeIndex: _changeIndex, + index: widget.index, + currentIndex: 0, + name: TranslationBase.of(context).help, ) ], ), diff --git a/lib/widgets/others/app_scaffold_widget.dart b/lib/widgets/others/app_scaffold_widget.dart index 4691332d..bb5323f4 100644 --- a/lib/widgets/others/app_scaffold_widget.dart +++ b/lib/widgets/others/app_scaffold_widget.dart @@ -16,14 +16,14 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:provider/provider.dart'; - +import 'package:animated_text_kit/animated_text_kit.dart'; import '../../locator.dart'; import 'floating_button_search.dart'; import '../progress_indicator/app_loader_widget.dart'; import 'arrow_back.dart'; import 'network_base_view.dart'; import 'not_auh_page.dart'; - +import 'package:diplomaticquarterapp/widgets/weather_slider/weather_slider.dart'; class AppScaffold extends StatelessWidget { final String appBarTitle; final Widget body; @@ -40,7 +40,7 @@ class AppScaffold extends StatelessWidget { final bool isShowDecPage; final List infoList; final Color backgroundColor; - + final bool isHelp; AuthenticatedUserObject authenticatedUserObject = locator(); @@ -59,7 +59,9 @@ class AppScaffold extends StatelessWidget { this.backgroundColor, this.isBottomBar, this.image, - this.infoList}); + this.infoList, + this.isHelp + }); @override Widget build(BuildContext context) { @@ -138,7 +140,7 @@ class AppScaffold extends StatelessWidget { // floatingActionButton: floatingActionButton ?? floatingActionButton, // bottomNavigationBar: // this.isBottomBar == true ? BottomBarSearch() : SizedBox() - floatingActionButton: FloatingSearchButton(), + //floatingActionButton: FloatingSearchButton(), ); } @@ -149,7 +151,60 @@ class AppScaffold extends StatelessWidget { buildBodyWidget() { // return body; //Stack(children: [body, buildAppLoaderWidget(isLoading)]); return Stack(children: [ - body, /*FloatingSearchButton()*/ + body, + isHelp?? Positioned( + + child:Column(children: [ + Container( + height:100, + width:150, + padding:EdgeInsets.all(5), + margin: EdgeInsets.only(right: 10.0, bottom: 0), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: Colors.white, + boxShadow: [ + BoxShadow(color: Colors.grey, spreadRadius: 3), + ], + ), + child: TyperAnimatedTextKit( + onTap: () { + + }, + text: [ + "Discipline is the best tool", + "Design first, then code", + "Do not patch bugs out, rewrite them", + "Do not test bugs out, design them out", + ], + textStyle: TextStyle( + fontSize: 14.0, + color:Colors.black54 + + ), + speed:Duration(milliseconds: 100), + textAlign: TextAlign.start, + alignment: AlignmentDirectional.topStart // or Alignment.topLeft + )), + + Positioned(child:Stack(children: [ + Positioned( + top:0, + right:50, + + child: Container( + + height: 0, + width:0, + decoration: ShapeDecoration( + color: Colors.grey, + shape: MessageBorder(reverse: true), + ))), + FloatingSearchButton() + ],)) + ],), left:SizeConfig.screenWidth -160, bottom:50) + + /*FloatingSearchButton()*/ ]); } } diff --git a/lib/widgets/others/bottom_bar.dart b/lib/widgets/others/bottom_bar.dart index 0615a7c8..68311f71 100644 --- a/lib/widgets/others/bottom_bar.dart +++ b/lib/widgets/others/bottom_bar.dart @@ -55,7 +55,7 @@ class BottomBarSearch extends StatefulWidget { class _SearchBot extends State { SearchProvider searchProvider = new SearchProvider(); - RobotProvider eventProvider = RobotProvider(); + RobotProvider Provider = RobotProvider(); bool isLoading = false; bool isError = false; final SpeechToText speech = SpeechToText(); diff --git a/lib/widgets/others/floating_button_search.dart b/lib/widgets/others/floating_button_search.dart index dc987e99..3c432de3 100644 --- a/lib/widgets/others/floating_button_search.dart +++ b/lib/widgets/others/floating_button_search.dart @@ -1,6 +1,7 @@ import 'dart:collection'; import 'dart:io'; import 'dart:math'; + import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; @@ -93,24 +94,30 @@ class _FloatingSearchButton extends State bool _hasSpeech = false; ProjectViewModel projectProvider; + AnimationController controller; + Animation offset; + @override void initState() { - // event.controller.stream.listen((p) { - // if (p['isRobot'] == 'true') { - // if (this.mounted) { - // setState(() { - // position = Offset(250, 400); - // activeAnimation = false; - // }); - // } - // } - // }); - + controller = + AnimationController(vsync: this, duration: Duration(seconds: 1)); + offset = Tween(begin: Offset.zero, end: Offset(0.0, 1.0)) + .animate(controller); + controller.reverse(); Future.delayed(const Duration(seconds: 2), () { requestPermissions(); - getUserData(); }); + controller.reverse(); + event.controller.stream.listen((p) { + if (p['isRobotVisible'] == 'true') { + if (this.mounted) { + setState(() { + controller.reverse(); + }); + } + } + }); super.initState(); } @@ -119,19 +126,19 @@ class _FloatingSearchButton extends State Widget build(BuildContext context) { projectProvider = Provider.of(context); return Container( - child: isShow ? getStack() : Stack(children: [Container()])); + child: + SlideTransition( + position: offset, + child: getStack())); } Widget getStack() { return Container( height: 150, width: 150, - margin: EdgeInsets.only(right: 0.0), + margin: EdgeInsets.only(left: 20.0), child: Stack(children: [ - // Column( - // mainAxisSize: MainAxisSize.min, - // crossAxisAlignment: CrossAxisAlignment.stretch, - // children: [ + GestureDetector( child: Container( child: Image.asset('assets/images/gif/robot-idle.gif'), @@ -140,8 +147,6 @@ class _FloatingSearchButton extends State initSpeechState().then((value) => {startVoiceSearch()}); }, ), - // ], - // ), Positioned( left: 15.0, top: 10, @@ -149,7 +154,8 @@ class _FloatingSearchButton extends State onTap: () { setState(() { if (this.mounted) { - isShow = false; + controller.forward(); + //isShow = false; } }); }, diff --git a/lib/widgets/weather_slider/weather_slider.dart b/lib/widgets/weather_slider/weather_slider.dart index 61d5c1d5..024b9240 100644 --- a/lib/widgets/weather_slider/weather_slider.dart +++ b/lib/widgets/weather_slider/weather_slider.dart @@ -163,8 +163,8 @@ class WeatherSlider extends StatelessWidget { } class MessageBorder extends ShapeBorder { final bool usePadding; - - MessageBorder({this.usePadding = true}); + final bool reverse; + MessageBorder({this.usePadding = true, this.reverse =false}); @override EdgeInsetsGeometry get dimensions => EdgeInsets.only(bottom: usePadding? 0 : 0); @@ -175,12 +175,22 @@ class MessageBorder extends ShapeBorder { @override Path getOuterPath(Rect rect, {TextDirection textDirection}) { rect = Rect.fromPoints(rect.bottomRight, rect.bottomLeft - Offset(0, 0)); - return Path() - ..addRRect(RRect.fromRectAndRadius(rect, Radius.circular(rect.height / 2))) - ..moveTo(rect.topCenter.dx - 10, rect.topCenter.dy) - ..relativeLineTo(10, -10) - ..relativeLineTo(10,10) - ..close(); + if(!reverse) { + return Path() + ..addRRect( + RRect.fromRectAndRadius(rect, Radius.circular(rect.height / 2))) + ..moveTo(rect.topCenter.dx - 10, rect.topCenter.dy) + ..relativeLineTo(10, -10)..relativeLineTo(10, 10) + ..close(); + }else{ + return Path() + ..addRRect( + RRect.fromRectAndRadius(rect, Radius.circular(rect.height / 2))) + ..moveTo(rect.topCenter.dx, rect.topCenter.dy) + ..relativeLineTo(10, 20) + ..relativeLineTo(20, -20) + ..close(); + } } @override diff --git a/pubspec.yaml b/pubspec.yaml index ae514553..d5646aad 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -143,7 +143,7 @@ dependencies: screen: ^0.0.5 #google maps places google_maps_place_picker: ^1.0.0 - + animated_text_kit: ^2.5.4 #Dependencies for video call implementation native_device_orientation: ^0.3.0 enum_to_string: ^1.0.9 From f083912d4398735e7c7bbae56670218c7d7408db Mon Sep 17 00:00:00 2001 From: Sultan Khan Date: Tue, 8 Dec 2020 14:56:26 +0300 Subject: [PATCH 17/71] voice command updated --- lib/widgets/typewriter/typewiter.dart | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 lib/widgets/typewriter/typewiter.dart diff --git a/lib/widgets/typewriter/typewiter.dart b/lib/widgets/typewriter/typewiter.dart new file mode 100644 index 00000000..e69de29b From c050c3f18939e5081af494b96aff7d99f6208906 Mon Sep 17 00:00:00 2001 From: Sultan Khan Date: Tue, 8 Dec 2020 14:56:34 +0300 Subject: [PATCH 18/71] voice command updated --- android/app/build.gradle | 8 +- lib/config/localized_values.dart | 7 +- lib/pages/landing/home_page.dart | 1 + lib/uitl/translations_delegate_base.dart | 3 + .../bottom_navigation/bottom_nav_bar.dart | 5 +- lib/widgets/drawer/app_drawer_widget.dart | 544 ++++++++---------- .../others/app_scaffold_pharmacy_widget.dart | 2 - lib/widgets/others/app_scaffold_widget.dart | 149 +++-- .../others/floating_button_search.dart | 212 ++++--- lib/widgets/typewriter/typewiter.dart | 72 +++ pubspec.yaml | 5 +- 11 files changed, 549 insertions(+), 459 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 54ea9373..06128dc0 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -7,9 +7,9 @@ if (localPropertiesFile.exists()) { } def flutterRoot = localProperties.getProperty('flutter.sdk') -if (flutterRoot == null) { - throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") -} +//if (flutterRoot == null) { +// throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +//} def flutterVersionCode = localProperties.getProperty('flutter.versionCode') if (flutterVersionCode == null) { @@ -74,7 +74,7 @@ dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "com.google.firebase:firebase-messaging:20.3.0" implementation 'pub.devrel:easypermissions:0.4.0' - implementation 'com.google.firebase:firebase-inappmessaging-display:17.2.0' +// implementation 'com.google.firebase:firebase-inappmessaging-display:17.2.0' implementation 'com.google.guava:guava:27.0.1-android' // Dependency on local binaries implementation fileTree(dir: 'libs', include: ['*.jar']) diff --git a/lib/config/localized_values.dart b/lib/config/localized_values.dart index 41d9d64a..af1bd592 100644 --- a/lib/config/localized_values.dart +++ b/lib/config/localized_values.dart @@ -1170,5 +1170,10 @@ const Map localizedValues = { "ar": "هذه الخدمة تم تصميمها لتتمكن من ربط الملفات الطبية للعائلة بملفك الطبي حتى تتمكن من إدارة سجلاتهم عن طريق تسجيل الدخول إلى ملفك الطبي." }, - "help": {"en": "Help", "ar": "مساعدة"} + "help": {"en": "Help", "ar": "مساعدة"}, + + "habibRobotText":{ + "en":"Hi, This is HABIB, your personal assistant. I'm here to assist you by voice commands. How can I help?", + "ar":"مرحباً ، معك حبيب مساعدك الشخصي. أنا هنا لمساعدتك بالأوامر الصوتية." + } }; diff --git a/lib/pages/landing/home_page.dart b/lib/pages/landing/home_page.dart index b8cf64bb..20e678b7 100644 --- a/lib/pages/landing/home_page.dart +++ b/lib/pages/landing/home_page.dart @@ -63,6 +63,7 @@ class _HomePageState extends State { onModelReady: (model) => model.getPatientRadOrders(), builder: (_, model, wi) => AppScaffold( isShowDecPage: false, + isHelp:true, body: Container( width: double.infinity, child: SingleChildScrollView( diff --git a/lib/uitl/translations_delegate_base.dart b/lib/uitl/translations_delegate_base.dart index 1cc06c7b..22ad9459 100644 --- a/lib/uitl/translations_delegate_base.dart +++ b/lib/uitl/translations_delegate_base.dart @@ -1127,6 +1127,9 @@ class TranslationBase { String get infoTodo => localizedValues['info-todo'][locale.languageCode]; String get familyInfo => localizedValues['family-info'][locale.languageCode]; String get help => localizedValues['help'][locale.languageCode]; + String get habibRobotText => localizedValues['habibRobotText'][locale.languageCode]; + + } class TranslationBaseDelegate extends LocalizationsDelegate { diff --git a/lib/widgets/bottom_navigation/bottom_nav_bar.dart b/lib/widgets/bottom_navigation/bottom_nav_bar.dart index 89d892f7..9d65d4b0 100644 --- a/lib/widgets/bottom_navigation/bottom_nav_bar.dart +++ b/lib/widgets/bottom_navigation/bottom_nav_bar.dart @@ -35,7 +35,8 @@ class _BottomNavBarState extends State { color: Colors.white, child: Padding( padding: EdgeInsets.symmetric(horizontal: 18), - child: Row( + child: Directionality( + textDirection:TextDirection.ltr, child:Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ @@ -97,7 +98,7 @@ class _BottomNavBarState extends State { name: TranslationBase.of(context).help, ) ], - ), + )), ), ); } diff --git a/lib/widgets/drawer/app_drawer_widget.dart b/lib/widgets/drawer/app_drawer_widget.dart index a45cba96..47e8b892 100644 --- a/lib/widgets/drawer/app_drawer_widget.dart +++ b/lib/widgets/drawer/app_drawer_widget.dart @@ -41,19 +41,15 @@ class _AppDrawerState extends State { var familyFileProvider = FamilyFilesProvider(); AuthenticatedUser user; AuthenticatedUser mainUser; - AuthenticatedUserObject authenticatedUserObject = locator< - AuthenticatedUserObject>(); + AuthenticatedUserObject authenticatedUserObject = + locator(); VitalSignService _vitalSignService = locator(); - @override Widget build(BuildContext context) { projectProvider = Provider.of(context); return SizedBox( - width: MediaQuery - .of(context) - .size - .width * 0.75, + width: MediaQuery.of(context).size.width * 0.75, child: Container( color: Colors.white, child: Drawer( @@ -72,67 +68,66 @@ class _AppDrawerState extends State { children: [ Container( child: - Image.asset('assets/images/DQ/DQ_logo.png'), + Image.asset('assets/images/DQ/DQ_logo.png'), margin: EdgeInsets.all( SizeConfig.imageSizeMultiplier * 4), ), (user != null && projectProvider.isLogin) ? Padding( - padding: EdgeInsets.all(15), - child: Column( - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - Row( + padding: EdgeInsets.all(15), + child: Column( + mainAxisAlignment: + MainAxisAlignment.start, children: [ - Padding( - padding: EdgeInsets.only( - right: 5), - child: Icon( - Icons.account_circle, + Row( + children: [ + Padding( + padding: EdgeInsets.only( + right: 5), + child: Icon( + Icons.account_circle, + color: Color(0xFF40ACC9), + )), + AppText( + user.firstName + + ' ' + + user.lastName, color: Color(0xFF40ACC9), - )), - AppText( - user.firstName + - ' ' + - user.lastName, - color: Color(0xFF40ACC9), - ) - ], - ), - Row(children: [ - Padding( - padding: EdgeInsets.only( - left: 30, top: 5), - child: Column( - children: [ - AppText( - TranslationBase - .of( - context) - .fileno + - ": " + - user.patientID - .toString(), - color: - Color(0xFF40ACC9), - fontSize: SizeConfig - .textMultiplier * - 1.5, - ), - AppText( - user.bloodGroup != null - ? 'Blood Group: ' + - user.bloodGroup - : '', - fontSize: SizeConfig - .textMultiplier * - 1.5, - ), - ], - )) - ]) - ])) + ) + ], + ), + Row(children: [ + Padding( + padding: EdgeInsets.only( + left: 30, top: 5), + child: Column( + children: [ + AppText( + TranslationBase.of( + context) + .fileno + + ": " + + user.patientID + .toString(), + color: + Color(0xFF40ACC9), + fontSize: SizeConfig + .textMultiplier * + 1.5, + ), + AppText( + user.bloodGroup != null + ? 'Blood Group: ' + + user.bloodGroup + : '', + fontSize: SizeConfig + .textMultiplier * + 1.5, + ), + ], + )) + ]) + ])) : SizedBox(), ], ), @@ -144,9 +139,7 @@ class _AppDrawerState extends State { children: [ InkWell( child: DrawerItem( - TranslationBase - .of(context) - .arabicChange, + TranslationBase.of(context).arabicChange, Icons.translate), onTap: () { // Navigator.of(context).pushNamed( @@ -161,263 +154,195 @@ class _AppDrawerState extends State { ), (user != null && projectProvider.isLogin) ? Column( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - user.isFamily == null || user.isFamily == false - ? InkWell( - child: DrawerItem( - TranslationBase - .of(context) - .family, - Icons.group, - textColor: Color(0xFF40ACC9), - iconColor: Color(0xFF40ACC9), - bottomLine: false, - sideArrow: true, - ), - onTap: () { - Navigator.of(context).pushNamed( - MY_FAMILIY, - ); - }, - ) - : SizedBox(), - FutureBuilder( - future: getFamilyFiles(), // async work - builder: (BuildContext context, - AsyncSnapshot< - GetAllSharedRecordsByStatusResponse> - snapshot) { - switch (snapshot.connectionState) { - case ConnectionState.waiting: - return Padding( - padding: EdgeInsets.all(10), - child: Text('Loading....')); - default: - if (snapshot.hasError) - return Padding( - padding: EdgeInsets.all(10), - child: Text(snapshot.error)); - else - return Container( - decoration: BoxDecoration( - border: Border( - bottom: BorderSide( - // <--- left side - color: Colors.grey[200], - width: 1.0, - ), - )), - child: Column( - children: [ - user.isFamily == true - ? Container( - padding: - EdgeInsets.only( - bottom: 5), - child: InkWell( - onTap: () { - switchUser( - mainUser, - context); - }, - child: Row( - crossAxisAlignment: - CrossAxisAlignment - .start, - children: < - Widget>[ - Expanded( - child: Icon( - Icons - .person), - ), - Expanded( - flex: 7, - child: Column( - crossAxisAlignment: - CrossAxisAlignment - .start, - children: < - Widget>[ - AppText( - mainUser - .firstName + - ' ' + - mainUser - .lastName), - AppText( - TranslationBase - .of( - context) - .fileno + - ": " + - mainUser - .patientID - .toString()), - ])), - ], - ))) - : SizedBox(), - Column( - mainAxisAlignment: - MainAxisAlignment - .start, - mainAxisSize: - MainAxisSize.min, - children: snapshot.data - .getAllSharedRecordsByStatusList - .map( - (result) { - return result - .status == - 3 - ? Container( - padding: EdgeInsets - .only( - bottom: - 5), + mainAxisAlignment: MainAxisAlignment.start, + children: [ + user.isFamily == null || + user.isFamily == false + ? InkWell( + child: DrawerItem( + TranslationBase.of(context).family, + Icons.group, + textColor: Color(0xFF40ACC9), + iconColor: Color(0xFF40ACC9), + bottomLine: false, + sideArrow: true, + ), + onTap: () { + Navigator.of(context).pushNamed( + MY_FAMILIY, + ); + }, + ) + : SizedBox(), + FutureBuilder( + future: getFamilyFiles(), // async work + builder: (BuildContext context, + AsyncSnapshot< + GetAllSharedRecordsByStatusResponse> + snapshot) { + switch (snapshot.connectionState) { + case ConnectionState.waiting: + return Padding( + padding: EdgeInsets.all(10), + child: Text('Loading....')); + default: + if (snapshot.hasError) + return Padding( + padding: EdgeInsets.all(10), + child: Text(snapshot.error)); + else + return Container( + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + // <--- left side + color: Colors.grey[200], + width: 1.0, + ), + )), + child: Column( + children: [ + user.isFamily == true + ? Container( + padding: + EdgeInsets.only( + bottom: 5), child: InkWell( onTap: () { switchUser( - result, + mainUser, context); }, child: Row( crossAxisAlignment: - CrossAxisAlignment - .start, + CrossAxisAlignment + .start, children: < Widget>[ Expanded( - child: - Icon(Icons - .person, - color: result - .responseID == - user - .patientID - ? Color( - 0xFF40ACC9) - : Colors - .black), + child: Icon( + Icons + .person), ), Expanded( flex: 7, - child: Padding( - padding: EdgeInsets - .only( - left: 5, - right: 5), - child: Column( - crossAxisAlignment: CrossAxisAlignment - .start, - children: < - Widget>[ - AppText( - result - .patientName, - color: result - .responseID == - user - .patientID - ? Color( - 0xFF40ACC9) - : Colors - .black), - AppText( - TranslationBase - .of( - context) - .fileno + - ": " + - result - .iD - .toString(), - color: result - .responseID == - user - .patientID - ? Color( - 0xFF40ACC9) - : Colors - .black), - ]))), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + AppText(mainUser.firstName + ' ' + mainUser.lastName), + AppText(TranslationBase.of(context).fileno + ": " + mainUser.patientID.toString()), + ])), ], ))) - : SizedBox(); - }).toList()) - ], - )); - } - }, - ), - InkWell( - child: DrawerItem( - TranslationBase - .of(context) - .notification, - Icons.notifications), - onTap: () { - //NotificationsPage - Navigator.of(context).pop(); - Navigator.push( - context, - MaterialPageRoute( - builder: (BuildContext context) => - NotificationsPage())); - }, - ), - InkWell( - child: DrawerItem( - TranslationBase - .of(context) - .appsetting, - Icons.settings_input_composite), - onTap: () { - Navigator.of(context).pushNamed( - SETTINGS, - ); - }, - ), - InkWell( - child: DrawerItem( - TranslationBase - .of(context) - .rateApp, - Icons.star), - onTap: () { - if (Platform.isIOS) { - launch( - "https://apps.apple.com/sa/app/dr-suliaman-alhabib/id733503978"); - } else { - launch( - "https://play.google.com/store/apps/details?id=com.ejada.hmg&hl=en"); - } - }, - ), - InkWell( - child: DrawerItem( - TranslationBase - .of(context) - .logout, - Icons.lock_open), - onTap: () { - logout(); - }, - ) - ], - ) + : SizedBox(), + Column( + mainAxisAlignment: + MainAxisAlignment + .start, + mainAxisSize: + MainAxisSize.min, + children: snapshot.data + .getAllSharedRecordsByStatusList + .map( + (result) { + return result + .status == + 3 + ? Container( + padding: EdgeInsets + .only( + bottom: + 5), + child: InkWell( + onTap: () { + switchUser( + result, + context); + }, + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + children: < + Widget>[ + Expanded( + child: + Icon(Icons.person, color: result.responseID == user.patientID ? Color(0xFF40ACC9) : Colors.black), + ), + Expanded( + flex: 7, + child: Padding( + padding: EdgeInsets.only(left: 5, right: 5), + child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + AppText(result.patientName, color: result.responseID == user.patientID ? Color(0xFF40ACC9) : Colors.black), + AppText(TranslationBase.of(context).fileno + ": " + result.iD.toString(), color: result.responseID == user.patientID ? Color(0xFF40ACC9) : Colors.black), + ]))), + ], + ))) + : SizedBox(); + }).toList()) + ], + )); + } + }, + ), + InkWell( + child: DrawerItem( + TranslationBase.of(context) + .notification, + Icons.notifications), + onTap: () { + //NotificationsPage + Navigator.of(context).pop(); + Navigator.push( + context, + MaterialPageRoute( + builder: (BuildContext context) => + NotificationsPage())); + }, + ), + InkWell( + child: DrawerItem( + TranslationBase.of(context).appsetting, + Icons.settings_input_composite), + onTap: () { + Navigator.of(context).pushNamed( + SETTINGS, + ); + }, + ), + InkWell( + child: DrawerItem( + TranslationBase.of(context).rateApp, + Icons.star), + onTap: () { + if (Platform.isIOS) { + launch( + "https://apps.apple.com/sa/app/dr-suliaman-alhabib/id733503978"); + } else { + launch( + "https://play.google.com/store/apps/details?id=com.ejada.hmg&hl=en"); + } + }, + ), + InkWell( + child: DrawerItem( + TranslationBase.of(context).logout, + Icons.lock_open), + onTap: () { + logout(); + }, + ) + ], + ) : InkWell( - child: DrawerItem( - TranslationBase - .of(context) - .loginregister, - Icons.lock_open), - onTap: () { - login(); - }, - ), + child: DrawerItem( + TranslationBase.of(context).loginregister, + Icons.lock_open), + onTap: () { + login(); + }, + ), ], ) ], @@ -436,9 +361,7 @@ class _AppDrawerState extends State { children: [ Column( children: [ - Text(TranslationBase - .of(context) - .poweredBy), + Text(TranslationBase.of(context).poweredBy), Image.asset( 'assets/images/cs_logo_container.png', width: SizeConfig.imageSizeMultiplier * 30, @@ -527,12 +450,11 @@ class _AppDrawerState extends State { this .familyFileProvider .silentLoggin(user is AuthenticatedUser ? null : user, - mainUser: user is AuthenticatedUser) + mainUser: user is AuthenticatedUser) .then((value) { GifLoaderDialogUtils.hideDialog(context); loginAfter(value, context); - }) - .catchError((err) { + }).catchError((err) { GifLoaderDialogUtils.hideDialog(context); print(err); AppToast.showErrorToast(message: err); diff --git a/lib/widgets/others/app_scaffold_pharmacy_widget.dart b/lib/widgets/others/app_scaffold_pharmacy_widget.dart index 764089e9..3121dca3 100644 --- a/lib/widgets/others/app_scaffold_pharmacy_widget.dart +++ b/lib/widgets/others/app_scaffold_pharmacy_widget.dart @@ -8,8 +8,6 @@ import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/others/bottom_bar.dart'; import 'package:diplomaticquarterapp/widgets/progress_indicator/app_loader_widget.dart'; import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; -import 'package:diplomaticquarterapp/widgets/robo-search/robosearch.dart'; -import 'package:diplomaticquarterapp/widgets/robo-search/search.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; diff --git a/lib/widgets/others/app_scaffold_widget.dart b/lib/widgets/others/app_scaffold_widget.dart index 23c5cae1..e0e89b45 100644 --- a/lib/widgets/others/app_scaffold_widget.dart +++ b/lib/widgets/others/app_scaffold_widget.dart @@ -12,18 +12,20 @@ import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/others/bottom_bar.dart'; import 'package:diplomaticquarterapp/widgets/progress_indicator/app_loader_widget.dart'; import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; +import 'package:diplomaticquarterapp/widgets/weather_slider/weather_slider.dart'; +import 'package:diplomaticquarterapp/widgets/typewriter/typewiter.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:provider/provider.dart'; -import 'package:animated_text_kit/animated_text_kit.dart'; +import 'package:diplomaticquarterapp/services/robo_search/event_provider.dart'; import '../../locator.dart'; import 'floating_button_search.dart'; import '../progress_indicator/app_loader_widget.dart'; import 'arrow_back.dart'; import 'network_base_view.dart'; import 'not_auh_page.dart'; -import 'package:diplomaticquarterapp/widgets/weather_slider/weather_slider.dart'; + class AppScaffold extends StatelessWidget { final String appBarTitle; @@ -47,9 +49,12 @@ class AppScaffold extends StatelessWidget { final List appBarIcons; final PreferredSizeWidget appBarWidget; + + ProjectViewModel projectProvider; AuthenticatedUserObject authenticatedUserObject = locator(); + AppScaffold( {@required this.body, this.appBarTitle = '', @@ -70,13 +75,14 @@ class AppScaffold extends StatelessWidget { this.appBarWidget, this.image, this.infoList, - this.isHelp}); + this.isHelp =false}); @override Widget build(BuildContext context) { AppGlobal.context = context; PreferredSizeWidget appBar; + projectProvider = Provider.of(context); if (this.appBarWidget == null) { PreferredSizeWidget appBarWidget = AppBarWidget( appBarTitle, @@ -108,10 +114,10 @@ class AppScaffold extends StatelessWidget { ) : baseViewModel != null ? NetworkBaseView( - child: buildBodyWidget(), + child: buildBodyWidget(context), baseViewModel: baseViewModel, ) - : buildBodyWidget(), + : buildBodyWidget(context), bottomSheet: bottomSheet, // floatingActionButton: floatingActionButton ?? floatingActionButton, // bottomNavigationBar: @@ -124,61 +130,12 @@ class AppScaffold extends StatelessWidget { return isLoading ? AppLoaderWidget() : Container(); } - buildBodyWidget() { + buildBodyWidget(context) { // return body; //Stack(children: [body, buildAppLoaderWidget(isLoading)]); return Stack(children: [ body, - isHelp ?? - Positioned( - child: Column( - children: [ - Container( - height: 100, - width: 150, - padding: EdgeInsets.all(5), - margin: EdgeInsets.only(right: 10.0, bottom: 0), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), - color: Colors.white, - boxShadow: [ - BoxShadow(color: Colors.grey, spreadRadius: 3), - ], - ), - child: TyperAnimatedTextKit( - onTap: () {}, - text: [ - "Discipline is the best tool", - "Design first, then code", - "Do not patch bugs out, rewrite them", - "Do not test bugs out, design them out", - ], - textStyle: - TextStyle(fontSize: 14.0, color: Colors.black54), - speed: Duration(milliseconds: 100), - textAlign: TextAlign.start, - alignment: AlignmentDirectional - .topStart // or Alignment.topLeft - )), - Positioned( - child: Stack( - children: [ - Positioned( - top: 0, - right: 50, - child: Container( - height: 0, - width: 0, - decoration: ShapeDecoration( - color: Colors.grey, - shape: MessageBorder(reverse: true), - ))), - FloatingSearchButton() - ], - )) - ], - ), - left: SizeConfig.screenWidth - 160, - bottom: 50) + isHelp ? RobotIcon() : Container() + /*FloatingSearchButton()*/ ]); @@ -278,3 +235,81 @@ class AppBarWidget extends StatelessWidget with PreferredSizeWidget { @override Size get preferredSize => Size(double.maxFinite, 60); } +class RobotIcon extends StatefulWidget { + + @override + _RobotIcon createState() => _RobotIcon(); +} + +class _RobotIcon extends State { + var event = RobotProvider(); + bool isAnimation =true; + + @override + void initState() { + event.controller.stream.listen((p) { + if (p['animationEnable'] == 'false') { + setState(() { + if (this.mounted) { + this.isAnimation = false; + } + }); + + } + }); + super.initState(); + } + @override + Widget build(BuildContext context) { + return Positioned( + child : + Column( + children: [ + + isAnimation ? Container(height:150,width:200,padding:EdgeInsets.all(5),margin:EdgeInsets.only(right:35.0,bottom:0 + ),decoration :BoxDecoration( + borderRadius:BorderRadius.circular(10), + color:Colors.white, + boxShadow: + [BoxShadow( + color: Colors.black, + spreadRadius: + 1 + ), + ], + ), + child:TyperAnimatedTextKit(text:Provider.of(context,listen:false).isArabic == true ? + "هذه الخدمة تم تصميمها لتتمكن من ربط الملفات الطبية للعائلة بملفك الطبي حتى تتمكن من إدارة سجلاتهم عن طريق تسجيل الدخول إلى ملفك الطبي." + : "Through this service, you will be able to link your family medical files to your medical file so that you can manage their records by login to your medical file.", + textLength: Provider.of(context,listen:false).isArabic== true ? "هذه الخدمة تم تصميمها لتتمكن من ربط الملفات الطبية للعائلة بملفك الطبي حتى تتمكن من إدارة سجلاتهم عن طريق تسجيل الدخول إلى ملفك الطبي.".length: "Through this service, you will be able to link your family medical files to your medical file so that you can manage their records by login to your medical file.".length + ) + + ) : Container(), + Stack( + children: + [ isAnimation ? Positioned(top:0,right:40,child: + Container(height:0,width:0, + decoration: + ShapeDecoration( + color: + Colors.grey, + shape: + MessageBorder( + reverse + : + true + ), + ) + ) + ) :Container(), + FloatingSearchButton() + ], + ) + + ], + ), + right: -30,bottom:50 + + ); + } +} \ No newline at end of file diff --git a/lib/widgets/others/floating_button_search.dart b/lib/widgets/others/floating_button_search.dart index 3c432de3..e235f28b 100644 --- a/lib/widgets/others/floating_button_search.dart +++ b/lib/widgets/others/floating_button_search.dart @@ -2,9 +2,13 @@ import 'dart:collection'; import 'dart:io'; import 'dart:math'; +import 'package:cached_network_image/cached_network_image.dart'; import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/core/service/AuthenticatedUserObject.dart'; +import 'package:diplomaticquarterapp/core/service/medical/vital_sign_service.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/DoctorProfile.dart'; import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; @@ -13,6 +17,7 @@ import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/parking_page.da import 'package:diplomaticquarterapp/pages/Blood/blood_donation.dart'; import 'package:diplomaticquarterapp/pages/Blood/my_balance_page.dart'; import 'package:diplomaticquarterapp/pages/BookAppointment/widgets/BranchView.dart'; +import 'package:diplomaticquarterapp/pages/ContactUs/LiveChat/livechat_page.dart'; import 'package:diplomaticquarterapp/pages/ContactUs/findus/findus_page.dart'; import 'package:diplomaticquarterapp/pages/DrawerPages/family/my-family.dart'; import 'package:diplomaticquarterapp/pages/ErService/AmbulanceReq.dart'; @@ -55,9 +60,10 @@ import 'package:speech_to_text/speech_to_text.dart'; import 'package:diplomaticquarterapp/pages/BookAppointment/DoctorProfile.dart'; import 'package:diplomaticquarterapp/pages/BookAppointment/Search.dart'; import 'package:flutter/cupertino.dart'; - +import 'package:diplomaticquarterapp/pages/pharmacies/screens/pharmacy_module_page.dart'; import 'package:smart_progress_bar/smart_progress_bar.dart'; import 'package:url_launcher/url_launcher.dart'; +import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/%E2%80%8B%20health_calculators.dart'; class FloatingSearchButton extends StatefulWidget { @override @@ -93,10 +99,10 @@ class _FloatingSearchButton extends State var sharedPref = new AppSharedPreferences(); bool _hasSpeech = false; ProjectViewModel projectProvider; - + bool isAnimationEnable = true; AnimationController controller; Animation offset; - + String networkImage; @override void initState() { controller = @@ -104,6 +110,7 @@ class _FloatingSearchButton extends State offset = Tween(begin: Offset.zero, end: Offset(0.0, 1.0)) .animate(controller); controller.reverse(); + initialSpeak(); Future.delayed(const Duration(seconds: 2), () { requestPermissions(); getUserData(); @@ -122,14 +129,23 @@ class _FloatingSearchButton extends State super.initState(); } + @override + void didUpdateWidget(FloatingSearchButton oldWidget) { + super.didUpdateWidget(oldWidget); + // event.controller.stream.listen((p) { + // if (p['animationEnable'] != 'false') { + // initialSpeak(); + // } + // }); + } + AuthenticatedUserObject authenticatedUserObject = + locator(); + VitalSignService _vitalSignService = locator(); @override Widget build(BuildContext context) { projectProvider = Provider.of(context); return Container( - child: - SlideTransition( - position: offset, - child: getStack())); + child: SlideTransition(position: offset, child: getStack())); } Widget getStack() { @@ -138,10 +154,15 @@ class _FloatingSearchButton extends State width: 150, margin: EdgeInsets.only(left: 20.0), child: Stack(children: [ - GestureDetector( child: Container( - child: Image.asset('assets/images/gif/robot-idle.gif'), + child:networkImage !=null ? CachedNetworkImage( + imageUrl: networkImage, + placeholder: (context, url) =>Image.asset('assets/images/gif/robot-idle.gif'), + errorWidget: (context, url, error) => Icon(Icons.error), + ) : Image.asset(isAnimationEnable == true + ? 'assets/images/gif/robot-speaking.gif' + : 'assets/images/gif/robot-idle.gif'), ), onTap: () { initSpeechState().then((value) => {startVoiceSearch()}); @@ -244,7 +265,6 @@ class _FloatingSearchButton extends State } void errorListener(SpeechRecognitionError error) { - print(error); event.setValue({"searchText": 'null'}); //setState(() { // reconizedWord = "${error.errorMsg} - ${error.permanent}"; @@ -283,64 +303,6 @@ class _FloatingSearchButton extends State doctorId: result['DoctorId'], doctorName: null, ); - - // List clnicID = unique(result['ClinicId']); - // if (result['ProjectId'] != 0 && - // clnicID.length > 0 && - // result['DoctorId'].length > 0) { - // if (clnicID.length == 1) { - // getDoctorsList( - // result['ProjectId'], - // clnicID[0], - // context, - // doctorId: result['DoctorId'], - // doctorName: null, - // ); - // } else { - // goToClinic(clnicID); - // } - // } else if (result['ProjectId'] != 0 && - // clnicID.length > 0 && - // result['DoctorId'].length == 0) { - // if (clnicID.length == 1) { - // getDoctorsList( - // result['ProjectId'], - // clnicID[0], - // context, - // ); - // } else { - // goToClinic(clnicID); - // } - // } else if (result['ProjectId'] == 0 && - // clnicID.length > 0 && - // result['DoctorId'].length == 0) { - // if (clnicID.length == 1) { - // getDoctorsList( - // result['ProjectId'], - // clnicID[0], - // context, - // ); - // } else { - // goToClinic(clnicID); - // } - // } else if (result['ProjectId'] == 0 && - // clnicID.length > 0 && - // result['DoctorId'].length > 0) { - // if (clnicID.length == 1) { - // getDoctorsList( - // result['ProjectId'], - // clnicID[0], - // context, - // doctorId: result['DoctorId'], - // doctorName: null, - // ); - // } else { - // goToClinic(clnicID); - // } - // } else { - // goToClinic(clnicID); - // } - // speak(); } break; case '102': @@ -639,6 +601,7 @@ class _FloatingSearchButton extends State case '44': { //chat need be implmented here. + Navigator.push(context, FadePage(page: LiveChatPage())); } break; case '45': @@ -656,14 +619,54 @@ class _FloatingSearchButton extends State Navigator.push(context, FadePage(page: FeedbackHomePage())); } break; + case '45': + { + launch('https://hmg.com/ir/ar/Pages/ShareInformation/home.aspx'); + break; + } + case '46': + { + launch('https://hmg.com/ir/ar/pages/home.aspx'); + break; + } + case '47': + { + //this.cs.sharedService.setSharedData(true, "isComingFromVoiceCommand"); + //this.cs.openFeedback(); + Navigator.push(context, FadePage(page: FeedbackHomePage())); + break; + } + case '48': + { + Navigator.push(context, FadePage(page: PharmacyPage())); + break; + } + case '50': + { + this.signOut(); + break; + } + case '51': + { + // Women health calculator + //this.cs.sharedService.setSharedData(true, "isOpenWomenHealthCalculator"); + //this.cs.navigateForward('/calculators/calculator'); + Navigator.push(context, FadePage(page: HealthCalculators())); + break; + } + case '52': + { + //this.bridge.openMyInvoices(); + break; + } + case '53': + { + launch("tel://920066666"); + break; + } default: { - // Navigator.pushAndRemoveUntil( - // context, - // MaterialPageRoute( - // builder: (context) => LandingPage()), - // (Route r) => false); speak(); } break; @@ -783,17 +786,22 @@ class _FloatingSearchButton extends State } speak() async { - // var voice = await flutterTts.getVoices; + setState(() { + this.networkImage = results['AnimationURL']; + this.isAnimationEnable = true; + }); + if (_currentLocaleId == 'en' && results['ReturnMessage'] != null) { - await flutterTts.setVoice({"name":"en-au-x-aub-network", "locale":"en-AU"}); + await flutterTts + .setVoice({"name": "en-au-x-aub-network", "locale": "en-AU"}); await flutterTts.speak(results['ReturnMessage']); } else if (results['ReturnMessage_Ar'] != null) { - await flutterTts.setVoice({"name":"ar-xa-x-ard-network", "locale":"ar"}); + await flutterTts + .setVoice({"name": "ar-xa-x-ard-network", "locale": "ar"}); await flutterTts.speak(results['ReturnMessage_Ar']); } - // Future.delayed(const Duration(seconds: 10), () { - // initSpeechState().then((value) => startVoiceSearch()); - // }); + + stopAnimation(); } goToClinic(List ids) { @@ -816,6 +824,50 @@ class _FloatingSearchButton extends State user = AuthenticatedUser.fromJson( await this.sharedPref.getObject(USER_PROFILE)); } - //await flutterTts.setVoice("en-us-x-sfg#male_1-local"); + } + + initialSpeak() async { + results = { + 'ReturnMessage_Ar': + "هذه الخدمة تم تصميمها لتتمكن من ربط الملفات الطبية للعائلة بملفك الطبي حتى تتمكن من إدارة سجلاتهم عن طريق تسجيل الدخول إلى ملفك الطبي.", + 'ReturnMessage': + "Through this service, you will be able to link your family medical files to your medical file so that you can manage their records by login to your medical file." + }; + this.speak(); + + if (Provider.of(context, listen: false).isArabic == + false && + results['ReturnMessage'] != null) { + await flutterTts + .setVoice({"name": "en-au-x-aub-network", "locale": "en-AU"}); + await flutterTts.speak(results['ReturnMessage']); + } else if (results['ReturnMessage_Ar'] != null) { + await flutterTts + .setVoice({"name": "ar-xa-x-ard-network", "locale": "ar"}); + await flutterTts.speak(results['ReturnMessage_Ar']); + + } + + this.isAnimationEnable = true; + stopAnimation(); + } + stopAnimation(){ + flutterTts.setCompletionHandler(() => { + event.setValue({"animationEnable": 'false'}), + setState(() { + this.networkImage = null; + this.isAnimationEnable = false; + }) + }); + } + signOut() async{ + authenticatedUserObject.logout(); + projectProvider.isLogin = false; + await authenticatedUserObject.getUser(); + _vitalSignService.heightCm = ""; + _vitalSignService.weightKg = ""; + await sharedPref.clear(); + this.user = null; + Navigator.of(context).pushNamed(HOME); } } diff --git a/lib/widgets/typewriter/typewiter.dart b/lib/widgets/typewriter/typewiter.dart index e69de29b..97a54150 100644 --- a/lib/widgets/typewriter/typewiter.dart +++ b/lib/widgets/typewriter/typewiter.dart @@ -0,0 +1,72 @@ +import 'package:flutter/material.dart'; + +class TyperAnimatedTextKit extends StatefulWidget { + final String text; + final int textLength; + TyperAnimatedTextKit({this.text, this.textLength}); + @override + _TyperState createState() => _TyperState(); +} + +class _TyperState extends State + with TickerProviderStateMixin { + Animation _characterCount; + AnimationController _controller; + int _stringIndex; + @override + void initState() { + _controller = new AnimationController( + duration: const Duration(seconds: 7), + vsync: this, + ); + + Future.delayed(const Duration(milliseconds: 500), () { + setState(() { + _stringIndex = _stringIndex == null ? 0 : _stringIndex + 1; + _characterCount = new StepTween(begin: 0, end: widget.textLength) + .animate(new CurvedAnimation(parent: _controller, curve: Curves.easeIn)); + + }); + _controller.forward(); + }); + + super.initState(); + } + + @override + void didUpdateWidget(TyperAnimatedTextKit oldWidget) { + super.didUpdateWidget(oldWidget); + _controller = new AnimationController( + duration: const Duration(seconds: 7), + vsync: this, + ); + + setState(() { + _stringIndex = _stringIndex == null ? 0 : _stringIndex + 1; + _characterCount = new StepTween(begin: 0, end: widget.textLength) + .animate(new CurvedAnimation(parent: _controller, curve: Curves.easeIn)); + + }); + _controller.forward(); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + @override + Widget build(BuildContext context) { + + return Container( + child: _characterCount == null ? null : new AnimatedBuilder( + animation: _characterCount, + builder: (BuildContext context, Widget child) { + String text = widget.text.substring(0, _characterCount.value); + return Text(text, style: TextStyle(color:Colors.black, fontSize: 12), textAlign: TextAlign.start, + + ); + }, + )); + } +} \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index e3e8bb06..51ccbe8f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -83,7 +83,7 @@ dependencies: google_maps_flutter: ^1.0.3 # Qr code Scanner TODO fix it - barcode_scanner: ^1.0.1 +# barcode_scanner: ^1.0.1 barcode_scan: any # Qr code Scanner barcode_scan_fix: ^1.0.2 @@ -146,7 +146,7 @@ dependencies: screen: ^0.0.5 #google maps places google_maps_place_picker: ^1.0.0 - animated_text_kit: ^2.5.4 + typewriter: ^0.0.3 #Dependencies for video call implementation native_device_orientation: ^0.3.0 enum_to_string: ^1.0.9 @@ -154,6 +154,7 @@ dependencies: wakelock: ^0.1.4 after_layout: ^1.0.7 twilio_programmable_video: ^0.5.0+3 + cached_network_image: ^2.4.1 flutter_tts: path: flutter_tts-voice_enhancement vibration: ^1.7.2 From 124173c9c404aa735483c9e5a2c62969de2e3d4b Mon Sep 17 00:00:00 2001 From: Sultan Khan Date: Wed, 9 Dec 2020 08:38:23 +0300 Subject: [PATCH 19/71] voice command updated --- speech_to_text/.github/workflows/main.yml | 19 + speech_to_text/.vscode/launch.json | 14 + speech_to_text/codestats.csv | 1 + speech_to_text/example/android/.gitignore | 11 + .../com/csdcorp/example/MainActivity.kt | 6 + speech_to_text/example/ios/.gitignore | 32 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + speech_to_text/example/lib/port.dart | 174 +++++ .../example/lib/provider_example.dart | 195 ++++++ speech_to_text/example/lib/stress.dart | 292 +++++++++ speech_to_text/lib/speech_to_text_web.dart | 95 +++ speech_to_text/scripts/tcov.sh | 5 + .../test/test_speech_to_text_platform.dart | 133 ++++ speech_to_text_/.github/workflows/master.yml | 19 + speech_to_text_/.gitignore | 11 + speech_to_text_/.metadata | 10 + speech_to_text_/CHANGELOG.md | 166 +++++ speech_to_text_/LICENSE | 29 + speech_to_text_/README.md | 150 +++++ speech_to_text_/android/.classpath | 6 + speech_to_text_/android/.gitignore | 8 + speech_to_text_/android/.project | 23 + .../org.eclipse.buildship.core.prefs | 13 + speech_to_text_/android/build.gradle | 44 ++ .../android/gradle/gradle.properties | 3 + .../android/gradle/local.properties | 3 + .../android/gradle/settings.gradle | 1 + .../gradle/wrapper/gradle-wrapper.properties | 5 + .../android/src/main/AndroidManifest.xml | 3 + .../speech_to_text/SpeechToTextPlugin.kt | 595 ++++++++++++++++++ speech_to_text_/example/.gitignore | 73 +++ speech_to_text_/example/.metadata | 10 + speech_to_text_/example/README.md | 155 +++++ speech_to_text_/example/android/.project | 17 + .../org.eclipse.buildship.core.prefs | 2 + .../example/android/app/build.gradle | 67 ++ .../android/app/src/debug/AndroidManifest.xml | 7 + .../android/app/src/main/AndroidManifest.xml | 32 + .../speech_to_text_example/MainActivity.kt | 12 + .../main/res/drawable/launch_background.xml | 12 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 544 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 442 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 721 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 1031 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 1443 bytes .../app/src/main/res/values/styles.xml | 8 + .../app/src/profile/AndroidManifest.xml | 7 + speech_to_text_/example/android/build.gradle | 31 + .../example/android/gradle.properties | 4 + .../gradle/wrapper/gradle-wrapper.properties | 6 + .../example/android/settings.gradle | 15 + .../assets/sounds/speech_to_text_cancel.m4r | Bin 0 -> 14006 bytes .../sounds/speech_to_text_listening.m4r | Bin 0 -> 16416 bytes .../assets/sounds/speech_to_text_stop.m4r | Bin 0 -> 17128 bytes .../ios/Flutter/AppFrameworkInfo.plist | 26 + .../example/ios/Flutter/Debug.xcconfig | 2 + .../example/ios/Flutter/Flutter.podspec | 18 + .../example/ios/Flutter/Release.xcconfig | 2 + speech_to_text_/example/ios/Podfile | 90 +++ speech_to_text_/example/ios/Podfile.lock | 29 + .../ios/Runner.xcodeproj/project.pbxproj | 578 +++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/xcschemes/Runner.xcscheme | 91 +++ .../contents.xcworkspacedata | 10 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../example/ios/Runner/AppDelegate.swift | 13 + .../AppIcon.appiconset/Contents.json | 122 ++++ .../Icon-App-1024x1024@1x.png | Bin 0 -> 10932 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 0 -> 564 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 0 -> 1283 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 0 -> 1588 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 0 -> 1025 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 0 -> 1716 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 0 -> 1920 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 0 -> 1283 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 0 -> 1895 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 0 -> 2665 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 0 -> 2665 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 0 -> 3831 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 0 -> 1888 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 0 -> 3294 bytes .../Icon-App-83.5x83.5@2x.png | Bin 0 -> 3612 bytes .../LaunchImage.imageset/Contents.json | 23 + .../LaunchImage.imageset/LaunchImage.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/README.md | 5 + .../Runner/Base.lproj/LaunchScreen.storyboard | 37 ++ .../ios/Runner/Base.lproj/Main.storyboard | 26 + speech_to_text_/example/ios/Runner/Info.plist | 49 ++ .../ios/Runner/Runner-Bridging-Header.h | 1 + speech_to_text_/example/lib/main.dart | 275 ++++++++ speech_to_text_/example/pubspec.yaml | 33 + speech_to_text_/example/test/widget_test.dart | 27 + speech_to_text_/ios/.gitignore | 37 ++ speech_to_text_/ios/Assets/.gitkeep | 0 .../ios/Classes/SpeechToTextPlugin.h | 4 + .../ios/Classes/SpeechToTextPlugin.m | 8 + .../ios/Classes/SwiftSpeechToTextPlugin.swift | 580 +++++++++++++++++ speech_to_text_/ios/speech_to_text.podspec | 22 + .../lib/speech_recognition_error.dart | 44 ++ .../lib/speech_recognition_error.g.dart | 22 + .../lib/speech_recognition_event.dart | 30 + .../lib/speech_recognition_result.dart | 140 +++++ .../lib/speech_recognition_result.g.dart | 41 ++ speech_to_text_/lib/speech_to_text.dart | 511 +++++++++++++++ .../lib/speech_to_text_provider.dart | 201 ++++++ speech_to_text_/pubspec.yaml | 31 + .../test/speech_recognition_error_test.dart | 65 ++ .../test/speech_recognition_event_test.dart | 42 ++ .../test/speech_recognition_result_test.dart | 134 ++++ .../test/speech_recognitions_words_test.dart | 86 +++ .../test/speech_to_text_provider_test.dart | 196 ++++++ speech_to_text_/test/speech_to_text_test.dart | 425 +++++++++++++ .../test/test_speech_channel_handler.dart | 134 ++++ .../test/test_speech_listener.dart | 36 ++ 118 files changed, 6809 insertions(+) create mode 100644 speech_to_text/.github/workflows/main.yml create mode 100644 speech_to_text/.vscode/launch.json create mode 100644 speech_to_text/codestats.csv create mode 100644 speech_to_text/example/android/.gitignore create mode 100644 speech_to_text/example/android/app/src/main/kotlin/com/csdcorp/example/MainActivity.kt create mode 100644 speech_to_text/example/ios/.gitignore create mode 100644 speech_to_text/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 speech_to_text/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 speech_to_text/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 speech_to_text/example/lib/port.dart create mode 100644 speech_to_text/example/lib/provider_example.dart create mode 100644 speech_to_text/example/lib/stress.dart create mode 100644 speech_to_text/lib/speech_to_text_web.dart create mode 100644 speech_to_text/scripts/tcov.sh create mode 100644 speech_to_text/test/test_speech_to_text_platform.dart create mode 100644 speech_to_text_/.github/workflows/master.yml create mode 100644 speech_to_text_/.gitignore create mode 100644 speech_to_text_/.metadata create mode 100644 speech_to_text_/CHANGELOG.md create mode 100644 speech_to_text_/LICENSE create mode 100644 speech_to_text_/README.md create mode 100644 speech_to_text_/android/.classpath create mode 100644 speech_to_text_/android/.gitignore create mode 100644 speech_to_text_/android/.project create mode 100644 speech_to_text_/android/.settings/org.eclipse.buildship.core.prefs create mode 100644 speech_to_text_/android/build.gradle create mode 100644 speech_to_text_/android/gradle/gradle.properties create mode 100644 speech_to_text_/android/gradle/local.properties create mode 100644 speech_to_text_/android/gradle/settings.gradle create mode 100644 speech_to_text_/android/gradle/wrapper/gradle-wrapper.properties create mode 100644 speech_to_text_/android/src/main/AndroidManifest.xml create mode 100644 speech_to_text_/android/src/main/kotlin/com/csdcorp/speech_to_text/SpeechToTextPlugin.kt create mode 100644 speech_to_text_/example/.gitignore create mode 100644 speech_to_text_/example/.metadata create mode 100644 speech_to_text_/example/README.md create mode 100644 speech_to_text_/example/android/.project create mode 100644 speech_to_text_/example/android/.settings/org.eclipse.buildship.core.prefs create mode 100644 speech_to_text_/example/android/app/build.gradle create mode 100644 speech_to_text_/example/android/app/src/debug/AndroidManifest.xml create mode 100644 speech_to_text_/example/android/app/src/main/AndroidManifest.xml create mode 100644 speech_to_text_/example/android/app/src/main/kotlin/com/csdcorp/speech_to_text_example/MainActivity.kt create mode 100644 speech_to_text_/example/android/app/src/main/res/drawable/launch_background.xml create mode 100644 speech_to_text_/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 speech_to_text_/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 speech_to_text_/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 speech_to_text_/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 speech_to_text_/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 speech_to_text_/example/android/app/src/main/res/values/styles.xml create mode 100644 speech_to_text_/example/android/app/src/profile/AndroidManifest.xml create mode 100644 speech_to_text_/example/android/build.gradle create mode 100644 speech_to_text_/example/android/gradle.properties create mode 100644 speech_to_text_/example/android/gradle/wrapper/gradle-wrapper.properties create mode 100644 speech_to_text_/example/android/settings.gradle create mode 100644 speech_to_text_/example/assets/sounds/speech_to_text_cancel.m4r create mode 100644 speech_to_text_/example/assets/sounds/speech_to_text_listening.m4r create mode 100644 speech_to_text_/example/assets/sounds/speech_to_text_stop.m4r create mode 100644 speech_to_text_/example/ios/Flutter/AppFrameworkInfo.plist create mode 100644 speech_to_text_/example/ios/Flutter/Debug.xcconfig create mode 100644 speech_to_text_/example/ios/Flutter/Flutter.podspec create mode 100644 speech_to_text_/example/ios/Flutter/Release.xcconfig create mode 100644 speech_to_text_/example/ios/Podfile create mode 100644 speech_to_text_/example/ios/Podfile.lock create mode 100644 speech_to_text_/example/ios/Runner.xcodeproj/project.pbxproj create mode 100644 speech_to_text_/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 speech_to_text_/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 speech_to_text_/example/ios/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 speech_to_text_/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 speech_to_text_/example/ios/Runner/AppDelegate.swift create mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png create mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png create mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png create mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png create mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png create mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png create mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png create mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png create mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png create mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png create mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png create mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png create mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png create mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png create mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png create mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json create mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png create mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png create mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png create mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md create mode 100644 speech_to_text_/example/ios/Runner/Base.lproj/LaunchScreen.storyboard create mode 100644 speech_to_text_/example/ios/Runner/Base.lproj/Main.storyboard create mode 100644 speech_to_text_/example/ios/Runner/Info.plist create mode 100644 speech_to_text_/example/ios/Runner/Runner-Bridging-Header.h create mode 100644 speech_to_text_/example/lib/main.dart create mode 100644 speech_to_text_/example/pubspec.yaml create mode 100644 speech_to_text_/example/test/widget_test.dart create mode 100644 speech_to_text_/ios/.gitignore create mode 100644 speech_to_text_/ios/Assets/.gitkeep create mode 100644 speech_to_text_/ios/Classes/SpeechToTextPlugin.h create mode 100644 speech_to_text_/ios/Classes/SpeechToTextPlugin.m create mode 100644 speech_to_text_/ios/Classes/SwiftSpeechToTextPlugin.swift create mode 100644 speech_to_text_/ios/speech_to_text.podspec create mode 100644 speech_to_text_/lib/speech_recognition_error.dart create mode 100644 speech_to_text_/lib/speech_recognition_error.g.dart create mode 100644 speech_to_text_/lib/speech_recognition_event.dart create mode 100644 speech_to_text_/lib/speech_recognition_result.dart create mode 100644 speech_to_text_/lib/speech_recognition_result.g.dart create mode 100644 speech_to_text_/lib/speech_to_text.dart create mode 100644 speech_to_text_/lib/speech_to_text_provider.dart create mode 100644 speech_to_text_/pubspec.yaml create mode 100644 speech_to_text_/test/speech_recognition_error_test.dart create mode 100644 speech_to_text_/test/speech_recognition_event_test.dart create mode 100644 speech_to_text_/test/speech_recognition_result_test.dart create mode 100644 speech_to_text_/test/speech_recognitions_words_test.dart create mode 100644 speech_to_text_/test/speech_to_text_provider_test.dart create mode 100644 speech_to_text_/test/speech_to_text_test.dart create mode 100644 speech_to_text_/test/test_speech_channel_handler.dart create mode 100644 speech_to_text_/test/test_speech_listener.dart diff --git a/speech_to_text/.github/workflows/main.yml b/speech_to_text/.github/workflows/main.yml new file mode 100644 index 00000000..87b78c31 --- /dev/null +++ b/speech_to_text/.github/workflows/main.yml @@ -0,0 +1,19 @@ +name: build + +on: + push: + branches: + - main + +jobs: + test: + name: Test on Ubuntu + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - uses: subosito/flutter-action@v1.3.2 + with: + flutter-version: '1.20.3' + channel: 'stable' + - run: flutter pub get + - run: flutter test diff --git a/speech_to_text/.vscode/launch.json b/speech_to_text/.vscode/launch.json new file mode 100644 index 00000000..9f8693fe --- /dev/null +++ b/speech_to_text/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Flutter", + "request": "launch", + "type": "dart", + "program": "example/lib/main.dart" + } + ] +} \ No newline at end of file diff --git a/speech_to_text/codestats.csv b/speech_to_text/codestats.csv new file mode 100644 index 00000000..7319cf19 --- /dev/null +++ b/speech_to_text/codestats.csv @@ -0,0 +1 @@ +2020/10/18 15:15:20,99.0,7,1003,111,324,568,75 diff --git a/speech_to_text/example/android/.gitignore b/speech_to_text/example/android/.gitignore new file mode 100644 index 00000000..0a741cb4 --- /dev/null +++ b/speech_to_text/example/android/.gitignore @@ -0,0 +1,11 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties diff --git a/speech_to_text/example/android/app/src/main/kotlin/com/csdcorp/example/MainActivity.kt b/speech_to_text/example/android/app/src/main/kotlin/com/csdcorp/example/MainActivity.kt new file mode 100644 index 00000000..9143acd8 --- /dev/null +++ b/speech_to_text/example/android/app/src/main/kotlin/com/csdcorp/example/MainActivity.kt @@ -0,0 +1,6 @@ +package com.csdcorp.example + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { +} diff --git a/speech_to_text/example/ios/.gitignore b/speech_to_text/example/ios/.gitignore new file mode 100644 index 00000000..e96ef602 --- /dev/null +++ b/speech_to_text/example/ios/.gitignore @@ -0,0 +1,32 @@ +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/speech_to_text/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/speech_to_text/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/speech_to_text/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/speech_to_text/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/speech_to_text/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..f9b0d7c5 --- /dev/null +++ b/speech_to_text/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/speech_to_text/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/speech_to_text/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..f9b0d7c5 --- /dev/null +++ b/speech_to_text/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/speech_to_text/example/lib/port.dart b/speech_to_text/example/lib/port.dart new file mode 100644 index 00000000..90af3822 --- /dev/null +++ b/speech_to_text/example/lib/port.dart @@ -0,0 +1,174 @@ +import 'package:flutter/material.dart'; +import 'package:speech_to_text/speech_to_text.dart'; +import 'package:speech_to_text/speech_recognition_result.dart'; +import 'package:speech_to_text/speech_recognition_error.dart'; + +void main() { + runApp(new MyApp()); +} + +List languages = [ + const Language('System', 'default'), + const Language('Francais', 'fr_FR'), + const Language('English', 'en_US'), + const Language('Pусский', 'ru_RU'), + const Language('Italiano', 'it_IT'), + const Language('Español', 'es_ES'), +]; + +class Language { + final String name; + final String code; + + const Language(this.name, this.code); +} + +class MyApp extends StatefulWidget { + @override + _MyAppState createState() => new _MyAppState(); +} + +class _MyAppState extends State { + SpeechToText _speech; + + bool _speechRecognitionAvailable = false; + bool _isListening = false; + + String transcription = ''; + + //String _currentLocale = 'en_US'; + Language selectedLang = languages.first; + + @override + initState() { + super.initState(); + activateSpeechRecognizer(); + } + + // Platform messages are asynchronous, so we initialize in an async method. + Future activateSpeechRecognizer() async { + print('_MyAppState.activateSpeechRecognizer... '); + _speech = SpeechToText(); + // _speech.setCurrentLocaleHandler(onCurrentLocale); + // _speech.setRecognitionStartedHandler(onRecognitionStarted); + // _speech.setRecognitionCompleteHandler(onRecognitionComplete); + _speechRecognitionAvailable = await _speech.initialize( + onError: errorHandler, onStatus: onSpeechAvailability); + List localeNames = await _speech.locales(); + languages.clear(); + localeNames.forEach((localeName) => + languages.add(Language(localeName.name, localeName.localeId))); + var currentLocale = await _speech.systemLocale(); + if (null != currentLocale) { + selectedLang = + languages.firstWhere((lang) => lang.code == currentLocale.localeId); + } + setState(() {}); + } + + @override + Widget build(BuildContext context) { + return new MaterialApp( + home: new Scaffold( + appBar: new AppBar( + title: new Text('SpeechRecognition'), + actions: [ + new PopupMenuButton( + onSelected: _selectLangHandler, + itemBuilder: (BuildContext context) => _buildLanguagesWidgets, + ) + ], + ), + body: new Padding( + padding: new EdgeInsets.all(8.0), + child: new Center( + child: new Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + new Expanded( + child: new Container( + padding: const EdgeInsets.all(8.0), + color: Colors.grey.shade200, + child: new Text(transcription))), + _buildButton( + onPressed: _speechRecognitionAvailable && !_isListening + ? () => start() + : null, + label: _isListening + ? 'Listening...' + : 'Listen (${selectedLang.code})', + ), + _buildButton( + onPressed: _isListening ? () => cancel() : null, + label: 'Cancel', + ), + _buildButton( + onPressed: _isListening ? () => stop() : null, + label: 'Stop', + ), + ], + ), + )), + ), + ); + } + + List> get _buildLanguagesWidgets => languages + .map((l) => new CheckedPopupMenuItem( + value: l, + checked: selectedLang == l, + child: new Text(l.name), + )) + .toList(); + + void _selectLangHandler(Language lang) { + setState(() => selectedLang = lang); + } + + Widget _buildButton({String label, VoidCallback onPressed}) => new Padding( + padding: new EdgeInsets.all(12.0), + child: new RaisedButton( + color: Colors.cyan.shade600, + onPressed: onPressed, + child: new Text( + label, + style: const TextStyle(color: Colors.white), + ), + )); + + void start() => _speech.listen( + onResult: onRecognitionResult, localeId: selectedLang.code); + + void cancel() { + _speech.cancel(); + setState(() => _isListening = false); + } + + void stop() { + _speech.stop(); + setState(() => _isListening = false); + } + + void onSpeechAvailability(String status) { + setState(() { + _speechRecognitionAvailable = _speech.isAvailable; + _isListening = _speech.isListening; + }); + } + + void onCurrentLocale(String locale) { + print('_MyAppState.onCurrentLocale... $locale'); + setState( + () => selectedLang = languages.firstWhere((l) => l.code == locale)); + } + + // void onRecognitionStarted() => setState(() => _isListening = true); + + void onRecognitionResult(SpeechRecognitionResult result) => + setState(() => transcription = result.recognizedWords); + + // void onRecognitionComplete() => setState(() => _isListening = false); + + void errorHandler(SpeechRecognitionError error) => print(error); +} diff --git a/speech_to_text/example/lib/provider_example.dart b/speech_to_text/example/lib/provider_example.dart new file mode 100644 index 00000000..6c14c4cb --- /dev/null +++ b/speech_to_text/example/lib/provider_example.dart @@ -0,0 +1,195 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:speech_to_text/speech_to_text.dart'; +import 'package:speech_to_text/speech_to_text_provider.dart'; + +void main() => runApp(ProviderDemoApp()); + +class ProviderDemoApp extends StatefulWidget { + @override + _ProviderDemoAppState createState() => _ProviderDemoAppState(); +} + +class _ProviderDemoAppState extends State { + final SpeechToText speech = SpeechToText(); + SpeechToTextProvider speechProvider; + + @override + void initState() { + super.initState(); + speechProvider = SpeechToTextProvider(speech); + initSpeechState(); + } + + Future initSpeechState() async { + await speechProvider.initialize(); + } + + @override + Widget build(BuildContext context) { + return ChangeNotifierProvider.value( + value: speechProvider, + child: MaterialApp( + home: Scaffold( + appBar: AppBar( + title: const Text('Speech to Text Provider Example'), + ), + body: SpeechProviderExampleWidget(), + ), + ), + ); + } +} + +class SpeechProviderExampleWidget extends StatefulWidget { + @override + _SpeechProviderExampleWidgetState createState() => + _SpeechProviderExampleWidgetState(); +} + +class _SpeechProviderExampleWidgetState + extends State { + String _currentLocaleId = ""; + + void _setCurrentLocale(SpeechToTextProvider speechProvider) { + if (speechProvider.isAvailable && _currentLocaleId.isEmpty) { + _currentLocaleId = speechProvider.systemLocale.localeId; + } + } + + @override + Widget build(BuildContext context) { + var speechProvider = Provider.of(context); + if (speechProvider.isNotAvailable) { + return Center( + child: Text( + 'Speech recognition not available, no permission or not available on the device.'), + ); + } + _setCurrentLocale(speechProvider); + return Column(children: [ + Center( + child: Text( + 'Speech recognition available', + style: TextStyle(fontSize: 22.0), + ), + ), + Container( + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + FlatButton( + child: Text('Start'), + onPressed: + !speechProvider.isAvailable || speechProvider.isListening + ? null + : () => speechProvider.listen( + partialResults: true, localeId: _currentLocaleId), + ), + FlatButton( + child: Text('Stop'), + onPressed: speechProvider.isListening + ? () => speechProvider.stop() + : null, + ), + FlatButton( + child: Text('Cancel'), + onPressed: speechProvider.isListening + ? () => speechProvider.cancel() + : null, + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + DropdownButton( + onChanged: (selectedVal) => _switchLang(selectedVal), + value: _currentLocaleId, + items: speechProvider.locales + .map( + (localeName) => DropdownMenuItem( + value: localeName.localeId, + child: Text(localeName.name), + ), + ) + .toList(), + ), + ], + ) + ], + ), + ), + Expanded( + flex: 4, + child: Column( + children: [ + Center( + child: Text( + 'Recognized Words', + style: TextStyle(fontSize: 22.0), + ), + ), + Expanded( + child: Container( + color: Theme.of(context).selectedRowColor, + child: Center( + child: speechProvider.hasResults + ? Text( + speechProvider.lastResult.recognizedWords, + textAlign: TextAlign.center, + ) + : Container(), + ), + ), + ), + ], + ), + ), + Expanded( + flex: 1, + child: Column( + children: [ + Center( + child: Text( + 'Error Status', + style: TextStyle(fontSize: 22.0), + ), + ), + Center( + child: speechProvider.hasError + ? Text(speechProvider.lastError.errorMsg) + : Container(), + ), + ], + ), + ), + Container( + padding: EdgeInsets.symmetric(vertical: 20), + color: Theme.of(context).backgroundColor, + child: Center( + child: speechProvider.isListening + ? Text( + "I'm listening...", + style: TextStyle(fontWeight: FontWeight.bold), + ) + : Text( + 'Not listening', + style: TextStyle(fontWeight: FontWeight.bold), + ), + ), + ), + ]); + } + + _switchLang(selectedVal) { + setState(() { + _currentLocaleId = selectedVal; + }); + print(selectedVal); + } +} diff --git a/speech_to_text/example/lib/stress.dart b/speech_to_text/example/lib/stress.dart new file mode 100644 index 00000000..0f83d33d --- /dev/null +++ b/speech_to_text/example/lib/stress.dart @@ -0,0 +1,292 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:speech_to_text/speech_recognition_error.dart'; +import 'package:speech_to_text/speech_recognition_result.dart'; +import 'package:speech_to_text/speech_to_text.dart'; + +void main() => runApp(MyApp()); + +class MyApp extends StatefulWidget { + @override + _MyAppState createState() => _MyAppState(); +} + +class _MyAppState extends State { + bool _hasSpeech = false; + bool _stressTest = false; + double level = 0.0; + int _stressLoops = 0; + String lastWords = ""; + String lastError = ""; + String lastStatus = ""; + String _currentLocaleId = ""; + List _localeNames = []; + final SpeechToText speech = SpeechToText(); + + @override + void initState() { + super.initState(); + } + + Future initSpeechState() async { + bool hasSpeech = await speech.initialize( + onError: errorListener, onStatus: statusListener); + if (hasSpeech) { + _localeNames = await speech.locales(); + + var systemLocale = await speech.systemLocale(); + _currentLocaleId = systemLocale.localeId; + } + + if (!mounted) return; + + setState(() { + _hasSpeech = hasSpeech; + }); + } + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + appBar: AppBar( + title: const Text('Speech to Text Example'), + ), + body: Column(children: [ + Center( + child: Text( + 'Speech recognition available', + style: TextStyle(fontSize: 22.0), + ), + ), + Container( + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + FlatButton( + child: Text('Initialize'), + onPressed: _hasSpeech ? null : initSpeechState, + ), + FlatButton( + child: Text('Stress Test'), + onPressed: stressTest, + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + FlatButton( + child: Text('Start'), + onPressed: !_hasSpeech || speech.isListening + ? null + : startListening, + ), + FlatButton( + child: Text('Stop'), + onPressed: speech.isListening ? stopListening : null, + ), + FlatButton( + child: Text('Cancel'), + onPressed: speech.isListening ? cancelListening : null, + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + DropdownButton( + onChanged: (selectedVal) => _switchLang(selectedVal), + value: _currentLocaleId, + items: _localeNames + .map( + (localeName) => DropdownMenuItem( + value: localeName.localeId, + child: Text(localeName.name), + ), + ) + .toList(), + ), + ], + ) + ], + ), + ), + Expanded( + flex: 4, + child: Column( + children: [ + Center( + child: Text( + 'Recognized Words', + style: TextStyle(fontSize: 22.0), + ), + ), + Expanded( + child: Stack( + children: [ + Container( + color: Theme.of(context).selectedRowColor, + child: Center( + child: Text( + lastWords, + textAlign: TextAlign.center, + ), + ), + ), + Positioned.fill( + bottom: 10, + child: Align( + alignment: Alignment.bottomCenter, + child: Container( + width: 40, + height: 40, + alignment: Alignment.center, + decoration: BoxDecoration( + boxShadow: [ + BoxShadow( + blurRadius: .26, + spreadRadius: level * 1.5, + color: Colors.black.withOpacity(.05)) + ], + color: Colors.white, + borderRadius: + BorderRadius.all(Radius.circular(50)), + ), + child: IconButton( + icon: Icon(Icons.mic), onPressed: () => null), + ), + ), + ), + ], + ), + ), + ], + ), + ), + Expanded( + flex: 1, + child: Column( + children: [ + Center( + child: Text( + 'Error Status', + style: TextStyle(fontSize: 22.0), + ), + ), + Center( + child: Text(lastError), + ), + ], + ), + ), + Container( + padding: EdgeInsets.symmetric(vertical: 20), + color: Theme.of(context).backgroundColor, + child: Center( + child: speech.isListening + ? Text( + "I'm listening...", + style: TextStyle(fontWeight: FontWeight.bold), + ) + : Text( + 'Not listening', + style: TextStyle(fontWeight: FontWeight.bold), + ), + ), + ), + ]), + ), + ); + } + + void stressTest() { + if (_stressTest) { + return; + } + _stressLoops = 0; + _stressTest = true; + print("Starting stress test..."); + startListening(); + } + + void changeStatusForStress(String status) { + if (!_stressTest) { + return; + } + if (speech.isListening) { + stopListening(); + } else { + if (_stressLoops >= 100) { + _stressTest = false; + print("Stress test complete."); + return; + } + print("Stress loop: $_stressLoops"); + ++_stressLoops; + startListening(); + } + } + + void startListening() { + lastWords = ""; + lastError = ""; + speech.listen( + onResult: resultListener, + listenFor: Duration(seconds: 10), + localeId: _currentLocaleId, + onSoundLevelChange: soundLevelListener, + cancelOnError: true, + partialResults: true); + setState(() {}); + } + + void stopListening() { + speech.stop(); + setState(() { + level = 0.0; + }); + } + + void cancelListening() { + speech.cancel(); + setState(() { + level = 0.0; + }); + } + + void resultListener(SpeechRecognitionResult result) { + setState(() { + lastWords = "${result.recognizedWords} - ${result.finalResult}"; + }); + } + + void soundLevelListener(double level) { + setState(() { + this.level = level; + }); + } + + void errorListener(SpeechRecognitionError error) { + setState(() { + lastError = "${error.errorMsg} - ${error.permanent}"; + }); + } + + void statusListener(String status) { + changeStatusForStress(status); + setState(() { + lastStatus = "$status"; + }); + } + + _switchLang(selectedVal) { + setState(() { + _currentLocaleId = selectedVal; + }); + print(selectedVal); + } +} diff --git a/speech_to_text/lib/speech_to_text_web.dart b/speech_to_text/lib/speech_to_text_web.dart new file mode 100644 index 00000000..9708b272 --- /dev/null +++ b/speech_to_text/lib/speech_to_text_web.dart @@ -0,0 +1,95 @@ +import 'package:speech_to_text_platform_interface/speech_to_text_platform_interface.dart'; + +class SpeechToTextPlugin extends SpeechToTextPlatform { + @override + + /// Returns true if the user has already granted permission to access the + /// microphone, does not prompt the user. + /// + /// This method can be called before [initialize] to check if permission + /// has already been granted. If this returns false then the [initialize] + /// call will prompt the user for permission if it is allowed to do so. + /// Note that applications cannot ask for permission again if the user has + /// denied them permission in the past. + Future hasPermission() async { + return false; + } + + /// Initialize speech recognition services, returns true if + /// successful, false if failed. + /// + /// This method must be called before any other speech functions. + /// If this method returns false no further [SpeechToText] methods + /// should be used. False usually means that the user has denied + /// permission to use speech. + /// + /// [debugLogging] controls whether there is detailed logging from the underlying + /// plugins. It is off by default, usually only useful for troubleshooting issues + /// with a paritcular OS version or device, fairly verbose + Future initialize( + {debugLogging = false, List options}) async { + return false; + } + + /// Stops the current listen for speech if active, does nothing if not. + /// + /// Stopping a listen session will cause a final result to be sent. Each + /// listen session should be ended with either [stop] or [cancel], for + /// example in the dispose method of a Widget. [cancel] is automatically + /// invoked by a permanent error if [cancelOnError] is set to true in the + /// [listen] call. + /// + /// *Note:* Cannot be used until a successful [initialize] call. Should + /// only be used after a successful [listen] call. + Future stop() async {} + + /// Cancels the current listen for speech if active, does nothing if not. + /// + /// Canceling means that there will be no final result returned from the + /// recognizer. Each listen session should be ended with either [stop] or + /// [cancel], for example in the dispose method of a Widget. [cancel] is + /// automatically invoked by a permanent error if [cancelOnError] is set + /// to true in the [listen] call. + /// + /// *Note* Cannot be used until a successful [initialize] call. Should only + /// be used after a successful [listen] call. + Future cancel() async {} + + /// Starts a listening session for speech and converts it to text. + /// + /// Cannot be used until a successful [initialize] call. There is a + /// time limit on listening imposed by both Android and iOS. The time + /// depends on the device, network, etc. Android is usually quite short, + /// especially if there is no active speech event detected, on the order + /// of ten seconds or so. + /// + /// [localeId] is an optional locale that can be used to listen in a language + /// other than the current system default. See [locales] to find the list of + /// supported languages for listening. + /// + /// [partialResults] if true the listen reports results as they are recognized, + /// when false only final results are reported. Defaults to true. + /// + /// [onDevice] if true the listen attempts to recognize locally with speech never + /// leaving the device. If it cannot do this the listen attempt will fail. This is + /// usually only needed for sensitive content where privacy or security is a concern. + /// + /// [sampleRate] optional for compatibility with certain iOS devices, some devices + /// crash with `sampleRate != device's supported sampleRate`, try 44100 if seeing + /// crashes + /// + Future listen( + {String localeId, + partialResults = true, + onDevice = false, + int listenMode, + sampleRate = 0}) async { + return false; + } + + /// returns the list of speech locales available on the device. + /// + Future> locales() async { + return []; + } +} diff --git a/speech_to_text/scripts/tcov.sh b/speech_to_text/scripts/tcov.sh new file mode 100644 index 00000000..5d8be65b --- /dev/null +++ b/speech_to_text/scripts/tcov.sh @@ -0,0 +1,5 @@ +# Ensure test errors fail the script +set -e +flutter test --coverage +coverPct=$(genhtml coverage/lcov.info -o coverage | tail -n 2 | head -n 1 | cut -d ' ' -f 4 | sed 's/%//') +scc lib | sed -n '4p' | tr -s ' ' | cut -d ' ' -f 2-7 | sed "s/^/$coverPct,/" | sed 's/ /,/g' | sed "s/^/`date '+%Y\/%m\/%d %H:%M:%S'`,/" >> codestats.csv \ No newline at end of file diff --git a/speech_to_text/test/test_speech_to_text_platform.dart b/speech_to_text/test/test_speech_to_text_platform.dart new file mode 100644 index 00000000..040fe7eb --- /dev/null +++ b/speech_to_text/test/test_speech_to_text_platform.dart @@ -0,0 +1,133 @@ +import 'package:flutter/services.dart'; +import 'package:speech_to_text/speech_recognition_error.dart'; +import 'package:speech_to_text/speech_recognition_result.dart'; +import 'package:speech_to_text/speech_to_text.dart'; +import 'package:speech_to_text_platform_interface/speech_to_text_platform_interface.dart'; + +class TestSpeechToTextPlatform extends SpeechToTextPlatform { + static const String listenExceptionCode = "listenFailedError"; + static const String listenExceptionMessage = "Failed"; + static const String listenExceptionDetails = "Device Listen Failure"; + + bool initResult = true; + bool initInvoked = false; + bool listenInvoked = false; + bool cancelInvoked = false; + bool stopInvoked = false; + bool localesInvoked = false; + bool hasPermissionResult = true; + bool listenException = false; + String listeningStatusResponse = SpeechToText.listeningStatus; + String listenLocale; + List localesResult = []; + static const String localeId1 = "en_US"; + static const String localeId2 = "fr_CA"; + static const String name1 = "English US"; + static const String name2 = "French Canada"; + static const String locale1 = "$localeId1:$name1"; + static const String locale2 = "$localeId2:$name2"; + static const String firstRecognizedWords = 'hello'; + static const String secondRecognizedWords = 'hello there'; + static const double firstConfidence = 0.85; + static const double secondConfidence = 0.62; + static const String firstRecognizedJson = + '{"alternates":[{"recognizedWords":"$firstRecognizedWords","confidence":$firstConfidence}],"finalResult":false}'; + static const String secondRecognizedJson = + '{"alternates":[{"recognizedWords":"$secondRecognizedWords","confidence":$secondConfidence}],"finalResult":false}'; + static const String finalRecognizedJson = + '{"alternates":[{"recognizedWords":"$secondRecognizedWords","confidence":$secondConfidence}],"finalResult":true}'; + static const SpeechRecognitionWords firstWords = + SpeechRecognitionWords(firstRecognizedWords, firstConfidence); + static const SpeechRecognitionWords secondWords = + SpeechRecognitionWords(secondRecognizedWords, secondConfidence); + static final SpeechRecognitionResult firstRecognizedResult = + SpeechRecognitionResult([firstWords], false); + static final SpeechRecognitionResult secondRecognizedResult = + SpeechRecognitionResult([secondWords], false); + static final SpeechRecognitionResult finalRecognizedResult = + SpeechRecognitionResult([secondWords], true); + static const String transientErrorJson = + '{"errorMsg":"network","permanent":false}'; + static const String permanentErrorJson = + '{"errorMsg":"network","permanent":true}'; + static final SpeechRecognitionError firstError = + SpeechRecognitionError("network", true); + static const double level1 = 0.5; + static const double level2 = 10; + + @override + Future hasPermission() async { + return hasPermissionResult; + } + + @override + Future initialize( + {debugLogging = false, List options}) async { + initInvoked = true; + return initResult; + } + + @override + Future stop() async { + stopInvoked = true; + } + + @override + Future cancel() async { + cancelInvoked = true; + } + + @override + Future listen( + {String localeId, + partialResults = true, + onDevice = false, + int listenMode, + sampleRate = 0}) async { + listenInvoked = true; + listenLocale = localeId; + if (listenException) { + throw PlatformException( + code: listenExceptionCode, + message: listenExceptionMessage, + details: listenExceptionDetails); + } + return true; + } + + @override + Future> locales() async { + localesInvoked = true; + return localesResult; + } + + void notifyListening() { + onStatus(SpeechToText.listeningStatus); + } + + void notifyFinalWords() { + onTextRecognition(finalRecognizedJson); + } + + void notifyPartialWords() { + onTextRecognition(firstRecognizedJson); + } + + void notifyPermanentError() { + onError(permanentErrorJson); + } + + void notifyTransientError() { + onError(transientErrorJson); + } + + void notifySoundLevel() { + onSoundLevel(level2); + } + + void setupLocales() { + localesResult.clear(); + localesResult.add(locale1); + localesResult.add(locale2); + } +} diff --git a/speech_to_text_/.github/workflows/master.yml b/speech_to_text_/.github/workflows/master.yml new file mode 100644 index 00000000..4d4cff1c --- /dev/null +++ b/speech_to_text_/.github/workflows/master.yml @@ -0,0 +1,19 @@ +name: build + +on: + push: + branches: + - master + +jobs: + test: + name: Test on Ubuntu + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - uses: subosito/flutter-action@v1.3.2 + with: + flutter-version: '1.17.1' + channel: 'stable' + - run: flutter pub get + - run: flutter test diff --git a/speech_to_text_/.gitignore b/speech_to_text_/.gitignore new file mode 100644 index 00000000..8969cbcd --- /dev/null +++ b/speech_to_text_/.gitignore @@ -0,0 +1,11 @@ +.DS_Store +.dart_tool/ + +.packages +.pub/ + +build/ +coverage/ +example/.flutter-plugins-dependencies +**/ios/Flutter/flutter_export_environment.sh +android/.idea/ diff --git a/speech_to_text_/.metadata b/speech_to_text_/.metadata new file mode 100644 index 00000000..1940d996 --- /dev/null +++ b/speech_to_text_/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: 2d2a1ffec95cc70a3218872a2cd3f8de4933c42f + channel: stable + +project_type: plugin diff --git a/speech_to_text_/CHANGELOG.md b/speech_to_text_/CHANGELOG.md new file mode 100644 index 00000000..477e110c --- /dev/null +++ b/speech_to_text_/CHANGELOG.md @@ -0,0 +1,166 @@ +# Changelog + +## 2.3.0 + +### New + * new parameter `onDevice` on the `listen` method enforces on device recognition for sensitive content + * onSoundLevelChange now supported on iOS + * added compile troubleshooting help to README.md + * `SpeechToTextProvider` is an alternate and simpler way to interact with the `SpeechToText` plugin. + * new `provider_example.dart` example for usage of `SpeechToTextProvider`. +### Fix + * on iOS handles some conflicts with other applications better to keep speech working after calls for example + + +## 2.2.0 + +### New + * improved error handling and logging in the iOS implementation + * added general guides for iOS to the README + * moved stress testing out of the main example + * iOS now defaults to using the speaker rather than the receiver for start /stop sounds when no headphones +### Fix + * iOS now properly deactivates the audio session when no longer listening + * start and stop sounds on iOS should be more reliable when available + +## 2.1.0 +### Breaking + * `listenFor` now calls `stop` rather than `cancel` as this seems like more useful behaviour + +### Fix + * Android no longer stops or cancels the speech recognizer if it has already been shutdown by a + timeout or other platform behaviour. + * Android no longer tries to restart the listener when it is already active + * Now properly notifies errors that happen after listening stops due to platform callback rather than + client request. See https://github.com/csdcorp/speech_to_text/issues/51 + +## 2.0.1 +### Fix + * Resolves an issue with the Android implementation not handling permission requests properly on apps + that didn't use the 1.12.x plugin APIs for registration. The permission dialog would not appear and + permission was denied. + + +## 2.0.0 + +### Breaking + + * Upgraded to New Swift 1.12 plugin structure, may work with older Flutter version but not guaranteed + +### New + + * the plugin now requests both speech and microphone permission on initialize on iOS + * added `debugLogging` parameter to the `initialize` method to control native logging + +### Fix + + * The Android implementation now blocks duplicate results notifications. It appears that at least on some + Android versions the final results notification onResults is notified twice when Android automatically + terminates the session due to a pause time. The de-duplication looks for successive notifications + with < 100 ms between them and blocks the second. If you miss any onResult notifications please post + an issue. + +## 1.1.0 + +### New + + * error_timeout has been separated into error_network_timeout and error_speech_timeout + +## 1.0.0 + +### New + * hasPermission to check for the current permission without bringing up the system dialog + * `listen` has a new optional `cancelOnError` parameter to support automatically canceling + a listening session on a permanent error. + * `listen` has a new optional `partialResults` parameter that controls whether the callback + receives partial or only final results. + +## 0.8.0 + +### New + + * speech recognizer now exposes multiple possible transcriptions for each recognized speech + * alternates list on SpeechRecognitionResult exposes alternate transcriptions of voice + * confidence on SpeechRecognitionResult gives an estimate of confidence in the transcription + * isConfident on SpeechRecognitionResult supports testing confidence + * hasConfidenceRating on SpeechRecognitionResult indicates if confidence was provided from the device + * new SpeechRecognitionWords class gives details on per transcription words and confidence + +### Fix + + * speechRecognizer availabilityDidChange was crashing if invoked due to an invalid parameter type + * Added iOS platform 10 to example Podfile to resolve compilation warnings + +## 0.7.2 + +### Breaking + + * Upgrade Swift to version 5 to match Flutter. Projects using this plugin must now switch to 5. + +## 0.7.1 + +### Fix + + * Upgrade Kotlin to 1.3.5 to match the Flutter 1.12 version + * Upgrade Gradle build to 3.5.0 to match the Flutter 1.12 version + * Android version of the plugin was repeating the system default locale in the `locales` list + +## 0.7.0 + +### New + + * locales method returns the list of available languages for speech + * new optional localeId parameter on listen method supports choosing the comprehension language separately from the current system locale. + +### Breaking + + * `cancel` and `stop` are now async + +## 0.6.3 + +### Fix + + * request permission fix on Android to ensure it doesn't conflict with other requests + +## 0.6.2 + +### Fix + + * channel invoke wasn't being done on the main thread in iOS + +## 0.6.1 + +### Fix + + * listening sound was failing due to timing, now uses play and record mode on iOS. + + ## 0.6.0 +### Breaking + + * The filenames for the optional sounds for iOS have changed. + +### New + + * Added an optional listenFor parameter to set a max duration to listen for speech and then automatically cancel. + +### Fix + + * Was failing to play sounds because of record mode. Now plays sounds before going into record mode and after coming out. + * Status listener was being ignored, now properly notifies on status changes. + +## 0.5.1 + * Fixes a problem where the recognizer left the AVAudioSession in record mode which meant that subsequent sounds couldn't be played. + +## 0.5.0 +Initial draft with limited functionality, supports: + * initializing speech recognition + * asking the user for permission if required + * listening for recognized speech + * canceling the current recognition session + * stopping the current recognition session +* Android and iOS 10+ support + +Missing: + * some error handling + * testing across multiple OS versions + * and more, to be discovered... diff --git a/speech_to_text_/LICENSE b/speech_to_text_/LICENSE new file mode 100644 index 00000000..7c3991c8 --- /dev/null +++ b/speech_to_text_/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2019, Corner Software Development Corp. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/speech_to_text_/README.md b/speech_to_text_/README.md new file mode 100644 index 00000000..af726f0e --- /dev/null +++ b/speech_to_text_/README.md @@ -0,0 +1,150 @@ +# speech_to_text + +[![pub package](https://img.shields.io/badge/pub-v2.3.0-blue)](https://pub.dartlang.org/packages/speech_to_text) [![build status](https://github.com/csdcorp/speech_to_text/workflows/build/badge.svg)](https://github.com/csdcorp/speech_to_text/actions?query=workflow%3Abuild) + +A library that exposes device specific speech recognition capability. + +This plugin contains a set of classes that make it easy to use the speech recognition +capabilities of the mobile device in Flutter. It supports both Android and iOS. The +target use cases for this library are commands and short phrases, not continuous spoken +conversion or always on listening. + +## Recent Updates + +The 2.3.0 version adds `SpeechToTextProvider` as a simpler way to interact with the plugin. Checkout +the new `provider_example.dart` for intended usage. + +The 2.2.0 version improves audio session handling and start / stop sound playback on iOS. + +*Note*: Feedback from any test devices is welcome. + +## Using + +To recognize text from the microphone import the package and call the plugin, like so: + +```dart +import 'package:speech_to_text/speech_to_text.dart' as stt; + + stt.SpeechToText speech = stt.SpeechToText(); + bool available = await speech.initialize( onStatus: statusListener, onError: errorListener ); + if ( available ) { + speech.listen( onResult: resultListener ); + } + else { + print("The user has denied the use of speech recognition."); + } + // some time later... + speech.stop() +``` + +### Initialize once +The `initialize` method only needs to be called once per application session. After that `listen`, +`start`, `stop`, and `cancel` can be used to interact with the plugin. Subsequent calls to `initialize` +are ignored which is safe but does mean that the `onStatus` and `onError` callbacks cannot be reset after +the first call to `initialize`. For that reason there should be only one instance of the plugin per +application. The `SpeechToTextProvider` is one way to create a single instance and easily reuse it in +multiple widgets. + +## Permissions + +Applications using this plugin require user permissions. +### iOS + +Add the following keys to your _Info.plist_ file, located in `/ios/Runner/Info.plist`: + +* `NSSpeechRecognitionUsageDescription` - describe why your app uses speech recognition. This is called _Privacy - Speech Recognition Usage Description_ in the visual editor. +* `NSMicrophoneUsageDescription` - describe why your app needs access to the microphone. This is called _Privacy - Microphone Usage Description_ in the visual editor. + +### Android + +Add the record audio permission to your _AndroidManifest.xml_ file, located in `/android/app/src/main/AndroidManifest.xml`. + +* `android.permission.RECORD_AUDIO` - this permission is required for microphone access. +* `android.permission.INTERNET` - this permission is required because speech recognition may use remote services. + +## Adding Sounds for iOS (optional) + +Android automatically plays system sounds when speech listening starts or stops but iOS does not. This plugin supports playing sounds to indicate listening status on iOS if sound files are available as assets in the application. To enable sounds in an application using this plugin add the sound files to the project and reference them in the assets section of the application `pubspec.yaml`. The location and filenames of the sound files must exactly match what +is shown below or they will not be found. The example application for the plugin shows the usage. *Note* These files should be very short as they delay +the start / end of the speech recognizer until the sound playback is complete. +```yaml + assets: + - assets/sounds/speech_to_text_listening.m4r + - assets/sounds/speech_to_text_cancel.m4r + - assets/sounds/speech_to_text_stop.m4r +``` +* `speech_to_text_listening.m4r` - played when the listen method is called. +* `speech_to_text_cancel.m4r` - played when the cancel method is called. +* `speech_to_text_stop.m4r` - played when the stop method is called. + +## Troubleshooting + +### SDK version error trying to compile for Android +``` +Manifest merger failed : uses-sdk:minSdkVersion 16 cannot be smaller than version 21 declared in library [:speech_to_text] +``` +The speech_to_text plugin requires at least Android SDK 21 because some of the speech functions in Android +were only introduced in that version. To fix this error you need to change the `build.gradle` entry to reflect +this version. Here's what the relevant part of that file looked like as of this writing: +``` + defaultConfig { + applicationId "com.example.app" + minSdkVersion 21 + targetSdkVersion 28 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } +``` + +### Incorrect Swift version trying to compile for iOS +``` +/Users/markvandergon/flutter/.pub-cache/hosted/pub.dartlang.org/speech_to_text-1.1.0/ios/Classes/SwiftSpeechToTextPlugin.swift:224:44: error: value of type 'SwiftSpeechToTextPlugin' has no member 'AVAudioSession' + rememberedAudioCategory = self.AVAudioSession.Category + ~~~~ ^~~~~~~~~~~~~~ + /Users/markvandergon/flutter/.pub-cache/hosted/pub.dartlang.org/speech_to_text-1.1.0/ios/Classes/SwiftSpeechToTextPlugin.swift:227:63: error: type 'Int' has no member 'notifyOthersOnDeactivation' + try self.audioSession.setActive(true, withFlags: .notifyOthersOnDeactivation) +``` +This happens when the Swift language version is not set correctly. See this thread for help https://github.com/csdcorp/speech_to_text/issues/45. + +### Swift not supported trying to compile for iOS +``` +`speech_to_text` does not specify a Swift version and none of the targets (`Runner`) integrating it have the `SWIFT_VERSION` attribute set. +``` +This usually happens for older projects that only support Objective-C. See this thread for help https://github.com/csdcorp/speech_to_text/issues/88. + +### Not working on a particular Android device +The symptom for this issue is that the `initialize` method will always fail. If you turn on debug logging +using the `debugLogging: true` flag on the `initialize` method you'll see `'Speech recognition unavailable'` +in the Android log. There's a lengthy issue discussion here https://github.com/csdcorp/speech_to_text/issues/36 +about this. The issue seems to be that the recognizer is not always automatically enabled on the device. Two +key things helped resolve the issue in this case at least. + +#### First +1. Go to Google Play +2. Search for 'Google' +3. You should find this app: https://play.google.com/store/apps/details?id=com.google.android.googlequicksearchbox +If 'Disabled' enable it + +This is the SO post that helped: https://stackoverflow.com/questions/28769320/how-to-check-wether-speech-recognition-is-available-or-not + +#### Second +Ensure the app has the required permissions. The symptom for this that you get a permanent error notification + 'error_audio_error` when starting a listen session. Here's a Stack Overflow post that addresses that + https://stackoverflow.com/questions/46376193/android-speechrecognizer-audio-recording-error + Here's the important excerpt: + >You should go to system setting, Apps, Google app, then enable its permission of microphone. + +### iOS recognition guidelines +Apple has quite a good guide on the user experience for using speech, the original is here +https://developer.apple.com/documentation/speech/sfspeechrecognizer This is the section that I think is particularly relevant: + +>#### Create a Great User Experience for Speech Recognition +>Here are some tips to consider when adding speech recognition support to your app. + +>**Be prepared to handle failures caused by speech recognition limits.** Because speech recognition is a network-based service, limits are enforced so that the service can remain freely available to all apps. Individual devices may be limited in the number of recognitions that can be performed per day, and each app may be throttled globally based on the number of requests it makes per day. If a recognition request fails quickly (within a second or two of starting), check to see if the recognition service became unavailable. If it is, you may want to ask users to try again later. + +>**Plan for a one-minute limit on audio duration.** Speech recognition places a relatively high burden on battery life and network usage. To minimize this burden, the framework stops speech recognition tasks that last longer than one minute. This limit is similar to the one for keyboard-related dictation. +Remind the user when your app is recording. For example, display a visual indicator and play sounds at the beginning and end of speech recognition to help users understand that they're being actively recorded. You can also display speech as it is being recognized so that users understand what your app is doing and see any mistakes made during the recognition process. + +>**Do not perform speech recognition on private or sensitive information.** Some speech is not appropriate for recognition. Don't send passwords, health or financial data, and other sensitive speech for recognition. diff --git a/speech_to_text_/android/.classpath b/speech_to_text_/android/.classpath new file mode 100644 index 00000000..eb19361b --- /dev/null +++ b/speech_to_text_/android/.classpath @@ -0,0 +1,6 @@ + + + + + + diff --git a/speech_to_text_/android/.gitignore b/speech_to_text_/android/.gitignore new file mode 100644 index 00000000..c6cbe562 --- /dev/null +++ b/speech_to_text_/android/.gitignore @@ -0,0 +1,8 @@ +*.iml +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build +/captures diff --git a/speech_to_text_/android/.project b/speech_to_text_/android/.project new file mode 100644 index 00000000..3050653c --- /dev/null +++ b/speech_to_text_/android/.project @@ -0,0 +1,23 @@ + + + speech_to_text + Project android_____ created by Buildship. + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.buildship.core.gradleprojectnature + + diff --git a/speech_to_text_/android/.settings/org.eclipse.buildship.core.prefs b/speech_to_text_/android/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 00000000..7a23d112 --- /dev/null +++ b/speech_to_text_/android/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,13 @@ +arguments= +auto.sync=false +build.scans.enabled=false +connection.gradle.distribution=GRADLE_DISTRIBUTION(VERSION(5.6.1)) +connection.project.dir= +eclipse.preferences.version=1 +gradle.user.home= +java.home= +jvm.arguments= +offline.mode=false +override.workspace.settings=true +show.console.view=true +show.executions.view=true diff --git a/speech_to_text_/android/build.gradle b/speech_to_text_/android/build.gradle new file mode 100644 index 00000000..6b23b300 --- /dev/null +++ b/speech_to_text_/android/build.gradle @@ -0,0 +1,44 @@ +group 'com.csdcorp.speech_to_text' +version '1.0-SNAPSHOT' + +buildscript { + ext.kotlin_version = '1.3.50' + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.5.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +rootProject.allprojects { + repositories { + google() + jcenter() + } +} + +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' + +android { + compileSdkVersion 28 + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + defaultConfig { + minSdkVersion 21 + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + lintOptions { + disable 'InvalidPackage' + } +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" +} diff --git a/speech_to_text_/android/gradle/gradle.properties b/speech_to_text_/android/gradle/gradle.properties new file mode 100644 index 00000000..94adc3a3 --- /dev/null +++ b/speech_to_text_/android/gradle/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true diff --git a/speech_to_text_/android/gradle/local.properties b/speech_to_text_/android/gradle/local.properties new file mode 100644 index 00000000..71a0a2e4 --- /dev/null +++ b/speech_to_text_/android/gradle/local.properties @@ -0,0 +1,3 @@ +sdk.dir=/Users/stephen.owens/Library/Android/sdk +flutter.sdk=/Users/stephen.owens/Documents/dev/flutter/sdk/flutter +org.gradle.jvmargs=-Xmx1536m -Duser.country=US -Duser.language=en \ No newline at end of file diff --git a/speech_to_text_/android/gradle/settings.gradle b/speech_to_text_/android/gradle/settings.gradle new file mode 100644 index 00000000..cdfc1c4b --- /dev/null +++ b/speech_to_text_/android/gradle/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'speech_to_text' diff --git a/speech_to_text_/android/gradle/wrapper/gradle-wrapper.properties b/speech_to_text_/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..674bdda0 --- /dev/null +++ b/speech_to_text_/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip diff --git a/speech_to_text_/android/src/main/AndroidManifest.xml b/speech_to_text_/android/src/main/AndroidManifest.xml new file mode 100644 index 00000000..61a73f32 --- /dev/null +++ b/speech_to_text_/android/src/main/AndroidManifest.xml @@ -0,0 +1,3 @@ + + diff --git a/speech_to_text_/android/src/main/kotlin/com/csdcorp/speech_to_text/SpeechToTextPlugin.kt b/speech_to_text_/android/src/main/kotlin/com/csdcorp/speech_to_text/SpeechToTextPlugin.kt new file mode 100644 index 00000000..7954add3 --- /dev/null +++ b/speech_to_text_/android/src/main/kotlin/com/csdcorp/speech_to_text/SpeechToTextPlugin.kt @@ -0,0 +1,595 @@ +package com.csdcorp.speech_to_text + +import androidx.annotation.NonNull; +import io.flutter.embedding.engine.plugins.FlutterPlugin +import android.Manifest +import android.annotation.TargetApi +import android.app.Activity +import android.content.Intent +import android.content.pm.PackageManager +import android.os.Build +import android.os.Bundle +import android.speech.RecognitionListener +import android.speech.SpeechRecognizer.createSpeechRecognizer +import android.speech.RecognizerIntent +import android.speech.SpeechRecognizer +import androidx.core.app.ActivityCompat +import androidx.core.content.ContextCompat +import io.flutter.plugin.common.MethodCall +import io.flutter.plugin.common.MethodChannel +import io.flutter.plugin.common.MethodChannel.MethodCallHandler +import io.flutter.plugin.common.MethodChannel.Result +import io.flutter.plugin.common.PluginRegistry +import io.flutter.plugin.common.PluginRegistry.Registrar +import org.json.JSONObject +import android.content.Context +import android.content.BroadcastReceiver +import android.os.Handler +import android.os.Looper +import android.util.Log +import io.flutter.embedding.engine.plugins.activity.ActivityAware +import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding +import io.flutter.plugin.common.BinaryMessenger +import org.json.JSONArray +import java.util.* + + +enum class SpeechToTextErrors { + multipleRequests, + unimplemented, + noLanguageIntent, + recognizerNotAvailable, + missingOrInvalidArg, + unknown +} + +enum class SpeechToTextCallbackMethods { + textRecognition, + notifyStatus, + notifyError, + soundLevelChange, +} + +enum class SpeechToTextStatus { + listening, + notListening, + unavailable, + available, +} + +enum class ListenMode { + deviceDefault, + dictation, + search, + confirmation, +} + +const val pluginChannelName = "plugin.csdcorp.com/speech_to_text" + +@TargetApi(8) +/** SpeechToTextPlugin */ +public class SpeechToTextPlugin : + MethodCallHandler, RecognitionListener, + PluginRegistry.RequestPermissionsResultListener, FlutterPlugin, + ActivityAware { + private var pluginContext: Context? = null + private var channel: MethodChannel? = null + private val minSdkForSpeechSupport = 21 + private val speechToTextPermissionCode = 28521 + private val missingConfidence: Double = -1.0 + private val logTag = "SpeechToTextPlugin" + private var currentActivity: Activity? = null + private var activeResult: Result? = null + private var initializedSuccessfully: Boolean = false + private var permissionToRecordAudio: Boolean = false + private var listening = false + private var debugLogging: Boolean = false + private var speechRecognizer: SpeechRecognizer? = null + private var recognizerIntent: Intent? = null + private var previousRecognizerLang: String? = null + private var previousPartialResults: Boolean = true + private var previousListenMode: ListenMode = ListenMode.deviceDefault + private var lastFinalTime: Long = 0 + private val handler: Handler = Handler(Looper.getMainLooper()) + private val defaultLanguageTag: String = Locale.getDefault().toLanguageTag() + + override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { + + onAttachedToEngine(flutterPluginBinding.getApplicationContext(), flutterPluginBinding.getBinaryMessenger()); + } + + // This static function is optional and equivalent to onAttachedToEngine. It supports the old + // pre-Flutter-1.12 Android projects. You are encouraged to continue supporting + // plugin registration via this function while apps migrate to use the new Android APIs + // post-flutter-1.12 via https://flutter.dev/go/android-project-migration. + // + // It is encouraged to share logic between onAttachedToEngine and registerWith to keep + // them functionally equivalent. Only one of onAttachedToEngine or registerWith will be called + // depending on the user's project. onAttachedToEngine or registerWith must both be defined + // in the same class. + companion object { + @JvmStatic + fun registerWith(registrar: Registrar) { + val speechPlugin = SpeechToTextPlugin() + speechPlugin.currentActivity = registrar.activity() + registrar.addRequestPermissionsResultListener(speechPlugin) + speechPlugin.onAttachedToEngine(registrar.context(), registrar.messenger()) + } + } + + private fun onAttachedToEngine(applicationContext: Context, messenger: BinaryMessenger) { + this.pluginContext = applicationContext; + channel = MethodChannel(messenger, pluginChannelName) + channel?.setMethodCallHandler(this) + } + + override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) { + this.pluginContext = null; + channel?.setMethodCallHandler(null) + channel = null + } + + override fun onDetachedFromActivity() { + currentActivity = null + } + + override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) { + currentActivity = binding.activity + binding.addRequestPermissionsResultListener(this) + } + + override fun onAttachedToActivity(binding: ActivityPluginBinding) { + currentActivity = binding.activity + binding.addRequestPermissionsResultListener(this) + } + + override fun onDetachedFromActivityForConfigChanges() { + currentActivity = null + } + + override fun onMethodCall(@NonNull call: MethodCall, @NonNull rawrResult: Result) { + val result = ChannelResultWrapper(rawrResult) + try { + when (call.method) { + "has_permission" -> hasPermission(result) + "initialize" -> { + var dlog = call.argument("debugLogging") + if (null != dlog) { + debugLogging = dlog + } + initialize(result) + } + "listen" -> { + var localeId = call.argument("localeId") + if (null == localeId) { + localeId = defaultLanguageTag + } + var partialResults = call.argument("partialResults") + if (null == partialResults) { + partialResults = true + } + val listenModeIndex = call.argument("listenMode") + if ( null == listenModeIndex ) { + result.error(SpeechToTextErrors.missingOrInvalidArg.name, + "listenMode is required", null) + return + } + startListening(result, localeId, partialResults, listenModeIndex ) + } + "stop" -> stopListening(result) + "cancel" -> cancelListening(result) + "locales" -> locales(result) + else -> result.notImplemented() + } + } catch (exc: Exception) { + Log.e(logTag, "Unexpected exception", exc) + result.error(SpeechToTextErrors.unknown.name, + "Unexpected exception", exc.localizedMessage) + } + } + + private fun hasPermission(result: Result) { + if (sdkVersionTooLow(result)) { + return + } + debugLog("Start has_permission") + val localContext = pluginContext + if (localContext != null) { + val hasPerm = ContextCompat.checkSelfPermission(localContext, + Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED + result.success(hasPerm) + } + } + + private fun initialize(result: Result) { + if (sdkVersionTooLow(result)) { + return + } + debugLog("Start initialize") + if (null != activeResult) { + result.error(SpeechToTextErrors.multipleRequests.name, + "Only one initialize at a time", null) + return + } + activeResult = result + val localContext = pluginContext + initializeIfPermitted(pluginContext) + } + + private fun sdkVersionTooLow(result: Result): Boolean { + if (Build.VERSION.SDK_INT < minSdkForSpeechSupport) { + result.success(false) + return true; + } + return false; + } + + private fun isNotInitialized(result: Result): Boolean { + if (!initializedSuccessfully || null == pluginContext) { + result.success(false) + } + return !initializedSuccessfully + } + + private fun isListening(): Boolean { + return listening + } + + private fun isNotListening(): Boolean { + return !listening + } + + private fun startListening(result: Result, languageTag: String, partialResults: Boolean, + listenModeIndex: Int) { + if (sdkVersionTooLow(result) || isNotInitialized(result) || isListening()) { + return + } + debugLog("Start listening") + var listenMode = ListenMode.deviceDefault + if ( listenModeIndex == ListenMode.dictation.ordinal) { + listenMode = ListenMode.dictation + } + setupRecognizerIntent(languageTag, partialResults, listenMode) + handler.post { + run { + speechRecognizer?.startListening(recognizerIntent) + } + } + notifyListening(isRecording = true) + result.success(true) + debugLog("Start listening done") + } + + private fun stopListening(result: Result) { + if (sdkVersionTooLow(result) || isNotInitialized(result) || isNotListening()) { + return + } + debugLog("Stop listening") + handler.post { + run { + speechRecognizer?.stopListening() + } + } + notifyListening(isRecording = false) + result.success(true) + debugLog("Stop listening done") + } + + private fun cancelListening(result: Result) { + if (sdkVersionTooLow(result) || isNotInitialized(result) || isNotListening()) { + return + } + debugLog("Cancel listening") + handler.post { + run { + speechRecognizer?.cancel() + } + } + notifyListening(isRecording = false) + result.success(true) + debugLog("Cancel listening done") + } + + private fun locales(result: Result) { + if (sdkVersionTooLow(result) || isNotInitialized(result)) { + return + } + var detailsIntent = RecognizerIntent.getVoiceDetailsIntent(pluginContext) + if (null == detailsIntent) { + detailsIntent = Intent(RecognizerIntent.ACTION_GET_LANGUAGE_DETAILS) + } + if (null == detailsIntent) { + result.error(SpeechToTextErrors.noLanguageIntent.name, + "Could not get voice details", null) + return + } + pluginContext?.sendOrderedBroadcast( + detailsIntent, null, LanguageDetailsChecker(result), + null, Activity.RESULT_OK, null, null) + } + + private fun notifyListening(isRecording: Boolean) { + debugLog("Notify listening") + listening = isRecording + val status = when (isRecording) { + true -> SpeechToTextStatus.listening.name + false -> SpeechToTextStatus.notListening.name + } + channel?.invokeMethod(SpeechToTextCallbackMethods.notifyStatus.name, status) + debugLog("Notify listening done") + } + + private fun updateResults(speechBundle: Bundle?, isFinal: Boolean) { + if (isDuplicateFinal( isFinal )) { + debugLog("Discarding duplicate final") + return + } + val userSaid = speechBundle?.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION) + if (null != userSaid && userSaid.isNotEmpty()) { + val speechResult = JSONObject() + speechResult.put("finalResult", isFinal) + val confidence = speechBundle?.getFloatArray(SpeechRecognizer.CONFIDENCE_SCORES) + val alternates = JSONArray() + for (resultIndex in 0..userSaid.size - 1) { + val speechWords = JSONObject() + speechWords.put("recognizedWords", userSaid[resultIndex]) + if (null != confidence && confidence.size >= userSaid.size) { + speechWords.put("confidence", confidence[resultIndex]) + } else { + speechWords.put("confidence", missingConfidence) + } + alternates.put(speechWords) + } + speechResult.put("alternates", alternates) + val jsonResult = speechResult.toString() + debugLog("Calling results callback") + channel?.invokeMethod(SpeechToTextCallbackMethods.textRecognition.name, + jsonResult) + } + } + + private fun isDuplicateFinal( isFinal: Boolean ) : Boolean { + if ( !isFinal ) { + return false + } + val delta = System.currentTimeMillis() - lastFinalTime + lastFinalTime = System.currentTimeMillis() + return delta >= 0 && delta < 100 + } + + private fun initializeIfPermitted(context: Context?) { + val localContext = context + if (null == localContext) { + completeInitialize() + return + } + permissionToRecordAudio = ContextCompat.checkSelfPermission(localContext, + Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED + debugLog("Checked permission") + if (!permissionToRecordAudio) { + val localActivity = currentActivity + if (null != localActivity) { + debugLog("Requesting permission") + ActivityCompat.requestPermissions(localActivity, + arrayOf(Manifest.permission.RECORD_AUDIO), speechToTextPermissionCode) + } else { + debugLog("no permission, no activity, completing") + completeInitialize() + } + } else { + debugLog("has permission, completing") + completeInitialize() + } + debugLog("leaving initializeIfPermitted") + } + + private fun completeInitialize() { + + debugLog("completeInitialize") + if (permissionToRecordAudio) { + debugLog("Testing recognition availability") + if (!SpeechRecognizer.isRecognitionAvailable(pluginContext)) { + Log.e(logTag, "Speech recognition not available on this device") + activeResult?.error(SpeechToTextErrors.recognizerNotAvailable.name, + "Speech recognition not available on this device", "") + activeResult = null + return + } + + debugLog("Creating recognizer") + speechRecognizer = createSpeechRecognizer(pluginContext).apply { + debugLog("Setting listener") + setRecognitionListener(this@SpeechToTextPlugin) + } + if (null == speechRecognizer) { + Log.e(logTag, "Speech recognizer null") + activeResult?.error( + SpeechToTextErrors.recognizerNotAvailable.name, + "Speech recognizer null", "") + activeResult = null + } + + debugLog("before setup intent") + setupRecognizerIntent(defaultLanguageTag, true, ListenMode.deviceDefault) + debugLog("after setup intent") + } + + initializedSuccessfully = permissionToRecordAudio + debugLog("sending result") + activeResult?.success(permissionToRecordAudio) + debugLog("leaving complete") + activeResult = null + } + + private fun setupRecognizerIntent(languageTag: String, partialResults: Boolean, listenMode: ListenMode) { + debugLog("setupRecognizerIntent") + if (previousRecognizerLang == null || + previousRecognizerLang != languageTag || + partialResults != previousPartialResults || previousListenMode != listenMode ) { + previousRecognizerLang = languageTag; + previousPartialResults = partialResults + previousListenMode = listenMode + handler.post { + run { + recognizerIntent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply { + debugLog("In RecognizerIntent apply") + putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM) + debugLog("put model") + val localContext = pluginContext + if (null != localContext) { + putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, + localContext.applicationInfo.packageName) + } + debugLog("put package") + putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, partialResults) + debugLog("put partial") + if (languageTag != Locale.getDefault().toLanguageTag()) { + putExtra(RecognizerIntent.EXTRA_LANGUAGE, languageTag); + debugLog("put languageTag") + } + } + } + } + } + } + + override fun onRequestPermissionsResult(requestCode: Int, permissions: Array?, + grantResults: IntArray?): Boolean { + when (requestCode) { + speechToTextPermissionCode -> { + if (null != grantResults) { + permissionToRecordAudio = grantResults.isNotEmpty() && + grantResults.get(0) == PackageManager.PERMISSION_GRANTED + } + completeInitialize() + return true + } + } + return false + } + + + override fun onPartialResults(results: Bundle?) = updateResults(results, false) + override fun onResults(results: Bundle?) = updateResults(results, true) + override fun onEndOfSpeech() = notifyListening(isRecording = false) + + override fun onError(errorCode: Int) { + val errorMsg = when (errorCode) { + SpeechRecognizer.ERROR_AUDIO -> "error_audio_error" + SpeechRecognizer.ERROR_CLIENT -> "error_client" + SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS -> "error_permission" + SpeechRecognizer.ERROR_NETWORK -> "error_network" + SpeechRecognizer.ERROR_NETWORK_TIMEOUT -> "error_network_timeout" + SpeechRecognizer.ERROR_NO_MATCH -> "error_no_match" + SpeechRecognizer.ERROR_RECOGNIZER_BUSY -> "error_busy" + SpeechRecognizer.ERROR_SERVER -> "error_server" + SpeechRecognizer.ERROR_SPEECH_TIMEOUT -> "error_speech_timeout" + else -> "error_unknown" + } + sendError(errorMsg) + } + + private fun debugLog( msg: String ) { + if ( debugLogging ) { + Log.d( logTag, msg ) + } + } + + private fun sendError(errorMsg: String) { + val speechError = JSONObject() + speechError.put("errorMsg", errorMsg) + speechError.put("permanent", true) + handler.post { + run { + channel?.invokeMethod(SpeechToTextCallbackMethods.notifyError.name, speechError.toString()) + } + } + } + + override fun onRmsChanged(rmsdB: Float) { + handler.post { + run { + channel?.invokeMethod(SpeechToTextCallbackMethods.soundLevelChange.name, rmsdB) + } + } + } + + override fun onReadyForSpeech(p0: Bundle?) {} + override fun onBufferReceived(p0: ByteArray?) {} + override fun onEvent(p0: Int, p1: Bundle?) {} + override fun onBeginningOfSpeech() {} +} + +// See https://stackoverflow.com/questions/10538791/how-to-set-the-language-in-speech-recognition-on-android/10548680#10548680 +class LanguageDetailsChecker(flutterResult: Result) : BroadcastReceiver() { + private val result: Result = flutterResult + private var supportedLanguages: List? = null + + private var languagePreference: String? = null + + override fun onReceive(context: Context, intent: Intent) { + val results = getResultExtras(true) + if (results.containsKey(RecognizerIntent.EXTRA_LANGUAGE_PREFERENCE)) { + languagePreference = results.getString(RecognizerIntent.EXTRA_LANGUAGE_PREFERENCE) + } + if (results.containsKey(RecognizerIntent.EXTRA_SUPPORTED_LANGUAGES)) { + supportedLanguages = results.getStringArrayList( + RecognizerIntent.EXTRA_SUPPORTED_LANGUAGES) + createResponse(supportedLanguages) + } + } + + private fun createResponse(supportedLanguages: List?) { + val currentLocale = Locale.getDefault() + val localeNames = ArrayList() + localeNames.add(buildIdNameForLocale(currentLocale)) + if (null != supportedLanguages) { + for (lang in supportedLanguages) { + if (currentLocale.toLanguageTag() == lang) { + continue + } + val locale = Locale.forLanguageTag(lang) + localeNames.add(buildIdNameForLocale(locale)) + } + } + result.success(localeNames) + + } + + private fun buildIdNameForLocale(locale: Locale): String { + val name = locale.displayName.replace(':', ' ') + return "${locale.language}_${locale.country}:$name" + } +} + +private class ChannelResultWrapper(result: Result) : Result { + // Caller handler + val handler: Handler = Handler(Looper.getMainLooper()) + val result: Result = result + + // make sure to respond in the caller thread + override fun success(results: Any?) { + + handler.post { + run { + result.success(results); + } + } + } + + override fun error(errorCode: String?, errorMessage: String?, data: Any?) { + handler.post { + run { + result.error(errorCode, errorMessage, data); + } + } + } + + override fun notImplemented() { + handler.post { + run { + result.notImplemented(); + } + } + } +} diff --git a/speech_to_text_/example/.gitignore b/speech_to_text_/example/.gitignore new file mode 100644 index 00000000..2ddde2a5 --- /dev/null +++ b/speech_to_text_/example/.gitignore @@ -0,0 +1,73 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +.dart_tool/ +.flutter-plugins +.packages +.pub-cache/ +.pub/ +/build/ + +# Android related +**/android/**/gradle-wrapper.jar +**/android/.gradle +**/android/captures/ +**/android/gradlew +**/android/gradlew.bat +**/android/local.properties +**/android/**/GeneratedPluginRegistrant.java + +# iOS/XCode related +**/ios/**/*.mode1v3 +**/ios/**/*.mode2v3 +**/ios/**/*.moved-aside +**/ios/**/*.pbxuser +**/ios/**/*.perspectivev3 +**/ios/**/*sync/ +**/ios/**/.sconsign.dblite +**/ios/**/.tags* +**/ios/**/.vagrant/ +**/ios/**/DerivedData/ +**/ios/**/Icon? +**/ios/**/Pods/ +**/ios/**/.symlinks/ +**/ios/**/profile +**/ios/**/xcuserdata +**/ios/.generated/ +**/ios/Flutter/App.framework +**/ios/Flutter/Flutter.framework +**/ios/Flutter/Generated.xcconfig +**/ios/Flutter/app.flx +**/ios/Flutter/app.zip +**/ios/Flutter/flutter_assets/ +**/ios/Flutter/flutter_export_environment.sh +**/ios/ServiceDefinitions.json +**/ios/Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!**/ios/**/default.mode1v3 +!**/ios/**/default.mode2v3 +!**/ios/**/default.pbxuser +!**/ios/**/default.perspectivev3 +!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages diff --git a/speech_to_text_/example/.metadata b/speech_to_text_/example/.metadata new file mode 100644 index 00000000..aeb01ee2 --- /dev/null +++ b/speech_to_text_/example/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: 2d2a1ffec95cc70a3218872a2cd3f8de4933c42f + channel: stable + +project_type: app diff --git a/speech_to_text_/example/README.md b/speech_to_text_/example/README.md new file mode 100644 index 00000000..92252821 --- /dev/null +++ b/speech_to_text_/example/README.md @@ -0,0 +1,155 @@ +# speech_to_text_example + +Demonstrates how to use the speech_to_text plugin. This example requires +that the plugin has been installed. It initializes speech recognition, +listens for words and prints them. + + +## Source + +```dart +import 'package:flutter/material.dart'; +import 'dart:async'; + +import 'package:speech_to_text/speech_to_text.dart'; +import 'package:speech_to_text/speech_recognition_result.dart'; +import 'package:speech_to_text/speech_recognition_error.dart'; + +void main() => runApp(MyApp()); + +class MyApp extends StatefulWidget { + @override + _MyAppState createState() => _MyAppState(); +} + +class _MyAppState extends State { + bool _hasSpeech = false; + String lastWords = ""; + String lastError = ""; + String lastStatus = ""; + final SpeechToText speech = SpeechToText(); + + @override + void initState() { + super.initState(); + initSpeechState(); + } + + Future initSpeechState() async { + bool hasSpeech = await speech.initialize(onError: errorListener, onStatus: statusListener ); + + if (!mounted) return; + setState(() { + _hasSpeech = hasSpeech; + }); + } + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + appBar: AppBar( + title: const Text('Speech to Text Example'), + ), + body: _hasSpeech + ? Column(children: [ + Expanded( + child: Center( + child: Text('Speech recognition available'), + ), + ), + Expanded( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + FlatButton( + child: Text('Start'), + onPressed: startListening, + ), + FlatButton( + child: Text('Stop'), + onPressed: stopListening, + ), + FlatButton( + child: Text('Cancel'), + onPressed:cancelListening, + ), + ], + ), + ), + Expanded( + child: Column( + children: [ + Center( + child: Text('Recognized Words'), + ), + Center( + child: Text(lastWords), + ), + ], + ), + ), + Expanded( + child: Column( + children: [ + Center( + child: Text('Error'), + ), + Center( + child: Text(lastError), + ), + ], + ), + ), + Expanded( + child: Center( + child: speech.isListening ? Text("I'm listening...") : Text( 'Not listening' ), + ), + ), + ]) + : Center( child: Text('Speech recognition unavailable', style: TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold))), + ), + ); + } + + void startListening() { + lastWords = ""; + lastError = ""; + speech.listen(onResult: resultListener ); + setState(() { + + }); + } + + void stopListening() { + speech.stop( ); + setState(() { + + }); + } + + void cancelListening() { + speech.cancel( ); + setState(() { + + }); + } + + void resultListener(SpeechRecognitionResult result) { + setState(() { + lastWords = "${result.recognizedWords} - ${result.finalResult}"; + }); + } + + void errorListener(SpeechRecognitionError error ) { + setState(() { + lastError = "${error.errorMsg} - ${error.permanent}"; + }); + } + void statusListener(String status ) { + setState(() { + lastStatus = "$status"; + }); + } +} +``` \ No newline at end of file diff --git a/speech_to_text_/example/android/.project b/speech_to_text_/example/android/.project new file mode 100644 index 00000000..d7d48141 --- /dev/null +++ b/speech_to_text_/example/android/.project @@ -0,0 +1,17 @@ + + + android___ + Project android___ created by Buildship. + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.buildship.core.gradleprojectnature + + diff --git a/speech_to_text_/example/android/.settings/org.eclipse.buildship.core.prefs b/speech_to_text_/example/android/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 00000000..e8895216 --- /dev/null +++ b/speech_to_text_/example/android/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,2 @@ +connection.project.dir= +eclipse.preferences.version=1 diff --git a/speech_to_text_/example/android/app/build.gradle b/speech_to_text_/example/android/app/build.gradle new file mode 100644 index 00000000..8b616f29 --- /dev/null +++ b/speech_to_text_/example/android/app/build.gradle @@ -0,0 +1,67 @@ +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + compileSdkVersion 28 + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + lintOptions { + disable 'InvalidPackage' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.csdcorp.speech_to_text_example" + minSdkVersion 21 + targetSdkVersion 28 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + testImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test:runner:1.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' +} diff --git a/speech_to_text_/example/android/app/src/debug/AndroidManifest.xml b/speech_to_text_/example/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 00000000..36edf838 --- /dev/null +++ b/speech_to_text_/example/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/speech_to_text_/example/android/app/src/main/AndroidManifest.xml b/speech_to_text_/example/android/app/src/main/AndroidManifest.xml new file mode 100644 index 00000000..b0912061 --- /dev/null +++ b/speech_to_text_/example/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + diff --git a/speech_to_text_/example/android/app/src/main/kotlin/com/csdcorp/speech_to_text_example/MainActivity.kt b/speech_to_text_/example/android/app/src/main/kotlin/com/csdcorp/speech_to_text_example/MainActivity.kt new file mode 100644 index 00000000..f44e470e --- /dev/null +++ b/speech_to_text_/example/android/app/src/main/kotlin/com/csdcorp/speech_to_text_example/MainActivity.kt @@ -0,0 +1,12 @@ +package com.csdcorp.speech_to_text_example + +import androidx.annotation.NonNull; +import io.flutter.embedding.android.FlutterActivity +import io.flutter.embedding.engine.FlutterEngine +import io.flutter.plugins.GeneratedPluginRegistrant + +class MainActivity: FlutterActivity() { + override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { + GeneratedPluginRegistrant.registerWith(flutterEngine); + } +} diff --git a/speech_to_text_/example/android/app/src/main/res/drawable/launch_background.xml b/speech_to_text_/example/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 00000000..304732f8 --- /dev/null +++ b/speech_to_text_/example/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/speech_to_text_/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/speech_to_text_/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..db77bb4b7b0906d62b1847e87f15cdcacf6a4f29 GIT binary patch literal 544 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAj~WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!h8bpbvhu0Wd6uZuB!w&u2PAxD2eNXD>P5D~Wn-+_Wa#27Xc zC?Zj|6r#X(-D3u$NCt}(Ms06KgJ4FxJVv{GM)!I~&n8Bnc94O7-Hd)cjDZswgC;Qs zO=b+9!WcT8F?0rF7!Uys2bs@gozCP?z~o%U|N3vA*22NaGQG zlg@K`O_XuxvZ&Ks^m&R!`&1=spLvfx7oGDKDwpwW`#iqdw@AL`7MR}m`rwr|mZgU`8P7SBkL78fFf!WnuYWm$5Z0 zNXhDbCv&49sM544K|?c)WrFfiZvCi9h0O)B3Pgg&ebxsLQ05GG~ AQ2+n{ literal 0 HcmV?d00001 diff --git a/speech_to_text_/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/speech_to_text_/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..17987b79bb8a35cc66c3c1fd44f5a5526c1b78be GIT binary patch literal 442 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5Xx&nMcT!A!W`0S9QKQy;}1Cl^CgaH=;G9cpY;r$Q>i*pfB zP2drbID<_#qf;rPZx^FqH)F_D#*k@@q03KywUtLX8Ua?`H+NMzkczFPK3lFz@i_kW%1NOn0|D2I9n9wzH8m|-tHjsw|9>@K=iMBhxvkv6m8Y-l zytQ?X=U+MF$@3 zt`~i=@j|6y)RWMK--}M|=T`o&^Ni>IoWKHEbBXz7?A@mgWoL>!*SXo`SZH-*HSdS+ yn*9;$7;m`l>wYBC5bq;=U}IMqLzqbYCidGC!)_gkIk_C@Uy!y&wkt5C($~2D>~)O*cj@FGjOCM)M>_ixfudOh)?xMu#Fs z#}Y=@YDTwOM)x{K_j*Q;dPdJ?Mz0n|pLRx{4n|)f>SXlmV)XB04CrSJn#dS5nK2lM zrZ9#~WelCp7&e13Y$jvaEXHskn$2V!!DN-nWS__6T*l;H&Fopn?A6HZ-6WRLFP=R` zqG+CE#d4|IbyAI+rJJ`&x9*T`+a=p|0O(+s{UBcyZdkhj=yS1>AirP+0R;mf2uMgM zC}@~JfByORAh4SyRgi&!(cja>F(l*O+nd+@4m$|6K6KDn_&uvCpV23&>G9HJp{xgg zoq1^2_p9@|WEo z*X_Uko@K)qYYv~>43eQGMdbiGbo>E~Q& zrYBH{QP^@Sti!`2)uG{irBBq@y*$B zi#&(U-*=fp74j)RyIw49+0MRPMRU)+a2r*PJ$L5roHt2$UjExCTZSbq%V!HeS7J$N zdG@vOZB4v_lF7Plrx+hxo7(fCV&}fHq)$ literal 0 HcmV?d00001 diff --git a/speech_to_text_/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/speech_to_text_/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..d5f1c8d34e7a88e3f88bea192c3a370d44689c3c GIT binary patch literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q8Ax83A=Cw=BuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFa`(sgt!6~Yi|1%a`XoT0ojZ}lNrNjb9xjc(B0U1_% zz5^97Xt*%oq$rQy4?0GKNfJ44uvxI)gC`h-NZ|&0-7(qS@?b!5r36oQ}zyZrNO3 zMO=Or+<~>+A&uN&E!^Sl+>xE!QC-|oJv`ApDhqC^EWD|@=#J`=d#Xzxs4ah}w&Jnc z$|q_opQ^2TrnVZ0o~wh<3t%W&flvYGe#$xqda2bR_R zvPYgMcHgjZ5nSA^lJr%;<&0do;O^tDDh~=pIxA#coaCY>&N%M2^tq^U%3DB@ynvKo}b?yu-bFc-u0JHzced$sg7S3zqI(2 z#Km{dPr7I=pQ5>FuK#)QwK?Y`E`B?nP+}U)I#c1+FM*1kNvWG|a(TpksZQ3B@sD~b zpQ2)*V*TdwjFOtHvV|;OsiDqHi=6%)o4b!)x$)%9pGTsE z-JL={-Ffv+T87W(Xpooq<`r*VzWQcgBN$$`u}f>-ZQI1BB8ykN*=e4rIsJx9>z}*o zo~|9I;xof literal 0 HcmV?d00001 diff --git a/speech_to_text_/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/speech_to_text_/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..4d6372eebdb28e45604e46eeda8dd24651419bc0 GIT binary patch literal 1443 zcmb`G{WsKk6vsdJTdFg%tJav9_E4vzrOaqkWF|A724Nly!y+?N9`YV6wZ}5(X(D_N(?!*n3`|_r0Hc?=PQw&*vnU?QTFY zB_MsH|!j$PP;I}?dppoE_gA(4uc!jV&0!l7_;&p2^pxNo>PEcNJv za5_RT$o2Mf!<+r?&EbHH6nMoTsDOa;mN(wv8RNsHpG)`^ymG-S5By8=l9iVXzN_eG%Xg2@Xeq76tTZ*dGh~Lo9vl;Zfs+W#BydUw zCkZ$o1LqWQO$FC9aKlLl*7x9^0q%0}$OMlp@Kk_jHXOjofdePND+j!A{q!8~Jn+s3 z?~~w@4?egS02}8NuulUA=L~QQfm;MzCGd)XhiftT;+zFO&JVyp2mBww?;QByS_1w! zrQlx%{^cMj0|Bo1FjwY@Q8?Hx0cIPF*@-ZRFpPc#bBw{5@tD(5%sClzIfl8WU~V#u zm5Q;_F!wa$BSpqhN>W@2De?TKWR*!ujY;Yylk_X5#~V!L*Gw~;$%4Q8~Mad z@`-kG?yb$a9cHIApZDVZ^U6Xkp<*4rU82O7%}0jjHlK{id@?-wpN*fCHXyXh(bLt* zPc}H-x0e4E&nQ>y%B-(EL=9}RyC%MyX=upHuFhAk&MLbsF0LP-q`XnH78@fT+pKPW zu72MW`|?8ht^tz$iC}ZwLp4tB;Q49K!QCF3@!iB1qOI=?w z7In!}F~ij(18UYUjnbmC!qKhPo%24?8U1x{7o(+?^Zu0Hx81|FuS?bJ0jgBhEMzf< zCgUq7r2OCB(`XkKcN-TL>u5y#dD6D!)5W?`O5)V^>jb)P)GBdy%t$uUMpf$SNV31$ zb||OojAbvMP?T@$h_ZiFLFVHDmbyMhJF|-_)HX3%m=CDI+ID$0^C>kzxprBW)hw(v zr!Gmda);ICoQyhV_oP5+C%?jcG8v+D@9f?Dk*!BxY}dazmrT@64UrP3hlslANK)bq z$67n83eh}OeW&SV@HG95P|bjfqJ7gw$e+`Hxo!4cx`jdK1bJ>YDSpGKLPZ^1cv$ek zIB?0S<#tX?SJCLWdMd{-ME?$hc7A$zBOdIJ)4!KcAwb=VMov)nK;9z>x~rfT1>dS+ zZ6#`2v@`jgbqq)P22H)Tx2CpmM^o1$B+xT6`(v%5xJ(?j#>Q$+rx_R|7TzDZe{J6q zG1*EcU%tE?!kO%^M;3aM6JN*LAKUVb^xz8-Pxo#jR5(-KBeLJvA@-gxNHx0M-ZJLl z;#JwQoh~9V?`UVo#}{6ka@II>++D@%KqGpMdlQ}?9E*wFcf5(#XQnP$Dk5~%iX^>f z%$y;?M0BLp{O3a(-4A?ewryHrrD%cx#Q^%KY1H zNre$ve+vceSLZcNY4U(RBX&)oZn*Py()h)XkE?PL$!bNb{N5FVI2Y%LKEm%yvpyTP z(1P?z~7YxD~Rf<(a@_y` literal 0 HcmV?d00001 diff --git a/speech_to_text_/example/android/app/src/main/res/values/styles.xml b/speech_to_text_/example/android/app/src/main/res/values/styles.xml new file mode 100644 index 00000000..00fa4417 --- /dev/null +++ b/speech_to_text_/example/android/app/src/main/res/values/styles.xml @@ -0,0 +1,8 @@ + + + + diff --git a/speech_to_text_/example/android/app/src/profile/AndroidManifest.xml b/speech_to_text_/example/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 00000000..36edf838 --- /dev/null +++ b/speech_to_text_/example/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/speech_to_text_/example/android/build.gradle b/speech_to_text_/example/android/build.gradle new file mode 100644 index 00000000..13546311 --- /dev/null +++ b/speech_to_text_/example/android/build.gradle @@ -0,0 +1,31 @@ +buildscript { + ext.kotlin_version = '1.3.50' + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.6.1' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +allprojects { + repositories { + google() + jcenter() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/speech_to_text_/example/android/gradle.properties b/speech_to_text_/example/android/gradle.properties new file mode 100644 index 00000000..a6738207 --- /dev/null +++ b/speech_to_text_/example/android/gradle.properties @@ -0,0 +1,4 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true +android.enableR8=true diff --git a/speech_to_text_/example/android/gradle/wrapper/gradle-wrapper.properties b/speech_to_text_/example/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..052e7951 --- /dev/null +++ b/speech_to_text_/example/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Mon Mar 16 08:57:32 EDT 2020 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip diff --git a/speech_to_text_/example/android/settings.gradle b/speech_to_text_/example/android/settings.gradle new file mode 100644 index 00000000..5a2f14fb --- /dev/null +++ b/speech_to_text_/example/android/settings.gradle @@ -0,0 +1,15 @@ +include ':app' + +def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() + +def plugins = new Properties() +def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') +if (pluginsFile.exists()) { + pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } +} + +plugins.each { name, path -> + def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() + include ":$name" + project(":$name").projectDir = pluginDirectory +} diff --git a/speech_to_text_/example/assets/sounds/speech_to_text_cancel.m4r b/speech_to_text_/example/assets/sounds/speech_to_text_cancel.m4r new file mode 100644 index 0000000000000000000000000000000000000000..ccb3afe392f563a0c8205265f8953c5cb801794a GIT binary patch literal 14006 zcmbumbyyrt(=WU%?hcCt*I-tSqSJzDU)YMe>^vnPN0CG!rA7>>VF)9Fzp1F;ilY@gZ4;QQm=U{H) z{;UT8xEufl3c>Y^iKqKSb~+V_x5cZUr>qv`#@FEx^0FWCkREA}9)fM}iX%}NH$=!? z9z`A~y;e@n-udq>>_Lwn2cNp!CZQ3JYZVVVoeQx?0KiKdb4E!3fI%)a9RdL2jws=D z0Z`!xX<^%s8Z{7DoAerH=U!H#&mw*TB?~wdjL-61U|&y^J#9(GCA5zF-7%VJ={MF$!@nl&gyU0qCaB&@g{;B`~gi&~Sm6aDYxgLaZ z5GoX<(WJB7(~o8J5@%Fz)m2NA)9}mr(}hKflZ#MNZHX{?i#{hS z$IHwAvc6-Tk(bnO))kZmfQP?#!AbK?yYJ3R&({zfFF1T5PUGE1>&_cSZqZFqd>&YG==a z9P_O-uI_|PUqH`1d`5|xkvwtm=H(~4O+WX-F}?8RMw@c4(!t~_`7AXVlvt|#)?+XI zcZ~}U8cTL|cF54r(5zo?=-_c^6YEsuxom0Y3wG^^gvEoUz{R^32Bf>YcvEy>JlS2e>zT$znZW-Lug|;gpns^u%N5k-kWKTtFkc(Ld+Kwjoa9p# z%V4M`#~NN9RV?FZ*CUYI3@>;_P7E*YkrY>L7>6!aosPhtG>H=x1))NlRym3}1!XWn z54qd(njon`H;tsvQjVUKnkjLp3nDj8)3;TD&M94NB2KrPw$#JoiS3e6CJ=Kpf#Bf&Ze^ zEW6QmakvZu)blAx=@n0~*W*n(Fm}P?7YHpCrIXcW8tUexBOTyqO)`zH?aO81fq$3_G5b7#;a z;X>i7r=R!G{rktxlLyxOr;Ba83JKxF&8jSM=_lg0j-4X=El*S&_|_VYZyph`n>i%$ zc7lu3=_79&`}M3!z30EDDgPGIW*CnLZEUQ>eo(>sp|@DmW7U(roV~Pk)}5D+VP3M7 zmlu|om$$S86Q1e6!e8+}%D?hrdiBgHDplf)Z!D+4X26Hn%tXQUA0%M#Yw0=(B%1KZWfiVElXp-(bD7QHb1D50UO0kDb7(D*TliCtg zLz1K__3wj#tZHE(4J0^7HFaT^ge)wjyhTp z(i71!HRgR`?l-m9s2fv40~evax_EL%h6CMH%u2rm=fVb$;`9u(`gXB2 zJ>qtDkD?_aPFy3d=ujk`IEF9jOoe%b+Lp&JlJapqttht^GImD%s62IN#T-8S6@q}{ z69$khqcZ>M0ihoh>Y`VZ3%4lbuE_>@aP zsD_Bhi^9ah=k8C?EGDM)Z1NG&oQa9qGdMWAsxLS@)SCHgJ|)~*pljgP`tbF2xKl#- z&+F?jXhQh+lM~b@VKT3^RpKXMjQqbA6ZiKiP)a1PwIBI6H{2ah+t9)8yz6U5n88VB zi^$ojmH*=q%s{2H8FoCFb;!eez;{sq03HGd;^AOt!VK#-NhX1R?EH59*s-xUbm&1- zSMk$j#Pa5*S~4}#mP@knhi}lYVrM;dVajtkVN~utJCmfms5&Rya~XO@Q>?5_9XSV_ zq-gYpW8@Bt`mLl!- ztLyl%_T~;(M#6n(Ij@s03pqK|_o-3PQbiPi#_pzt%Pqt!GX49~D`1`^X6r7h%_(3= zkoJuRQ*>5(@cj5TU_@Vr9QZwk{_=rcN5?j1xNmP1qv0w|r}fFH?siaYHiEGg-`BuJ z@QxOXFALsTWa8}1eF~>uSM6rb7Jk9ij(61^zcwgcg4w6p?NvNe3Qb%f! z%ZqhvgM=cXm}Ta;9a&nz^+^aoUN<@mGQKkAJ>5`8TIYehYEG%tRW;Vak!-)Y9U^tE zQtkpLM2;WjrkZHzdM6-r)H8-A4bJ@I=}6t!Fjl}~=RSdnabzj$2+E`M8`gDxYOWtb zRVaHdCqSJ)6AI00@z{hm#;ozk;ZN|m#`#IEfHKi~{sjO~Hz_N`$cpTu{X@pX?blEr ze{#04;Sc4*f&=69l?*N2n_XT3Gy*2REp_pR@eL2Hr6_&#`}8>)lC&Z@zXB)rg-B8` zb*-BPyW3vb$pSCn1EoG?0uVIq!gi!wL>p&xamx{rh%PtZKS$mG8G3Y&nHu)DqX(Dw zenQ$`Cikv(4?ob93Tn6MtU#%t?XI2It;OkSCU0-P8H`9t9g%S` zt`E`R7NGPgav(J3q)%Qp-jnT|V_`zOQ`#^(R~GybB2Y!u>cp4JIgXsBeC@r1#wX&M4fP>sF5X>xU%A94}_qiw1?BoFkJS>6yU)`a6 zryGE7!fXhfWxA;u(IXkF(YB;u_k%S=^3v0;wBdE+)&vr_)b7LW)gc59frq1(1tYqr z#6REXHgN5rao+F2;$|yqvx7O!XTZvkt5bEO*!04b+Ybvl_`bc!I6m2aMDP_gk$$|w zCuen>G%{7h^4|dOcFwUSlZ9qKolFa&xtHYq%b zDMXwQ(2`in_cd`=07%c0)RD{6<2Z9p{D%tZmLxyPD=kq#Hvk~7R;yNq;s5feR)_E< zZLmC}XOL9<20@*!yQ4k7UinK4@CBBfqt3w&Bt#v3l;_7NKbztKNzp+M15!HF_mdy93HRRkB2~gCfwgKOC84UjA-UNALW1LZ8q)p3^GYwBGm@v+ zb}fmR{`3!mKdCBwuAz$Qimq2v3h+3!Ad02p`w)|#f4bm(;q#}DMnnM}@j0uN)qNeKIwYNacSA#kJ@ityfiB{=9}d{qOQ^brv*3_KroZ_!Q(zNI*_ zhsIvH?g{)r=tF-u^)TBkCh6s3$NyR3tnJpkt%LQFZSh>fhMNInu05 z?sN3hTp**g8qxjmpLXYdU$^By5O+xH#3&YwY4D6SVASf}BiomRD=7fLra?*ZhGz!m zGRpwNu9GJbO%*C&a@*F28)b>As8^b-6)O-p0v@()7Q67C&Fas3dy{KVlTg9iD$X~4 z2IIFSI$CL+RfK~P32Q*KDM@e(3t5!r-0!`0r3mv=JWqyjId=3fR9wxGZ|Ri{WoxJ8 zlq?`jP|pR$+3C0+r-tja@+aFr7MvGjC~uD*jv5zk!?R>^uo+PCTI;lh^}VMdJzano z4OwZcS#`}**S~R*8}sMgu!xKWK8RM6Vw=PdscqGCILEpvSbo^q;sao+@dHp+G>5`4 zvY-W@u1;J#9xKkNhW@lIMtWLRIeG+qUHkrBk6j54xi=#TIVul0UUE(aiNs*VQqsIr zSnaEbn6~ciJ@_d5o$R=1PjEjpOWa6ut+bloLZuB01(pR}Og;}@m+7Js5})(Q4;FP9ofQbOmFNrT$&4(3n4JAW3*Nw75y7xD z%=tM{*0Ru~!uhvVVo^~N%0BGy%I z;ysI`r0G4>v2KrH0rAcFt*Wo_m|lJ3YMXy_MA^*N`c+Lb@m0)o7*d@s?%U3~lWf5N z?w4d?_Om83nx<>TWYK3Bb)DKHtTS`y;@l|=L<{=AfUTfz{o8V2H#-HJK6pAb8jU|% z4~*BkTb7W$u07dTI8s#0!Ph)OK5sq9H2+?2-nJi*0)I@*Kz|Uo#8%Vgy+>0CQY(+0 zr%f`@2fxW<;t6}O;xl;tg)%7mjY4pca&2%6nG00!D8T=Qz6ATt9lM!|JLs-oCnEVh zVMZg;v_($3Lz*i@rV#R7svmd4XIE1*}E;Ws_+(zZtD zHKwBwn?OImNJKb7#wMo&plkg|WS}!dEId>GuTKN_E}%}GhYMPVv474wzg8Jd4CWK3 zeH9qqrYK=d_M-X9fHP>~F$@PUM2tp9M&71?7&no2rQ^;a8afe?mBDK`tT4i*+MB7b zRvAnmL35Z}Rz?NE*xKwOQJ%6kX$*x&;`kKx4gPu&dxsPt-UnO0=}6C`ruC!MQNAp;9`5Z^o}bggs6?7O(GHM*cgCC2(sE22%ulB z1^l2@YCg9m#RQlF6<*|a#N7LH(&lUXk-I+piV`=Kd$MsYC4z#`aNRCVA zCX@wAlFLiH;X+I3)Cc@{N#vM*73ooC%amyWVkQ@gPT3G<#)W{UW&GWc4@jOG?0%RIFbv_0zP@Xv4s(tP7Z?`k}p}1z) zx==;DEqdHsygy&y!Gne9mB<#;P=SzGHzX$mnU&kr3*q@9PqUH$k9OP|GRrM7ws3Lh z7v4nB$`&s#K;8weRZ^u<>%Ts4CLCea$JpLS7jxYrH;+Z4837o+N8n_l(bIPDbZQ%|4l#R(c{Zb)%fkI|SM|N3Yx++Sxb?@!?@kyTt zQ>jGHU1}4ttdDo^V6iw(n0SAW&B`h8?%NTDMD%P@)#QrFEv_5td+7SiWMk#px8^3J z4ISBvq?kb=7Igx6a4xHr8wdJEX!qL>#5@3LW9!F2aNnsCFx7J9b)Vsu7U`?mY z#QCuLL?5lgPO3qVl4KUy$*dUaoT@=o{>5z={?*rph3oWKuzlQkbYXDg#5J7Vw6Q+P zx0PZC!HD-3ihK}^q))1(D8%hVEEGW}jg#D-um=j|mzjt;wEOACHns}DR1}o29w{ug zgjh&XefL;e=)7Ak<})cTIY-Dq#-dECjJL0})& zw<@Acn4*~yWM%X18>_F>n*%T|WuQ_k86vlOMl60yW6jFGb;DnODmFON4`iN%T4d=Ml!_6|# zD*aR-XrYl9e}SPGEVNWskZ*z@2pa+H8g3qjt9)42IrU__H@j$g8dh|%``I<0Skg^%c!}a~wfsJYrX6Y{d02kOL zF075?enCLIqpqM(K=%DwUXs8;+O$)2Fvdf$^9xp~9vjfZnT$XYk4$e!25y*bK*|r^ zK;x;k@)vt%IdN|v`|YNt9wMNJ=l)JH*Hg+Do-YP7+$&zx_Ll!#6GiU@zw!#;1^}D^ zr`&A2EPl~F8=N9rPtdJSXu~yhSm)|C<#*@ZV^w7nS608*g56#=USwq7_O|Idzkz^o zK0`KxvnHfWd}Hlza?O1O`IB%}D;oYXy6y0QKGT|V;M5aHQW2+^?vX>%j?gu!P8*0whnGG^z$ zNw4Dm*p#%K2N|0j`|i_ZlF7f=@O~#xZv|ge?6{zXb3oyLtmP)nZ$0+FTuoj^rc03V z3i{Gg3ILjR$VS2n+O9?vsXNm&SAKy;5WkXC&*`Lb>ihXr&mpU1`t*K+v1R*UkM8u5 zL0Re2^FTX%LhSLgJ(gXbY5^~*R0v5m6h(V|e(C~l8u>v42N`hw9IZ5QPo04m3()0z z==JT!f?u9jdHWNK8;9@eO{IUQQb33|jxacs-?j0jVQzbUTadE!3KT_#;@q2NuGrR; zL920sqq!AR&&6YdMj?Y~E+&EeC%Uc=&Fu2jn;+%6QI}OX26}Ssg03bOv>Gy_B4G{P zB*}tQ{csWlh*(9!@s@d?7I{hHtsNyeSxM;!^+Ra9Nx#-+ZMoTgwxGG+K@qxGDKOZe z9^R(IIAaXP490s!!sj4`*T=!vMy|m#>gP37j=X2LX-^si?7PvPjt`VbQW1AD2>_1T2Fh$$ALZ zC1j0hBvq)8Eg_eevj5Eiu<^>jbMJQYIbZ_>wpMmGg>z3&bSH&QPA)Ri7OPld5a1KD zKH<#{gq%3oc$K9cc1F;rBuXHBTQxlIn8>c_)fUlHQ~YPG5+kPt79w2v&d!0M5@@ zb_N!=f1p(te-pxJg5I78c7FbVhwz)bvCkD3gIo_*Nu?_DT#e$Ia40F%0X0`b_1n$@ zXk7@dDN*ZGhK)gQLZY@peo>$SzW=^fE%65Sn}i1#q}<3ceW624={H(1OT|{C0$5DR z*`s$A&Sq>Cx|v;#h@)~R_DX^acu0<3Lz?mfKEe&L%zE>1iCHmwQ~uN)2M6dU#VL=! z+8b)aJ?0!StoAKSRaPE~3c2VjOq&8`5A>N{AS`j!5M>0XQt&-Y(!EvvlaU-Ng8Rv7 zhwDveNg`I`jiVze4j*J_dD>?pZT}6R$gp%nVOZ0uoZC{ksp?GIW}B$HJxstfoJ(pyAx=` z%$JQx?&!O{*9#R^WRt>I6~_^5c*^U^R?ev?R*`iGo1@<5)h!3C2(|8!h7mrvkhPpe zJkr5k4Vrk(42CZGX19>`A-h)ws2(%XhYI?)#xB@}tUW7fJsdlbO5?`9brW#5sN< zOWgO)Gzwk;$4aM1Tw^>(Qy<6P1cq`6s|ywiduYonQ{ca5BCsB-U%o)%{D!C!$JEKa zBX?`wt!|Z5d@;0@X%WVS(1q(Gk%jVxe>IQNgxRlK8o;B+h)#ga>}oplii~q4cuSlg z#k1a5#k6rUICWn!6Im6st?+Vx{_v*r&e~8_NQ9kDZ)Uy5kpE(A{w)IO!yPN8Xe1m? z{MuBVv&^@hEh>^l3jfvEDF8nlkej2D<$1l&=?Y3Aa`y;5&k9)WIH?<7F*p=Tt0K9% z>S%ZRL0i_Pg6vwdam7Ai^P9+vYPr6vxW7ec%mD!S8ewP1)zW{!Uv!#tEal;E?loB z?qM=@d)A9;jLq(9GIs#V_iroExA`U-3q_hWhhm+>JTM#Rn@^OR~oG-%sgr zaWGih;6s*OM5oT%MH5BA7J-4S2S2PV%2Sa9$dTZwCP_2z-S6TwPIy`v#?lJMe5dQx zq`&`JnnRY*{}n(rbOf5F$-;am)~#lzeBHcR`C9cM@53)#WE*>Zj+y&* zow@a`Mx=PWdHapB>1pWK6$#XSbE5%xY*Mvo+TK%o1&(XI zGKT?AR7<)}nDnXIbR?dn=K4NTBP}N~j-#*dXB>&Z*scQ4AYhQJSRWV}$K{m^hD(#9 z`R=uaxc!Pv4?SAj(D)?F)NE<@ab5r`(a1fGHCMacVg(!-;hqyD&z@uZh8iT5xWvu; zdnC@7ngkV}nV26aIf5^@7!YNLmqEuPnN-Y$SVb9D#?3>?m|Fy4p{w7Gk0bdL`*B6u;s^Cm}XC?|pNC+6Krncuv z@_x|yv>g!A-D{}2b*I!Ms4Sb?^q2r$xH_RcAAV=jV&Hq(-fi;D5I~qo)^wSn4j_NN z|NpKKeB^usUAy`_J-9gO|8jb7v^A)*@F#72f&8R$VKR{V*k6r6b;AmO95*KWrjBut z-b`b2yIKoHAw~;la*h#{r)H72e6Yu>&+#s%&s-m zgwsjCn^1_*mP%?}60^t(l*QvqpsZ(1uXCy!Vt;77?TGaj%NN+NuBXpbE4NK#T^l*_ z4=G6ZHd?x4B@}E$^W-fM9Pognnn{nIv+qz~%aHPA+5v5g?)e;-lAZq1_EUS2V8ZVA z?Q+Iy;CmJHth~UbxBC-dAQct2%me9$aPK%#km?o$SbrY8{;n2$ifAES!z^&1Xaq& z3^mTU4Q&gLp|Nw}?vgY{C%i_n4}SLDfV#BTMxSaLsZ$?`8=_Hl}{L@B_(fVYgq`3uc^DF75J?kAjhC;2p9!!p_!KG`L*f zo4tZg;_fuA=@1P~lQ;N+Y)S;nHes3fyGWu~25cF7e=?tThel-Zn_^~N1;Peq1JAt7 zOq7x#1J(-2NmL?$g2@FckF9MgcnIK>tE%>S1S|CKq?~|0E!;!*F0xZb_ZDvNuRC9l zH#)puAUowN{*^)X_&Y9v-rDBm4K8;7CJj97)=cjoEq))|NCQ$%Dk8})IUqGaPOP*K=a=ZhI-XYN?YcP~u_TcClLS4ucfe!Kg#_ZmnDat#~W z&j?mgvK>!S4X!uRqn3@24GMN6?GUsiZIQxO$TJ=;wZY#YMzPVsk`<>K$qBLO+_0^< zJ*H&-(&k`|Yqx4`M_u?Xal}^rz-{Sfu+!T~{(Sk`h2Nd>qlp&i*SL^F?C*IxRN{8f z3l92VVeHB|Q5gp5j*J|y+eK7Px<#x`2p`A9&{>SFJ!N+<&$(ey}#Jvzv2_&S{+YD z8tq3xdb}=vtpc6l;$BmvjqgjDJYvC3nOjE@ReTYQEyz^@>?(2sqBq$stoFpx;x$$> z5Kn_eX2hqau#jF6nLfQO(+%;)kIhO|foPb#g3rah8 zj0^|(Poglhdc50%QU*TWb~bIj+I#=#wpZb>)$TU$R_T_YbxtDJM^8p=Yck~C>is#_ zh6yEgoJhokowg6fw7yekWVbgfc{+f3FQRn-4org}x7*Cc(swd!F&&robn)RTSqvodm7eR=<#Xz<% zAGw9#HhJ|W{|lx%0!lTJUaFSMmF4mn_eS+PWnUHnB z@pHz&i0ylL5;=#K!WPHw{c8g{7jAVX58oc1-MtUUfxYO?C#fPJfU+wyTN=36nRsNX z+p#Vn$`s)CZlSJzSEFt{GDftM6`BtQBm3jAznl$U1R$L4l_hHDQ(>Xoki8(HS{wl( zLb#e(6h7LM+VK%chN{2y~cHo z3kTBc!SMi{i!8{Ru-Wz$aG0Y7W3s;;@#X4ebhDPpk!qmP1o&wzaGHv_uo1pYX3bQ@ z)$JMQLKv{=3169|CZkX1d7&pgg>)GjAO|4eC5agq?X9ycvlk%Ta4%Ier%&$sFq>e1 zmej3-?)pGR#-CX!{Uea+&QPV?pNEEc?xAsh&x%p4UL@UlRJ<+U-hO9 zZAq!#-Z`J)BB7#NPyrOoQzTQj(B)(y4$F03g13 z^!sl6$ooX)(#>3_(XWw6uW|+{eUEF=ILM~pz(gfQk4rWciNfIn2KeQe~6GX1p5)zyY=T7b>{M*0y z2P#awcKh9ab`eOOdmtypFkdLDb}v_~7kvrjf4@^oA@&W~l~xo<2~areN@B6dk;ppo z*1kegTseUe&-fc@7dD}yAd(W5p6pdfiXeZuYH~fQD5atc0V1hCY0z(Tx%9~6epbA^ ztQc1ub>Si zkY8JBn#Wl$Je>SK=;#=r{yd1% z1$E{-%ILI+(EXm++=bK$cv7A@r#bw{C-d)w>|X~)t~ou_89fFLJ_Y9aKKdP2tvq1= zc_hDaT3PdVdwbg{?)J8y#y6KW_&pY@oFKYCU5Lk%9Orq1LHnTX{HCZK!$tw%S}@^# zdC;0JKb#w6yDv z@REx8=9+SJJjo+3&9lWnMrzI`29s4F)FMB^&A!X7GZ)fmvMN-iw2nPuVDf4zOsh{; zufF0sbWN7HDZoH53o?Giscw;NUGsg6;}e%gAS)dJem@p~k{ZxXGAkmM)0!B!r2ZfS zb*3S4ed*Vg{8D|?Qsm>c-R++-v@I8)3p&HAot6gyYPkNbpu}kKDR4;e9m_trEa~%S z*2Q(=458)6i-NUrkQ(RA7;m3ITs2%5;GC=C;GfWo%oj;WID=k`7(I4Yw&p-pj25o% z)+m2n9Oe^p|n4; zzh*)w)M%{x+Cv(kDu1x&vd!#qW)|Kz%K=bpvrCd4z@>=mA07$NiWXOF>nrnCPgiLs ztP#f!RmpHZw+WRb7}8OSq!D<7N~S`ex7~Nk5h}aEj2mJaw5=gf;D%&+<={F@O5}|S z7WnB;NR#|pt$Rv=P#KamK=-z6yGY5h8i|yn^TDkPBN@)1%UQ2s9gXn#vjI{}$#Ofuw~Q8V@JD~-D(0xv zgJS&Xxl#xn>3$ZRZM-*)iGX|{3G*^0if13UehsqurhTOYoW*?27>0&EM^Az<08P8* z6(EyZN@gI6L|TPCkFr6?{(5P+i-s`pHjr`)s_=L*Q9qdrCE9v~b{r1qknd3lTpT7^ z&Zm?bN;W&8K7r6AU$M8VfiXUWAW1ie-T9s=NMzlWofatvMu-z`Si~PjZJec43t%YNA#hu0e$9ukdH z64r$%NHkqKV4d1$T#E)4`zEMO>%jf6Y|+lZ6qC=r`@^t6iggG289k5 z4RpD9P`Q2^>UG#bdf((k5lSY$vy*Bs4HTSr%6l@KS}1qWwY}V=L3%nIxvhGj>~v}H z#L75OWk76{K>!8;+#dD2Hu{o)D_sb(kyxB|7r8zqruw! zAA65S9_{|WH?hdcT;i+UFSe@_RntwL1eE_gud4RDnNWnk`Gna+oH4MTqh`}HSgAxqt zFlfS{_8+bcg5kNW0>iWYvuq5*bDcg6FfYNu0tOD|B{*Fep4$+F zK?DW{7>HqgB5-pzd%h&k^xS_|7*q8ycQ=7?SqF<}{+DR}_a%mf#eXmNf9e5nq&D_$ z&;MVwvB3z&$sH_A{sw}XlLNbnv$MSgyN#xYqs6l)2^>uvES~p#)@UfHio?WE*za4< ztv&YwK=q&BQNaHQeBA#L!2I0*t$H@$m*kQBuj2ow0Be@>v$=^6j5Gi5zHos#`Psm{ wY@EEBocw~^{DPePEMRUyFc@Y?|JmK?*?lkm_YR6Co|e3?*!j8HIl(?l!o)yCi6E*FbQ0O>hk`bB5>L&))kx z*ZKF=HFsBat<_7aYih0TnF0U+q!zATjtV@Y6aXl_a%&d{J3B`nF6b%H&dk{LRSy8X z?*`<{1=Z6=E04kr>}F`3@0!ITWdrK7co-6PUSR!XaC~MZAo z$dB$G@(1Gf0*08?I`@illV)Pb57Mb7Q6k4^dcLpDoRSZqALiS;a;3L6f_^83jw=@MX&R#b`wFRFJg_Z*?Z7{2`qS4x>zh*#MO(5hv{3^J4Vi?+X_L0z_TO z&NY}+7kbicJ=ugg@aECu5?q|c^~b!kLUBrJbj;#>lKl!ANq8kdRLR%H!(>omj#jMf zp4BgEHbW=h@y4!VE;WoqRi`7WZq*5063#Csp+Fhjkkmp&V+M?wHT|O2R%3Y>6$(%& zAQ=H<5=k)-!N&HxCU$T+niCB^FhCC0HTf@G4#9gac{&jwZ80cWdXPrdfB$}WWQLNH z&6OsHC54Elpcxb+ZM5?z+iNbAGbl!R2*P`PmL)40r?n6LBme?naL41M*O-CKSP|cF zD!d;OKfP$v^+De4nc`nEpi|xL%^VeKuNjkmlt^VJm4ela!jPHenW1iZ+63RVZ0Z>4 z;vo{a#!a22MR0uj&c1SMAKc=WTqHe8Yxf~CcVJXYlrU8h4w3|+zfGK9qoJXpU4K39 zc60*?v%Wus#XS~}DBL2Cr2X}(S{&v)AL<6PKi&E&+1oTeL7s%~yE`uN9&LN*dH$BC zBFUNI>(N9bzkF#Ol7R(RU`LZ9VAe_(zSMahZDZbR;@>I8VRo?%dY45v+cifLZ+mu_ z>@3wi`d>kY&lI=Ev>{Ko-F|=L!4USQbrIe-e|)+KnttEw=C~h*IA)9)PWGshX*p0{zocw_=ue2g2j~YJ8pY2%Uy`AT@HKW z&n^{W!Vj7e3yx|u5TGi?Cj2HJdRGw=ohl<8>q?-%3p&7N7NsVPM3NT$Zv1oJzWrIr zjbC~=P8KJk$BRLk{C!s-UJSx5cT=I62y?3z5?8&e-Q?$0LHQ~b4pjf>LFc@&#;O*n z4f4#GngQIO%Huxc#4oj%1&Y8WHtnAQ{*bKEgDaEYA`DYgeZhOzUP4QzVN^kV0N^tu z?;30*TH5GHJQ<``kf>r+FAoJC0$3q^!|Krou}7YGo4qTS1BIN-X{beEPfD%ibq{wh-Qeks%Lg#;{mb)t z9w1A}Tx-$L43I^iXYF1L;k(dcp&Ue*S+G9V~vN#Ao$}9tv|aZer0KSpH4%i zO=;sVR#s6QiDXPui~WCYXUeNf5|VuNF}%%j#zsR!JKLtDr0D7CnR*rem&DEbaJQ~L z=pj)pEomku&B^?QnqtqXwNb+sWHgcvXE8>LO_nXZmgo}6NY1Sp|JT zB}t9D(2N2Ulj*xs{YP6uvTH65p@8_}tON%MseDlw(j2UEfQ@?!8d0RC{$R2lDU%^u zO60e&8um3TF)4U-5m{5WX=0SKd*LDPm#*;FosGOEair;X_SqqcQ-gV&RZz!O4s5TV)&F9!Q3tK%L9$vDimy4(Wklmy;~Hk+T}B z&j{)ItX#>+e>ahGWIp!lW5))KSs7bjTST;|`mmvWkHUsPSVk1&LnEqb9RE(hc^KjQ z0B&w>!22%j_gUPW^{^cs5hQ&4O_c9DS_63Bvs)PXP_FkZXQTtjE_&B{P`)^2Ql9oB zlO|?lqzA6A4-Q;fSO*~KulJA;RcOF?czC==&&UXXq499!yRgm()Zdu-9=(!jl~G{( zwW?-qCDX!;hu$N#L9z_LgfwS;K#!L_Q8l1xt6T!OM)UDl@ z7nZ&+qmcNp_4|8z@JAAl&9%IT2fIywPs9HQbN1ientFOlf{-I9b+?&4JU9q*6YJCih2CU76+z5L@d2a++$*a4NFwq#-*WX|e=&=LG^jdGS!9@Xl( z05!Y5E|Rtw(-XdF&EU;tuR76HP7IzijJZFGEQ6#duHdAzkBetr?1Q`O+Ja@3zK0ub zah!x`xr<9LWm5_$>%0GK!~?$)6D5tZ=p z+BXm67XXIv@bEu7!U-=TeP2&KVuU_4kaGYytvtP+001<8Pp^AS0APFja7_dN8y=qL z1OQ;Xed{{_0Q^tU1^|Hg_U+qN=ne?lry~Hs*x$eE383+KWA^}jo4xWZ{j`L1~ zcjuj7gfZ)Ua^FPbtS4u8dNE4Ulg-m$fAWRJ4WLyoq67{MVB9nZ2KUrN??EEY9q^Xs z%R8<=50_Z5nU}{%n5Qn!x1MI&TcOSru#a{r%mu^3%A%n&gQ^?38YJ=uC>2vy`mk@W zKUPPb%;<>0zx_D0nu0t@i9erTyBtDOFEas&L#5Io1F%E}qXZIh5{#4tNs_l8L<{2b zYk@<#u5z*&5>ZpaWO1w>Xu%osZjqsp$ef^NA`Zl>ko>d*8KG2$>jvqB;vl_BF*EjD zOP4F&#W(LclBsv+L0;1N1kOnLW?_xgL{ub#(eK|-L@S*aDw~f>CuqdK*W}V+#4JML zC{~~Vjp}4U*coqjR5U(`(p)D>kFpfYQ%PE5(*s6TDWzBS#m6VBq#@n8x zBo>;Q#h)Q$y=F@i@E!CtZU|;6lzS(OCY%rZat|M}u<1AVGu@U?@h!*TaGr7>)l~Gw zQe;1IFm=fAo7*$0!2smZ*gJeXUWj~pzek&gCZ;GYL znF>boR0|}lHq;xrpF4eJQ@zf$8utA<9&h}NXzY;NexC#X%}!u}UU15X>FY4v!w*S) zr_$z);$pL6U0$;x6?@WF=j{m=9;W@O)LQ74hnc0ZvvHj5hmi=Dp3H1aQ*^V9icL;P zllAy-5W3r!Dg5y5hsZawUL0w(oY)B_&Bj^*c^ziGp(s zj$A(K>3I$kKw~pIk~k_QoD2YfIzAoGbNi4aSYv(yk^wH7T?l;~__cyB-B4_B#gQ$g zFmfUE8CMuYgAG!rQmu!pzQX=+J+S9atjb@tXERCt77M>P^3zN1??dTuuCWd4>Y*Dr?k5t@dEyBTf?sp%7cyIm)lrqgG9~BnJ{vzBFHU@_qt0|Tg z_Y)h9B=Jh>JndDa$*L75BSbN&SF^2J`Veve{Hh8>^_amLQ8*=jOtuvHMJ4`%C@2vO z3`NveTdL0DRjmMSo}KtGLg_7}iHWredJhi(f<*}?0DdDU1Yt?GzU&c zM=P*lYT)d4QCoyter|>X_K8Z~@ zKJ3@|IWjbmD|L6$LnHV{@I~G~MMuKJ{nq#QKcO{-yF00Ow;S@-f*}Z7Ktk@iog{Mq zCNQLI8R9E^^8%(n2LE~h`*;8Ke*R>0uk*+0XYJN#XPjC5_R>9T0+tn8Xq=vGGIF&4 z3$H{%6?R5E?XP-?0@S(}E&`=@?zMl8e5hPpj+b>PS=hyEvt{b%j zdT&%dj8buuTt9OCVOt@K@@1akXWO3vz`0Bprpb&n0RYT8`zg{F0E#2)>)li>u}I1R z7pIb$Yyj5qrQgmU(t`CtTzE7y#=Cps9HHcviPUkJ#L3GqnNplQgXhq6hg2;%R-Boytk>P=kz(DO8@2uQZMK=JQt_ z8}!(Tyey@tRNigq)9QF%5xKckcmO2NUxIRE7Yrnli^rXBad$km+~4`X*POul3?Ip+ z-~^QUO>+>Jgo+vqJSbqYzH#qoZ7DT9G! zvJ8M3N~~Sq=6oMf&}Pq&WKdGvi$t)fyeF=@W~#N3&JQ8S6PkP>X07F#f}iO|tZYf` z@J>?uLbnI7C8oXDU9rHzb(`nH$M;}6$o4&?yT-iI{$b2v$}Fq%u0cO0MxSRg z=V{g5H_|mCb^}96H{VJIiC_E4E;ppa$n8YeNo$##of z1W>ad;)rC-h0-oKHAFKE3h0xBOL&hmHhQ$0UR)6wcZ`fvAFVDCu$M(kt-2sp5EHpF z+eGV+3WKmQyVTfFS@I#X(q`YnLkpRbsKSm(!wIrjBHE#p% zURJl#Mut{L9^>RcFREnb;yMM#LHH6&%xm#)a)Sndcb1%fm(b)qvewz?z=>N5>anHHPET)I!rCeh)&I4ieO8D<^fYnGw z-*Gc-8cv?P^wxP5OT8*jLrqaA!}}bPX>XNi%#eqbFab0WfAo>+f}zX9<6uuGx~dlt z<>Odq41Asr4%I(y#OwBOL5k>xtP9F4C_>Gy`God}rb z!+Rmr z@47nK7I+GfT+RRBp%GQPElD(Rn9HI^(Ri_|CSf{i)6lBZ+Gt}VsjfGfTYW`$wka=E zXfr=$f(!GOif;^QjT!Nh%I4hUvEmV+9Q_Q+l|4<9bUd!cHW?x{nIu#emnSq`J#F{F zf#kg9FN|P_L(b2y9q!Lx@%kcVf!9bMTc;I(oARuxhtoeYs27CGSi&{Cq9`!_lMf!J zHmxUL#o~vV?_%_cPX1QVi+VWN)q>p7GJ1*X)wd0dW?e3`IwkfI5St7 z2$$SEnaVwAE_?orSyV;oNFtH3qJWml8oFc8HmP4M;zgElp4c({3 z)Pxj$+hSe%o7#DDnC3Icg*zU+n@<+V-kO=5cNDl?#Xqxm9rdy2AK#d3&kD3QjLX{Z zS3Sq2%pN7CLLWc=S;}60_*(DD^XVG02=>=G-?g)6D=clZuQh~eMTWCr_@V?edF9iU zLAAEcqd(1sYm`*^u~m{5o5>tMP1_MNppm%mO$upBeK_Jwy&N?b0HQ`wmh^~9iPo*+ zLiqmfiN;dwU`+qiLmJS@4+SsC{jS$$skZPEGvSBN|B{OwHOA5u06Ss_iqRI9&r6SX zi8kE2l+nTCafMIZaOBd7{{9Ak%=AlODH;tGzjWWajtHM*tODzVK&8j8n8=YQk=E~| zU?0&%B&KO?rfd_p)G*FwslB^u%aaQ-_}y_Wcl@dC*ab~WWjl6&#B{EMZJ)$R3a3Je zwfR0u4RaDGt}+>M2o?@A-?Wo3fsO;8kUn17nID)18_uEVh47-lxLK8@nG}aiC7*BO z`i!!&9QBad;%Q0T@XhVd`s#V7ie4ASntaX3!8r0t6|ca3M;Tkw>X1q8e>tzZQuisu zq5I{~m)ZZt4|2bIxSIQ}#1bdhpKR`+rV6j;4>~JB58IwocKSmB((R~S(bfHJMWHB} zyqG8@6=*6vAuT7cxT^*(DMxgE)aeIgp8lN{@@|WS(_n`wF0i$=@v}T;qaN!p#WEn09 z?|!9dW^1D%L@N`J548%4$V&yPS}D7K#1!Od7;X0zbec3T5>kV+&?590bQ4$Jf=yS6 zK;@87o;%>?!B5^5KCAeVN;R-!6n&fh6!}2vv(q;|;`QjX``xoD&t0ob$jrruecO~; zO@~XD_k2OmZE2!kEBcO=e^VCYAG3le^8BA5%aC`w%<Xf@s=2smq<6x@b?J&4ggt-g0GAE4QZ8{$L) z<0hg+B#Wkeg@{wV_pzL6!cnq0;->^(=2BAP&RN{<4|FVvf=Q3SlJ-X0m?_H@RD>TW zXf8U^4U4fm)2>^icon$~ROMgT>0qey3{p^q*mz`1v}V)tjYhI6JBtKh-Fi$1>9jr& zV_3O3CJgj+*{H@%;~|&e># zN*_CM6M<%{#9)Ms_-zKDlG|IjX#r`5*IgL*B-AaY$l1`kk`Hey+6gEY>@n=`rV~ zIr(G@H;v>~+rqlp%g`tSM}Sjo!zV|F7)&G@50oV4tDo)qD-+7Yn?hzu!Kr)|qLfpE zrQTN{c_zV~+GRiyE+XBpkHi#ANcm;2_WQS;{;5=(6bW4|l6!8dwX{r?44!$WVEk${ zg2b?vT^Prpa{d7H;SC64yg0m!_ML9l>1^mAu%%Z^w9E`9vAfAbK(1#3cqbhhjNz?Z zq+V>O_r`Gl*4n zM)mz5MPP@nj_XUvo$%d>(nt2y#_KxW?P=0;8S%$RnFjY;WM?)3$oEmos0I(is+_)W z4+*`-bAtv(mtU^c#OYcR7*CtOa?gJOsedOhGa;G)@5?*IDWer(^zN8YW0BCP2GF)P zm)BBBFvKz#ji{$cToD6uXCUAMo#h4S`eQ?^Vxv&m$n{#vDxHlac$ z!S4cXdWzkTnqZ8;bA4TL0p6VFbHR51LB488NJaa3RykOo9p~Lcm@_61$HAN2bK8MtH{P37{;nh2_F#I}z@kAfdKmM*Aep~!(plnB4GcB(o?mxz@_c}u-d?d}aDu=&;xDttME`eoXq{TTb8E#S zh~uN7-=(Iw3d+Nd z(WVPAm;G>WzE1U0A5CwGp zXl|=%9Ym-%oDm^Dynwb4E#9K_p3M(o;+%0!X=9S05DJ3 zOp4nF$yTzQj-f#}C5@_a+NEC!%f#X@4!5hNhA1MY1>9FkVV)8ZBjSjPLaPL#XI6Op z*5^FsQ!0O8;G+|cqj7)stQ+=e?#*q%w;IQPZ|-?S7dd2WrAG1ZUU+|4_)o_=)SLZ( zy|f+1DqIT8X4ZP0X1DJ)d>ai)sgmMrCA3#H@4?!p|E8$LJ0pSFvHQ0w^sDjb55iSh zZsFXDjvhF@S6tk2lJdjGCI?ln1L|=+;PG!VS(K8(_!c9jCEZ@yi1tEg&FNpcg}#T1 zBh`ee;kbBbSx0K~Q}42#C}#~hT%g%qe4pJptdcDd`mNZsaXJ+2R)Hs$W>~5VPqq1{ zV7f9YI9OSvtgdy)J6_{k>Td>V%)`s3#X)Q}-fsaR7CsE}5|K!u(&R)kqVWewwFXY~d9i|G@qSY|p22Jr9d2wWU4C8|GufCT$oV}7`yLMwh*%StHN%{0 zgo_Z6Z`6)LM`s)Oob@;TCNV2tT}>bMM9_nT|B!F$kFIm8H&3!60+%LrR*??64_@7b zny)#Dl)|G!g(YnCR8J>QRbnpseG!3jl!1tdBM=|z$HpV`km*~<*YNJ=bI2J)_|J6q z<|bpp*zWt&=D6WcE1tS44x4%xf-!KLVbmFGI9x1&*&jt1e%8jrfGZ9pklzkwOYl6c zmfJA6uvzMbo2mbhPh?F4L~a#?T3>+wpLn zPs5ILyfMK`o5-0nIpk{iGq{(G!>u@r%v?)t}9IAfJz-b*BTTajG*7{fNkOv*O%6hyhIs zFcY$CLQ_^8iP2%2Z%|sPMvit=rKpw(3$7c0l>z&G;q)*nur+`;>*rSvnA&p{JEEU} z3Qh7S&(kaZ+`CEo@1$Y~k9fa-(fb`WQb~dRpB;u#o8j%V|LX0F<@9j(HZ($?gG0}w z;{Ch04zBg*_j;$@&YVPTJG5;ZDr1P>jqHJt3TE)JUUn>O&?{0;5J~zNs(?JmK1;7eu(Y7O zAUB_O<|16us8GO86yiaa7aN@RijL$ojeO2E?W8=0yEJ8R?puO&H`_3|A*5(irzMHi zsDsW@Eky(S#1-3PKYi2rzh+zI*9I|}`28{D)U)U2_WdQPexnx3l(!ge(n|~oEKQ#< zd$Y4lc`EzTXoWk6-(u~9IU1xrc%P=4F?`nSO8O>IdZ;WKkRMtdR#uDntuDB}V^!3B zy8jSDoFS^#tr?E%7ZvqN9?q}+E-FUI>Cp6^0EI`8qUy=2m3@$3Gg zSIy3m;sw&w-rf%!v|P*@L!GfCY3*x9M3psEDeY^KL5xO$Y16SG8gwjD)#CYE4coS5 zU+GlIb*wPTc;X6kCxKhIius*UI;+}ppIvg3BbmasMK%Sy^K!n~v<7@ChJ8i_r@`Vv zTJnR7kS~?YWW0z6e=2_y{|P?R-ld%+J0R3iSKeQ*qBVkgh8?d9n z`iYzv#7*7p;{A91gz36HoUavLap-NGZC?4PX#e~?aE##o`Xn9h1(IRm0I`&JUJew6RvwE_Q_q7H7WWek9}E-dW$%rAE+$o>h>u zL!^fCB*v?4cR*d6_bMW{&$8CQDnlrRG^6ciNyGDskLLJ(8|7{~}R<+~Rj z7d?$-YDu-H4oRodTGPC#xZc^%(1Y7+53QOLV9fDO*T}&4^2!|l`M{t%1<)IQZ z`YHL>WH*uw^0$$lOq5_&{%pt z(epY>k-;0vpK13sis^-^PUSu7{ADDf*`@$?mcDqxIGnT$3S~lkQlDQr0hlv#ZUcL< z!R3mzL%(T@h9ZI5J$q-{XT6%9M^1FL)+P1sxjB;sB=3sF2GxTD{xvN)54t%n>&~nD zbzcW*xrdCu-#+ve=(?SpmpzkN3c)OGC+1t_#`b7iqp?36y^4XyCx2@s#V7X?F6b#Vk$t|>@;CF3%>K)pnKLb*b|TbCyNX}d4E zpUw4v&^nZ(r!by&Fy@oD(oY$3L~gvKz3)!e9Nb$ipXtI`X1|Q#rzdR4%NFzOa*$x< zCZ?i~BvCNfn-)lJ>#!)Zn4$xQ}IFRRB73|IMigUYggs_W27D`NmI{>y_Q!!3^`i@W|1%Uj6!@CU*3 zv+50vD(*Tjw+3b72*-22@l^qIdwH}fpxc1wcf|J(j_S!XZ zbBvWjuFeB7%V*v{OzeGf9L*(u77GR=B6_%_c|!1TkJuzCU}V`w;<93~gkmo8>q@_2 z(f3v}KUz4Lok2jYMHr)q2rn-rmr@jeuIKNH^-MjRoSHV&Ug}y$P{;KfGKj4P;fapV zW^%6slG1(5Aq+NB`d3c>g{V0flRb z`7|T;%NB5^2UWl&Q)Rtf z(PvjJ^lXovRV{Xsz2gP;IKhxxiHMD)5-Gv)AD=dAd-L3V0a^7r%&UOz;m$9IKiCc% z`uREhut?eHsHz<}0>N$Zb&;f1I(`8c(Pv6@xPJ)itaZcHCAY(W<*kQQi*R43&={?c3a)ldTZhm?`632IJ{&XuebWBkE9spoy<8>NknHRj2Y z8h3cA{RYd-pde|#rXG=R!dZZK6*TUIO+)a!;|AB*rk+1*Q@OpBU1-Ii6}7GpZBc_DXi-pY*ijG zJHBxH0SRerT!otoaVqP>sV_l;X?TsXW&x&+zOiz@dNkLn$Sq|agT`sLBga|q5_}ne z6otol%o5gxT)LFf&XN4CM*7hfcd5ytvc)X{|2nWM0r{>Pi6Fsp?&O5f%-TMcm*kx4 z@#E&!QSr}(*T@XDE=bt08?y2Q+0gC2nTE9eg=~8HXL5-^0XZqUSh4Birj+hJvUKdN4Gg-GLbMz4 zW7m()Y$VVecd8*OLOK<$Mko#b_pK%m`Nv~YgEvtwE+c%ELC$$%nj7dr)7xLuUEb8; zBzVpH8ZnC+Bk1Yc)CXa_CwDRwSgz?mjDIIsBd^X7iyfm{OkQppc*t5AP^?+ruif*D4} zZ>jX%JkY^AtXc5FkzZJ?9d;$m9hZmOkwWL<48`ld<5*0p8t3%YU*tJFPK{>e3bUO( z{Kv%PkNyv~5c`*|Zii^dli~f#b>0uzrx(cO@Vl;edY2n(Z=SII5X^_K!+92ArzC1Y z>TPeCCN;@D?bMOzIZf*P3=F))ncU3e_-0C#fs`#dpKOsm@XWrAZS2z5hY`=uVK9!W z{CPg!|M_LwOS0|kkj~xMi)YTN1|x+4dzm3jra$#VC!| zyc}wh0GzRX-w#wFY%x4jQZ&jK<0OWH4=WyZjHu3AH%=*yGIINHn2ne>8YsLN=XsRs z{47s_U9^V7Xv^FVW4qysCYa82tOTevkE|7&O{tRG9lU~JWRI$B)si`63z8HgQUbB=wVt@mj5fQh($yh0J;9-H(# zI^P^%8;{&&7#e=dBeY(@+#G7|qEX>sc`BWnS2I!h${fxZ4Wp_X+`=Re-}cexO)z|x zuy<+Q%~TH8uPA!(?hvSR(DM?SFEt6OUZ{pw0n1Hr;Zy0wf>Z-Lw29kFOL@=s?5H{= z7$g~f_7H-dS7UI*MT}*E1OQf55x3us`5a$DP&;Gqj-`uua@68lXNTj_94D)W+dt81 zV)F{JWl4Tc)CvqCScgPz88OF~#I^$da{cpz^d{KwS?Q(o`tr&55VG>(e|_jL*}Zyr zvsiUrvv1pNo$;Gq zzEqbSefp5;+9Zxy5zG)G2=q;N+E%1XPZ4KW=``aj38`Suj0DhmiU=ktyKZcSx4EkA z&`1ztRbP`XAvX?-Gi+K$C`fv~SoUK#Q+4uiLXl9|X<*{4XhKTu@qlC@H=P-eOlgL= z!VbBlB=*P=#{+}cH*>j?Qe`ut*yz9xQIIajQ>S_`SC5L-MAYCOh9teVs)i%KI)lrs zlG`<(Cfaviwf%Zh7BvZA?zg00Q8J}z6|FDF$O2J7BelUC+NNYmR1ZRU{F9mQ9Q)5ynm#uZ15UU&yvtB#!(1 zh-n?^dMdFdS-_-$HLM4_3W=niq-Mr~H31y9159W9}gMR9~!_^wxtv4Ur z@kH+`PBWb?LxaqF-;-p?qllwEOoe@SJpSvj)cxT77WOT@%wIioCfNq=6gV_-U3Aib zbRbu^)3g8abzt3yrO!V$W=4wbd+|2}e}tUxb`RHeLZ1BV!0SyX-M^++4?KU2PCeW^ zEcx2I4XLLa?%aji<{qn3t>Cb|?=j>O!&8%2um#Ly;^=7<$9zR0beHN)Zxo{{XV&P< z2Mlx0AhBMbX$mo2SIv$zC+@`HmFlD0tHE z&X}k6MB@c9D9Yq`B5XN_a|}N~8Vp&o0gn8BNj2`^gucXpx-2tt1kAP{@3Wuq)n)tU zc{ij9VtDg7Em(K`G<|-}-EHrY?KA!sF~#wndtVb#QocZa=rbjon??|6b4}*o*m#sO zeikbA`C=RVp~=-1?~Jr$Obm=D73M3_U0AT9443BiiF7Q-PaaL>UVc8%5pMj=AioqR z>g-jgNuxH}+b?lqbFH(8p{#v*+X)5zRv~kokyHIRYc`RNgnQ!7&`rMY6mni`;g=cbkQ(@WG+$3ezV&YkwVB#DM$LNj=yG!y5`#B%@X4GxP-v-E226D^a3-oT@cSN=rJ)!S5Wd^q&8*07RE6 z(MTEMvwa)Us?O5+@qR!;U`_S%Ief^{Sb#t_7vCg?GFEmiC;+Cg%~WW}WWJSFX7(Y- z65LtT`15X$9jga$!Bs;+QXC@zRL+}*koupVethwO#BV;{*KGUXw#)xqtKuGSuD(1Y2FA(AFaS;;30pX;V{sV!(19h+dJ(#>^+{1=NQ+>x@c zFkyLEj1i=l%cW|e8f$_5Zh<&Z2a;F%Bxu_6i^#~NmB5NB9sYOH_? zYf*~kM1po_efM(u;J(cz;}2p()r&S%Pwm^0x{x%R*TN|>A^2z$$KHG zx|CyNn}slJ!}09>t9m9}O394?8cWRP>actmacdk2GErahHz}io0xn?& z{@2f(uv{(oXmnFbus^_gMRNu^ez0Q)C7E1Xz)g|q;XashN2o=s_bAY(q^SVqN}JFm zp2gcmkEaL7L$~3J*X^&`?(rwjb^b%|(~Wjw^*Dss*zqHeonK(QGY=JF{@g?&5I@-O zkvygm_lgh3$vjHX@_6rbheZdUSpslsk2&C6Uz^|=Y|d5Qm-@t6he~D=Uk+n=hJM{f z-cJNT^CtO0TDT8)kwlMc{_NzfMrh*gB@d0CO!!H}3Bw}%=CH@9)rGRi{OZJ-L@u=3 zJr0sdu5@L9y0o!V*pV#JTbRK(d2o3baf8LKwD#eK`3!`yLWfz!fwma$>@ZBEMkLBWB4Zu2P9Qo zYqgRJ)bmfYdaw0EPrH#6#!ZhGT;u>jZMP-gKIh^ZOX5P}BHXNvmp0S2HWZw2O%OSV zT=pn1G4LaYG)hyJt)o;86xr;mOdsX=#G;V`@e`$chp`6Dq#Zg_#nFFI3ui9(CgK;5 zm8QI3%&d>RDqxHlNbW~4`CnHLCKA-JzI`Br;cecF@UQ#bA=^t~@c9dvJ8!eAOZafO z`*JtV=la~|Yr{6Zj3>DqE$OMMPuNR0ZXEviNvtIIE?9ISgm>5Q5;pGsd@)7WPwd#V zahoh5dehWX(0}l^kUx;H3@%}j|tCP_etf!GMY>0ezwJEv=-uw zK;h)1$$;kVEez66`GiTO+<%F(7_n zo0AgzjKY`u5V#pnDyK@^Am68;CGi^50KT(zhD1!3tdmQ{LtFN!?mHSZMMHcHXGnK zJ0;Qm`B`<$iqWL!Z+@>DzniO~KPg{r4a~G$65bO&GU*%;j!$ra0jE!oDu$s4o;6A* z>LqWFB+#=wj6(xLVTQ7ZMPWd%{CUOSRW86h65*K65%uFXV-I!ND%MF(KuolK5QT3^ z70szct@2n4^6rJkqs52l&H2g^7d;vHXoqxjs&|(q!3xo1Qiu$d%{JaI_M3)i1`2{= zne)S=5H3uuzMz5-x@?_UOiCUR|f9qvN@`2RUPT>X5z_*i#5 z-MP_X0A7pQGAppA(|r>AltZ;7k)|9*Y(BEBNYxOqmoCrK^pq+d!jP3Joh#HO=C&;m z%Tl`5MR|l*v9<4UpLPD23W^oDW>DUBz7s>s&z{L%J{XS z{9BOxGDY%C2No>1LKhmGpZzNCtD#wqbzp-of1SnMmvit3kK}Hm;R1-s=XzWWzd1B6 zg>W1?fj!4Wu48eOR+WY%evHlsk}RQFIoABI&!4Kt2=f6h&Iu~zXDtkg22*ODc9%}c z%xb#G5yPah@f_M5jUz~UjPJ6OZ>G+N{nseRT0&Y2Wg5&RxLg`NZ)kjImm;j-q=fs- zb)0J1_xJV&X=@3>rBKFlupci`Ffj&)KF|?53Fd6(RE4eSw2OZBQGBD@rdyw2<6It0 zw(0T&!N4Is#nHE{qW%*+DdVH_eCCU7*ru>?SqXW%~BIXJjOlWD%#xm%e* zIbdaesp%B}K(zz_P*es0LUU?f3;w15&k0odf1Qi`TkrqPVE_P_Kv!pDTWGPKtL;C1 z0{^Gae_Mn0`#%Kyr;GoqpMPuqTTSF&;XfS1)zaAIUlq(7J2Puz=oy8b+5c;n)qu~? zydNlWTA6)u{zrlyTpZl&|CL|4xP!Afg@QS>B??hDGiwK^3i#d5+TH>xV7l1-r{UL% zP@;jpNPN|knmL=l@>hDD0GgZg7mEMLz^^W@CSRbkjf<sNn&G zF0QWs8s)WRW~c+aUO@^Sf$6INrC0rbmHoqepk-hGDf!O({ZmxSGD+s#kiQ7Ymdr zyP3JZj#Jvs{FVPhRR8J0M#Gs854J?vnhw+dqdX;RL`L^`Ouh4(e-oFQ(@@Uqr#;{-Fn{8I>fTT--p|% z{70)yV#6On2tA@0Cqu$eN-Z_n%FvF8;XKNZ?VbCCAk?dPiL`bF3{lpwmX!T~eTLJ) z9UHOm9&0+%e(Bdq2VhY&km%+PIDmBzfs@=iBIs_3Jb*Kw>rncRzC2tiJMn<5Bwh?# zHO4jBZ_q^2ijZom-3BvD;kO`{Xwdlhd%MI1~2+FZk(xo`iZE zhoYRM;|@8>i^YQ5uFIl8%k;mKM)ywJ^p*TweG&1Ktvx~9>GWtX3X~` zJ4%liX}j(@Induw&jZ!bc){DnK2qi+@GW5k+G`6ybReC8TSxP4Bx!5hwfR${A@ zj=hKO6mW}8Y377P=BNCgM>!C(#gv+M`3Sd-ty_|ie5i%ui?bwb(Q~9>XI49XiLZJQ zXbyuFd27=mwlj15iVVs`J0#wp3aXSCvK@>d+lDz8d0f6{^R#DFw>^%^%t0TkK0E8O zl)NpY<~5bYgMG}4(KwqcaBv{{(YS+)J4O0;DNA_5!U*w-KbXGnSl>Psb|Yr&FpW< zQQ?3(k?0@|vT2yUheKs@G%u+bRj4o9T+;c|>5_($2G{9=+GLL$(A{yH{mavFk>n69 z(sG9E-fZ@seZf6ZFmXa~@3s_#0F0M*i~6lCUzh` z5GR<%Ww{K|hKckkRQyuSAhbnFOVzRj=tc@9nJ-8S}IUq3!* z-@y^*KYd-zZbWAby$M*5)293?J)~fVH(6=wZYALsQ(95V_a5_m8u!~}@StL*dU7n| zQk|~rr>l zNM;U(I9PrVRq%Uqto1;;+Ndm^8C-&Rb=I67b||CvLn_)xtl9uIFD7d$WnyxXS&%tK zFtS*tdVC&CM?z98rBIfK79k%<>jjrn?`fRRF<@$t8OQatHnlnkwGLp9C^J+p?#wLTvhXA32393j zf6NLZO#L9f+Ev(e=3GuGk*-H-6Eom{zpML+BfN5mw)D+#3Hir1JsyiMsd7&4EiP~4 z*@$xWICXC#LuJ@fAt)5z)$l+ae>_g9X{zODEJ5~fGtj;2IU6yl%xnbJcuL@?!-Q{Q2|nY&P%8Lf_mmKY{Oh2miL#)(Jy@i%l6v-`_v6^gOOV zibCst-#z8m{k}fkg^n(fU%CYVG!SQ|6BNyH@F#SnLc@MK;4=$<9KXykbW+gPmX>$n zm-R5Mr*+S)Gy+tkzL%%5hp?@dx;Ugnw?RPy7dvrC<~u4=iM)%9v~Ox!y7PYT+@opM>C>wRdu0relM;i5R+%iWyj&Fh#uz3)V-u)l(f!JtLb}{Q9AM=Q|u%)=|VaJRKh;mxg<&Moog5Iar3gIPr-B^ z&cxH>@3|3NbTxEEa7eGt>u;cW!hsL#HIJSGU>x~ay+w+f-`~=6c7p#V^SID0alyah}FS=Yucu z+o+~!rYK1cXaRuZUoKwLM_{w5%)mjfO01TvyR*Lm0H~n>sS<1zSf=kGNIDF-<$WsJ zym=8cAL~aT00>p>5boVeXW{bP@jf*oK(T3>*dPkcV#1vWb*LIK6E+>6#863LN%oDW zSxjKcMam!&y~PAj)rlU63>@)vbl+jB!Djf}M>9$@bo&rcP;H`>+u70E1-8fzyD@+y+BfhD4pNqb;x>&t$3&DYI0gI{YOx;<@0=vsc-hMcb^ZitbKh7i(9Q=^<8PF2zksoE*GHt1|9J2PclbW!1h z6DhAHQTQIE@EQ-RnbyVpJB~Oip2l~dokTh4-#6%GKO+^Zjp!=fwNkE+%kQo&l2Wp0 z4Lm$exgwLrWn?;|bQ4pF5EL7f)$yo5qtXtHeV{>5DNQSVXX_m!p}-!+2uICK%OFXY zGk`OETCtt&#;YUvKL61Fdb+3hr(xCmk;Y)hoJ3$;wXECXY;2f?|1F(JYTh|1>wc6O zk*uE)y`<3Y;iVSkjM{3q%el7A7u_gEd8#AVP?^ubXw$WPfroKwT*HBNC zMx{+n5=SMX_>~HIQ%*}|K63-L-P_y!_M@$Z#ojcYXp=Xt4@8s`zs9@uh#QdAE1&OL zds)>}2Q7hSOs$GuUqQEzkDp#+1?GqyUH7(Goq3=TQZW6X^Qc(~r6#6j)V^7MHbmD+!&Z|OsOdQCNpVw!;z2%Y?|cd zRm!?Bd>Lj6sf1SKz-`Xcp`ju0@bJ9OA8u9mBqb$+f`ZDj9KbO5W{I^nOY@E_?42~r zB=zT%V&lq40Kve;%?_MMO;DR;K0Z^VuuY}Ei9f>d-a*9~Ee$2uM)*t~EeI`fJiK4H zlu8v&7LVH9Ts1LLhF{hD_1j2uURsAfhWNpqgB=de+#IhvE|hQis(Sec8SxwgR2X)@ z`5$Mf)yS2}JER?HBo!zZ@=d)QXKfh~b`>@$=Vnf7_X+K*{fzi&v2jSFu-&q2in4@o zgo!1El(Dp%6fe1HI}>b^^Ihf>Wo1zyrOA1c4DQ()Z=|!a;O#9s>0<7F%B#LjqBG;d z^axF77wL}Zw*>cjvFL*eH$-GbZX3Swpba_~GOTnJ?c5^Yn(ax_&f(Fz#M!f$28{s~{J3!~ zDp_1o;?ejxV`}WAEP7&#tra>F36xh+2C`yd)Zla#whSiMmY5b)O5^4tgw7ztYXY^`1~WF7D;|sBwIbgID^)m@-(>>66P}REHM(?N2H21K}5`!;|{a72~DlNeOe` zUn$c5n%XIkkcp_IH`&ROE=d)sgjw#N(@dBcWcS;A1+K@Y=hp!0b0TgY2yO+HQ9)+};4 zFc*x1SlZU!qy_+h;p|u?6%pOJQX8oQ^{s`!^Lqk-s~F9sjC29&pnpum&CLy1S#fjc zc@Itj=TqE%N#<|MH#MD3Toc3N;rq#bjf<}e+2}v$;|w0qx@ho$Uqw91>DlJR+)hMe zCeS#m%~_o<{^>?}%cnPR5qA33`dZ`?=M&Dlw_&U4v+Rm?u?>?f_TQUr zyuG?H1ctiFv*9~JI-0F`Zu`Hv7d3sR0r-B%;7*BLo1%y!ja{GD28`1}X2C4!=Tx{d z_boPbvLbEYdRVSseyc(^r-olX)qi<^lZPgQPr7LOeUaC9B>>xJk-0BMf*`Gb1H}2U z?2ynLSpVjD^y-|jwRgMM_CuYhJ9Odlu{S?IL3PhKf8nt^@Ui@Ew`cC*^dWHSzFF)k zV|@=Aco*0URe|2a@>Y%2;B$NEhmEJghk!K*r?wkizd^E zHCT3_^lNwp02bp$I;Bug=p7(K#@iddqOUsA*2k zxUX7nDONubTz{WFFkbX>8v7?#eDBPz8U<%DU82Xg;ip%*ie2b)f)QsC@LS7JFsr6*o&&D8NEN z11hhCW5GixD2bK{Lci;^{X_mSTRv9IVVm6F5^rxNH0fdX~A~XvNK8c(=6(E1<_yR@FcYdJux}g zDd5F=yXY~7!88aX@wb86+qUm&+Gc2Io`{IN zo8nxt=4gMP)YIu!)}uRfJidRH_$pAXRkB~exqcR$&WoQB7&|D|4mv&Q4fK+NVkQLo zBc7ft`#+BP`SIrmx=>IcsrI(NNC;tAUwsi$hZTnCiHCO;9NZmb03zaJ!+1v(KU7@b zW*1G0o;+Yd5!kwZbp6|V^qc?ggZJh6Q?5nb@%5vNp+hrN_5P;`-}?e@Ld&DMF`lz1 z@W<|WhSU(29zKz+X&hkSn|l z1u%`UV@aNr7jd_o%iTpFfSgf=c$UW8k1>+VV+!}5Mbxb5pj@T7ojZjY)aOwFAZe$< z>8kK5-k{3ajhM;=y+;FpATJ;+Qo~u?v!SH1bZ|LV zpG!Qnsj5=+@nC1hT;uY!6ZPB?$I4pUfU(8SEQ}i!B9XY5%8QQ~Hf}0GlmMFo@5KU$ zN4rJ4p7PcmTOaNpKfqSkk3L8AstnrhW)5qMhLMQ>u(!U@ z8Sw^yyzSpRhX85Fkj&cJT3iNGTwgL8a?m0^%dnpd8?*d#3joqhRO+CYnBaQUb689q zz;HraSmc=N>3LI|R6d{C^W#t;P~zo3oUzcvk1~8FMusVt&{fG)>%n$s-F@Kkm%01L-W3*q^Mt3~ z>#Iu$);vIy8j-XcW@!C!CwZ7Tx*~9lktQN%pfF5+KMV^=1s##Bk1DPoLcI450sX~0 zKsdLQ$HP8>(lu8-K(D~!J{h-wUp{Hh${fsRW(q=ecLj+9@Z%&loIjkE@tOBF=F1G~ zB~o5u>8QNAItOLne^Uw5)u)=SAYf8R`skx=qd@HXQ{0rDC5)!bq8>EN`B}VC9N_D) zH_Wn1Fx=g*V_C~}9DY)2IBLhK+SyK-c81idDizf-L&`00J)!4iBtIQJ`~9j)=5ILm zyp|4a!%o}2d?t#S8%s5>SoK-qbKl<|&OCCY5bD50k0XCm8y0rp}oUR9;a956+Lc!fR3)$)h+jG z@0@2GK8f9n7+gXr9u9NQHy5D8(ENNd$m{#6Uh+my?(TjlTHQ63V-W3b#ZpI1(l$LIv?f5ZbE z55~9mv;}GupNk~ro#DU`LvfN_PNjO97|#C?Gwlz6j;UZPSw8l^N_g=@MW2~o+}`{5 z?)|wr3eQl@^B<@rX98j@&ffNjT?2J&q>7rzywqP zOy%2?G{+KMz*_X958#0(7k>3&cm7`Nm#^phIpyEpUGBXshm<(GUOD<*P5=N(Ru8?W z1DM+e0Xg}ua6T3Ok8SfY#7;z5uMLkw2kd6@Bvi5bD+!pwbKxc!h|cG-|H4Xuwa0A0>bP2s=r* zx`*cZoYsjsyehrE3tVVEz5VFEU9$y!?7ckfk$#Z0`;=x<)jF0}U8JND+KI;L4EEzD zF8Lh;_YN406o^_N$?!p;W2`nIvL?Vdtp6IJR#24()CRv`UnQh%5?7@nj!;W8Ow4vz znnV315U+|i3&0`D`U^a;h((5HnVBB@{n%O9h^}Bg<>geRfY#Z#kk44f3A@*~&DvRg z!Ir?3{U|``A;I$-TR+XlHE8}7$&w{27m@Y$h-X9lW0nB4OH;0l-c+Ol#T;abK<~wo zxSzla=j*`Q%m=U*g`y6Mf0d3#C+>ili?{x$%~g;eAGNFjinD=*#-K<>@=(Rw2Y(Hh zAE=fXe$KLtmSgc%vObz1g$5~5z(~6E2)CBg#@^^2jO9!i zrPzFI4IfC8M+)o9?G#zSNmCE&k3CSw-d2+HsnM%*pVNi9BdDJD9^ZDn<*qYqJ!{lu z0{4pxj0vZHm0f-cpYcJP%W`h@)k~dzg@zrM9H~s3@J9Ufj`0miK9R*A{gTk7dwRa# zVi&%dQws0_aI@y4Qu{N+)GSj9{Tr@N-18f$LNCPu?o%GC)TmtI+k5#l_h}TQy#9!@ z6CHfa&k!#q+LPhzP&F=G25@fl^lzVqwXkaWM4{sOCZ1?gk5r0RqFN!w?y-vysC7Nf!S=N`PQ zCKt6$g&Y7#mLveuwhai==Se}_(4P}j@Xb@@%>cMh;+I(;KzKfCn8%-qJEt>mjOWHBF>zn|?hf!Kfk&?|4S%~^Z& zVnsbbJ$#(k&LLO=P9O|Ewh|U8BpK7BB{FSVw7Bh)y50wWsL!^3Z_~}!%lkmbr+2e^ z@qWj8KkJ}JfmaJ+lrOAZ-bP$jwy9QYFBY*%w+SxkCNa)OT5a1!M%RZ#3QB&JGo4{B z_w^8i)GND^r0c|AzSb};u$2&>L6p;u%wRLmeHdtB7D%#-Y$cPK8Zr8_^4APJ~q}5%Gm>(pBby=>2L$D1M=%& zBl^~Nb$y|?l}YTk@%@{mT-S<;z{mWjRnIYy>l+-#q;Xp&Ta9)@(+2MVTh9#t6n3(> zsGEe2U(w4g{+*;tJMdS^%B*-OQoeCbeMf$<1`+}Af<^^zuur+Hs&Jl6<^`NDjIJDyuEdMo+y_1gH@gmhV5!pygt|gU<2?W~*=SYs zWEx~-sn}mK^lCjSK6Gu|vP&Ln6)iud53>n0KF?0m>}#)Q)L97NqL1L|rGMg`b42nb ztHF0PUJBKB-!u7pz5%?@8tM@Y?bl8P06|12p)Y@Vd)g8;>gYusWsE;8`v0Xfr3Apa zz3Db~!dq9YOFf@)W^ru_0IfKikE_%QVFB}_F(=T;;z2$xv`x(^HdD zG@ajnOU(GnM*1gTKH-l0?Z(DeBF?QE5efkzX&a(t!ObTi7*A14k(%b2RzUdhZDri* zf%~e%z}|VwDp;ZB;VL^;b}eaBJayWZ|a_L z>nU_4!MpaNdg0|={xhWsc)&`T1e(5*d<3@1L@iy)IKiipl^^V8Z#twv)VUtjC9-`Z zh0UR_SQAke5hFiw7KR~+W1$AXHN5%#5j7ry$YyOSUf>%?h@oAS!^a7+Amc5hw?`G$ zRAqq=gC7In=Btas%{zGt4Qd-&qQ!)^TbH_jcxaX2gN$tDSndLmy8o(@wcz~FaHLeX zG$8AU7bm^4-17?aAt0DDt~qHvpuc-Cvp%u#X3}II*uMU$9P1?aZSjCrf2`E z@f&MBz>623_vS4SWHK{Cgb77iO${p|J#ZiUyl*a!>$umKri@@A@;g@RuuG|;~txR7#1pBTM3!S6d9H~iXLja2^Cs!Z&*IE>j zAD#ZD%aM4AtMw@lJ^14RHbtp$Al(mt8YMcd(QP<cIQYnH)V69J5R$q8yE$on#&XeB1O2g7oWP^E(gwU*|#MfXQnr za#?jQ?mASm0)_0idqR?&gn46$1mXfe;{eyco0)w}j-pI?>SC=oPZbe$na+wv-o$bX z6n6BQAC7)T0Fu&5G}YfWydTS+na2IW#ifRSwl$?Q+%mS;srb2hFB$?Mdm1By;9#3@ z7MAEing)StMVWxQnPVtLAnb{(K#eQk!PD!&6=;itvA^qR;JcIFN3p|EVZc{7GhG-( z-lKKeAYVVQFL|6>yN)o?ZgED`_0{jLMLoF%f{R0}!VdwG9QCO=1e`3{Dzx?w zrcXjolMk;;V!nh-yH9#h934;LFHvNe3wyl*>e-?umfp3|j z4y|^3ga6~6;jmEYrdp|HE+ry&C=wdydCawaFr*J&#*NaGzjHv zOuIr4{|)142P&Hf2|s~*kMzJ+*f*pkbOaxA#kJV1>iq%S9M)c?j1LFwnzFnvU&cu@ z)A6FQ9pRJ$yuZ(!QC}yf=`R1X>*RQ)qpj}e&Zc-UDp=GulJK$u05F^*U`(@>v4Eq$ zn?4^7!3?o+)zkWu7}V-1kl4sMz|Z0eYCHp-9E>{N>*g~e4}9!>vh)EwG*QVW_vSq& z$vwliKdlZ$Pb!JgfHA?uHLYYA<|HL#5?@|EgnMU!X48}VNNo>T;QrBPT@erf)YVD@OagWWz*`TDl z;ubJj$jcJT>613NW+UhkMWHsKIroeJ&UeC|xe|1*?{g}}UWlFJl9Rh!n4Xf`G0frr zB+6&|gouGr&WT{?po9x&&~E{G*6vVcWmU|yi|f@df9bIoSg}NeR(+qGVK!Ps1%&dv zFOZ5KD-6=rjDf9Vub{`!%_p(ZIQO?b4DsE)+vm_U#HZ1a|XfAy_bGxjLl@W4e`>Qgu#ANf+IQ(muIBGSJY;-&#IRzUpb|WHQQAW|1 zLGmQ|qD?Yxy0ct;rbAWB?@9F2m^BYXKU|9XHs0pX&ArPkA9o)PVPtXIxov^y68kYB zs*Q0MYEnC(Q%rUMR@A4<%az{ggAgIPcL z-c&b{5+CQTSG9LHa4%=`{NeQK(e(&=1U*@Zvl3cgsCoStdKY*U_&(E4J%V#=J09ea zj9tN-Xm%i%)8t-G|HdCRZoW5(Cbmj%F7O;54PJ#nyI*xmJl&6BBwwq}}BNHglrZ?$zYZNWf*I26MqmzP9!=1uvO5T(3LGw#= zWful~dT>^FPr|F2T+aS4AlYPscjyQpAT2|i`u@e1fuk?+c3k6out+Xi=rWE!?>y{~ zp^b+(5@kaclO+uUeyX*JUbJH~D-2`6-+4P`fkM;XIeguctwTpOFL519dkWh2+!g*K zdX_Q?s9!rD1V#f_t~X(4m9di$5CH26Qrqw^g@w9ml=!$}#=X$i+lSuUhr?}_EmzO` zz!~WJ&$;zCu6y&&#!u__yM4q=xWY5kOme@A2)sr1t6H>hqwYVcg0(*(k!p#*Xo|E6 z&t$P)u&YGue`6d}@P6kgn0ipSfvzJ)4teU65);vIq*ux6WvkH(MbMGK!Z3!o(70iu z;_w+fJ>qz|l?Vh-?(d)i*XkX*np6#|V2!mY*%ciy%t;Ba^L&RO#WRUhmD+ob;c0xz zw3YetD5gWHRzgUCluB;!@rf2Aj0pqH)^yGNTZjmR?{EZ?I& z5;SKV2$pD1cCLg(#wbcAEx@)W#(@cJ^r14N6j=BDjlf|U&}C0Jpu|Qmv?w_9+aD8u zX53Myj=(aH0h%w=?CT5LuOe-yK%Omo0jV9#$Uqihst@j+$)AC8KwqpsIP`QMZ*{o` zirqkOU%T$*8+q;xPZ8EZW1t@v;r33z76S_1@mY#QXor;2pT~Yx%s0@NECC5{QQO@p zYj_P1Y`MMWa8tk`8hs*HQ=28JNgCSxk#KSpLR`Q*^!^38s2b^R_ER8P2;8egSEcwS zbw=LEQ0ay_Yf1tDR3eY|aPaz9$FCNz*P&ri9hsJAQqh83y=4~Q7}j~KzPDIWhw<>` z(Pi}l$rWku8luZ(Ma=m+%261jczH%s=ty)#8TLuAR!)to=C2W*c?Ug2^_h>ii7iu| zH&_tYbBi%!;UbbAZ&xJ^X&rR&kRYEcrNdv5M02VEyj*b?c6`-v3NbDOl=K5DJ=B+k zGElp4^zS7HrP&%!f89snWl<8C9IF-fD^N!>XQsrxUB)olP8VGk0fAeeD{&BoU34rG2#`}PqXV!_rrwd{8DQsgC3TLKzdi9il|CI0e zc)QIFd$yT>Wd&VGW5E1WQ%V11D9%YHvY0Z0{$qYy{##A<-q!9g(EwU=Brv^DnOb*{4M= zND%qAoSOL@DkR|wcP>tJne8^BjAk`2>4vp;A-u}oe%d6NDP%!UV-ZK~fhcOB0l4hU zCS?quc6~c}X8p#t&QrcaXXb@{#8fvC=-BjM&T%jsWI)fWMQqflZKxge-uSHd;&}P` z_~H2I=>v4|0{ZlD?7o`zNzfB|6?i=*{=(=j@0ZZuwsaeczuNF?D@l>PeNLIYgLPCV zR!=!1Pm0N9rd}ZX;04VV5NUerTQF)&n@_w8+6bvc12~-!Mz_E&cDnJn^|v-%*M3XvHS|$x!^5= zw2g+1WTH2sMU~<0(j%WL{0P8HLE3^`n2(hOtrS<~?BAcs3*@^G_dlw(@1N1{5EN&9 z-}aG35z*t@kTbx_VN2Wy{SJ02vqL5>4Ci!W)FLa)NS6tkf=6Mp1eGbs5@S`Ti>F;W zed^R&`(ODK0l=9w-Vky5xDu{&c$Jg#&;X}d#7@OO^Ndl zvl;-$^c{gSv$GTapJPs>^Vly6U@v8##jf*>Sy1f;aQ2TqNBXk$nNpmZ_Q~~Wz3Or= z;O9(F^MOC~4(bS9%i|F|^z)qAy@B<{-L*J4Nt&Bc=m_B|+Ogtt*o=PPxVP!62V zQF*YdH7E>|Nuf1Uy3h#%Ahs1D_Q?o2{vFz+e@{0_{@$CWn0)Si8x>fy9hv=nea7~( zNisId;;kZr)^~Kyfm*V@S&gs)(PqB(f|smFEU%WEYY%ZND7a-^dNTTtaNK`cE0oa@ znZPAhYcTXF40hZ3+%?nIRy{C9j%|7GWG9k418^5=6 zb2xKOC=9Vb&t1jXl9asvE)X1yeOC0 zyMB1;P1xRE$*1r>zpOia2)zIFdvN&IarN~<;A7q6c|A%4Ub1K7kYU`SwWVN6&6b2W zi&`nwK5fwc1H^8rS z)a3R~Vg<`q{o=CPrjv-nqymzridlq{q$9h}qW&>On@0rzLarJ7Xv!D)?G--+kkUr8 zYMsa5`1Lc=)|M((a@3HU)o-6<$v|&p1 z|4i`tWEIhly*lO9ikoj8zYkaYb9rGDM~n_cg(rf4N1Y462Ei@xQk98%o{mDs`-Q`Jz72M@8Ch4TVlJ7*(J8lJEwN*^OlBO>TSPJD zv~8i-aN5dLi(A~BASSyb{-rc6tJ*1AoIwmn0+S_N4YG)-s%A}T9=b$poeV+7D7i!z zi(85%k%&k-L;WZ(0K`xo8epc>-vK8Dk+-F(UcvGCHQP)VG?VmR%anj#%LsSF2bZ@C zBtFokMubqweAd@SQRjv`!9GvP&8y&w_g$Q`iR5;3Y?^gF-bn1O?M2*mUP6A29G_ZE zU~$v>`sGA@Xn`RKvN#xj2Wi5;-jQNo0UPw;-_ z!t+flc$}r{CNp_}zvZwm60>Gfa=}l&gdmwNWup!qkqglct631y^Ly>-IA{nd+JV2Y zZ=>yD|1uZ?pj7r_Am^j(eIBZBs#n;#eLt4>Qk}6t@!e}eLH&e%MvW5rkzSnXt^(cy zxL77aM}cq)Y)J-W-zuK1GwukI`X7{hPGuN4Ev+`mvT5hH_cS`!#&rUUGha9&7SyL^ zl9#C9=AJ7Ehu3u1C=vaz&_9Owkc}ZI%x?{jTAk952oHwc<=yrDX3@X&epv8!}Wb)o=SAr%XfJk~doL@THfUTOdU5=yi`5mfcU z8@F)K#-+wg5Z3*q$VKTkZVC+tn6&v=eq zZ+v1~&eL`Pbd16p@mU>)10k>L{7QdW?-X~4fs@_d{#G8H#MSSm3H2E?H$8f3nOCkU zp#?+(VFcoDweUL%xPsBFgQL)7+lwisI;$MR&4^fi>@KU22^D8L5)WxM5IN#nAcR>C zgbNQsqXDJ1PB_kex@g|*Iaqxlf(bgIW*n-UXGY0@10FUEHT*~^8|Ot$emXp)f%T{L zi^tw8=*;PT+pfQAeq5kqKJ@tBt8!O|{L-j4@Dj)niVWwb{oQY;G^mpF$wrq+e!=dT z+mSw+)``m|7k_E#5D2smt-!4izmdzVSKDq_93Tmf*Cv-bXCmv~j_SwT;R;2Mp>mDJ z`IK{$0Ri9$s=;A{Q6A*42`xgs5M1^3JR%O)(EciVdN3%Jb!?Mn>1&UI`mxI(ASbyK zfLR+<662dM*MWnC#|aQ>xa}{Hj4=?jcBKaj7i02}A|(`s1QveJ&^c~j^W_x}MP#B? z)_q~FOCvVA8GZ+^3~(w8IK5^8Vx6}?%QE4Gi*}Z74|-#n&W62?v<9sdnIP`kUe$^w zSZ`Ysc;ew8N@y@4cboxuuH!u0?6cJn7;VVF#=o?|Tc_yedJrZoocBJTX77D;@2y&g zy_TF0Exz+R>~UW=yw_Q&fc6nbA3#*f7?@XQx3s6mSCW12+(iecw+)cAtjgD*FHsm7 zd0!lkfg=9~e8{F-%5`C5R1YtjNk`LI&Z^75iY^EG3K`_{SyGA&RdfLm>uz;;)$m-% zSb;@S21CVW+dY*>*wBV{L!C5_-zVqNN!sDxApoK*B7q5d_B>F0?yf9-9?*U-+RISB z1aKN10S4`4_VEnpr#V~fCM@JQ`T_#IMNi!=7mIW?i#o!yynWqoP#qvEdff*?e?IO!-2QBxzs+BT z6MP)Xh^8g2JN^USAe(g6pZ-;TUztwJ5{lPK9W{f=IYW$L+nbU8!Eae9K0RE%X5#4( zBUrsE#e>$&*?3)XtHDm7Z{B(^2~}!YU(LF*BeEWNF^r8RoyYIAv>Fk}-fl;k*3~-< zzA=dXCg$Rh4Yck6&oWNM|Il;x{uaH)NOX16dzecp_Hbd-8-} zo`%CjcD+bXpj~!wNZKQ2wGZz!fEX%C;Y+8X9se&$XE2grTeGi>_3f-|f$K*PzCOJd zr@IH;y?mEPVs}tzZ|m>s<9MIrx93NJCqQ+%hJgN%or@2>#yFor>M?j(uA$cdH z+R@vrN+m8DF4U?^-8(S#;;j;LM0Lrs2>*Ry;hYkgMX>RS8O?2)R)yOviX*6bd@_Ru z?%?F0Eitd^0?I<#)BgmI=}6J6jd|7$S+n!;cJ`;3cU`T3bo?M~9RB{WeHw?k^s2CG zPKTpm6PTW)e-H=YC6dDO9!d7&1~E{NtNwI6$&&U)+|#hdU;~(phP47h@GLPjXqlNS zg+df8r{efg0-HTET7Y#-E#vl z++FM_{|$p2T;0sWNqz!B)jYot@5Wy(gzW^jy2m~V@AaZqc`!6ZacV>hs!1EPkuo{>@ z2Vm}5{-3me{3ckM&p#>ue!;E*CBQnd0fsObs$i&r;VlfX9B?qo;K*QkRAFF;ffoi@ z7!+XOhXIxkBn5*63~yj~mcN5R4+fZ0fM6?eko$l97?|$_1580dZvXM0!_hE!!e9x5 z8Vs*sV1j`T1}<17@Lb)@|FN5}@N-*WuMvRM+%4QpVZOY*<+J~fqy9g;8>S-v)Aj#J z2S6k?cCN6Jfi555?He^o zSTGd!hY!!CJ=X%D_-}xVhxdPyo^uFF@bLVP;Qwa;RxDSAg(>WHQ-JCJ ztP3|MmjD|l9~&2+CYOK^kAM+|%c5GN-rBVC1?<1>Ba|K|nDrXKJ4Ua<@Cuyb*8 F{x65=vylJ* literal 0 HcmV?d00001 diff --git a/speech_to_text_/example/ios/Flutter/AppFrameworkInfo.plist b/speech_to_text_/example/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 00000000..6b4c0f78 --- /dev/null +++ b/speech_to_text_/example/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 8.0 + + diff --git a/speech_to_text_/example/ios/Flutter/Debug.xcconfig b/speech_to_text_/example/ios/Flutter/Debug.xcconfig new file mode 100644 index 00000000..e8efba11 --- /dev/null +++ b/speech_to_text_/example/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/speech_to_text_/example/ios/Flutter/Flutter.podspec b/speech_to_text_/example/ios/Flutter/Flutter.podspec new file mode 100644 index 00000000..5ca30416 --- /dev/null +++ b/speech_to_text_/example/ios/Flutter/Flutter.podspec @@ -0,0 +1,18 @@ +# +# NOTE: This podspec is NOT to be published. It is only used as a local source! +# + +Pod::Spec.new do |s| + s.name = 'Flutter' + s.version = '1.0.0' + s.summary = 'High-performance, high-fidelity mobile apps.' + s.description = <<-DESC +Flutter provides an easy and productive way to build and deploy high-performance mobile apps for Android and iOS. + DESC + s.homepage = 'https://flutter.io' + s.license = { :type => 'MIT' } + s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' } + s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s } + s.ios.deployment_target = '8.0' + s.vendored_frameworks = 'Flutter.framework' +end diff --git a/speech_to_text_/example/ios/Flutter/Release.xcconfig b/speech_to_text_/example/ios/Flutter/Release.xcconfig new file mode 100644 index 00000000..399e9340 --- /dev/null +++ b/speech_to_text_/example/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/speech_to_text_/example/ios/Podfile b/speech_to_text_/example/ios/Podfile new file mode 100644 index 00000000..ab7d5b46 --- /dev/null +++ b/speech_to_text_/example/ios/Podfile @@ -0,0 +1,90 @@ +# Uncomment this line to define a global platform for your project +platform :ios, '10.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def parse_KV_file(file, separator='=') + file_abs_path = File.expand_path(file) + if !File.exists? file_abs_path + return []; + end + generated_key_values = {} + skip_line_start_symbols = ["#", "/"] + File.foreach(file_abs_path) do |line| + next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } + plugin = line.split(pattern=separator) + if plugin.length == 2 + podname = plugin[0].strip() + path = plugin[1].strip() + podpath = File.expand_path("#{path}", file_abs_path) + generated_key_values[podname] = podpath + else + puts "Invalid plugin specification: #{line}" + end + end + generated_key_values +end + +target 'Runner' do + use_frameworks! + use_modular_headers! + + # Flutter Pod + + copied_flutter_dir = File.join(__dir__, 'Flutter') + copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework') + copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec') + unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path) + # Copy Flutter.framework and Flutter.podspec to Flutter/ to have something to link against if the xcode backend script has not run yet. + # That script will copy the correct debug/profile/release version of the framework based on the currently selected Xcode configuration. + # CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist. + + generated_xcode_build_settings_path = File.join(copied_flutter_dir, 'Generated.xcconfig') + unless File.exist?(generated_xcode_build_settings_path) + raise "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path) + cached_framework_dir = generated_xcode_build_settings['FLUTTER_FRAMEWORK_DIR']; + + unless File.exist?(copied_framework_path) + FileUtils.cp_r(File.join(cached_framework_dir, 'Flutter.framework'), copied_flutter_dir) + end + unless File.exist?(copied_podspec_path) + FileUtils.cp(File.join(cached_framework_dir, 'Flutter.podspec'), copied_flutter_dir) + end + end + + # Keep pod path relative so it can be checked into Podfile.lock. + pod 'Flutter', :path => 'Flutter' + + # Plugin Pods + + # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock + # referring to absolute paths on developers' machines. + system('rm -rf .symlinks') + system('mkdir -p .symlinks/plugins') + plugin_pods = parse_KV_file('../.flutter-plugins') + plugin_pods.each do |name, path| + symlink = File.join('.symlinks', 'plugins', name) + File.symlink(path, symlink) + pod name, :path => File.join(symlink, 'ios') + end +end + +# Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system. +install! 'cocoapods', :disable_input_output_paths => true + +post_install do |installer| + installer.pods_project.targets.each do |target| + target.build_configurations.each do |config| + config.build_settings['ENABLE_BITCODE'] = 'NO' + end + end +end diff --git a/speech_to_text_/example/ios/Podfile.lock b/speech_to_text_/example/ios/Podfile.lock new file mode 100644 index 00000000..60c8b57d --- /dev/null +++ b/speech_to_text_/example/ios/Podfile.lock @@ -0,0 +1,29 @@ +PODS: + - Flutter (1.0.0) + - speech_to_text (0.0.1): + - Flutter + - Try + - Try (2.1.1) + +DEPENDENCIES: + - Flutter (from `Flutter`) + - speech_to_text (from `.symlinks/plugins/speech_to_text/ios`) + +SPEC REPOS: + trunk: + - Try + +EXTERNAL SOURCES: + Flutter: + :path: Flutter + speech_to_text: + :path: ".symlinks/plugins/speech_to_text/ios" + +SPEC CHECKSUMS: + Flutter: 0e3d915762c693b495b44d77113d4970485de6ec + speech_to_text: b43a7d99aef037bd758ed8e45d79bbac035d2dfe + Try: 5ef669ae832617b3cee58cb2c6f99fb767a4ff96 + +PODFILE CHECKSUM: 0ba44ad07df4ab62269dc769727cf0f12b1e453d + +COCOAPODS: 1.9.3 diff --git a/speech_to_text_/example/ios/Runner.xcodeproj/project.pbxproj b/speech_to_text_/example/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 00000000..c40af650 --- /dev/null +++ b/speech_to_text_/example/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,578 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + C446300A034BF27D9F1ACEF9 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E76E9615C6B4FABD88067D55 /* Pods_Runner.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 59AFE6BB0B596A0E0811BDFF /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 6280E2A777726D2043BF80B7 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + C3909A4B7EC98A20255210E3 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + E76E9615C6B4FABD88067D55 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + C446300A034BF27D9F1ACEF9 /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7937AF765430D66F28F7FEEF /* Frameworks */ = { + isa = PBXGroup; + children = ( + E76E9615C6B4FABD88067D55 /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + A68CCF1640763A551D35BD31 /* Pods */, + 7937AF765430D66F28F7FEEF /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 97C146F11CF9000F007C117D /* Supporting Files */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; + 97C146F11CF9000F007C117D /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + A68CCF1640763A551D35BD31 /* Pods */ = { + isa = PBXGroup; + children = ( + 59AFE6BB0B596A0E0811BDFF /* Pods-Runner.debug.xcconfig */, + 6280E2A777726D2043BF80B7 /* Pods-Runner.release.xcconfig */, + C3909A4B7EC98A20255210E3 /* Pods-Runner.profile.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 949FCB95217187F2C022D6A9 /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 8B0988F04B6AE44AA0304FEF /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1020; + ORGANIZATIONNAME = "The Chromium Authors"; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + DevelopmentTeam = 3X949YE9K2; + LastSwiftMigration = 0910; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 8B0988F04B6AE44AA0304FEF /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 949FCB95217187F2C022D6A9 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 3X949YE9K2; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.csdcorp.speechToTextExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 3X949YE9K2; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.csdcorp.speechToTextExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 3X949YE9K2; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.csdcorp.speechToTextExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/speech_to_text_/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/speech_to_text_/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..1d526a16 --- /dev/null +++ b/speech_to_text_/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/speech_to_text_/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/speech_to_text_/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 00000000..a28140cf --- /dev/null +++ b/speech_to_text_/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/speech_to_text_/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/speech_to_text_/example/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..21a3cc14 --- /dev/null +++ b/speech_to_text_/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/speech_to_text_/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/speech_to_text_/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/speech_to_text_/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/speech_to_text_/example/ios/Runner/AppDelegate.swift b/speech_to_text_/example/ios/Runner/AppDelegate.swift new file mode 100644 index 00000000..70693e4a --- /dev/null +++ b/speech_to_text_/example/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..d36b1fab --- /dev/null +++ b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..dc9ada4725e9b0ddb1deab583e5b5102493aa332 GIT binary patch literal 10932 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 literal 0 HcmV?d00001 diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..f091b6b0bca859a3f474b03065bef75ba58a9e4c GIT binary patch literal 1588 zcmV-42Fv-0P)C1SqPt}wig>|5Crh^=oyX$BK<}M8eLU3e2hGT;=G|!_SP)7zNI6fqUMB=)y zRAZ>eDe#*r`yDAVgB_R*LB*MAc)8(b{g{9McCXW!lq7r(btRoB9!8B-#AI6JMb~YFBEvdsV)`mEQO^&#eRKx@b&x- z5lZm*!WfD8oCLzfHGz#u7sT0^VLMI1MqGxF^v+`4YYnVYgk*=kU?HsSz{v({E3lb9 z>+xILjBN)t6`=g~IBOelGQ(O990@BfXf(DRI5I$qN$0Gkz-FSc$3a+2fX$AedL4u{ z4V+5Ong(9LiGcIKW?_352sR;LtDPmPJXI{YtT=O8=76o9;*n%_m|xo!i>7$IrZ-{l z-x3`7M}qzHsPV@$v#>H-TpjDh2UE$9g6sysUREDy_R(a)>=eHw-WAyfIN z*qb!_hW>G)Tu8nSw9yn#3wFMiLcfc4pY0ek1}8(NqkBR@t4{~oC>ryc-h_ByH(Cg5 z>ao-}771+xE3um9lWAY1FeQFxowa1(!J(;Jg*wrg!=6FdRX+t_<%z&d&?|Bn){>zm zZQj(aA_HeBY&OC^jj*)N`8fa^ePOU72VpInJoI1?`ty#lvlNzs(&MZX+R%2xS~5Kh zX*|AU4QE#~SgPzOXe9>tRj>hjU@c1k5Y_mW*Jp3fI;)1&g3j|zDgC+}2Q_v%YfDax z!?umcN^n}KYQ|a$Lr+51Nf9dkkYFSjZZjkma$0KOj+;aQ&721~t7QUKx61J3(P4P1 zstI~7-wOACnWP4=8oGOwz%vNDqD8w&Q`qcNGGrbbf&0s9L0De{4{mRS?o0MU+nR_! zrvshUau0G^DeMhM_v{5BuLjb#Hh@r23lDAk8oF(C+P0rsBpv85EP>4CVMx#04MOfG z;P%vktHcXwTj~+IE(~px)3*MY77e}p#|c>TD?sMatC0Tu4iKKJ0(X8jxQY*gYtxsC z(zYC$g|@+I+kY;dg_dE>scBf&bP1Nc@Hz<3R)V`=AGkc;8CXqdi=B4l2k|g;2%#m& z*jfX^%b!A8#bI!j9-0Fi0bOXl(-c^AB9|nQaE`*)Hw+o&jS9@7&Gov#HbD~#d{twV zXd^Tr^mWLfFh$@Dr$e;PBEz4(-2q1FF0}c;~B5sA}+Q>TOoP+t>wf)V9Iy=5ruQa;z)y zI9C9*oUga6=hxw6QasLPnee@3^Rr*M{CdaL5=R41nLs(AHk_=Y+A9$2&H(B7!_pURs&8aNw7?`&Z&xY_Ye z)~D5Bog^td-^QbUtkTirdyK^mTHAOuptDflut!#^lnKqU md>ggs(5nOWAqO?umG&QVYK#ibz}*4>0000U6E9hRK9^#O7(mu>ETqrXGsduA8$)?`v2seloOCza43C{NQ$$gAOH**MCn0Q?+L7dl7qnbRdqZ8LSVp1ItDxhxD?t@5_yHg6A8yI zC*%Wgg22K|8E#!~cTNYR~@Y9KepMPrrB8cABapAFa=`H+UGhkXUZV1GnwR1*lPyZ;*K(i~2gp|@bzp8}og7e*#% zEnr|^CWdVV!-4*Y_7rFvlww2Ze+>j*!Z!pQ?2l->4q#nqRu9`ELo6RMS5=br47g_X zRw}P9a7RRYQ%2Vsd0Me{_(EggTnuN6j=-?uFS6j^u69elMypu?t>op*wBx<=Wx8?( ztpe^(fwM6jJX7M-l*k3kEpWOl_Vk3@(_w4oc}4YF4|Rt=2V^XU?#Yz`8(e?aZ@#li0n*=g^qOcVpd-Wbok=@b#Yw zqn8u9a)z>l(1kEaPYZ6hwubN6i<8QHgsu0oE) ziJ(p;Wxm>sf!K+cw>R-(^Y2_bahB+&KI9y^);#0qt}t-$C|Bo71lHi{_+lg#f%RFy z0um=e3$K3i6K{U_4K!EX?F&rExl^W|G8Z8;`5z-k}OGNZ0#WVb$WCpQu-_YsiqKP?BB# vzVHS-CTUF4Ozn5G+mq_~Qqto~ahA+K`|lyv3(-e}00000NkvXXu0mjfd`9t{ literal 0 HcmV?d00001 diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d0ef06e7edb86cdfe0d15b4b0d98334a86163658 GIT binary patch literal 1716 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 literal 0 HcmV?d00001 diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c8f9ed8f5cee1c98386d13b17e89f719e83555b2 GIT binary patch literal 1895 zcmV-t2blPYP)FQtfgmafE#=YDCq`qUBt#QpG%*H6QHY765~R=q zZ6iudfM}q!Pz#~9JgOi8QJ|DSu?1-*(kSi1K4#~5?#|rh?sS)(-JQqX*}ciXJ56_H zdw=^s_srbAdqxlvGyrgGet#6T7_|j;95sL%MtM;q86vOxKM$f#puR)Bjv9Zvz9-di zXOTSsZkM83)E9PYBXC<$6(|>lNLVBb&&6y{NByFCp%6+^ALR@NCTse_wqvNmSWI-m z!$%KlHFH2omF!>#%1l3LTZg(s7eof$7*xB)ZQ0h?ejh?Ta9fDv59+u#MokW+1t8Zb zgHv%K(u9G^Lv`lh#f3<6!JVTL3(dCpxHbnbA;kKqQyd1~^Xe0VIaYBSWm6nsr;dFj z4;G-RyL?cYgsN1{L4ZFFNa;8)Rv0fM0C(~Tkit94 zz#~A)59?QjD&pAPSEQ)p8gP|DS{ng)j=2ux)_EzzJ773GmQ_Cic%3JJhC0t2cx>|v zJcVusIB!%F90{+}8hG3QU4KNeKmK%T>mN57NnCZ^56=0?&3@!j>a>B43pi{!u z7JyDj7`6d)qVp^R=%j>UIY6f+3`+qzIc!Y_=+uN^3BYV|o+$vGo-j-Wm<10%A=(Yk^beI{t%ld@yhKjq0iNjqN4XMGgQtbKubPM$JWBz}YA65k%dm*awtC^+f;a-x4+ddbH^7iDWGg&N0n#MW{kA|=8iMUiFYvMoDY@sPC#t$55gn6ykUTPAr`a@!(;np824>2xJthS z*ZdmT`g5-`BuJs`0LVhz+D9NNa3<=6m;cQLaF?tCv8)zcRSh66*Z|vXhG@$I%U~2l z?`Q zykI#*+rQ=z6Jm=Bui-SfpDYLA=|vzGE(dYm=OC8XM&MDo7ux4UF1~0J1+i%aCUpRe zt3L_uNyQ*cE(38Uy03H%I*)*Bh=Lb^Xj3?I^Hnbeq72(EOK^Y93CNp*uAA{5Lc=ky zx=~RKa4{iTm{_>_vSCm?$Ej=i6@=m%@VvAITnigVg{&@!7CDgs908761meDK5azA} z4?=NOH|PdvabgJ&fW2{Mo$Q0CcD8Qc84%{JPYt5EiG{MdLIAeX%T=D7NIP4%Hw}p9 zg)==!2Lbp#j{u_}hMiao9=!VSyx0gHbeCS`;q&vzeq|fs`y&^X-lso(Ls@-706qmA z7u*T5PMo_w3{se1t2`zWeO^hOvTsohG_;>J0wVqVe+n)AbQCx)yh9;w+J6?NF5Lmo zecS@ieAKL8%bVd@+-KT{yI|S}O>pYckUFs;ry9Ow$CD@ztz5K-*D$^{i(_1llhSh^ zEkL$}tsQt5>QA^;QgjgIfBDmcOgi5YDyu?t6vSnbp=1+@6D& z5MJ}B8q;bRlVoxasyhcUF1+)o`&3r0colr}QJ3hcSdLu;9;td>kf@Tcn<@9sIx&=m z;AD;SCh95=&p;$r{Xz3iWCO^MX83AGJ(yH&eTXgv|0=34#-&WAmw{)U7OU9!Wz^!7 zZ%jZFi@JR;>Mhi7S>V7wQ176|FdW2m?&`qa(ScO^CFPR80HucLHOTy%5s*HR0^8)i h0WYBP*#0Ks^FNSabJA*5${_#%002ovPDHLkV1oKhTl@e3 literal 0 HcmV?d00001 diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..a6d6b8609df07bf62e5100a53a01510388bd2b22 GIT binary patch literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ literal 0 HcmV?d00001 diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a6d6b8609df07bf62e5100a53a01510388bd2b22 GIT binary patch literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ literal 0 HcmV?d00001 diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..75b2d164a5a98e212cca15ea7bf2ab5de5108680 GIT binary patch literal 3831 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 literal 0 HcmV?d00001 diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..c4df70d39da7941ef3f6dcb7f06a192d8dcb308d GIT binary patch literal 1888 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 iW8Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 00000000..89c2725b --- /dev/null +++ b/speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/speech_to_text_/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/speech_to_text_/example/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 00000000..f2e259c7 --- /dev/null +++ b/speech_to_text_/example/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/speech_to_text_/example/ios/Runner/Base.lproj/Main.storyboard b/speech_to_text_/example/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 00000000..f3c28516 --- /dev/null +++ b/speech_to_text_/example/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/speech_to_text_/example/ios/Runner/Info.plist b/speech_to_text_/example/ios/Runner/Info.plist new file mode 100644 index 00000000..a69c0fce --- /dev/null +++ b/speech_to_text_/example/ios/Runner/Info.plist @@ -0,0 +1,49 @@ + + + + + NSMicrophoneUsageDescription + This example listens for speech on the device microphone on your request. + NSSpeechRecognitionUsageDescription + This example recognizes words as you speak them and displays them. + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + speech_to_text_example + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/speech_to_text_/example/ios/Runner/Runner-Bridging-Header.h b/speech_to_text_/example/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 00000000..7335fdf9 --- /dev/null +++ b/speech_to_text_/example/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" \ No newline at end of file diff --git a/speech_to_text_/example/lib/main.dart b/speech_to_text_/example/lib/main.dart new file mode 100644 index 00000000..0115b828 --- /dev/null +++ b/speech_to_text_/example/lib/main.dart @@ -0,0 +1,275 @@ +import 'dart:async'; +import 'dart:math'; + +import 'package:flutter/material.dart'; +import 'package:permission_handler/permission_handler.dart'; +import 'package:speech_to_text/speech_recognition_error.dart'; +import 'package:speech_to_text/speech_recognition_result.dart'; +import 'package:speech_to_text/speech_to_text.dart'; + +void main() => runApp(MyApp()); + +class MyApp extends StatefulWidget { + @override + _MyAppState createState() => _MyAppState(); +} + +class _MyAppState extends State { + bool _hasSpeech = false; + double level = 0.0; + double minSoundLevel = 50000; + double maxSoundLevel = -50000; + String lastWords = ""; + String lastError = ""; + String lastStatus = ""; + String _currentLocaleId = ""; + List _localeNames = []; + final SpeechToText speech = SpeechToText(); + + @override + void initState() { + requestPermissions(); + super.initState(); + } + + Future initSpeechState() async { + bool hasSpeech = await speech.initialize( + onError: errorListener, onStatus: statusListener); + if (hasSpeech) { + _localeNames = await speech.locales(); + + var systemLocale = await speech.systemLocale(); + _currentLocaleId = systemLocale.localeId; + } + + if (!mounted) return; + + setState(() { + _hasSpeech = hasSpeech; + }); + } + + void requestPermissions() async{ + Map statuses = await [ + Permission.microphone, + ].request(); + } + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + appBar: AppBar( + title: const Text('Speech to Text CloudSolution'), + ), + body: Column(children: [ + Center( + child: Text( + 'Speech recognition available', + style: TextStyle(fontSize: 22.0), + ), + ), + Container( + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + FlatButton( + child: Text('Initialize'), + onPressed: _hasSpeech ? null : initSpeechState, + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + FlatButton( + child: Text('Start'), + onPressed: !_hasSpeech || speech.isListening + ? null + : startListening, + ), + FlatButton( + child: Text('Stop'), + onPressed: speech.isListening ? stopListening : null, + ), + FlatButton( + child: Text('Cancel'), + onPressed: speech.isListening ? cancelListening : null, + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + DropdownButton( + onChanged: (selectedVal) => _switchLang(selectedVal), + value: _currentLocaleId, + items: _localeNames + .map( + (localeName) => DropdownMenuItem( + value: localeName.localeId, + child: Text(localeName.name), + ), + ) + .toList(), + ), + ], + ) + ], + ), + ), + Expanded( + flex: 4, + child: Column( + children: [ + Center( + child: Text( + 'Recognized Words', + style: TextStyle(fontSize: 22.0), + ), + ), + Expanded( + child: Stack( + children: [ + Container( + color: Theme.of(context).selectedRowColor, + child: Center( + child: Text( + lastWords, + textAlign: TextAlign.center, + ), + ), + ), + Positioned.fill( + bottom: 10, + child: Align( + alignment: Alignment.bottomCenter, + child: Container( + width: 40, + height: 40, + alignment: Alignment.center, + decoration: BoxDecoration( + boxShadow: [ + BoxShadow( + blurRadius: .26, + spreadRadius: level * 1.5, + color: Colors.black.withOpacity(.05)) + ], + color: Colors.white, + borderRadius: + BorderRadius.all(Radius.circular(50)), + ), + child: IconButton(icon: Icon(Icons.mic)), + ), + ), + ), + ], + ), + ), + ], + ), + ), + Expanded( + flex: 1, + child: Column( + children: [ + Center( + child: Text( + 'Error Status', + style: TextStyle(fontSize: 22.0), + ), + ), + Center( + child: Text(lastError), + ), + ], + ), + ), + Container( + padding: EdgeInsets.symmetric(vertical: 20), + color: Theme.of(context).backgroundColor, + child: Center( + child: speech.isListening + ? Text( + "I'm listening...", + style: TextStyle(fontWeight: FontWeight.bold), + ) + : Text( + 'Not listening', + style: TextStyle(fontWeight: FontWeight.bold), + ), + ), + ), + ]), + ), + ); + } + + void startListening() { + lastWords = ""; + lastError = ""; + speech.listen( + onResult: resultListener, + listenFor: Duration(seconds: 10), + localeId: _currentLocaleId, + onSoundLevelChange: soundLevelListener, + cancelOnError: true, + partialResults: true, + onDevice: true, + listenMode: ListenMode.confirmation); + setState(() {}); + } + + void stopListening() { + speech.stop(); + setState(() { + level = 0.0; + }); + } + + void cancelListening() { + speech.cancel(); + setState(() { + level = 0.0; + }); + } + + void resultListener(SpeechRecognitionResult result) { + setState(() { + lastWords = "${result.recognizedWords} - ${result.finalResult}"; + }); + } + + void soundLevelListener(double level) { + minSoundLevel = min(minSoundLevel, level); + maxSoundLevel = max(maxSoundLevel, level); + // print("sound level $level: $minSoundLevel - $maxSoundLevel "); + setState(() { + this.level = level; + }); + } + + void errorListener(SpeechRecognitionError error) { + // print("Received error status: $error, listening: ${speech.isListening}"); + setState(() { + lastError = "${error.errorMsg} - ${error.permanent}"; + }); + } + + void statusListener(String status) { + // print( + // "Received listener status: $status, listening: ${speech.isListening}"); + setState(() { + lastStatus = "$status"; + }); + } + + _switchLang(selectedVal) { + setState(() { + _currentLocaleId = selectedVal; + }); + print(selectedVal); + } +} diff --git a/speech_to_text_/example/pubspec.yaml b/speech_to_text_/example/pubspec.yaml new file mode 100644 index 00000000..d2bfcff7 --- /dev/null +++ b/speech_to_text_/example/pubspec.yaml @@ -0,0 +1,33 @@ +name: speech_to_text_example +description: Demonstrates how to use the speech_to_text plugin. +version: 1.1.0 +publish_to: 'none' + +environment: + sdk: ">=2.1.0 <3.0.0" + +dependencies: + flutter: + sdk: flutter + + cupertino_icons: ^0.1.2 + permission_handler: ^5.0.1+1 + + provider: + +dev_dependencies: + flutter_test: + sdk: flutter + + speech_to_text: + path: ../ + +# The following section is specific to Flutter. +flutter: + + uses-material-design: true + + assets: + - assets/sounds/speech_to_text_listening.m4r + - assets/sounds/speech_to_text_cancel.m4r + - assets/sounds/speech_to_text_stop.m4r diff --git a/speech_to_text_/example/test/widget_test.dart b/speech_to_text_/example/test/widget_test.dart new file mode 100644 index 00000000..639a52fb --- /dev/null +++ b/speech_to_text_/example/test/widget_test.dart @@ -0,0 +1,27 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility that Flutter provides. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../lib/main.dart'; + +void main() { + testWidgets('Verify Platform version', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(MyApp()); + + // Verify that platform version is retrieved. + expect( + find.byWidgetPredicate( + (Widget widget) => + widget is Text && widget.data.startsWith('Running on:'), + ), + findsOneWidget, + ); + }); +} diff --git a/speech_to_text_/ios/.gitignore b/speech_to_text_/ios/.gitignore new file mode 100644 index 00000000..aa479fd3 --- /dev/null +++ b/speech_to_text_/ios/.gitignore @@ -0,0 +1,37 @@ +.idea/ +.vagrant/ +.sconsign.dblite +.svn/ + +.DS_Store +*.swp +profile + +DerivedData/ +build/ +GeneratedPluginRegistrant.h +GeneratedPluginRegistrant.m + +.generated/ + +*.pbxuser +*.mode1v3 +*.mode2v3 +*.perspectivev3 + +!default.pbxuser +!default.mode1v3 +!default.mode2v3 +!default.perspectivev3 + +xcuserdata + +*.moved-aside + +*.pyc +*sync/ +Icon? +.tags* + +/Flutter/Generated.xcconfig +/Flutter/flutter_export_environment.sh \ No newline at end of file diff --git a/speech_to_text_/ios/Assets/.gitkeep b/speech_to_text_/ios/Assets/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/speech_to_text_/ios/Classes/SpeechToTextPlugin.h b/speech_to_text_/ios/Classes/SpeechToTextPlugin.h new file mode 100644 index 00000000..1785eb8f --- /dev/null +++ b/speech_to_text_/ios/Classes/SpeechToTextPlugin.h @@ -0,0 +1,4 @@ +#import + +@interface SpeechToTextPlugin : NSObject +@end diff --git a/speech_to_text_/ios/Classes/SpeechToTextPlugin.m b/speech_to_text_/ios/Classes/SpeechToTextPlugin.m new file mode 100644 index 00000000..20d0327d --- /dev/null +++ b/speech_to_text_/ios/Classes/SpeechToTextPlugin.m @@ -0,0 +1,8 @@ +#import "SpeechToTextPlugin.h" +#import + +@implementation SpeechToTextPlugin ++ (void)registerWithRegistrar:(NSObject*)registrar { + [SwiftSpeechToTextPlugin registerWithRegistrar:registrar]; +} +@end diff --git a/speech_to_text_/ios/Classes/SwiftSpeechToTextPlugin.swift b/speech_to_text_/ios/Classes/SwiftSpeechToTextPlugin.swift new file mode 100644 index 00000000..68687967 --- /dev/null +++ b/speech_to_text_/ios/Classes/SwiftSpeechToTextPlugin.swift @@ -0,0 +1,580 @@ +import Flutter +import UIKit +import Speech +import os.log +import Try + +public enum SwiftSpeechToTextMethods: String { + case has_permission + case initialize + case listen + case stop + case cancel + case locales + case unknown // just for testing +} + +public enum SwiftSpeechToTextCallbackMethods: String { + case textRecognition + case notifyStatus + case notifyError + case soundLevelChange +} + +public enum SpeechToTextStatus: String { + case listening + case notListening + case unavailable + case available +} + +public enum SpeechToTextErrors: String { + case onDeviceError + case noRecognizerError + case listenFailedError + case missingOrInvalidArg +} + +public enum ListenMode: Int { + case deviceDefault = 0 + case dictation = 1 + case search = 2 + case confirmation = 3 +} + +struct SpeechRecognitionWords : Codable { + let recognizedWords: String + let confidence: Decimal +} + +struct SpeechRecognitionResult : Codable { + let alternates: [SpeechRecognitionWords] + let finalResult: Bool +} + +struct SpeechRecognitionError : Codable { + let errorMsg: String + let permanent: Bool +} + +enum SpeechToTextError: Error { + case runtimeError(String) +} + + +@available(iOS 10.0, *) +public class SwiftSpeechToTextPlugin: NSObject, FlutterPlugin { + private var channel: FlutterMethodChannel + private var registrar: FlutterPluginRegistrar + private var recognizer: SFSpeechRecognizer? + private var currentRequest: SFSpeechAudioBufferRecognitionRequest? + private var currentTask: SFSpeechRecognitionTask? + private var listeningSound: AVAudioPlayer? + private var successSound: AVAudioPlayer? + private var cancelSound: AVAudioPlayer? + private var rememberedAudioCategory: AVAudioSession.Category? + private var previousLocale: Locale? + private var onPlayEnd: (() -> Void)? + private var returnPartialResults: Bool = true + private var failedListen: Bool = false + private var listening = false + private let audioSession = AVAudioSession.sharedInstance() + private let audioEngine = AVAudioEngine() + private let jsonEncoder = JSONEncoder() + private let busForNodeTap = 0 + private let speechBufferSize: AVAudioFrameCount = 1024 + private static var subsystem = Bundle.main.bundleIdentifier! + private let pluginLog = OSLog(subsystem: "com.csdcorp.speechToText", category: "plugin") + + public static func register(with registrar: FlutterPluginRegistrar) { + let channel = FlutterMethodChannel(name: "plugin.csdcorp.com/speech_to_text", binaryMessenger: registrar.messenger()) + let instance = SwiftSpeechToTextPlugin( channel, registrar: registrar ) + registrar.addMethodCallDelegate(instance, channel: channel ) + } + + init( _ channel: FlutterMethodChannel, registrar: FlutterPluginRegistrar ) { + self.channel = channel + self.registrar = registrar + } + + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + switch call.method { + case SwiftSpeechToTextMethods.has_permission.rawValue: + hasPermission( result ) + case SwiftSpeechToTextMethods.initialize.rawValue: + initialize( result ) + case SwiftSpeechToTextMethods.listen.rawValue: + guard let argsArr = call.arguments as? Dictionary, + let partialResults = argsArr["partialResults"] as? Bool, let onDevice = argsArr["onDevice"] as? Bool, let listenModeIndex = argsArr["listenMode"] as? Int + else { + DispatchQueue.main.async { + result(FlutterError( code: SpeechToTextErrors.missingOrInvalidArg.rawValue, + message:"Missing arg partialResults, onDevice, and listenMode are required", + details: nil )) + } + return + } + var localeStr: String? = nil + if let localeParam = argsArr["localeId"] as? String { + localeStr = localeParam + } + guard let listenMode = ListenMode(rawValue: listenModeIndex) else { + DispatchQueue.main.async { + result(FlutterError( code: SpeechToTextErrors.missingOrInvalidArg.rawValue, + message:"invalid value for listenMode, must be 0-2, was \(listenModeIndex)", + details: nil )) + } + return + } + + listenForSpeech( result, localeStr: localeStr, partialResults: partialResults, onDevice: onDevice, listenMode: listenMode ) + case SwiftSpeechToTextMethods.stop.rawValue: + stopSpeech( result ) + case SwiftSpeechToTextMethods.cancel.rawValue: + cancelSpeech( result ) + case SwiftSpeechToTextMethods.locales.rawValue: + locales( result ) + default: + os_log("Unrecognized method: %{PUBLIC}@", log: pluginLog, type: .error, call.method) + DispatchQueue.main.async { + result( FlutterMethodNotImplemented) + } + } + } + + private func hasPermission( _ result: @escaping FlutterResult) { + let has = SFSpeechRecognizer.authorizationStatus() == SFSpeechRecognizerAuthorizationStatus.authorized && + AVAudioSession.sharedInstance().recordPermission == AVAudioSession.RecordPermission.granted + DispatchQueue.main.async { + result( has ) + } + } + + private func initialize( _ result: @escaping FlutterResult) { + var success = false + let status = SFSpeechRecognizer.authorizationStatus() + switch status { + case SFSpeechRecognizerAuthorizationStatus.notDetermined: + SFSpeechRecognizer.requestAuthorization({(status)->Void in + success = status == SFSpeechRecognizerAuthorizationStatus.authorized + if ( success ) { + AVAudioSession.sharedInstance().requestRecordPermission({(granted: Bool)-> Void in + if granted { + self.setupSpeechRecognition(result) + } else{ + self.sendBoolResult( false, result ); + os_log("User denied permission", log: self.pluginLog, type: .info) + } + }) + } + else { + self.sendBoolResult( false, result ); + } + }); + case SFSpeechRecognizerAuthorizationStatus.denied: + os_log("Permission permanently denied", log: self.pluginLog, type: .info) + sendBoolResult( false, result ); + case SFSpeechRecognizerAuthorizationStatus.restricted: + os_log("Device restriction prevented initialize", log: self.pluginLog, type: .info) + sendBoolResult( false, result ); + default: + os_log("Has permissions continuing with setup", log: self.pluginLog, type: .debug) + setupSpeechRecognition(result) + } + } + + fileprivate func sendBoolResult( _ value: Bool, _ result: @escaping FlutterResult) { + DispatchQueue.main.async { + result( value ) + } + } + + fileprivate func setupListeningSound() { + listeningSound = loadSound("assets/sounds/speech_to_text_listening.m4r") + successSound = loadSound("assets/sounds/speech_to_text_stop.m4r") + cancelSound = loadSound("assets/sounds/speech_to_text_cancel.m4r") + } + + fileprivate func loadSound( _ assetPath: String ) -> AVAudioPlayer? { + var player: AVAudioPlayer? = nil + let soundKey = registrar.lookupKey(forAsset: assetPath ) + guard !soundKey.isEmpty else { + return player + } + if let soundPath = Bundle.main.path(forResource: soundKey, ofType:nil) { + let soundUrl = URL(fileURLWithPath: soundPath ) + do { + player = try AVAudioPlayer(contentsOf: soundUrl ) + player?.delegate = self + } catch { + // no audio + } + } + return player + } + + private func setupSpeechRecognition( _ result: @escaping FlutterResult) { + setupRecognizerForLocale( locale: Locale.current ) + guard recognizer != nil else { + sendBoolResult( false, result ); + return + } + recognizer?.delegate = self + setupListeningSound() + + sendBoolResult( true, result ); + } + + private func setupRecognizerForLocale( locale: Locale ) { + if ( previousLocale == locale ) { + return + } + previousLocale = locale + recognizer = SFSpeechRecognizer( locale: locale ) + } + + private func getLocale( _ localeStr: String? ) -> Locale { + guard let aLocaleStr = localeStr else { + return Locale.current + } + let locale = Locale(identifier: aLocaleStr) + return locale + } + + private func stopSpeech( _ result: @escaping FlutterResult) { + if ( !listening ) { + sendBoolResult( false, result ); + return + } + stopAllPlayers() + if let sound = successSound { + onPlayEnd = {() -> Void in + self.currentTask?.finish() + self.stopCurrentListen( ) + self.sendBoolResult( true, result ) + return + } + sound.play() + } + else { + stopCurrentListen( ) + sendBoolResult( true, result ); + } + } + + private func cancelSpeech( _ result: @escaping FlutterResult) { + if ( !listening ) { + sendBoolResult( false, result ); + return + } + stopAllPlayers() + if let sound = cancelSound { + onPlayEnd = {() -> Void in + self.currentTask?.cancel() + self.stopCurrentListen( ) + self.sendBoolResult( true, result ) + return + } + sound.play() + } + else { + self.currentTask?.cancel() + stopCurrentListen( ) + sendBoolResult( true, result ); + } + } + + private func stopAllPlayers() { + cancelSound?.stop() + successSound?.stop() + listeningSound?.stop() + } + + private func stopCurrentListen( ) { + stopAllPlayers() + currentRequest?.endAudio() + + do { + try trap { + self.audioEngine.stop() + } + } + catch { + os_log("Error stopping engine: %{PUBLIC}@", log: pluginLog, type: .error, error.localizedDescription) + } + do { + try trap { + let inputNode = self.audioEngine.inputNode + inputNode.removeTap(onBus: self.busForNodeTap); + } + } + catch { + os_log("Error removing trap: %{PUBLIC}@", log: pluginLog, type: .error, error.localizedDescription) + } + do { + if let rememberedAudioCategory = rememberedAudioCategory { + try self.audioSession.setCategory(rememberedAudioCategory) + } + } + catch { + os_log("Error stopping listen: %{PUBLIC}@", log: pluginLog, type: .error, error.localizedDescription) + } + do { + try self.audioSession.setActive(false, options: .notifyOthersOnDeactivation) + } + catch { + os_log("Error deactivation: %{PUBLIC}@", log: pluginLog, type: .info, error.localizedDescription) + } + currentRequest = nil + currentTask = nil + onPlayEnd = nil + listening = false + } + + private func listenForSpeech( _ result: @escaping FlutterResult, localeStr: String?, partialResults: Bool, onDevice: Bool, listenMode: ListenMode ) { + if ( nil != currentTask || listening ) { + sendBoolResult( false, result ); + return + } + do { + // let inErrorTest = true + failedListen = false + returnPartialResults = partialResults + setupRecognizerForLocale(locale: getLocale(localeStr)) + guard let localRecognizer = recognizer else { + result(FlutterError( code: SpeechToTextErrors.noRecognizerError.rawValue, + message:"Failed to create speech recognizer", + details: nil )) + return + } + if ( onDevice ) { + if #available(iOS 13.0, *), !localRecognizer.supportsOnDeviceRecognition { + result(FlutterError( code: SpeechToTextErrors.onDeviceError.rawValue, + message:"on device recognition is not supported on this device", + details: nil )) + } + } + rememberedAudioCategory = self.audioSession.category + try self.audioSession.setCategory(AVAudioSession.Category.playAndRecord, options: .defaultToSpeaker) + // try self.audioSession.setMode(AVAudioSession.Mode.measurement) + try self.audioSession.setMode(AVAudioSession.Mode.default) + try self.audioSession.setActive(true, options: .notifyOthersOnDeactivation) + if let sound = listeningSound { + self.onPlayEnd = {()->Void in + if ( !self.failedListen ) { + self.listening = true + self.invokeFlutter( SwiftSpeechToTextCallbackMethods.notifyStatus, arguments: SpeechToTextStatus.listening.rawValue ) + + } + } + sound.play() + } + self.audioEngine.reset(); + let inputNode = self.audioEngine.inputNode + if(inputNode.inputFormat(forBus: 0).channelCount == 0){ + throw SpeechToTextError.runtimeError("Not enough available inputs.") + } + self.currentRequest = SFSpeechAudioBufferRecognitionRequest() + guard let currentRequest = self.currentRequest else { + sendBoolResult( false, result ); + return + } + currentRequest.shouldReportPartialResults = true + if #available(iOS 13.0, *), onDevice { + currentRequest.requiresOnDeviceRecognition = true + } + switch listenMode { + case ListenMode.dictation: + currentRequest.taskHint = SFSpeechRecognitionTaskHint.dictation + break + case ListenMode.search: + currentRequest.taskHint = SFSpeechRecognitionTaskHint.search + break + case ListenMode.confirmation: + currentRequest.taskHint = SFSpeechRecognitionTaskHint.confirmation + break + default: + break + } + self.currentTask = self.recognizer?.recognitionTask(with: currentRequest, delegate: self ) + let recordingFormat = inputNode.outputFormat(forBus: self.busForNodeTap) + try trap { + inputNode.installTap(onBus: self.busForNodeTap, bufferSize: self.speechBufferSize, format: recordingFormat) { (buffer: AVAudioPCMBuffer, when: AVAudioTime) in + currentRequest.append(buffer) + self.updateSoundLevel( buffer: buffer ) + } + } + // if ( inErrorTest ){ + // throw SpeechToTextError.runtimeError("for testing only") + // } + self.audioEngine.prepare() + try self.audioEngine.start() + if nil == listeningSound { + listening = true + self.invokeFlutter( SwiftSpeechToTextCallbackMethods.notifyStatus, arguments: SpeechToTextStatus.listening.rawValue ) + } + sendBoolResult( true, result ); + } + catch { + failedListen = true + os_log("Error starting listen: %{PUBLIC}@", log: pluginLog, type: .error, error.localizedDescription) + stopCurrentListen() + sendBoolResult( false, result ); + invokeFlutter( SwiftSpeechToTextCallbackMethods.notifyStatus, arguments: SpeechToTextStatus.notListening.rawValue ) + let speechError = SpeechRecognitionError(errorMsg: "error_listen_failed", permanent: true ) + do { + let errorResult = try jsonEncoder.encode(speechError) + invokeFlutter( SwiftSpeechToTextCallbackMethods.notifyError, arguments: String( data:errorResult, encoding: .utf8) ) + } catch { + os_log("Could not encode JSON", log: pluginLog, type: .error) + } + } + } + + private func updateSoundLevel( buffer: AVAudioPCMBuffer) { + guard + let channelData = buffer.floatChannelData + else { + return + } + + let channelDataValue = channelData.pointee + let channelDataValueArray = stride(from: 0, + to: Int(buffer.frameLength), + by: buffer.stride).map{ channelDataValue[$0] } + let frameLength = Float(buffer.frameLength) + let rms = sqrt(channelDataValueArray.map{ $0 * $0 }.reduce(0, +) / frameLength ) + let avgPower = 20 * log10(rms) + self.invokeFlutter( SwiftSpeechToTextCallbackMethods.soundLevelChange, arguments: avgPower ) + } + + /// Build a list of localId:name with the current locale first + private func locales( _ result: @escaping FlutterResult ) { + var localeNames = [String](); + let locales = SFSpeechRecognizer.supportedLocales(); + let currentLocale = Locale.current + if let idName = buildIdNameForLocale(forIdentifier: currentLocale.identifier ) { + localeNames.append(idName) + } + for locale in locales { + if ( locale.identifier == currentLocale.identifier) { + continue + } + if let idName = buildIdNameForLocale(forIdentifier: locale.identifier ) { + localeNames.append(idName) + } + } + DispatchQueue.main.async { + result(localeNames) + } + } + + private func buildIdNameForLocale( forIdentifier: String ) -> String? { + var idName: String? + if let name = Locale.current.localizedString(forIdentifier: forIdentifier ) { + let sanitizedName = name.replacingOccurrences(of: ":", with: " ") + idName = "\(forIdentifier):\(sanitizedName)" + } + return idName + } + + private func handleResult( _ transcriptions: [SFTranscription], isFinal: Bool ) { + if ( !isFinal && !returnPartialResults ) { + return + } + var speechWords: [SpeechRecognitionWords] = [] + for transcription in transcriptions { + let words: SpeechRecognitionWords = SpeechRecognitionWords(recognizedWords: transcription.formattedString, confidence: confidenceIn( transcription)) + speechWords.append( words ) + } + let speechInfo = SpeechRecognitionResult(alternates: speechWords, finalResult: isFinal ) + do { + let speechMsg = try jsonEncoder.encode(speechInfo) + if let speechStr = String( data:speechMsg, encoding: .utf8) { + os_log("Encoded JSON result: %{PUBLIC}@", log: pluginLog, type: .debug, speechStr ) + invokeFlutter( SwiftSpeechToTextCallbackMethods.textRecognition, arguments: speechStr ) + } + } catch { + os_log("Could not encode JSON", log: pluginLog, type: .error) + } + } + + private func confidenceIn( _ transcription: SFTranscription ) -> Decimal { + guard ( transcription.segments.count > 0 ) else { + return 0; + } + var totalConfidence: Float = 0.0; + for segment in transcription.segments { + totalConfidence += segment.confidence + } + let avgConfidence: Float = totalConfidence / Float(transcription.segments.count ) + let confidence: Float = (avgConfidence * 1000).rounded() / 1000 + return Decimal( string: String( describing: confidence ) )! + } + + private func invokeFlutter( _ method: SwiftSpeechToTextCallbackMethods, arguments: Any? ) { + DispatchQueue.main.async { + self.channel.invokeMethod( method.rawValue, arguments: arguments ) + } + } + +} + +@available(iOS 10.0, *) +extension SwiftSpeechToTextPlugin : SFSpeechRecognizerDelegate { + public func speechRecognizer(_ speechRecognizer: SFSpeechRecognizer, availabilityDidChange available: Bool) { + let availability = available ? SpeechToTextStatus.available.rawValue : SpeechToTextStatus.unavailable.rawValue + os_log("Availability changed: %{PUBLIC}@", log: pluginLog, type: .debug, availability) + invokeFlutter( SwiftSpeechToTextCallbackMethods.notifyStatus, arguments: availability ) + } +} + +@available(iOS 10.0, *) +extension SwiftSpeechToTextPlugin : SFSpeechRecognitionTaskDelegate { + public func speechRecognitionDidDetectSpeech(_ task: SFSpeechRecognitionTask) { + // Do nothing for now + } + + public func speechRecognitionTaskFinishedReadingAudio(_ task: SFSpeechRecognitionTask) { + reportError(source: "FinishedReadingAudio", error: task.error) + invokeFlutter( SwiftSpeechToTextCallbackMethods.notifyStatus, arguments: SpeechToTextStatus.notListening.rawValue ) + } + + public func speechRecognitionTaskWasCancelled(_ task: SFSpeechRecognitionTask) { + reportError(source: "TaskWasCancelled", error: task.error) + invokeFlutter( SwiftSpeechToTextCallbackMethods.notifyStatus, arguments: SpeechToTextStatus.notListening.rawValue ) + } + + public func speechRecognitionTask(_ task: SFSpeechRecognitionTask, didFinishSuccessfully successfully: Bool) { + reportError(source: "FinishSuccessfully", error: task.error) + stopCurrentListen( ) + } + + public func speechRecognitionTask(_ task: SFSpeechRecognitionTask, didHypothesizeTranscription transcription: SFTranscription) { + reportError(source: "HypothesizeTranscription", error: task.error) + handleResult( [transcription], isFinal: false ) + } + + public func speechRecognitionTask(_ task: SFSpeechRecognitionTask, didFinishRecognition recognitionResult: SFSpeechRecognitionResult) { + reportError(source: "FinishRecognition", error: task.error) + let isFinal = recognitionResult.isFinal + handleResult( recognitionResult.transcriptions, isFinal: isFinal ) + } + + private func reportError( source: String, error: Error?) { + if ( nil != error) { + os_log("%{PUBLIC}@ with error: %{PUBLIC}@", log: pluginLog, type: .debug, source, error.debugDescription) + } + } +} + +@available(iOS 10.0, *) +extension SwiftSpeechToTextPlugin : AVAudioPlayerDelegate { + + public func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, + successfully flag: Bool) { + if let playEnd = self.onPlayEnd { + playEnd() + } + } +} diff --git a/speech_to_text_/ios/speech_to_text.podspec b/speech_to_text_/ios/speech_to_text.podspec new file mode 100644 index 00000000..1db79aa0 --- /dev/null +++ b/speech_to_text_/ios/speech_to_text.podspec @@ -0,0 +1,22 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html +# +Pod::Spec.new do |s| + s.name = 'speech_to_text' + s.version = '0.0.1' + s.summary = 'A new flutter plugin project.' + s.description = <<-DESC +A new flutter plugin project. + DESC + s.homepage = 'http://example.com' + s.license = { :file => '../LICENSE' } + s.author = { 'Your Company' => 'email@example.com' } + s.source = { :path => '.' } + s.source_files = 'Classes/**/*' + s.public_header_files = 'Classes/**/*.h' + s.dependency 'Flutter' + s.dependency 'Try' + + s.ios.deployment_target = '8.0' +end + diff --git a/speech_to_text_/lib/speech_recognition_error.dart b/speech_to_text_/lib/speech_recognition_error.dart new file mode 100644 index 00000000..2ab6cd4d --- /dev/null +++ b/speech_to_text_/lib/speech_recognition_error.dart @@ -0,0 +1,44 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'speech_recognition_error.g.dart'; + +/// A single error returned from the underlying speech services. +/// +/// Errors are either transient or permanent. Permanent errors +/// block speech recognition from continuing and must be +/// addressed before recogntion will work. Transient errors +/// cause individual recognition sessions to fail but subsequent +/// attempts may well succeed. +@JsonSerializable() +class SpeechRecognitionError { + /// Use this to differentiate the various error conditions. + /// + /// Not meant for display to the user. + final String errorMsg; + + /// True means that recognition cannot continue until + /// the error is resolved. + final bool permanent; + + SpeechRecognitionError(this.errorMsg, this.permanent); + + factory SpeechRecognitionError.fromJson(Map json) => + _$SpeechRecognitionErrorFromJson(json); + Map toJson() => _$SpeechRecognitionErrorToJson(this); + + @override + String toString() { + return "SpeechRecognitionError msg: $errorMsg, permanent: $permanent"; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + other is SpeechRecognitionError && + errorMsg == other.errorMsg && + permanent == other.permanent; + } + + @override + int get hashCode => errorMsg.hashCode; +} diff --git a/speech_to_text_/lib/speech_recognition_error.g.dart b/speech_to_text_/lib/speech_recognition_error.g.dart new file mode 100644 index 00000000..65299f6d --- /dev/null +++ b/speech_to_text_/lib/speech_recognition_error.g.dart @@ -0,0 +1,22 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'speech_recognition_error.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +SpeechRecognitionError _$SpeechRecognitionErrorFromJson( + Map json) { + return SpeechRecognitionError( + json['errorMsg'] as String, + json['permanent'] as bool, + ); +} + +Map _$SpeechRecognitionErrorToJson( + SpeechRecognitionError instance) => + { + 'errorMsg': instance.errorMsg, + 'permanent': instance.permanent, + }; diff --git a/speech_to_text_/lib/speech_recognition_event.dart b/speech_to_text_/lib/speech_recognition_event.dart new file mode 100644 index 00000000..71729365 --- /dev/null +++ b/speech_to_text_/lib/speech_recognition_event.dart @@ -0,0 +1,30 @@ +import 'package:speech_to_text/speech_recognition_error.dart'; +import 'package:speech_to_text/speech_recognition_result.dart'; + +enum SpeechRecognitionEventType { + finalRecognitionEvent, + partialRecognitionEvent, + errorEvent, + statusChangeEvent, + soundLevelChangeEvent, +} + +/// A single event in a stream of speech recognition events. +/// +/// Use [eventType] to determine what type of event it is and depending on that +/// use the other properties to get information about it. +class SpeechRecognitionEvent { + final SpeechRecognitionEventType eventType; + final SpeechRecognitionError _error; + final SpeechRecognitionResult _result; + final bool _listening; + final double _level; + + SpeechRecognitionEvent( + this.eventType, this._result, this._error, this._listening, this._level); + + bool get isListening => _listening; + double get level => _level; + SpeechRecognitionResult get recognitionResult => _result; + SpeechRecognitionError get error => _error; +} diff --git a/speech_to_text_/lib/speech_recognition_result.dart b/speech_to_text_/lib/speech_recognition_result.dart new file mode 100644 index 00000000..38509f65 --- /dev/null +++ b/speech_to_text_/lib/speech_recognition_result.dart @@ -0,0 +1,140 @@ +import 'dart:collection'; + +import 'package:json_annotation/json_annotation.dart'; + +part 'speech_recognition_result.g.dart'; + +/// A sequence of recognized words from the speech recognition +/// service. +/// +/// Depending on the platform behaviour the words may come in all +/// at once at the end or as partial results as each word is +/// recognized. Use the [finalResult] flag to determine if the +/// result is considered final by the platform. +@JsonSerializable(explicitToJson: true) +class SpeechRecognitionResult { + List _alternates; + + /// Returns a list of possible transcriptions of the speech. + /// + /// The first value is always the same as the [recognizedWords] + /// value. Use the confidence for each alternate transcription + /// to determine how likely it is. Note that not all platforms + /// do a good job with confidence, there are convenience methods + /// on [SpeechRecogntionWords] to work with possibly missing + /// confidence values. + List get alternates => + UnmodifiableListView(_alternates); + + /// The sequence of words that is the best transcription of + /// what was said. + /// + /// This is the same as the first value of [alternates]. + String get recognizedWords => + _alternates.isNotEmpty ? _alternates.first.recognizedWords : ""; + + /// False means the words are an interim result, true means + /// they are the final recognition. + final bool finalResult; + + /// The confidence that the [recognizedWords] are correct. + /// + /// Confidence is expressed as a value between 0 and 1. -1 + /// means that the confidence value was not available. + double get confidence => + _alternates.isNotEmpty ? _alternates.first.confidence : 0; + + /// true if there is confidence in this recognition, false otherwise. + /// + /// There are two separate ways for there to be confidence, the first + /// is if the confidence is missing, which is indicated by a value of + /// -1. The second is if the confidence is greater than or equal + /// [threshold]. If [threshold] is not provided it defaults to 0.8. + bool isConfident( + {double threshold = SpeechRecognitionWords.confidenceThreshold}) => + _alternates.isNotEmpty + ? _alternates.first.isConfident(threshold: threshold) + : false; + + /// true if [confidence] is not the [missingConfidence] value, false + /// otherwise. + bool get hasConfidenceRating => + _alternates.isNotEmpty ? _alternates.first.hasConfidenceRating : false; + + SpeechRecognitionResult(this._alternates, this.finalResult); + + @override + String toString() { + return "SpeechRecognitionResult words: $_alternates, final: $finalResult"; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + other is SpeechRecognitionResult && + recognizedWords == other.recognizedWords && + finalResult == other.finalResult; + } + + @override + int get hashCode => recognizedWords.hashCode; + + factory SpeechRecognitionResult.fromJson(Map json) => + _$SpeechRecognitionResultFromJson(json); + Map toJson() => _$SpeechRecognitionResultToJson(this); +} + +/// A set of words recognized in a [SpeechRecognitionResult]. +/// +/// Each result will have one or more [SpeechRecognitionWords] +/// with a varying degree of confidence about each set of words. +@JsonSerializable() +class SpeechRecognitionWords { + /// The sequence of words recognized + final String recognizedWords; + + /// The confidence that the [recognizedWords] are correct. + /// + /// Confidence is expressed as a value between 0 and 1. 0 + /// means that the confidence value was not available. Use + /// [isConfident] which will ignore 0 values automatically. + final double confidence; + + static const double confidenceThreshold = 0.8; + static const double missingConfidence = -1; + + const SpeechRecognitionWords(this.recognizedWords, this.confidence); + + /// true if there is confidence in this recognition, false otherwise. + /// + /// There are two separate ways for there to be confidence, the first + /// is if the confidence is missing, which is indicated by a value of + /// -1. The second is if the confidence is greater than or equal + /// [threshold]. If [threshold] is not provided it defaults to 0.8. + bool isConfident({double threshold = confidenceThreshold}) => + confidence == missingConfidence || confidence >= threshold; + + /// true if [confidence] is not the [missingConfidence] value, false + /// otherwise. + bool get hasConfidenceRating => confidence != missingConfidence; + + @override + String toString() { + return "SpeechRecognitionWords words: $recognizedWords, confidence: $confidence"; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + other is SpeechRecognitionWords && + recognizedWords == other.recognizedWords && + confidence == other.confidence; + } + + @override + int get hashCode => recognizedWords.hashCode; + + factory SpeechRecognitionWords.fromJson(Map json) => + _$SpeechRecognitionWordsFromJson(json); + Map toJson() => _$SpeechRecognitionWordsToJson(this); +} diff --git a/speech_to_text_/lib/speech_recognition_result.g.dart b/speech_to_text_/lib/speech_recognition_result.g.dart new file mode 100644 index 00000000..023e5485 --- /dev/null +++ b/speech_to_text_/lib/speech_recognition_result.g.dart @@ -0,0 +1,41 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'speech_recognition_result.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +SpeechRecognitionResult _$SpeechRecognitionResultFromJson( + Map json) { + return SpeechRecognitionResult( + (json['alternates'] as List) + ?.map((e) => e == null + ? null + : SpeechRecognitionWords.fromJson(e as Map)) + ?.toList(), + json['finalResult'] as bool, + ); +} + +Map _$SpeechRecognitionResultToJson( + SpeechRecognitionResult instance) => + { + 'alternates': instance.alternates?.map((e) => e?.toJson())?.toList(), + 'finalResult': instance.finalResult, + }; + +SpeechRecognitionWords _$SpeechRecognitionWordsFromJson( + Map json) { + return SpeechRecognitionWords( + json['recognizedWords'] as String, + (json['confidence'] as num)?.toDouble(), + ); +} + +Map _$SpeechRecognitionWordsToJson( + SpeechRecognitionWords instance) => + { + 'recognizedWords': instance.recognizedWords, + 'confidence': instance.confidence, + }; diff --git a/speech_to_text_/lib/speech_to_text.dart b/speech_to_text_/lib/speech_to_text.dart new file mode 100644 index 00000000..343706e6 --- /dev/null +++ b/speech_to_text_/lib/speech_to_text.dart @@ -0,0 +1,511 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:math'; + +import 'package:clock/clock.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; +import 'package:speech_to_text/speech_recognition_error.dart'; +import 'package:speech_to_text/speech_recognition_result.dart'; + +enum ListenMode { + deviceDefault, + dictation, + search, + confirmation, +} + +/// Notified as words are recognized with the current set of recognized words. +/// +/// See the [onResult] argument on the [listen] method for use. +typedef SpeechResultListener = void Function(SpeechRecognitionResult result); + +/// Notified if errors occur during recognition or intialization. +/// +/// Possible errors per the Android docs are described here: +/// https://developer.android.com/reference/android/speech/SpeechRecognizer +/// "error_audio_error" +/// "error_client" +/// "error_permission" +/// "error_network" +/// "error_network_timeout" +/// "error_no_match" +/// "error_busy" +/// "error_server" +/// "error_speech_timeout" +/// See the [onError] argument on the [initialize] method for use. +typedef SpeechErrorListener = void Function( + SpeechRecognitionError errorNotification); + +/// Notified when recognition status changes. +/// +/// See the [onStatus] argument on the [initialize] method for use. +typedef SpeechStatusListener = void Function(String status); + +/// Notified when the sound level changes during a listen method. +/// +/// [level] is a measure of the decibels of the current sound on +/// the recognition input. See the [onSoundLevelChange] argument on +/// the [listen] method for use. +typedef SpeechSoundLevelChange = Function(double level); + +/// An interface to device specific speech recognition services. +/// +/// The general flow of a speech recognition session is as follows: +/// ```Dart +/// SpeechToText speech = SpeechToText(); +/// bool isReady = await speech.initialize(); +/// if ( isReady ) { +/// await speech.listen( resultListener: resultListener ); +/// } +/// ... +/// // At some point later +/// speech.stop(); +/// ``` +class SpeechToText { + static const String listenMethod = 'listen'; + static const String textRecognitionMethod = 'textRecognition'; + static const String notifyErrorMethod = 'notifyError'; + static const String notifyStatusMethod = 'notifyStatus'; + static const String soundLevelChangeMethod = "soundLevelChange"; + static const String notListeningStatus = "notListening"; + static const String listeningStatus = "listening"; + + static const MethodChannel speechChannel = + const MethodChannel('plugin.csdcorp.com/speech_to_text'); + static final SpeechToText _instance = + SpeechToText.withMethodChannel(speechChannel); + bool _initWorked = false; + bool _recognized = false; + bool _listening = false; + bool _cancelOnError = false; + bool _partialResults = false; + int _listenStartedAt = 0; + int _lastSpeechEventAt = 0; + Duration _pauseFor; + Duration _listenFor; + + /// True if not listening or the user called cancel / stop, false + /// if cancel/stop were invoked by timeout or error condition. + bool _userEnded = false; + String _lastRecognized = ""; + String _lastStatus = ""; + double _lastSoundLevel = 0; + Timer _listenTimer; + LocaleName _systemLocale; + SpeechRecognitionError _lastError; + SpeechResultListener _resultListener; + SpeechErrorListener errorListener; + SpeechStatusListener statusListener; + SpeechSoundLevelChange _soundLevelChange; + + final MethodChannel channel; + factory SpeechToText() => _instance; + + @visibleForTesting + SpeechToText.withMethodChannel(this.channel); + + /// True if words have been recognized during the current [listen] call. + /// + /// Goes false as soon as [cancel] is called. + bool get hasRecognized => _recognized; + + /// The last set of recognized words received. + /// + /// This is maintained across [cancel] calls but cleared on the next + /// [listen]. + String get lastRecognizedWords => _lastRecognized; + + /// The last status update received, see [initialize] to register + /// an optional listener to be notified when this changes. + String get lastStatus => _lastStatus; + + /// The last sound level received during a listen event. + /// + /// The sound level is a measure of how loud the current + /// input is during listening. Use the [onSoundLevelChange] + /// argument in the [listen] method to get notified of + /// changes. + double get lastSoundLevel => _lastSoundLevel; + + /// True if [initialize] succeeded + bool get isAvailable => _initWorked; + + /// True if [listen] succeeded and [stop] or [cancel] has not been called. + /// + /// Also goes false when listening times out if listenFor was set. + bool get isListening => _listening; + bool get isNotListening => !isListening; + + /// The last error received or null if none, see [initialize] to + /// register an optional listener to be notified of errors. + SpeechRecognitionError get lastError => _lastError; + + /// True if an error has been received, see [lastError] for details + bool get hasError => null != lastError; + + /// Returns true if the user has already granted permission to access the + /// microphone, does not prompt the user. + /// + /// This method can be called before [initialize] to check if permission + /// has already been granted. If this returns false then the [initialize] + /// call will prompt the user for permission if it is allowed to do so. + /// Note that applications cannot ask for permission again if the user has + /// denied them permission in the past. + Future get hasPermission async { + bool hasPermission = await channel.invokeMethod('has_permission'); + return hasPermission; + } + + /// Initialize speech recognition services, returns true if + /// successful, false if failed. + /// + /// This method must be called before any other speech functions. + /// If this method returns false no further [SpeechToText] methods + /// should be used. Should only be called once if successful but does protect + /// itself if called repeatedly. False usually means that the user has denied + /// permission to use speech. The usual option in that case is to give them + /// instructions on how to open system settings and grant permission. + /// + /// [onError] is an optional listener for errors like + /// timeout, or failure of the device speech recognition. + /// [onStatus] is an optional listener for status changes from + /// listening to not listening. + /// [debugLogging] controls whether there is detailed logging from the underlying + /// plugins. It is off by default, usually only useful for troubleshooting issues + /// with a paritcular OS version or device, fairly verbose + Future initialize( + {SpeechErrorListener onError, + SpeechStatusListener onStatus, + debugLogging = false}) async { + if (_initWorked) { + return Future.value(_initWorked); + } + errorListener = onError; + statusListener = onStatus; + channel.setMethodCallHandler(_handleCallbacks); + _initWorked = await channel + .invokeMethod('initialize', {"debugLogging": debugLogging}); + return _initWorked; + } + + /// Stops the current listen for speech if active, does nothing if not. + /// + /// Stopping a listen session will cause a final result to be sent. Each + /// listen session should be ended with either [stop] or [cancel], for + /// example in the dispose method of a Widget. [cancel] is automatically + /// invoked by a permanent error if [cancelOnError] is set to true in the + /// [listen] call. + /// + /// *Note:* Cannot be used until a successful [initialize] call. Should + /// only be used after a successful [listen] call. + Future stop() async { + _userEnded = true; + return _stop(); + } + + Future _stop() async { + if (!_initWorked) { + return; + } + _shutdownListener(); + await channel.invokeMethod('stop'); + } + + /// Cancels the current listen for speech if active, does nothing if not. + /// + /// Canceling means that there will be no final result returned from the + /// recognizer. Each listen session should be ended with either [stop] or + /// [cancel], for example in the dispose method of a Widget. [cancel] is + /// automatically invoked by a permanent error if [cancelOnError] is set + /// to true in the [listen] call. + /// + /// *Note* Cannot be used until a successful [initialize] call. Should only + /// be used after a successful [listen] call. + Future cancel() async { + _userEnded = true; + return _cancel(); + } + + Future _cancel() async { + if (!_initWorked) { + return; + } + _shutdownListener(); + await channel.invokeMethod('cancel'); + } + + /// Starts a listening session for speech and converts it to text, + /// invoking the provided [onResult] method as words are recognized. + /// + /// Cannot be used until a successful [initialize] call. There is a + /// time limit on listening imposed by both Android and iOS. The time + /// depends on the device, network, etc. Android is usually quite short, + /// especially if there is no active speech event detected, on the order + /// of ten seconds or so. + /// + /// When listening is done always invoke either [cancel] or [stop] to + /// end the session, even if it times out. [cancelOnError] provides an + /// automatic way to ensure this happens. + /// + /// [onResult] is an optional listener that is notified when words + /// are recognized. + /// + /// [listenFor] sets the maximum duration that it will listen for, after + /// that it automatically stops the listen for you. + /// + /// [pauseFor] sets the maximum duration of a pause in speech with no words + /// detected, after that it automatically stops the listen for you. + /// + /// [localeId] is an optional locale that can be used to listen in a language + /// other than the current system default. See [locales] to find the list of + /// supported languages for listening. + /// + /// [onSoundLevelChange] is an optional listener that is notified when the + /// sound level of the input changes. Use this to update the UI in response to + /// more or less input. The values currently differ between Ancroid and iOS, + /// haven't yet been able to determine from the Android documentation what the + /// value means. On iOS the value returned is in decibels. + /// + /// [cancelOnError] if true then listening is automatically canceled on a + /// permanent error. This defaults to false. When false cancel should be + /// called from the error handler. + /// + /// [partialResults] if true the listen reports results as they are recognized, + /// when false only final results are reported. Defaults to true. + /// + /// [onDevice] if true the listen attempts to recognize locally with speech never + /// leaving the device. If it cannot do this the listen attempt will fail. This is + /// usually only needed for sensitive content where privacy or security is a concern. + Future listen( + {SpeechResultListener onResult, + Duration listenFor, + Duration pauseFor, + String localeId, + SpeechSoundLevelChange onSoundLevelChange, + cancelOnError = false, + partialResults = true, + onDevice = false, + ListenMode listenMode = ListenMode.confirmation}) async { + if (!_initWorked) { + throw SpeechToTextNotInitializedException(); + } + _userEnded = false; + _cancelOnError = cancelOnError; + _recognized = false; + _resultListener = onResult; + _soundLevelChange = onSoundLevelChange; + _partialResults = partialResults; + Map listenParams = { + "partialResults": partialResults || null != pauseFor, + "onDevice": onDevice, + "listenMode": listenMode.index, + }; + if (null != localeId) { + listenParams["localeId"] = localeId; + } + try { + bool started = await channel.invokeMethod(listenMethod, listenParams); + if (started) { + _listenStartedAt = clock.now().millisecondsSinceEpoch; + _setupListenAndPause(pauseFor, listenFor); + } + } on PlatformException catch (e) { + throw ListenFailedException(e.details); + } + } + + void _setupListenAndPause(Duration pauseFor, Duration listenFor) { + _pauseFor = null; + _listenFor = null; + if (null == pauseFor && null == listenFor) { + return; + } + var minDuration; + if (null == pauseFor) { + _listenFor = Duration(milliseconds: listenFor.inMilliseconds); + minDuration = listenFor; + } else if (null == listenFor) { + _pauseFor = Duration(milliseconds: pauseFor.inMilliseconds); + minDuration = pauseFor; + } else { + _listenFor = Duration(milliseconds: listenFor.inMilliseconds); + _pauseFor = Duration(milliseconds: pauseFor.inMilliseconds); + var minMillis = min(listenFor.inMilliseconds - _elapsedListenMillis, + pauseFor.inMilliseconds); + minDuration = Duration(milliseconds: minMillis); + } + _listenTimer = Timer(minDuration, _stopOnPauseOrListen); + } + + int get _elapsedListenMillis => + clock.now().millisecondsSinceEpoch - _listenStartedAt; + int get _elapsedSinceSpeechEvent => + clock.now().millisecondsSinceEpoch - _lastSpeechEventAt; + + void _stopOnPauseOrListen() { + if (null != _listenFor && + _elapsedListenMillis >= _listenFor.inMilliseconds) { + _stop(); + } else if (null != _pauseFor && + _elapsedSinceSpeechEvent >= _pauseFor.inMilliseconds) { + _stop(); + } else { + _setupListenAndPause(_pauseFor, _listenFor); + } + } + + /// returns the list of speech locales available on the device. + /// + /// This method is useful to find the identifier to use + /// for the [listen] method, it is the [localeId] member of the + /// [LocaleName]. + /// + /// Each [LocaleName] in the returned list has the + /// identifier for the locale as well as a name for + /// display. The name is localized for the system locale on + /// the device. + Future> locales() async { + if (!_initWorked) { + throw SpeechToTextNotInitializedException(); + } + final List locales = await channel.invokeMethod('locales'); + List filteredLocales = locales + .map((locale) { + var components = locale.split(":"); + if (components.length != 2) { + return null; + } + return LocaleName(components[0], components[1]); + }) + .where((item) => item != null) + .toList(); + if (filteredLocales.isNotEmpty) { + _systemLocale = filteredLocales.first; + } else { + _systemLocale = null; + } + filteredLocales.sort((ln1, ln2) => ln1.name.compareTo(ln2.name)); + return filteredLocales; + } + + /// returns the locale that will be used if no localeId is passed + /// to the [listen] method. + Future systemLocale() async { + if (null == _systemLocale) { + await locales(); + } + return Future.value(_systemLocale); + } + + Future _handleCallbacks(MethodCall call) async { + // print("SpeechToText call: ${call.method} ${call.arguments}"); + switch (call.method) { + case textRecognitionMethod: + if (call.arguments is String) { + _onTextRecognition(call.arguments); + } + break; + case notifyErrorMethod: + if (call.arguments is String) { + await _onNotifyError(call.arguments); + } + break; + case notifyStatusMethod: + if (call.arguments is String) { + _onNotifyStatus(call.arguments); + } + break; + case soundLevelChangeMethod: + if (call.arguments is double) { + _onSoundLevelChange(call.arguments); + } + break; + default: + } + } + + void _onTextRecognition(String resultJson) { + _lastSpeechEventAt = clock.now().millisecondsSinceEpoch; + Map resultMap = jsonDecode(resultJson); + SpeechRecognitionResult speechResult = + SpeechRecognitionResult.fromJson(resultMap); + if (!_partialResults && !speechResult.finalResult) { + return; + } + _recognized = true; + // print("Recognized text $resultJson"); + + _lastRecognized = speechResult.recognizedWords; + if (null != _resultListener) { + _resultListener(speechResult); + } + } + + Future _onNotifyError(String errorJson) async { + if (isNotListening && _userEnded) { + return; + } + Map errorMap = jsonDecode(errorJson); + SpeechRecognitionError speechError = + SpeechRecognitionError.fromJson(errorMap); + _lastError = speechError; + if (null != errorListener) { + errorListener(speechError); + } + if (_cancelOnError && speechError.permanent) { + await _cancel(); + } + } + + void _onNotifyStatus(String status) { + _lastStatus = status; + _listening = status == listeningStatus; + // print(status); + if (null != statusListener) { + statusListener(status); + } + } + + void _onSoundLevelChange(double level) { + if (isNotListening) { + return; + } + _lastSoundLevel = level; + if (null != _soundLevelChange) { + _soundLevelChange(level); + } + } + + _shutdownListener() { + _listening = false; + _recognized = false; + _listenTimer?.cancel(); + _listenTimer = null; + } + + @visibleForTesting + Future processMethodCall(MethodCall call) async { + return await _handleCallbacks(call); + } +} + +/// A single locale with a [name], localized to the current system locale, +/// and a [localeId] which can be used in the [listen] method to choose a +/// locale for speech recognition. +class LocaleName { + final String localeId; + final String name; + LocaleName(this.localeId, this.name); +} + +/// Thrown when a method is called that requires successful +/// initialization first. +class SpeechToTextNotInitializedException implements Exception {} + +/// Thrown when listen fails to properly start a speech listening session +/// on the device +class ListenFailedException implements Exception { + final String details; + ListenFailedException(this.details); +} diff --git a/speech_to_text_/lib/speech_to_text_provider.dart b/speech_to_text_/lib/speech_to_text_provider.dart new file mode 100644 index 00000000..91adf3b4 --- /dev/null +++ b/speech_to_text_/lib/speech_to_text_provider.dart @@ -0,0 +1,201 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:speech_to_text/speech_recognition_error.dart'; +import 'package:speech_to_text/speech_recognition_event.dart'; +import 'package:speech_to_text/speech_recognition_result.dart'; +import 'package:speech_to_text/speech_to_text.dart'; + +/// Simplifies interaction with [SpeechToText] by handling all the callbacks and notifying +/// listeners as events happen. +/// +/// Here's an example of using the [SpeechToTextProvider] +/// ``` +/// var speechProvider = SpeechToTextProvider( SpeechToText()); +/// var available = await speechProvider.initialize(); +/// StreamSubscription _subscription; +/// _subscription = speechProvider.recognitionController.stream.listen((recognitionEvent) { +/// if (recognitionEvent.eventType == SpeechRecognitionEventType.finalRecognitionEvent ) { +/// print("I heard: ${recognitionEvent.recognitionResult.recognizedWords}"); +/// } +/// }); +/// speechProvider.addListener(() { +/// var words = speechProvider.lastWords; +/// }); +class SpeechToTextProvider extends ChangeNotifier { + final StreamController _recognitionController = + StreamController.broadcast(); + final SpeechToText _speechToText; + SpeechRecognitionResult _lastResult; + double _lastLevel = 0; + List _locales = []; + LocaleName _systemLocale; + + /// Only construct one instance in an application. + /// + /// Do not call `initialize` on the [SpeechToText] that is passed as a parameter, instead + /// call the [initialize] method on this class. + SpeechToTextProvider(this._speechToText); + + Stream get stream => _recognitionController.stream; + + /// Returns the last result received, may be null. + SpeechRecognitionResult get lastResult => _lastResult; + + /// Returns the last error received, may be null. + SpeechRecognitionError get lastError => _speechToText.lastError; + + /// Returns the last sound level received. + /// + /// Note this is only available when the `soundLevel` is set to true on + /// a call to [listen], will be 0 at all other times. + double get lastLevel => _lastLevel; + + /// Initializes the provider and the contained [SpeechToText] instance. + /// + /// Returns true if [SpeechToText] was initialized successful and can now + /// be used, false otherwse. + Future initialize() async { + if (isAvailable) { + return isAvailable; + } + bool availableBefore = _speechToText.isAvailable; + bool available = + await _speechToText.initialize(onStatus: _onStatus, onError: _onError); + if (available) { + _locales = []; + _locales.addAll(await _speechToText.locales()); + _systemLocale = await _speechToText.systemLocale(); + } + if (availableBefore != available) { + notifyListeners(); + } + return available; + } + + /// Returns true if the provider has been initialized and can be used to recognize speech. + bool get isAvailable => _speechToText.isAvailable; + + /// Returns true if the provider cannot be used to recognize speech, either because it has not + /// yet been initialized or because initialization failed. + bool get isNotAvailable => !_speechToText.isAvailable; + + /// Returns true if [SpeechToText] is listening for new speech. + bool get isListening => _speechToText.isListening; + + /// Returns true if [SpeechToText] is not listening for new speech. + bool get isNotListening => _speechToText.isNotListening; + + /// Returns true if [SpeechToText] has a previous error. + bool get hasError => _speechToText.hasError; + + /// Returns true if [lastResult] has a last result. + bool get hasResults => null != _lastResult; + + /// Returns the list of locales that are available on the device for speech recognition. + List get locales => _locales; + + /// Returns the locale that is currently set as active on the device. + LocaleName get systemLocale => _systemLocale; + + /// Start listening for new events, set [partialResults] to true to receive interim + /// recognition results. + /// + /// [soundLevel] set to true to be notified on changes to the input sound level + /// on the microphone. + /// + /// [listenFor] sets the maximum duration that it will listen for, after + /// that it automatically stops the listen for you. + /// + /// [pauseFor] sets the maximum duration of a pause in speech with no words + /// detected, after that it automatically stops the listen for you. + /// + /// Call this only after a successful [initialize] call + void listen( + {bool partialResults = false, + bool soundLevel = false, + Duration listenFor, + Duration pauseFor}) { + _lastLevel = 0; + _lastResult = null; + if (soundLevel) { + _speechToText.listen( + partialResults: partialResults, + listenFor: listenFor, + pauseFor: pauseFor, + cancelOnError: true, + onResult: _onListenResult, + // onSoundLevelChange: _onSoundLevelChange); + ); + } else { + _speechToText.listen( + partialResults: partialResults, + listenFor: listenFor, + pauseFor: pauseFor, + cancelOnError: true, + onResult: _onListenResult); + } + } + + /// Stops a current active listening session. + /// + /// Call this after calling [listen] to stop the recognizer from listening further + /// and return the current result as final. + void stop() { + _speechToText.stop(); + notifyListeners(); + } + + /// Cancel a current active listening session. + /// + /// Call this after calling [listen] to stop the recognizer from listening further + /// and ignore any results recognized so far. + void cancel() { + _speechToText.cancel(); + notifyListeners(); + } + + void _onError(SpeechRecognitionError errorNotification) { + _recognitionController.add(SpeechRecognitionEvent( + SpeechRecognitionEventType.errorEvent, + null, + errorNotification, + isListening, + null)); + notifyListeners(); + } + + void _onStatus(String status) { + _recognitionController.add(SpeechRecognitionEvent( + SpeechRecognitionEventType.statusChangeEvent, + null, + null, + isListening, + null)); + notifyListeners(); + } + + void _onListenResult(SpeechRecognitionResult result) { + _lastResult = result; + _recognitionController.add(SpeechRecognitionEvent( + result.finalResult + ? SpeechRecognitionEventType.finalRecognitionEvent + : SpeechRecognitionEventType.partialRecognitionEvent, + result, + null, + isListening, + null)); + notifyListeners(); + } + + // void _onSoundLevelChange(double level) { + // _lastLevel = level; + // _recognitionController.add(SpeechRecognitionEvent( + // SpeechRecognitionEventType.soundLevelChangeEvent, + // null, + // null, + // null, + // level)); + // notifyListeners(); + // } +} diff --git a/speech_to_text_/pubspec.yaml b/speech_to_text_/pubspec.yaml new file mode 100644 index 00000000..34b3da29 --- /dev/null +++ b/speech_to_text_/pubspec.yaml @@ -0,0 +1,31 @@ +name: speech_to_text +description: A Flutter plugin that exposes device specific speech to text recognition capability. + + + +environment: + sdk: ">=2.1.0 <3.0.0" + flutter: ">=1.10.0" + +dependencies: + flutter: + sdk: flutter + json_annotation: ^3.0.0 + clock: ^1.0.1 + +dev_dependencies: + flutter_test: + sdk: flutter + build_runner: ^1.0.0 + json_serializable: ^3.0.0 + fake_async: ^1.0.1 + +flutter: + plugin: + platforms: + android: + package: com.csdcorp.speech_to_text + pluginClass: SpeechToTextPlugin + ios: + pluginClass: SpeechToTextPlugin + diff --git a/speech_to_text_/test/speech_recognition_error_test.dart b/speech_to_text_/test/speech_recognition_error_test.dart new file mode 100644 index 00000000..202ae4cd --- /dev/null +++ b/speech_to_text_/test/speech_recognition_error_test.dart @@ -0,0 +1,65 @@ +import 'dart:convert'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:speech_to_text/speech_recognition_error.dart'; + +void main() { + const String msg1 = "msg1"; + + setUp(() {}); + + group('properties', () { + test('equals true for same object', () { + SpeechRecognitionError error = SpeechRecognitionError(msg1, false); + expect(error, error); + }); + test('equals true for different object same values', () { + SpeechRecognitionError error1 = SpeechRecognitionError(msg1, false); + SpeechRecognitionError error2 = SpeechRecognitionError(msg1, false); + expect(error1, error2); + }); + test('equals false for different object', () { + SpeechRecognitionError error1 = SpeechRecognitionError(msg1, false); + SpeechRecognitionError error2 = SpeechRecognitionError("msg2", false); + expect(error1, isNot(error2)); + }); + test('hash same for same object', () { + SpeechRecognitionError error = SpeechRecognitionError(msg1, false); + expect(error.hashCode, error.hashCode); + }); + test('hash same for different object same values', () { + SpeechRecognitionError error1 = SpeechRecognitionError(msg1, false); + SpeechRecognitionError error2 = SpeechRecognitionError(msg1, false); + expect(error1.hashCode, error2.hashCode); + }); + test('hash different for different object', () { + SpeechRecognitionError error1 = SpeechRecognitionError(msg1, false); + SpeechRecognitionError error2 = SpeechRecognitionError("msg2", false); + expect(error1.hashCode, isNot(error2.hashCode)); + }); + test('toString as expected', () { + SpeechRecognitionError error1 = SpeechRecognitionError(msg1, false); + expect(error1.toString(), + "SpeechRecognitionError msg: $msg1, permanent: false"); + }); + }); + group('json', () { + test('loads properly', () { + var json = jsonDecode('{"errorMsg":"$msg1","permanent":true}'); + SpeechRecognitionError error = SpeechRecognitionError.fromJson(json); + expect(error.errorMsg, msg1); + expect(error.permanent, isTrue); + json = jsonDecode('{"errorMsg":"$msg1","permanent":false}'); + error = SpeechRecognitionError.fromJson(json); + expect(error.permanent, isFalse); + }); + test('roundtrips properly', () { + var json = jsonDecode('{"errorMsg":"$msg1","permanent":true}'); + SpeechRecognitionError error = SpeechRecognitionError.fromJson(json); + var roundtripJson = error.toJson(); + SpeechRecognitionError roundtripError = + SpeechRecognitionError.fromJson(roundtripJson); + expect(error, roundtripError); + }); + }); +} diff --git a/speech_to_text_/test/speech_recognition_event_test.dart b/speech_to_text_/test/speech_recognition_event_test.dart new file mode 100644 index 00000000..ceaaab8a --- /dev/null +++ b/speech_to_text_/test/speech_recognition_event_test.dart @@ -0,0 +1,42 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:speech_to_text/speech_recognition_event.dart'; + +import 'test_speech_channel_handler.dart'; + +void main() { + group('properties', () { + test('status listening matches', () { + var event = SpeechRecognitionEvent( + SpeechRecognitionEventType.statusChangeEvent, null, null, true, null); + expect(event.eventType, SpeechRecognitionEventType.statusChangeEvent); + expect(event.isListening, isTrue); + }); + test('result matches', () { + var event = SpeechRecognitionEvent( + SpeechRecognitionEventType.finalRecognitionEvent, + TestSpeechChannelHandler.firstRecognizedResult, + null, + null, + null); + expect(event.eventType, SpeechRecognitionEventType.finalRecognitionEvent); + expect(event.recognitionResult, + TestSpeechChannelHandler.firstRecognizedResult); + }); + test('error matches', () { + var event = SpeechRecognitionEvent(SpeechRecognitionEventType.errorEvent, + null, TestSpeechChannelHandler.firstError, null, null); + expect(event.eventType, SpeechRecognitionEventType.errorEvent); + expect(event.error, TestSpeechChannelHandler.firstError); + }); + test('sound level matches', () { + var event = SpeechRecognitionEvent( + SpeechRecognitionEventType.soundLevelChangeEvent, + null, + null, + null, + TestSpeechChannelHandler.level1); + expect(event.eventType, SpeechRecognitionEventType.soundLevelChangeEvent); + expect(event.level, TestSpeechChannelHandler.level1); + }); + }); +} diff --git a/speech_to_text_/test/speech_recognition_result_test.dart b/speech_to_text_/test/speech_recognition_result_test.dart new file mode 100644 index 00000000..1516779a --- /dev/null +++ b/speech_to_text_/test/speech_recognition_result_test.dart @@ -0,0 +1,134 @@ +import 'dart:convert'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:speech_to_text/speech_recognition_result.dart'; + +void main() { + final String firstRecognizedWords = 'hello'; + final String secondRecognizedWords = 'hello there'; + final double firstConfidence = 0.85; + final double secondConfidence = 0.62; + final String firstRecognizedJson = + '{"alternates":[{"recognizedWords":"$firstRecognizedWords","confidence":$firstConfidence}],"finalResult":false}'; + final String secondRecognizedJson = + '{"alternates":[{"recognizedWords":"$secondRecognizedWords","confidence":$secondConfidence}],"finalResult":false}'; + final SpeechRecognitionWords firstWords = + SpeechRecognitionWords(firstRecognizedWords, firstConfidence); + final SpeechRecognitionWords secondWords = + SpeechRecognitionWords(secondRecognizedWords, secondConfidence); + + setUp(() {}); + + group('recognizedWords', () { + test('empty if no alternates', () { + SpeechRecognitionResult result = SpeechRecognitionResult([], true); + expect(result.recognizedWords, isEmpty); + }); + test('matches first alternate', () { + SpeechRecognitionResult result = + SpeechRecognitionResult([firstWords, secondWords], true); + expect(result.recognizedWords, firstRecognizedWords); + }); + }); + group('alternates', () { + test('empty if no alternates', () { + SpeechRecognitionResult result = SpeechRecognitionResult([], true); + expect(result.alternates, isEmpty); + }); + test('expected contents', () { + SpeechRecognitionResult result = + SpeechRecognitionResult([firstWords, secondWords], true); + expect(result.alternates, contains(firstWords)); + expect(result.alternates, contains(secondWords)); + }); + test('in order', () { + SpeechRecognitionResult result = + SpeechRecognitionResult([firstWords, secondWords], true); + expect(result.alternates.first, firstWords); + }); + }); + group('confidence', () { + test('0 if no alternates', () { + SpeechRecognitionResult result = SpeechRecognitionResult([], true); + expect(result.confidence, 0); + }); + test('isConfident false if no alternates', () { + SpeechRecognitionResult result = SpeechRecognitionResult([], true); + expect(result.isConfident(), isFalse); + }); + test('isConfident matches first alternate', () { + SpeechRecognitionResult result = + SpeechRecognitionResult([firstWords, secondWords], true); + expect(result.isConfident(), firstWords.isConfident()); + }); + test('hasConfidenceRating false if no alternates', () { + SpeechRecognitionResult result = SpeechRecognitionResult([], true); + expect(result.hasConfidenceRating, isFalse); + }); + test('hasConfidenceRating matches first alternate', () { + SpeechRecognitionResult result = + SpeechRecognitionResult([firstWords, secondWords], true); + expect(result.hasConfidenceRating, firstWords.hasConfidenceRating); + }); + }); + group('json', () { + test('loads correctly', () { + var json = jsonDecode(firstRecognizedJson); + SpeechRecognitionResult result = SpeechRecognitionResult.fromJson(json); + expect(result.recognizedWords, firstRecognizedWords); + expect(result.confidence, firstConfidence); + }); + test('roundtrips correctly', () { + var json = jsonDecode(firstRecognizedJson); + SpeechRecognitionResult result = SpeechRecognitionResult.fromJson(json); + var roundTripJson = result.toJson(); + SpeechRecognitionResult roundtripResult = + SpeechRecognitionResult.fromJson(roundTripJson); + expect(result, roundtripResult); + }); + }); + group('overrides', () { + test('toString works with no alternates', () { + SpeechRecognitionResult result = SpeechRecognitionResult([], true); + expect( + result.toString(), "SpeechRecognitionResult words: [], final: true"); + }); + test('toString works with alternates', () { + SpeechRecognitionResult result = + SpeechRecognitionResult([firstWords], true); + expect(result.toString(), + "SpeechRecognitionResult words: [SpeechRecognitionWords words: hello, confidence: 0.85], final: true"); + }); + test('hash same for same object', () { + SpeechRecognitionResult result = + SpeechRecognitionResult([firstWords], true); + expect(result.hashCode, result.hashCode); + }); + test('hash differs for different objects', () { + SpeechRecognitionResult result1 = + SpeechRecognitionResult([firstWords], true); + SpeechRecognitionResult result2 = + SpeechRecognitionResult([secondWords], true); + expect(result1.hashCode, isNot(result2.hashCode)); + }); + test('equals same for same object', () { + SpeechRecognitionResult result = + SpeechRecognitionResult([firstWords], true); + expect(result, result); + }); + test('equals same for different object same values', () { + SpeechRecognitionResult result1 = + SpeechRecognitionResult([firstWords], true); + SpeechRecognitionResult result1a = + SpeechRecognitionResult([firstWords], true); + expect(result1, result1a); + }); + test('equals differs for different objects', () { + SpeechRecognitionResult result1 = + SpeechRecognitionResult([firstWords], true); + SpeechRecognitionResult result2 = + SpeechRecognitionResult([secondWords], true); + expect(result1, isNot(result2)); + }); + }); +} diff --git a/speech_to_text_/test/speech_recognitions_words_test.dart b/speech_to_text_/test/speech_recognitions_words_test.dart new file mode 100644 index 00000000..36a9ef0e --- /dev/null +++ b/speech_to_text_/test/speech_recognitions_words_test.dart @@ -0,0 +1,86 @@ +import 'dart:convert'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:speech_to_text/speech_recognition_result.dart'; + +void main() { + final String firstRecognizedWords = 'hello'; + final String secondRecognizedWords = 'hello there'; + final double firstConfidence = 0.85; + final double secondConfidence = 0.62; + final String firstRecognizedJson = + '{"recognizedWords":"$firstRecognizedWords","confidence":$firstConfidence}'; + final SpeechRecognitionWords firstWords = + SpeechRecognitionWords(firstRecognizedWords, firstConfidence); + final SpeechRecognitionWords secondWords = + SpeechRecognitionWords(secondRecognizedWords, secondConfidence); + + setUp(() {}); + + group('properties', () { + test('words', () { + expect(firstWords.recognizedWords, firstRecognizedWords); + expect(secondWords.recognizedWords, secondRecognizedWords); + }); + test('confidence', () { + expect(firstWords.confidence, firstConfidence); + expect(secondWords.confidence, secondConfidence); + expect(firstWords.hasConfidenceRating, isTrue); + }); + test('equals true for same object', () { + expect(firstWords, firstWords); + }); + test('equals true for different object with same values', () { + SpeechRecognitionWords firstWordsA = + SpeechRecognitionWords(firstRecognizedWords, firstConfidence); + expect(firstWords, firstWordsA); + }); + test('equals false for different results', () { + expect(firstWords, isNot(secondWords)); + }); + test('hash same for same object', () { + expect(firstWords.hashCode, firstWords.hashCode); + }); + test('hash same for different object with same values', () { + SpeechRecognitionWords firstWordsA = + SpeechRecognitionWords(firstRecognizedWords, firstConfidence); + expect(firstWords.hashCode, firstWordsA.hashCode); + }); + test('hash different for different results', () { + expect(firstWords.hashCode, isNot(secondWords.hashCode)); + }); + }); + group('isConfident', () { + test('true when >= 0.8', () { + expect(firstWords.isConfident(), isTrue); + }); + test('false when < 0.8', () { + expect(secondWords.isConfident(), isFalse); + }); + test('respects threshold', () { + expect(secondWords.isConfident(threshold: 0.5), isTrue); + }); + test('true when missing', () { + SpeechRecognitionWords words = SpeechRecognitionWords( + firstRecognizedWords, SpeechRecognitionWords.missingConfidence); + expect(words.isConfident(), isTrue); + expect(words.hasConfidenceRating, isFalse); + }); + }); + group('json', () { + test('loads correctly', () { + var json = jsonDecode(firstRecognizedJson); + SpeechRecognitionWords words = SpeechRecognitionWords.fromJson(json); + expect(words.recognizedWords, firstRecognizedWords); + expect(words.confidence, firstConfidence); + }); + test('roundtrips correctly', () { + var json = jsonDecode(firstRecognizedJson); + SpeechRecognitionWords words = SpeechRecognitionWords.fromJson(json); + var roundTripJson = words.toJson(); + SpeechRecognitionWords roundtripWords = + SpeechRecognitionWords.fromJson(roundTripJson); + expect(words, roundtripWords); + }); + }); +} diff --git a/speech_to_text_/test/speech_to_text_provider_test.dart b/speech_to_text_/test/speech_to_text_provider_test.dart new file mode 100644 index 00000000..25366b6f --- /dev/null +++ b/speech_to_text_/test/speech_to_text_provider_test.dart @@ -0,0 +1,196 @@ +import 'package:fake_async/fake_async.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:speech_to_text/speech_to_text.dart'; +import 'package:speech_to_text/speech_to_text_provider.dart'; + +import 'test_speech_channel_handler.dart'; +import 'test_speech_listener.dart'; + +void main() { + SpeechToTextProvider provider; + SpeechToText speechToText; + TestSpeechChannelHandler speechHandler; + TestSpeechListener speechListener; + + TestWidgetsFlutterBinding.ensureInitialized(); + + setUp(() { + speechToText = SpeechToText.withMethodChannel(SpeechToText.speechChannel); + speechHandler = TestSpeechChannelHandler(speechToText); + speechToText.channel + .setMockMethodCallHandler(speechHandler.methodCallHandler); + provider = SpeechToTextProvider(speechToText); + speechListener = TestSpeechListener(provider); + provider.addListener(speechListener.onNotify); + }); + + tearDown(() { + speechToText.channel.setMockMethodCallHandler(null); + }); + + group('delegates', () { + test('isListening matches delegate defaults', () { + expect(provider.isListening, speechToText.isListening); + expect(provider.isNotListening, speechToText.isNotListening); + }); + test('isAvailable matches delegate defaults', () { + expect(provider.isAvailable, speechToText.isAvailable); + expect(provider.isNotAvailable, !speechToText.isAvailable); + }); + test('isAvailable matches delegate after init', () async { + expect(await provider.initialize(), isTrue); + expect(provider.isAvailable, speechToText.isAvailable); + expect(provider.isNotAvailable, !speechToText.isAvailable); + }); + test('hasError matches delegate after error', () async { + expect(await provider.initialize(), isTrue); + expect(provider.hasError, speechToText.hasError); + }); + }); + group('listening', () { + test('notifies on initialize', () async { + fakeAsync((fa) { + provider.initialize(); + fa.flushMicrotasks(); + expect(speechListener.notified, isTrue); + expect(speechListener.isAvailable, isTrue); + }); + }); + test('notifies on listening', () async { + fakeAsync((fa) { + setupForListen(provider, fa, speechListener); + expect(speechListener.notified, isTrue); + expect(speechListener.isListening, isTrue); + expect(provider.hasResults, isFalse); + }); + }); + test('notifies on final words', () async { + fakeAsync((fa) { + setupForListen(provider, fa, speechListener); + speechListener.reset(); + speechHandler.notifyFinalWords(); + fa.flushMicrotasks(); + expect(speechListener.notified, isTrue); + expect(provider.hasResults, isTrue); + var result = speechListener.recognitionResult; + expect(result.recognizedWords, + TestSpeechChannelHandler.secondRecognizedWords); + expect(result.finalResult, isTrue); + }); + }); + test('hasResult false after listening before new results', () async { + fakeAsync((fa) { + setupForListen(provider, fa, speechListener); + speechHandler.notifyFinalWords(); + provider.stop(); + setupForListen(provider, fa, speechListener); + fa.flushMicrotasks(); + expect(provider.hasResults, isFalse); + }); + }); + test('notifies on partial words', () async { + fakeAsync((fa) { + setupForListen(provider, fa, speechListener, partialResults: true); + speechListener.reset(); + speechHandler.notifyPartialWords(); + fa.flushMicrotasks(); + expect(speechListener.notified, isTrue); + expect(provider.hasResults, isTrue); + var result = speechListener.recognitionResult; + expect(result.recognizedWords, + TestSpeechChannelHandler.firstRecognizedWords); + expect(result.finalResult, isFalse); + }); + }); + }); + group('soundLevel', () { + test('notifies when requested', () async { + fakeAsync((fa) { + setupForListen(provider, fa, speechListener, + partialResults: true, soundLevel: true); + speechListener.reset(); + speechHandler.notifySoundLevel(); + fa.flushMicrotasks(); + expect(speechListener.notified, isTrue); + expect(speechListener.soundLevel, TestSpeechChannelHandler.level2); + }); + }); + test('no notification by default', () async { + fakeAsync((fa) { + setupForListen(provider, fa, speechListener, + partialResults: true, soundLevel: false); + speechListener.reset(); + speechHandler.notifySoundLevel(); + fa.flushMicrotasks(); + expect(speechListener.notified, isFalse); + expect(speechListener.soundLevel, 0); + }); + }); + }); + group('stop/cancel', () { + test('notifies on stop', () async { + fakeAsync((fa) { + provider.initialize(); + setupForListen(provider, fa, speechListener); + speechListener.reset(); + provider.stop(); + fa.flushMicrotasks(); + expect(speechListener.notified, isTrue); + expect(speechListener.isListening, isFalse); + }); + }); + test('notifies on cancel', () async { + fakeAsync((fa) { + provider.initialize(); + setupForListen(provider, fa, speechListener); + speechListener.reset(); + provider.cancel(); + fa.flushMicrotasks(); + expect(speechListener.notified, isTrue); + expect(speechListener.isListening, isFalse); + }); + }); + }); + group('error handling', () { + test('hasError matches delegate default', () async { + expect(await provider.initialize(), isTrue); + expect(provider.hasError, speechToText.hasError); + }); + test('notifies on error', () async { + fakeAsync((fa) { + provider.initialize(); + setupForListen(provider, fa, speechListener); + speechListener.reset(); + speechHandler.notifyPermanentError(); + expect(speechListener.notified, isTrue); + expect(speechListener.hasError, isTrue); + }); + }); + }); + group('locale', () { + test('locales empty before init', () async { + expect(provider.systemLocale, isNull); + expect(provider.locales, isEmpty); + }); + test('set from SpeechToText after init', () async { + fakeAsync((fa) { + speechHandler.setupLocales(); + provider.initialize(); + fa.flushMicrotasks(); + expect( + provider.systemLocale.localeId, TestSpeechChannelHandler.localeId1); + expect(provider.locales, hasLength(speechHandler.locales.length)); + }); + }); + }); +} + +void setupForListen(SpeechToTextProvider provider, FakeAsync fa, + TestSpeechListener speechListener, + {bool partialResults = false, bool soundLevel = false}) { + provider.initialize(); + fa.flushMicrotasks(); + speechListener.reset(); + provider.listen(partialResults: partialResults, soundLevel: soundLevel); + fa.flushMicrotasks(); +} diff --git a/speech_to_text_/test/speech_to_text_test.dart b/speech_to_text_/test/speech_to_text_test.dart new file mode 100644 index 00000000..7b4701ff --- /dev/null +++ b/speech_to_text_/test/speech_to_text_test.dart @@ -0,0 +1,425 @@ +import 'package:fake_async/fake_async.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:speech_to_text/speech_recognition_error.dart'; +import 'package:speech_to_text/speech_recognition_result.dart'; +import 'package:speech_to_text/speech_to_text.dart'; + +import 'test_speech_channel_handler.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + TestSpeechListener listener; + TestSpeechChannelHandler speechHandler; + SpeechToText speech; + + setUp(() { + listener = TestSpeechListener(); + speech = SpeechToText.withMethodChannel(SpeechToText.speechChannel); + speechHandler = TestSpeechChannelHandler(speech); + speech.channel.setMockMethodCallHandler(speechHandler.methodCallHandler); + }); + + tearDown(() { + speech.channel.setMockMethodCallHandler(null); + }); + + group('hasPermission', () { + test('true if platform reports true', () async { + expect(await speech.hasPermission, true); + }); + test('false if platform reports false', () async { + speechHandler.hasPermissionResult = false; + expect(await speech.hasPermission, false); + }); + }); + group('init', () { + test('succeeds on platform success', () async { + expect(await speech.initialize(), true); + expect(speechHandler.initInvoked, true); + expect(speech.isAvailable, true); + }); + test('only invokes once', () async { + expect(await speech.initialize(), true); + speechHandler.initInvoked = false; + expect(await speech.initialize(), true); + expect(speechHandler.initInvoked, false); + }); + test('fails on platform failure', () async { + speechHandler.initResult = false; + expect(await speech.initialize(), false); + expect(speech.isAvailable, false); + }); + }); + + group('listen', () { + test('fails with exception if not initialized', () async { + try { + await speech.listen(); + fail("Expected an exception."); + } on SpeechToTextNotInitializedException { + // This is a good result + } + }); + test('fails with exception if init fails', () async { + try { + speechHandler.initResult = false; + await speech.initialize(); + await speech.listen(); + fail("Expected an exception."); + } on SpeechToTextNotInitializedException { + // This is a good result + } + }); + test('invokes listen after successful init', () async { + await speech.initialize(); + await speech.listen(); + expect(speechHandler.listenLocale, isNull); + expect(speechHandler.listenInvoked, true); + }); + test('converts platformException to listenFailed', () async { + await speech.initialize(); + speechHandler.listenException = true; + try { + await speech.listen(); + fail("Should have thrown"); + } on ListenFailedException catch (e) { + expect(e.details, TestSpeechChannelHandler.listenExceptionDetails); + } catch (wrongE) { + fail("Should have been ListenFailedException"); + } + }); + test('stops listen after listenFor duration', () async { + fakeAsync((fa) { + speech.initialize(); + fa.flushMicrotasks(); + speech.listen(listenFor: Duration(seconds: 2)); + fa.flushMicrotasks(); + expect(speech.isListening, isTrue); + fa.elapse(Duration(seconds: 2)); + expect(speech.isListening, isFalse); + }); + }); + test('stops listen after listenFor duration even with speech event', + () async { + fakeAsync((fa) { + speech.initialize(); + fa.flushMicrotasks(); + speech.listen(listenFor: Duration(seconds: 1)); + speech.processMethodCall(MethodCall(SpeechToText.textRecognitionMethod, + TestSpeechChannelHandler.firstRecognizedJson)); + fa.flushMicrotasks(); + expect(speech.isListening, isTrue); + fa.elapse(Duration(seconds: 1)); + expect(speech.isListening, isFalse); + }); + }); + test('stops listen after pauseFor duration with no speech', () async { + fakeAsync((fa) { + speech.initialize(); + fa.flushMicrotasks(); + speech.listen(pauseFor: Duration(seconds: 2)); + fa.flushMicrotasks(); + expect(speech.isListening, isTrue); + fa.elapse(Duration(seconds: 2)); + expect(speech.isListening, isFalse); + }); + }); + test('stops listen after pauseFor with longer listenFor duration', + () async { + fakeAsync((fa) { + speech.initialize(); + fa.flushMicrotasks(); + speech.listen( + pauseFor: Duration(seconds: 1), listenFor: Duration(seconds: 5)); + fa.flushMicrotasks(); + expect(speech.isListening, isTrue); + fa.elapse(Duration(seconds: 1)); + expect(speech.isListening, isFalse); + }); + }); + test('stops listen after listenFor with longer pauseFor duration', + () async { + fakeAsync((fa) { + speech.initialize(); + fa.flushMicrotasks(); + speech.listen( + listenFor: Duration(seconds: 1), pauseFor: Duration(seconds: 5)); + fa.flushMicrotasks(); + expect(speech.isListening, isTrue); + fa.elapse(Duration(seconds: 1)); + expect(speech.isListening, isFalse); + }); + }); + test('keeps listening after pauseFor with speech event', () async { + fakeAsync((fa) { + speech.initialize(); + fa.flushMicrotasks(); + speech.listen(pauseFor: Duration(seconds: 2)); + fa.flushMicrotasks(); + fa.elapse(Duration(seconds: 1)); + speech.processMethodCall(MethodCall(SpeechToText.textRecognitionMethod, + TestSpeechChannelHandler.firstRecognizedJson)); + fa.flushMicrotasks(); + fa.elapse(Duration(seconds: 1)); + expect(speech.isListening, isTrue); + }); + }); + test('uses localeId if provided', () async { + await speech.initialize(); + await speech.listen(localeId: TestSpeechChannelHandler.localeId1); + expect(speechHandler.listenInvoked, true); + expect(speechHandler.listenLocale, TestSpeechChannelHandler.localeId1); + }); + test('calls speech listener', () async { + await speech.initialize(); + await speech.listen(onResult: listener.onSpeechResult); + await speech.processMethodCall(MethodCall( + SpeechToText.textRecognitionMethod, + TestSpeechChannelHandler.firstRecognizedJson)); + expect(listener.speechResults, 1); + expect( + listener.results, [TestSpeechChannelHandler.firstRecognizedResult]); + expect(speech.lastRecognizedWords, + TestSpeechChannelHandler.firstRecognizedWords); + }); + test('calls speech listener with multiple', () async { + await speech.initialize(); + await speech.listen(onResult: listener.onSpeechResult); + await speech.processMethodCall(MethodCall( + SpeechToText.textRecognitionMethod, + TestSpeechChannelHandler.firstRecognizedJson)); + await speech.processMethodCall(MethodCall( + SpeechToText.textRecognitionMethod, + TestSpeechChannelHandler.secondRecognizedJson)); + expect(listener.speechResults, 2); + expect(listener.results, [ + TestSpeechChannelHandler.firstRecognizedResult, + TestSpeechChannelHandler.secondRecognizedResult + ]); + expect(speech.lastRecognizedWords, + TestSpeechChannelHandler.secondRecognizedWords); + }); + }); + + group('status callback', () { + test('invoked on listen', () async { + await speech.initialize( + onError: listener.onSpeechError, onStatus: listener.onSpeechStatus); + await speech.processMethodCall(MethodCall( + SpeechToText.notifyStatusMethod, SpeechToText.listeningStatus)); + expect(listener.speechStatus, 1); + expect(listener.statuses.contains(SpeechToText.listeningStatus), true); + }); + }); + + group('soundLevel callback', () { + test('invoked on listen', () async { + await speech.initialize(); + await speech.listen(onSoundLevelChange: listener.onSoundLevel); + await speech.processMethodCall(MethodCall( + SpeechToText.soundLevelChangeMethod, + TestSpeechChannelHandler.level1)); + expect(listener.soundLevel, 1); + expect(listener.soundLevels, contains(TestSpeechChannelHandler.level1)); + }); + test('sets lastLevel', () async { + await speech.initialize(); + await speech.listen(onSoundLevelChange: listener.onSoundLevel); + await speech.processMethodCall(MethodCall( + SpeechToText.soundLevelChangeMethod, + TestSpeechChannelHandler.level1)); + expect(speech.lastSoundLevel, TestSpeechChannelHandler.level1); + }); + }); + + group('cancel', () { + test('does nothing if not initialized', () async { + speech.cancel(); + expect(speechHandler.cancelInvoked, false); + }); + test('cancels an active listen', () async { + await speech.initialize(); + await speech.listen(); + await speech.cancel(); + expect(speechHandler.cancelInvoked, true); + expect(speech.isListening, isFalse); + }); + }); + group('stop', () { + test('does nothing if not initialized', () async { + speech.stop(); + expect(speechHandler.cancelInvoked, false); + }); + test('stops an active listen', () async { + await speech.initialize(); + speech.listen(); + speech.stop(); + expect(speechHandler.stopInvoked, true); + }); + }); + group('error', () { + test('notifies handler with transient', () async { + await speech.initialize(onError: listener.onSpeechError); + await speech.listen(); + await speech.processMethodCall(MethodCall(SpeechToText.notifyErrorMethod, + TestSpeechChannelHandler.transientErrorJson)); + expect(listener.speechErrors, 1); + expect(listener.errors.first.permanent, isFalse); + }); + test('notifies handler with permanent', () async { + await speech.initialize(onError: listener.onSpeechError); + await speech.listen(); + await speech.processMethodCall(MethodCall(SpeechToText.notifyErrorMethod, + TestSpeechChannelHandler.permanentErrorJson)); + expect(listener.speechErrors, 1); + expect(listener.errors.first.permanent, isTrue); + }); + test('continues listening on transient', () async { + await speech.initialize(onError: listener.onSpeechError); + await speech.listen(); + await speech.processMethodCall(MethodCall(SpeechToText.notifyErrorMethod, + TestSpeechChannelHandler.transientErrorJson)); + expect(speech.isListening, isTrue); + }); + test('continues listening on permanent if cancel not explicitly requested', + () async { + await speech.initialize(onError: listener.onSpeechError); + await speech.listen(); + await speech.processMethodCall(MethodCall(SpeechToText.notifyErrorMethod, + TestSpeechChannelHandler.permanentErrorJson)); + expect(speech.isListening, isTrue); + }); + test('stops listening on permanent if cancel explicitly requested', + () async { + await speech.initialize(onError: listener.onSpeechError); + await speech.listen(cancelOnError: true); + await speech.processMethodCall(MethodCall(SpeechToText.notifyErrorMethod, + TestSpeechChannelHandler.permanentErrorJson)); + expect(speech.isListening, isFalse); + }); + test('Error not sent after cancel', () async { + await speech.initialize(onError: listener.onSpeechError); + await speech.listen(); + await speech.cancel(); + await speech.processMethodCall(MethodCall(SpeechToText.notifyErrorMethod, + TestSpeechChannelHandler.permanentErrorJson)); + expect(speech.isListening, isFalse); + expect(listener.speechErrors, 0); + }); + test('Error still sent after implicit cancel', () async { + await speech.initialize(onError: listener.onSpeechError); + await speech.listen(cancelOnError: true); + await speech.processMethodCall(MethodCall(SpeechToText.notifyErrorMethod, + TestSpeechChannelHandler.permanentErrorJson)); + await speech.processMethodCall(MethodCall(SpeechToText.notifyErrorMethod, + TestSpeechChannelHandler.permanentErrorJson)); + expect(speech.isListening, isFalse); + expect(listener.speechErrors, 2); + }); + }); + group('locales', () { + test('fails with exception if not initialized', () async { + try { + await speech.locales(); + fail("Expected an exception."); + } on SpeechToTextNotInitializedException { + // This is a good result + } + }); + test('system locale null if not initialized', () async { + LocaleName current; + try { + current = await speech.systemLocale(); + fail("Expected an exception."); + } on SpeechToTextNotInitializedException { + expect(current, isNull); + } + }); + test('handles an empty list', () async { + await speech.initialize(onError: listener.onSpeechError); + List localeNames = await speech.locales(); + expect(speechHandler.localesInvoked, isTrue); + expect(localeNames, isEmpty); + }); + test('returns expected locales', () async { + await speech.initialize(onError: listener.onSpeechError); + speechHandler.locales.add(TestSpeechChannelHandler.locale1); + speechHandler.locales.add(TestSpeechChannelHandler.locale2); + List localeNames = await speech.locales(); + expect(localeNames, hasLength(speechHandler.locales.length)); + expect(localeNames[0].localeId, TestSpeechChannelHandler.localeId1); + expect(localeNames[0].name, TestSpeechChannelHandler.name1); + expect(localeNames[1].localeId, TestSpeechChannelHandler.localeId2); + expect(localeNames[1].name, TestSpeechChannelHandler.name2); + }); + test('skips incorrect locales', () async { + await speech.initialize(onError: listener.onSpeechError); + speechHandler.locales.add("InvalidJunk"); + speechHandler.locales.add(TestSpeechChannelHandler.locale1); + List localeNames = await speech.locales(); + expect(localeNames, hasLength(1)); + expect(localeNames[0].localeId, TestSpeechChannelHandler.localeId1); + expect(localeNames[0].name, TestSpeechChannelHandler.name1); + }); + test('system locale matches first returned locale', () async { + await speech.initialize(onError: listener.onSpeechError); + speechHandler.locales.add(TestSpeechChannelHandler.locale1); + speechHandler.locales.add(TestSpeechChannelHandler.locale2); + LocaleName current = await speech.systemLocale(); + expect(current.localeId, TestSpeechChannelHandler.localeId1); + }); + }); + group('status', () { + test('recognized false at start', () async { + expect(speech.hasRecognized, isFalse); + }); + test('listening false at start', () async { + expect(speech.isListening, isFalse); + }); + }); + test('available false at start', () async { + expect(speech.isAvailable, isFalse); + }); + test('hasError false at start', () async { + expect(speech.hasError, isFalse); + }); + test('lastError null at start', () async { + expect(speech.lastError, isNull); + }); + test('status empty at start', () async { + expect(speech.lastStatus, isEmpty); + }); +} + +class TestSpeechListener { + int speechResults = 0; + List results = []; + int speechErrors = 0; + List errors = []; + int speechStatus = 0; + List statuses = []; + int soundLevel = 0; + List soundLevels = []; + + void onSpeechResult(SpeechRecognitionResult result) { + ++speechResults; + results.add(result); + } + + void onSpeechError(SpeechRecognitionError errorResult) { + ++speechErrors; + errors.add(errorResult); + } + + void onSpeechStatus(String status) { + ++speechStatus; + statuses.add(status); + } + + void onSoundLevel(double level) { + ++soundLevel; + soundLevels.add(level); + } +} diff --git a/speech_to_text_/test/test_speech_channel_handler.dart b/speech_to_text_/test/test_speech_channel_handler.dart new file mode 100644 index 00000000..a55f0670 --- /dev/null +++ b/speech_to_text_/test/test_speech_channel_handler.dart @@ -0,0 +1,134 @@ +import 'package:flutter/services.dart'; +import 'package:speech_to_text/speech_recognition_error.dart'; +import 'package:speech_to_text/speech_recognition_result.dart'; +import 'package:speech_to_text/speech_to_text.dart'; + +/// Holds a set of responses and acts as a mock for the platform specific +/// implementations allowing test cases to determine what the result of +/// a call should be. +class TestSpeechChannelHandler { + final SpeechToText _speech; + + bool listenException = false; + + static const String listenExceptionCode = "listenFailedError"; + static const String listenExceptionMessage = "Failed"; + static const String listenExceptionDetails = "Device Listen Failure"; + + TestSpeechChannelHandler(this._speech); + + bool initResult = true; + bool initInvoked = false; + bool listenInvoked = false; + bool cancelInvoked = false; + bool stopInvoked = false; + bool localesInvoked = false; + bool hasPermissionResult = true; + String listeningStatusResponse = SpeechToText.listeningStatus; + String listenLocale; + List locales = []; + static const String localeId1 = "en_US"; + static const String localeId2 = "fr_CA"; + static const String name1 = "English US"; + static const String name2 = "French Canada"; + static const String locale1 = "$localeId1:$name1"; + static const String locale2 = "$localeId2:$name2"; + static const String firstRecognizedWords = 'hello'; + static const String secondRecognizedWords = 'hello there'; + static const double firstConfidence = 0.85; + static const double secondConfidence = 0.62; + static const String firstRecognizedJson = + '{"alternates":[{"recognizedWords":"$firstRecognizedWords","confidence":$firstConfidence}],"finalResult":false}'; + static const String secondRecognizedJson = + '{"alternates":[{"recognizedWords":"$secondRecognizedWords","confidence":$secondConfidence}],"finalResult":false}'; + static const String finalRecognizedJson = + '{"alternates":[{"recognizedWords":"$secondRecognizedWords","confidence":$secondConfidence}],"finalResult":true}'; + static const SpeechRecognitionWords firstWords = + SpeechRecognitionWords(firstRecognizedWords, firstConfidence); + static const SpeechRecognitionWords secondWords = + SpeechRecognitionWords(secondRecognizedWords, secondConfidence); + static final SpeechRecognitionResult firstRecognizedResult = + SpeechRecognitionResult([firstWords], false); + static final SpeechRecognitionResult secondRecognizedResult = + SpeechRecognitionResult([secondWords], false); + static final SpeechRecognitionResult finalRecognizedResult = + SpeechRecognitionResult([secondWords], true); + static const String transientErrorJson = + '{"errorMsg":"network","permanent":false}'; + static const String permanentErrorJson = + '{"errorMsg":"network","permanent":true}'; + static final SpeechRecognitionError firstError = + SpeechRecognitionError("network", true); + static const double level1 = 0.5; + static const double level2 = 10; + + Future methodCallHandler(MethodCall methodCall) async { + switch (methodCall.method) { + case "has_permission": + return hasPermissionResult; + break; + case "initialize": + initInvoked = true; + return initResult; + break; + case "cancel": + cancelInvoked = true; + return true; + break; + case "stop": + stopInvoked = true; + return true; + break; + case SpeechToText.listenMethod: + listenInvoked = true; + if (listenException) { + throw PlatformException( + code: listenExceptionCode, + message: listenExceptionMessage, + details: listenExceptionDetails); + } + listenLocale = methodCall.arguments["localeId"]; + await _speech.processMethodCall(MethodCall( + SpeechToText.notifyStatusMethod, listeningStatusResponse)); + return initResult; + break; + case "locales": + localesInvoked = true; + return locales; + break; + default: + } + return initResult; + } + + void notifyFinalWords() { + _speech.processMethodCall( + MethodCall(SpeechToText.textRecognitionMethod, finalRecognizedJson)); + } + + void notifyPartialWords() { + _speech.processMethodCall( + MethodCall(SpeechToText.textRecognitionMethod, firstRecognizedJson)); + } + + void notifyPermanentError() { + _speech.processMethodCall( + MethodCall(SpeechToText.notifyErrorMethod, permanentErrorJson)); + } + + void notifyTransientError() { + _speech.processMethodCall( + MethodCall(SpeechToText.notifyErrorMethod, transientErrorJson)); + } + + void notifySoundLevel() { + _speech.processMethodCall( + MethodCall(SpeechToText.soundLevelChangeMethod, level2)); + } + + void setupLocales() { + locales.clear(); + locales.add(locale1); + locales.add(locale2); + } +} diff --git a/speech_to_text_/test/test_speech_listener.dart b/speech_to_text_/test/test_speech_listener.dart new file mode 100644 index 00000000..1efcd81c --- /dev/null +++ b/speech_to_text_/test/test_speech_listener.dart @@ -0,0 +1,36 @@ +import 'package:speech_to_text/speech_recognition_error.dart'; +import 'package:speech_to_text/speech_recognition_result.dart'; +import 'package:speech_to_text/speech_to_text_provider.dart'; + +/// Holds the results of notification by the [SpeechToTextProvider] +class TestSpeechListener { + final SpeechToTextProvider _speechProvider; + + bool isListening = false; + bool isFinal = false; + bool isAvailable = false; + bool notified = false; + bool hasError = false; + SpeechRecognitionResult recognitionResult; + SpeechRecognitionError lastError; + double soundLevel; + + TestSpeechListener(this._speechProvider); + + void reset() { + isListening = false; + isFinal = false; + isAvailable = false; + notified = false; + } + + void onNotify() { + notified = true; + isAvailable = _speechProvider.isAvailable; + isListening = _speechProvider.isListening; + recognitionResult = _speechProvider.lastResult; + hasError = _speechProvider.hasError; + lastError = _speechProvider.lastError; + soundLevel = _speechProvider.lastLevel; + } +} From a004610ac3a2f443f11fa1e48ce3644069ced3b2 Mon Sep 17 00:00:00 2001 From: Sultan Khan Date: Wed, 9 Dec 2020 08:38:35 +0300 Subject: [PATCH 20/71] voice command updatd --- lib/widgets/others/app_scaffold_widget.dart | 73 +-- .../others/floating_button_search.dart | 84 ++- speech_to_text/.github/workflows/main.yml | 19 - speech_to_text/.vscode/launch.json | 14 - speech_to_text/codestats.csv | 1 - speech_to_text/example/android/.gitignore | 11 - .../com/csdcorp/example/MainActivity.kt | 6 - speech_to_text/example/ios/.gitignore | 32 - .../xcshareddata/IDEWorkspaceChecks.plist | 8 - .../xcshareddata/WorkspaceSettings.xcsettings | 8 - .../xcshareddata/WorkspaceSettings.xcsettings | 8 - speech_to_text/example/lib/port.dart | 174 ----- .../example/lib/provider_example.dart | 195 ------ speech_to_text/example/lib/stress.dart | 292 --------- speech_to_text/lib/speech_to_text_web.dart | 95 --- speech_to_text/scripts/tcov.sh | 5 - .../test/test_speech_to_text_platform.dart | 133 ---- speech_to_text_/.github/workflows/master.yml | 19 - speech_to_text_/.gitignore | 11 - speech_to_text_/.metadata | 10 - speech_to_text_/CHANGELOG.md | 166 ----- speech_to_text_/LICENSE | 29 - speech_to_text_/README.md | 150 ----- speech_to_text_/android/.classpath | 6 - speech_to_text_/android/.gitignore | 8 - speech_to_text_/android/.project | 23 - .../org.eclipse.buildship.core.prefs | 13 - speech_to_text_/android/build.gradle | 44 -- .../android/gradle/gradle.properties | 3 - .../android/gradle/local.properties | 3 - .../android/gradle/settings.gradle | 1 - .../gradle/wrapper/gradle-wrapper.properties | 5 - .../android/src/main/AndroidManifest.xml | 3 - .../speech_to_text/SpeechToTextPlugin.kt | 595 ------------------ speech_to_text_/example/.gitignore | 73 --- speech_to_text_/example/.metadata | 10 - speech_to_text_/example/README.md | 155 ----- speech_to_text_/example/android/.project | 17 - .../org.eclipse.buildship.core.prefs | 2 - .../example/android/app/build.gradle | 67 -- .../android/app/src/debug/AndroidManifest.xml | 7 - .../android/app/src/main/AndroidManifest.xml | 32 - .../speech_to_text_example/MainActivity.kt | 12 - .../main/res/drawable/launch_background.xml | 12 - .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 544 -> 0 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 442 -> 0 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 721 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 1031 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 1443 -> 0 bytes .../app/src/main/res/values/styles.xml | 8 - .../app/src/profile/AndroidManifest.xml | 7 - speech_to_text_/example/android/build.gradle | 31 - .../example/android/gradle.properties | 4 - .../gradle/wrapper/gradle-wrapper.properties | 6 - .../example/android/settings.gradle | 15 - .../assets/sounds/speech_to_text_cancel.m4r | Bin 14006 -> 0 bytes .../sounds/speech_to_text_listening.m4r | Bin 16416 -> 0 bytes .../assets/sounds/speech_to_text_stop.m4r | Bin 17128 -> 0 bytes .../ios/Flutter/AppFrameworkInfo.plist | 26 - .../example/ios/Flutter/Debug.xcconfig | 2 - .../example/ios/Flutter/Flutter.podspec | 18 - .../example/ios/Flutter/Release.xcconfig | 2 - speech_to_text_/example/ios/Podfile | 90 --- speech_to_text_/example/ios/Podfile.lock | 29 - .../ios/Runner.xcodeproj/project.pbxproj | 578 ----------------- .../contents.xcworkspacedata | 7 - .../xcshareddata/xcschemes/Runner.xcscheme | 91 --- .../contents.xcworkspacedata | 10 - .../xcshareddata/IDEWorkspaceChecks.plist | 8 - .../example/ios/Runner/AppDelegate.swift | 13 - .../AppIcon.appiconset/Contents.json | 122 ---- .../Icon-App-1024x1024@1x.png | Bin 10932 -> 0 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 564 -> 0 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 1283 -> 0 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 1588 -> 0 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 1025 -> 0 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 1716 -> 0 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 1920 -> 0 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 1283 -> 0 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 1895 -> 0 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 2665 -> 0 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 2665 -> 0 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 3831 -> 0 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 1888 -> 0 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 3294 -> 0 bytes .../Icon-App-83.5x83.5@2x.png | Bin 3612 -> 0 bytes .../LaunchImage.imageset/Contents.json | 23 - .../LaunchImage.imageset/LaunchImage.png | Bin 68 -> 0 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 68 -> 0 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 68 -> 0 bytes .../LaunchImage.imageset/README.md | 5 - .../Runner/Base.lproj/LaunchScreen.storyboard | 37 -- .../ios/Runner/Base.lproj/Main.storyboard | 26 - speech_to_text_/example/ios/Runner/Info.plist | 49 -- .../ios/Runner/Runner-Bridging-Header.h | 1 - speech_to_text_/example/lib/main.dart | 275 -------- speech_to_text_/example/pubspec.yaml | 33 - speech_to_text_/example/test/widget_test.dart | 27 - speech_to_text_/ios/.gitignore | 37 -- speech_to_text_/ios/Assets/.gitkeep | 0 .../ios/Classes/SpeechToTextPlugin.h | 4 - .../ios/Classes/SpeechToTextPlugin.m | 8 - .../ios/Classes/SwiftSpeechToTextPlugin.swift | 580 ----------------- speech_to_text_/ios/speech_to_text.podspec | 22 - .../lib/speech_recognition_error.dart | 44 -- .../lib/speech_recognition_error.g.dart | 22 - .../lib/speech_recognition_event.dart | 30 - .../lib/speech_recognition_result.dart | 140 ----- .../lib/speech_recognition_result.g.dart | 41 -- speech_to_text_/lib/speech_to_text.dart | 511 --------------- .../lib/speech_to_text_provider.dart | 201 ------ speech_to_text_/pubspec.yaml | 31 - .../test/speech_recognition_error_test.dart | 65 -- .../test/speech_recognition_event_test.dart | 42 -- .../test/speech_recognition_result_test.dart | 134 ---- .../test/speech_recognitions_words_test.dart | 86 --- .../test/speech_to_text_provider_test.dart | 196 ------ speech_to_text_/test/speech_to_text_test.dart | 425 ------------- .../test/test_speech_channel_handler.dart | 134 ---- .../test/test_speech_listener.dart | 36 -- 120 files changed, 89 insertions(+), 6877 deletions(-) delete mode 100644 speech_to_text/.github/workflows/main.yml delete mode 100644 speech_to_text/.vscode/launch.json delete mode 100644 speech_to_text/codestats.csv delete mode 100644 speech_to_text/example/android/.gitignore delete mode 100644 speech_to_text/example/android/app/src/main/kotlin/com/csdcorp/example/MainActivity.kt delete mode 100644 speech_to_text/example/ios/.gitignore delete mode 100644 speech_to_text/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 speech_to_text/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings delete mode 100644 speech_to_text/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings delete mode 100644 speech_to_text/example/lib/port.dart delete mode 100644 speech_to_text/example/lib/provider_example.dart delete mode 100644 speech_to_text/example/lib/stress.dart delete mode 100644 speech_to_text/lib/speech_to_text_web.dart delete mode 100644 speech_to_text/scripts/tcov.sh delete mode 100644 speech_to_text/test/test_speech_to_text_platform.dart delete mode 100644 speech_to_text_/.github/workflows/master.yml delete mode 100644 speech_to_text_/.gitignore delete mode 100644 speech_to_text_/.metadata delete mode 100644 speech_to_text_/CHANGELOG.md delete mode 100644 speech_to_text_/LICENSE delete mode 100644 speech_to_text_/README.md delete mode 100644 speech_to_text_/android/.classpath delete mode 100644 speech_to_text_/android/.gitignore delete mode 100644 speech_to_text_/android/.project delete mode 100644 speech_to_text_/android/.settings/org.eclipse.buildship.core.prefs delete mode 100644 speech_to_text_/android/build.gradle delete mode 100644 speech_to_text_/android/gradle/gradle.properties delete mode 100644 speech_to_text_/android/gradle/local.properties delete mode 100644 speech_to_text_/android/gradle/settings.gradle delete mode 100644 speech_to_text_/android/gradle/wrapper/gradle-wrapper.properties delete mode 100644 speech_to_text_/android/src/main/AndroidManifest.xml delete mode 100644 speech_to_text_/android/src/main/kotlin/com/csdcorp/speech_to_text/SpeechToTextPlugin.kt delete mode 100644 speech_to_text_/example/.gitignore delete mode 100644 speech_to_text_/example/.metadata delete mode 100644 speech_to_text_/example/README.md delete mode 100644 speech_to_text_/example/android/.project delete mode 100644 speech_to_text_/example/android/.settings/org.eclipse.buildship.core.prefs delete mode 100644 speech_to_text_/example/android/app/build.gradle delete mode 100644 speech_to_text_/example/android/app/src/debug/AndroidManifest.xml delete mode 100644 speech_to_text_/example/android/app/src/main/AndroidManifest.xml delete mode 100644 speech_to_text_/example/android/app/src/main/kotlin/com/csdcorp/speech_to_text_example/MainActivity.kt delete mode 100644 speech_to_text_/example/android/app/src/main/res/drawable/launch_background.xml delete mode 100644 speech_to_text_/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png delete mode 100644 speech_to_text_/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png delete mode 100644 speech_to_text_/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png delete mode 100644 speech_to_text_/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png delete mode 100644 speech_to_text_/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 speech_to_text_/example/android/app/src/main/res/values/styles.xml delete mode 100644 speech_to_text_/example/android/app/src/profile/AndroidManifest.xml delete mode 100644 speech_to_text_/example/android/build.gradle delete mode 100644 speech_to_text_/example/android/gradle.properties delete mode 100644 speech_to_text_/example/android/gradle/wrapper/gradle-wrapper.properties delete mode 100644 speech_to_text_/example/android/settings.gradle delete mode 100644 speech_to_text_/example/assets/sounds/speech_to_text_cancel.m4r delete mode 100644 speech_to_text_/example/assets/sounds/speech_to_text_listening.m4r delete mode 100644 speech_to_text_/example/assets/sounds/speech_to_text_stop.m4r delete mode 100644 speech_to_text_/example/ios/Flutter/AppFrameworkInfo.plist delete mode 100644 speech_to_text_/example/ios/Flutter/Debug.xcconfig delete mode 100644 speech_to_text_/example/ios/Flutter/Flutter.podspec delete mode 100644 speech_to_text_/example/ios/Flutter/Release.xcconfig delete mode 100644 speech_to_text_/example/ios/Podfile delete mode 100644 speech_to_text_/example/ios/Podfile.lock delete mode 100644 speech_to_text_/example/ios/Runner.xcodeproj/project.pbxproj delete mode 100644 speech_to_text_/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata delete mode 100644 speech_to_text_/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme delete mode 100644 speech_to_text_/example/ios/Runner.xcworkspace/contents.xcworkspacedata delete mode 100644 speech_to_text_/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 speech_to_text_/example/ios/Runner/AppDelegate.swift delete mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png delete mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png delete mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png delete mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png delete mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png delete mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png delete mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png delete mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png delete mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png delete mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png delete mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png delete mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png delete mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png delete mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png delete mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png delete mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json delete mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png delete mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png delete mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png delete mode 100644 speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md delete mode 100644 speech_to_text_/example/ios/Runner/Base.lproj/LaunchScreen.storyboard delete mode 100644 speech_to_text_/example/ios/Runner/Base.lproj/Main.storyboard delete mode 100644 speech_to_text_/example/ios/Runner/Info.plist delete mode 100644 speech_to_text_/example/ios/Runner/Runner-Bridging-Header.h delete mode 100644 speech_to_text_/example/lib/main.dart delete mode 100644 speech_to_text_/example/pubspec.yaml delete mode 100644 speech_to_text_/example/test/widget_test.dart delete mode 100644 speech_to_text_/ios/.gitignore delete mode 100644 speech_to_text_/ios/Assets/.gitkeep delete mode 100644 speech_to_text_/ios/Classes/SpeechToTextPlugin.h delete mode 100644 speech_to_text_/ios/Classes/SpeechToTextPlugin.m delete mode 100644 speech_to_text_/ios/Classes/SwiftSpeechToTextPlugin.swift delete mode 100644 speech_to_text_/ios/speech_to_text.podspec delete mode 100644 speech_to_text_/lib/speech_recognition_error.dart delete mode 100644 speech_to_text_/lib/speech_recognition_error.g.dart delete mode 100644 speech_to_text_/lib/speech_recognition_event.dart delete mode 100644 speech_to_text_/lib/speech_recognition_result.dart delete mode 100644 speech_to_text_/lib/speech_recognition_result.g.dart delete mode 100644 speech_to_text_/lib/speech_to_text.dart delete mode 100644 speech_to_text_/lib/speech_to_text_provider.dart delete mode 100644 speech_to_text_/pubspec.yaml delete mode 100644 speech_to_text_/test/speech_recognition_error_test.dart delete mode 100644 speech_to_text_/test/speech_recognition_event_test.dart delete mode 100644 speech_to_text_/test/speech_recognition_result_test.dart delete mode 100644 speech_to_text_/test/speech_recognitions_words_test.dart delete mode 100644 speech_to_text_/test/speech_to_text_provider_test.dart delete mode 100644 speech_to_text_/test/speech_to_text_test.dart delete mode 100644 speech_to_text_/test/test_speech_channel_handler.dart delete mode 100644 speech_to_text_/test/test_speech_listener.dart diff --git a/lib/widgets/others/app_scaffold_widget.dart b/lib/widgets/others/app_scaffold_widget.dart index a1908b6e..6f3481eb 100644 --- a/lib/widgets/others/app_scaffold_widget.dart +++ b/lib/widgets/others/app_scaffold_widget.dart @@ -48,9 +48,7 @@ class AppScaffold extends StatelessWidget { final double preferredSize; final List appBarIcons; final PreferredSizeWidget appBarWidget; - ProjectViewModel projectProvider; - final List imagesInfo; AuthenticatedUserObject authenticatedUserObject = locator(); @@ -84,7 +82,6 @@ class AppScaffold extends StatelessWidget { AppGlobal.context = context; PreferredSizeWidget appBar; - projectProvider = Provider.of(context); if (this.appBarWidget == null) { PreferredSizeWidget appBarWidget = AppBarWidget( appBarTitle, @@ -97,8 +94,8 @@ class AppScaffold extends StatelessWidget { appBar = preferredSize == 0 ? appBarWidget : PreferredSize( - child: appBarWidget, - preferredSize: Size.fromHeight(preferredSize)); + child: appBarWidget, + preferredSize: Size.fromHeight(preferredSize)); } else { appBar = this.appBarWidget; } @@ -106,60 +103,7 @@ class AppScaffold extends StatelessWidget { return Scaffold( backgroundColor: backgroundColor ?? Theme.of(context).scaffoldBackgroundColor, - appBar: isShowAppBar - ? AppBar( - elevation: 0, - backgroundColor: Theme.of(context).appBarTheme.color, - textTheme: TextTheme( - headline6: - TextStyle(color: Colors.white, fontWeight: FontWeight.bold), - ), - title: Texts( - authenticatedUserObject.isLogin || !isShowDecPage - ? appBarTitle.toUpperCase() - : TranslationBase.of(context).serviceInformationTitle, - color: Colors.white, - bold: true, - ), - leading: Builder( - builder: (BuildContext context) { - return ArrowBack(); - }, - ), - centerTitle: true, - actions: [ - image != null - ? InkWell( - onTap: () => Navigator.push( - context, - FadePage( - page: InsuranceUpdate(), - ), - ), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Image.asset( - image, - height: SizeConfig.heightMultiplier * 5, - width: SizeConfig.heightMultiplier * 5, - color: Colors.white, - ), - ), - ) - : IconButton( - icon: Icon(FontAwesomeIcons.home), - color: Colors.white, - onPressed: () { - Navigator.pushAndRemoveUntil( - context, - MaterialPageRoute( - builder: (context) => LandingPage()), - (Route r) => false); - }, - ), - ], - ) - : null, + appBar: appBar, body: (!Provider.of(context, listen: false).isLogin && isShowDecPage) ? NotAutPage( @@ -174,11 +118,8 @@ class AppScaffold extends StatelessWidget { baseViewModel: baseViewModel, ) : buildBodyWidget(context), - bottomSheet: - (Provider.of(context, listen: false).isLogin || - !isShowDecPage) - ? bottomSheet - : null, + bottomSheet: bottomSheet + //floatingActionButton: floatingActionButton ?? floatingActionButton, // bottomNavigationBar: // this.isBottomBar == true ? BottomBarSearch() : SizedBox() @@ -194,9 +135,7 @@ class AppScaffold extends StatelessWidget { // return body; //Stack(children: [body, buildAppLoaderWidget(isLoading)]); return Stack(children: [ body, - isHelp ? RobotIcon() : Container() - - /*FloatingSearchButton()*/ + isHelp==true ? RobotIcon() : Container() ]); } } diff --git a/lib/widgets/others/floating_button_search.dart b/lib/widgets/others/floating_button_search.dart index cbeaafc5..5608f517 100644 --- a/lib/widgets/others/floating_button_search.dart +++ b/lib/widgets/others/floating_button_search.dart @@ -5,6 +5,7 @@ import 'dart:math'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/config/size_config.dart'; import 'package:diplomaticquarterapp/core/service/AuthenticatedUserObject.dart'; import 'package:diplomaticquarterapp/core/service/medical/vital_sign_service.dart'; import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; @@ -49,6 +50,7 @@ import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; import 'package:diplomaticquarterapp/uitl/app_toast.dart'; import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/text/app_texts_widget.dart'; import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; @@ -131,7 +133,7 @@ class _FloatingSearchButton extends State @override void didUpdateWidget(FloatingSearchButton oldWidget) { - super.didUpdateWidget(oldWidget); + // super.didUpdateWidget(oldWidget); // event.controller.stream.listen((p) { // if (p['animationEnable'] != 'false') { // initialSpeak(); @@ -169,6 +171,8 @@ class _FloatingSearchButton extends State : 'assets/images/gif/robot-idle.gif'), ), onTap: () { + + new RoboSearch(context: context).showAlertDialog(context); initSpeechState().then((value) => {startVoiceSearch()}); }, ), @@ -879,3 +883,81 @@ class _FloatingSearchButton extends State Navigator.of(context).pushNamed(HOME); } } + +class RoboSearch { + final BuildContext context; + var event = RobotProvider(); + var searchText = null; + RoboSearch({ + @required this.context, + }); + + showAlertDialog(BuildContext context) { + // set up the buttons + + // set up the AlertDialog + AlertDialog alert = AlertDialog( + content: StatefulBuilder( + builder: (BuildContext context, StateSetter setState) { + setState(() { + event.controller.stream.listen((p) { + if (p['searchText'] != null) { + setState(() { + searchText = p['searchText']; + }); + } + }); + }); + return Container( + color: Colors.white, + height: SizeConfig.realScreenHeight * 0.5, + width: SizeConfig.realScreenWidth * 0.8, + child: Container( + child: Column(children: [ + Expanded( + flex: 1, + child: Center( + child: Image.asset( + 'assets/images/habib-logo.png', + height: 75, + width: 75, + ))), + Expanded( + flex: 3, + child: Center( + child: Container( + margin: EdgeInsets.all(20), + padding: EdgeInsets.all(10), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(100), + border: Border.all(width: 2, color: Colors.red)), + child: Icon( + Icons.mic, + color: Colors.blue, + size: 48, + ), + ))), + Expanded( + flex: 1, + child: Center( + child: Text(searchText != null + ? searchText + : 'Try saying something'))) + ]), + )); + }), + ); + + // show the dialog + showDialog( + context: context, + builder: (BuildContext context) { + return alert; + }, + ); + } + + static closeAlertDialog(BuildContext context) { + Navigator.of(context).pop(); + } +} diff --git a/speech_to_text/.github/workflows/main.yml b/speech_to_text/.github/workflows/main.yml deleted file mode 100644 index 87b78c31..00000000 --- a/speech_to_text/.github/workflows/main.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: build - -on: - push: - branches: - - main - -jobs: - test: - name: Test on Ubuntu - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - uses: subosito/flutter-action@v1.3.2 - with: - flutter-version: '1.20.3' - channel: 'stable' - - run: flutter pub get - - run: flutter test diff --git a/speech_to_text/.vscode/launch.json b/speech_to_text/.vscode/launch.json deleted file mode 100644 index 9f8693fe..00000000 --- a/speech_to_text/.vscode/launch.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "Flutter", - "request": "launch", - "type": "dart", - "program": "example/lib/main.dart" - } - ] -} \ No newline at end of file diff --git a/speech_to_text/codestats.csv b/speech_to_text/codestats.csv deleted file mode 100644 index 7319cf19..00000000 --- a/speech_to_text/codestats.csv +++ /dev/null @@ -1 +0,0 @@ -2020/10/18 15:15:20,99.0,7,1003,111,324,568,75 diff --git a/speech_to_text/example/android/.gitignore b/speech_to_text/example/android/.gitignore deleted file mode 100644 index 0a741cb4..00000000 --- a/speech_to_text/example/android/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -gradle-wrapper.jar -/.gradle -/captures/ -/gradlew -/gradlew.bat -/local.properties -GeneratedPluginRegistrant.java - -# Remember to never publicly share your keystore. -# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app -key.properties diff --git a/speech_to_text/example/android/app/src/main/kotlin/com/csdcorp/example/MainActivity.kt b/speech_to_text/example/android/app/src/main/kotlin/com/csdcorp/example/MainActivity.kt deleted file mode 100644 index 9143acd8..00000000 --- a/speech_to_text/example/android/app/src/main/kotlin/com/csdcorp/example/MainActivity.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.csdcorp.example - -import io.flutter.embedding.android.FlutterActivity - -class MainActivity: FlutterActivity() { -} diff --git a/speech_to_text/example/ios/.gitignore b/speech_to_text/example/ios/.gitignore deleted file mode 100644 index e96ef602..00000000 --- a/speech_to_text/example/ios/.gitignore +++ /dev/null @@ -1,32 +0,0 @@ -*.mode1v3 -*.mode2v3 -*.moved-aside -*.pbxuser -*.perspectivev3 -**/*sync/ -.sconsign.dblite -.tags* -**/.vagrant/ -**/DerivedData/ -Icon? -**/Pods/ -**/.symlinks/ -profile -xcuserdata -**/.generated/ -Flutter/App.framework -Flutter/Flutter.framework -Flutter/Flutter.podspec -Flutter/Generated.xcconfig -Flutter/app.flx -Flutter/app.zip -Flutter/flutter_assets/ -Flutter/flutter_export_environment.sh -ServiceDefinitions.json -Runner/GeneratedPluginRegistrant.* - -# Exceptions to above rules. -!default.mode1v3 -!default.mode2v3 -!default.pbxuser -!default.perspectivev3 diff --git a/speech_to_text/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/speech_to_text/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d98100..00000000 --- a/speech_to_text/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/speech_to_text/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/speech_to_text/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index f9b0d7c5..00000000 --- a/speech_to_text/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - PreviewsEnabled - - - diff --git a/speech_to_text/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/speech_to_text/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index f9b0d7c5..00000000 --- a/speech_to_text/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - PreviewsEnabled - - - diff --git a/speech_to_text/example/lib/port.dart b/speech_to_text/example/lib/port.dart deleted file mode 100644 index 90af3822..00000000 --- a/speech_to_text/example/lib/port.dart +++ /dev/null @@ -1,174 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:speech_to_text/speech_to_text.dart'; -import 'package:speech_to_text/speech_recognition_result.dart'; -import 'package:speech_to_text/speech_recognition_error.dart'; - -void main() { - runApp(new MyApp()); -} - -List languages = [ - const Language('System', 'default'), - const Language('Francais', 'fr_FR'), - const Language('English', 'en_US'), - const Language('Pусский', 'ru_RU'), - const Language('Italiano', 'it_IT'), - const Language('Español', 'es_ES'), -]; - -class Language { - final String name; - final String code; - - const Language(this.name, this.code); -} - -class MyApp extends StatefulWidget { - @override - _MyAppState createState() => new _MyAppState(); -} - -class _MyAppState extends State { - SpeechToText _speech; - - bool _speechRecognitionAvailable = false; - bool _isListening = false; - - String transcription = ''; - - //String _currentLocale = 'en_US'; - Language selectedLang = languages.first; - - @override - initState() { - super.initState(); - activateSpeechRecognizer(); - } - - // Platform messages are asynchronous, so we initialize in an async method. - Future activateSpeechRecognizer() async { - print('_MyAppState.activateSpeechRecognizer... '); - _speech = SpeechToText(); - // _speech.setCurrentLocaleHandler(onCurrentLocale); - // _speech.setRecognitionStartedHandler(onRecognitionStarted); - // _speech.setRecognitionCompleteHandler(onRecognitionComplete); - _speechRecognitionAvailable = await _speech.initialize( - onError: errorHandler, onStatus: onSpeechAvailability); - List localeNames = await _speech.locales(); - languages.clear(); - localeNames.forEach((localeName) => - languages.add(Language(localeName.name, localeName.localeId))); - var currentLocale = await _speech.systemLocale(); - if (null != currentLocale) { - selectedLang = - languages.firstWhere((lang) => lang.code == currentLocale.localeId); - } - setState(() {}); - } - - @override - Widget build(BuildContext context) { - return new MaterialApp( - home: new Scaffold( - appBar: new AppBar( - title: new Text('SpeechRecognition'), - actions: [ - new PopupMenuButton( - onSelected: _selectLangHandler, - itemBuilder: (BuildContext context) => _buildLanguagesWidgets, - ) - ], - ), - body: new Padding( - padding: new EdgeInsets.all(8.0), - child: new Center( - child: new Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - new Expanded( - child: new Container( - padding: const EdgeInsets.all(8.0), - color: Colors.grey.shade200, - child: new Text(transcription))), - _buildButton( - onPressed: _speechRecognitionAvailable && !_isListening - ? () => start() - : null, - label: _isListening - ? 'Listening...' - : 'Listen (${selectedLang.code})', - ), - _buildButton( - onPressed: _isListening ? () => cancel() : null, - label: 'Cancel', - ), - _buildButton( - onPressed: _isListening ? () => stop() : null, - label: 'Stop', - ), - ], - ), - )), - ), - ); - } - - List> get _buildLanguagesWidgets => languages - .map((l) => new CheckedPopupMenuItem( - value: l, - checked: selectedLang == l, - child: new Text(l.name), - )) - .toList(); - - void _selectLangHandler(Language lang) { - setState(() => selectedLang = lang); - } - - Widget _buildButton({String label, VoidCallback onPressed}) => new Padding( - padding: new EdgeInsets.all(12.0), - child: new RaisedButton( - color: Colors.cyan.shade600, - onPressed: onPressed, - child: new Text( - label, - style: const TextStyle(color: Colors.white), - ), - )); - - void start() => _speech.listen( - onResult: onRecognitionResult, localeId: selectedLang.code); - - void cancel() { - _speech.cancel(); - setState(() => _isListening = false); - } - - void stop() { - _speech.stop(); - setState(() => _isListening = false); - } - - void onSpeechAvailability(String status) { - setState(() { - _speechRecognitionAvailable = _speech.isAvailable; - _isListening = _speech.isListening; - }); - } - - void onCurrentLocale(String locale) { - print('_MyAppState.onCurrentLocale... $locale'); - setState( - () => selectedLang = languages.firstWhere((l) => l.code == locale)); - } - - // void onRecognitionStarted() => setState(() => _isListening = true); - - void onRecognitionResult(SpeechRecognitionResult result) => - setState(() => transcription = result.recognizedWords); - - // void onRecognitionComplete() => setState(() => _isListening = false); - - void errorHandler(SpeechRecognitionError error) => print(error); -} diff --git a/speech_to_text/example/lib/provider_example.dart b/speech_to_text/example/lib/provider_example.dart deleted file mode 100644 index 6c14c4cb..00000000 --- a/speech_to_text/example/lib/provider_example.dart +++ /dev/null @@ -1,195 +0,0 @@ -import 'dart:async'; - -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:speech_to_text/speech_to_text.dart'; -import 'package:speech_to_text/speech_to_text_provider.dart'; - -void main() => runApp(ProviderDemoApp()); - -class ProviderDemoApp extends StatefulWidget { - @override - _ProviderDemoAppState createState() => _ProviderDemoAppState(); -} - -class _ProviderDemoAppState extends State { - final SpeechToText speech = SpeechToText(); - SpeechToTextProvider speechProvider; - - @override - void initState() { - super.initState(); - speechProvider = SpeechToTextProvider(speech); - initSpeechState(); - } - - Future initSpeechState() async { - await speechProvider.initialize(); - } - - @override - Widget build(BuildContext context) { - return ChangeNotifierProvider.value( - value: speechProvider, - child: MaterialApp( - home: Scaffold( - appBar: AppBar( - title: const Text('Speech to Text Provider Example'), - ), - body: SpeechProviderExampleWidget(), - ), - ), - ); - } -} - -class SpeechProviderExampleWidget extends StatefulWidget { - @override - _SpeechProviderExampleWidgetState createState() => - _SpeechProviderExampleWidgetState(); -} - -class _SpeechProviderExampleWidgetState - extends State { - String _currentLocaleId = ""; - - void _setCurrentLocale(SpeechToTextProvider speechProvider) { - if (speechProvider.isAvailable && _currentLocaleId.isEmpty) { - _currentLocaleId = speechProvider.systemLocale.localeId; - } - } - - @override - Widget build(BuildContext context) { - var speechProvider = Provider.of(context); - if (speechProvider.isNotAvailable) { - return Center( - child: Text( - 'Speech recognition not available, no permission or not available on the device.'), - ); - } - _setCurrentLocale(speechProvider); - return Column(children: [ - Center( - child: Text( - 'Speech recognition available', - style: TextStyle(fontSize: 22.0), - ), - ), - Container( - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - FlatButton( - child: Text('Start'), - onPressed: - !speechProvider.isAvailable || speechProvider.isListening - ? null - : () => speechProvider.listen( - partialResults: true, localeId: _currentLocaleId), - ), - FlatButton( - child: Text('Stop'), - onPressed: speechProvider.isListening - ? () => speechProvider.stop() - : null, - ), - FlatButton( - child: Text('Cancel'), - onPressed: speechProvider.isListening - ? () => speechProvider.cancel() - : null, - ), - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - DropdownButton( - onChanged: (selectedVal) => _switchLang(selectedVal), - value: _currentLocaleId, - items: speechProvider.locales - .map( - (localeName) => DropdownMenuItem( - value: localeName.localeId, - child: Text(localeName.name), - ), - ) - .toList(), - ), - ], - ) - ], - ), - ), - Expanded( - flex: 4, - child: Column( - children: [ - Center( - child: Text( - 'Recognized Words', - style: TextStyle(fontSize: 22.0), - ), - ), - Expanded( - child: Container( - color: Theme.of(context).selectedRowColor, - child: Center( - child: speechProvider.hasResults - ? Text( - speechProvider.lastResult.recognizedWords, - textAlign: TextAlign.center, - ) - : Container(), - ), - ), - ), - ], - ), - ), - Expanded( - flex: 1, - child: Column( - children: [ - Center( - child: Text( - 'Error Status', - style: TextStyle(fontSize: 22.0), - ), - ), - Center( - child: speechProvider.hasError - ? Text(speechProvider.lastError.errorMsg) - : Container(), - ), - ], - ), - ), - Container( - padding: EdgeInsets.symmetric(vertical: 20), - color: Theme.of(context).backgroundColor, - child: Center( - child: speechProvider.isListening - ? Text( - "I'm listening...", - style: TextStyle(fontWeight: FontWeight.bold), - ) - : Text( - 'Not listening', - style: TextStyle(fontWeight: FontWeight.bold), - ), - ), - ), - ]); - } - - _switchLang(selectedVal) { - setState(() { - _currentLocaleId = selectedVal; - }); - print(selectedVal); - } -} diff --git a/speech_to_text/example/lib/stress.dart b/speech_to_text/example/lib/stress.dart deleted file mode 100644 index 0f83d33d..00000000 --- a/speech_to_text/example/lib/stress.dart +++ /dev/null @@ -1,292 +0,0 @@ -import 'dart:async'; - -import 'package:flutter/material.dart'; -import 'package:speech_to_text/speech_recognition_error.dart'; -import 'package:speech_to_text/speech_recognition_result.dart'; -import 'package:speech_to_text/speech_to_text.dart'; - -void main() => runApp(MyApp()); - -class MyApp extends StatefulWidget { - @override - _MyAppState createState() => _MyAppState(); -} - -class _MyAppState extends State { - bool _hasSpeech = false; - bool _stressTest = false; - double level = 0.0; - int _stressLoops = 0; - String lastWords = ""; - String lastError = ""; - String lastStatus = ""; - String _currentLocaleId = ""; - List _localeNames = []; - final SpeechToText speech = SpeechToText(); - - @override - void initState() { - super.initState(); - } - - Future initSpeechState() async { - bool hasSpeech = await speech.initialize( - onError: errorListener, onStatus: statusListener); - if (hasSpeech) { - _localeNames = await speech.locales(); - - var systemLocale = await speech.systemLocale(); - _currentLocaleId = systemLocale.localeId; - } - - if (!mounted) return; - - setState(() { - _hasSpeech = hasSpeech; - }); - } - - @override - Widget build(BuildContext context) { - return MaterialApp( - home: Scaffold( - appBar: AppBar( - title: const Text('Speech to Text Example'), - ), - body: Column(children: [ - Center( - child: Text( - 'Speech recognition available', - style: TextStyle(fontSize: 22.0), - ), - ), - Container( - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - FlatButton( - child: Text('Initialize'), - onPressed: _hasSpeech ? null : initSpeechState, - ), - FlatButton( - child: Text('Stress Test'), - onPressed: stressTest, - ), - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - FlatButton( - child: Text('Start'), - onPressed: !_hasSpeech || speech.isListening - ? null - : startListening, - ), - FlatButton( - child: Text('Stop'), - onPressed: speech.isListening ? stopListening : null, - ), - FlatButton( - child: Text('Cancel'), - onPressed: speech.isListening ? cancelListening : null, - ), - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - DropdownButton( - onChanged: (selectedVal) => _switchLang(selectedVal), - value: _currentLocaleId, - items: _localeNames - .map( - (localeName) => DropdownMenuItem( - value: localeName.localeId, - child: Text(localeName.name), - ), - ) - .toList(), - ), - ], - ) - ], - ), - ), - Expanded( - flex: 4, - child: Column( - children: [ - Center( - child: Text( - 'Recognized Words', - style: TextStyle(fontSize: 22.0), - ), - ), - Expanded( - child: Stack( - children: [ - Container( - color: Theme.of(context).selectedRowColor, - child: Center( - child: Text( - lastWords, - textAlign: TextAlign.center, - ), - ), - ), - Positioned.fill( - bottom: 10, - child: Align( - alignment: Alignment.bottomCenter, - child: Container( - width: 40, - height: 40, - alignment: Alignment.center, - decoration: BoxDecoration( - boxShadow: [ - BoxShadow( - blurRadius: .26, - spreadRadius: level * 1.5, - color: Colors.black.withOpacity(.05)) - ], - color: Colors.white, - borderRadius: - BorderRadius.all(Radius.circular(50)), - ), - child: IconButton( - icon: Icon(Icons.mic), onPressed: () => null), - ), - ), - ), - ], - ), - ), - ], - ), - ), - Expanded( - flex: 1, - child: Column( - children: [ - Center( - child: Text( - 'Error Status', - style: TextStyle(fontSize: 22.0), - ), - ), - Center( - child: Text(lastError), - ), - ], - ), - ), - Container( - padding: EdgeInsets.symmetric(vertical: 20), - color: Theme.of(context).backgroundColor, - child: Center( - child: speech.isListening - ? Text( - "I'm listening...", - style: TextStyle(fontWeight: FontWeight.bold), - ) - : Text( - 'Not listening', - style: TextStyle(fontWeight: FontWeight.bold), - ), - ), - ), - ]), - ), - ); - } - - void stressTest() { - if (_stressTest) { - return; - } - _stressLoops = 0; - _stressTest = true; - print("Starting stress test..."); - startListening(); - } - - void changeStatusForStress(String status) { - if (!_stressTest) { - return; - } - if (speech.isListening) { - stopListening(); - } else { - if (_stressLoops >= 100) { - _stressTest = false; - print("Stress test complete."); - return; - } - print("Stress loop: $_stressLoops"); - ++_stressLoops; - startListening(); - } - } - - void startListening() { - lastWords = ""; - lastError = ""; - speech.listen( - onResult: resultListener, - listenFor: Duration(seconds: 10), - localeId: _currentLocaleId, - onSoundLevelChange: soundLevelListener, - cancelOnError: true, - partialResults: true); - setState(() {}); - } - - void stopListening() { - speech.stop(); - setState(() { - level = 0.0; - }); - } - - void cancelListening() { - speech.cancel(); - setState(() { - level = 0.0; - }); - } - - void resultListener(SpeechRecognitionResult result) { - setState(() { - lastWords = "${result.recognizedWords} - ${result.finalResult}"; - }); - } - - void soundLevelListener(double level) { - setState(() { - this.level = level; - }); - } - - void errorListener(SpeechRecognitionError error) { - setState(() { - lastError = "${error.errorMsg} - ${error.permanent}"; - }); - } - - void statusListener(String status) { - changeStatusForStress(status); - setState(() { - lastStatus = "$status"; - }); - } - - _switchLang(selectedVal) { - setState(() { - _currentLocaleId = selectedVal; - }); - print(selectedVal); - } -} diff --git a/speech_to_text/lib/speech_to_text_web.dart b/speech_to_text/lib/speech_to_text_web.dart deleted file mode 100644 index 9708b272..00000000 --- a/speech_to_text/lib/speech_to_text_web.dart +++ /dev/null @@ -1,95 +0,0 @@ -import 'package:speech_to_text_platform_interface/speech_to_text_platform_interface.dart'; - -class SpeechToTextPlugin extends SpeechToTextPlatform { - @override - - /// Returns true if the user has already granted permission to access the - /// microphone, does not prompt the user. - /// - /// This method can be called before [initialize] to check if permission - /// has already been granted. If this returns false then the [initialize] - /// call will prompt the user for permission if it is allowed to do so. - /// Note that applications cannot ask for permission again if the user has - /// denied them permission in the past. - Future hasPermission() async { - return false; - } - - /// Initialize speech recognition services, returns true if - /// successful, false if failed. - /// - /// This method must be called before any other speech functions. - /// If this method returns false no further [SpeechToText] methods - /// should be used. False usually means that the user has denied - /// permission to use speech. - /// - /// [debugLogging] controls whether there is detailed logging from the underlying - /// plugins. It is off by default, usually only useful for troubleshooting issues - /// with a paritcular OS version or device, fairly verbose - Future initialize( - {debugLogging = false, List options}) async { - return false; - } - - /// Stops the current listen for speech if active, does nothing if not. - /// - /// Stopping a listen session will cause a final result to be sent. Each - /// listen session should be ended with either [stop] or [cancel], for - /// example in the dispose method of a Widget. [cancel] is automatically - /// invoked by a permanent error if [cancelOnError] is set to true in the - /// [listen] call. - /// - /// *Note:* Cannot be used until a successful [initialize] call. Should - /// only be used after a successful [listen] call. - Future stop() async {} - - /// Cancels the current listen for speech if active, does nothing if not. - /// - /// Canceling means that there will be no final result returned from the - /// recognizer. Each listen session should be ended with either [stop] or - /// [cancel], for example in the dispose method of a Widget. [cancel] is - /// automatically invoked by a permanent error if [cancelOnError] is set - /// to true in the [listen] call. - /// - /// *Note* Cannot be used until a successful [initialize] call. Should only - /// be used after a successful [listen] call. - Future cancel() async {} - - /// Starts a listening session for speech and converts it to text. - /// - /// Cannot be used until a successful [initialize] call. There is a - /// time limit on listening imposed by both Android and iOS. The time - /// depends on the device, network, etc. Android is usually quite short, - /// especially if there is no active speech event detected, on the order - /// of ten seconds or so. - /// - /// [localeId] is an optional locale that can be used to listen in a language - /// other than the current system default. See [locales] to find the list of - /// supported languages for listening. - /// - /// [partialResults] if true the listen reports results as they are recognized, - /// when false only final results are reported. Defaults to true. - /// - /// [onDevice] if true the listen attempts to recognize locally with speech never - /// leaving the device. If it cannot do this the listen attempt will fail. This is - /// usually only needed for sensitive content where privacy or security is a concern. - /// - /// [sampleRate] optional for compatibility with certain iOS devices, some devices - /// crash with `sampleRate != device's supported sampleRate`, try 44100 if seeing - /// crashes - /// - Future listen( - {String localeId, - partialResults = true, - onDevice = false, - int listenMode, - sampleRate = 0}) async { - return false; - } - - /// returns the list of speech locales available on the device. - /// - Future> locales() async { - return []; - } -} diff --git a/speech_to_text/scripts/tcov.sh b/speech_to_text/scripts/tcov.sh deleted file mode 100644 index 5d8be65b..00000000 --- a/speech_to_text/scripts/tcov.sh +++ /dev/null @@ -1,5 +0,0 @@ -# Ensure test errors fail the script -set -e -flutter test --coverage -coverPct=$(genhtml coverage/lcov.info -o coverage | tail -n 2 | head -n 1 | cut -d ' ' -f 4 | sed 's/%//') -scc lib | sed -n '4p' | tr -s ' ' | cut -d ' ' -f 2-7 | sed "s/^/$coverPct,/" | sed 's/ /,/g' | sed "s/^/`date '+%Y\/%m\/%d %H:%M:%S'`,/" >> codestats.csv \ No newline at end of file diff --git a/speech_to_text/test/test_speech_to_text_platform.dart b/speech_to_text/test/test_speech_to_text_platform.dart deleted file mode 100644 index 040fe7eb..00000000 --- a/speech_to_text/test/test_speech_to_text_platform.dart +++ /dev/null @@ -1,133 +0,0 @@ -import 'package:flutter/services.dart'; -import 'package:speech_to_text/speech_recognition_error.dart'; -import 'package:speech_to_text/speech_recognition_result.dart'; -import 'package:speech_to_text/speech_to_text.dart'; -import 'package:speech_to_text_platform_interface/speech_to_text_platform_interface.dart'; - -class TestSpeechToTextPlatform extends SpeechToTextPlatform { - static const String listenExceptionCode = "listenFailedError"; - static const String listenExceptionMessage = "Failed"; - static const String listenExceptionDetails = "Device Listen Failure"; - - bool initResult = true; - bool initInvoked = false; - bool listenInvoked = false; - bool cancelInvoked = false; - bool stopInvoked = false; - bool localesInvoked = false; - bool hasPermissionResult = true; - bool listenException = false; - String listeningStatusResponse = SpeechToText.listeningStatus; - String listenLocale; - List localesResult = []; - static const String localeId1 = "en_US"; - static const String localeId2 = "fr_CA"; - static const String name1 = "English US"; - static const String name2 = "French Canada"; - static const String locale1 = "$localeId1:$name1"; - static const String locale2 = "$localeId2:$name2"; - static const String firstRecognizedWords = 'hello'; - static const String secondRecognizedWords = 'hello there'; - static const double firstConfidence = 0.85; - static const double secondConfidence = 0.62; - static const String firstRecognizedJson = - '{"alternates":[{"recognizedWords":"$firstRecognizedWords","confidence":$firstConfidence}],"finalResult":false}'; - static const String secondRecognizedJson = - '{"alternates":[{"recognizedWords":"$secondRecognizedWords","confidence":$secondConfidence}],"finalResult":false}'; - static const String finalRecognizedJson = - '{"alternates":[{"recognizedWords":"$secondRecognizedWords","confidence":$secondConfidence}],"finalResult":true}'; - static const SpeechRecognitionWords firstWords = - SpeechRecognitionWords(firstRecognizedWords, firstConfidence); - static const SpeechRecognitionWords secondWords = - SpeechRecognitionWords(secondRecognizedWords, secondConfidence); - static final SpeechRecognitionResult firstRecognizedResult = - SpeechRecognitionResult([firstWords], false); - static final SpeechRecognitionResult secondRecognizedResult = - SpeechRecognitionResult([secondWords], false); - static final SpeechRecognitionResult finalRecognizedResult = - SpeechRecognitionResult([secondWords], true); - static const String transientErrorJson = - '{"errorMsg":"network","permanent":false}'; - static const String permanentErrorJson = - '{"errorMsg":"network","permanent":true}'; - static final SpeechRecognitionError firstError = - SpeechRecognitionError("network", true); - static const double level1 = 0.5; - static const double level2 = 10; - - @override - Future hasPermission() async { - return hasPermissionResult; - } - - @override - Future initialize( - {debugLogging = false, List options}) async { - initInvoked = true; - return initResult; - } - - @override - Future stop() async { - stopInvoked = true; - } - - @override - Future cancel() async { - cancelInvoked = true; - } - - @override - Future listen( - {String localeId, - partialResults = true, - onDevice = false, - int listenMode, - sampleRate = 0}) async { - listenInvoked = true; - listenLocale = localeId; - if (listenException) { - throw PlatformException( - code: listenExceptionCode, - message: listenExceptionMessage, - details: listenExceptionDetails); - } - return true; - } - - @override - Future> locales() async { - localesInvoked = true; - return localesResult; - } - - void notifyListening() { - onStatus(SpeechToText.listeningStatus); - } - - void notifyFinalWords() { - onTextRecognition(finalRecognizedJson); - } - - void notifyPartialWords() { - onTextRecognition(firstRecognizedJson); - } - - void notifyPermanentError() { - onError(permanentErrorJson); - } - - void notifyTransientError() { - onError(transientErrorJson); - } - - void notifySoundLevel() { - onSoundLevel(level2); - } - - void setupLocales() { - localesResult.clear(); - localesResult.add(locale1); - localesResult.add(locale2); - } -} diff --git a/speech_to_text_/.github/workflows/master.yml b/speech_to_text_/.github/workflows/master.yml deleted file mode 100644 index 4d4cff1c..00000000 --- a/speech_to_text_/.github/workflows/master.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: build - -on: - push: - branches: - - master - -jobs: - test: - name: Test on Ubuntu - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - uses: subosito/flutter-action@v1.3.2 - with: - flutter-version: '1.17.1' - channel: 'stable' - - run: flutter pub get - - run: flutter test diff --git a/speech_to_text_/.gitignore b/speech_to_text_/.gitignore deleted file mode 100644 index 8969cbcd..00000000 --- a/speech_to_text_/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -.DS_Store -.dart_tool/ - -.packages -.pub/ - -build/ -coverage/ -example/.flutter-plugins-dependencies -**/ios/Flutter/flutter_export_environment.sh -android/.idea/ diff --git a/speech_to_text_/.metadata b/speech_to_text_/.metadata deleted file mode 100644 index 1940d996..00000000 --- a/speech_to_text_/.metadata +++ /dev/null @@ -1,10 +0,0 @@ -# This file tracks properties of this Flutter project. -# Used by Flutter tool to assess capabilities and perform upgrades etc. -# -# This file should be version controlled and should not be manually edited. - -version: - revision: 2d2a1ffec95cc70a3218872a2cd3f8de4933c42f - channel: stable - -project_type: plugin diff --git a/speech_to_text_/CHANGELOG.md b/speech_to_text_/CHANGELOG.md deleted file mode 100644 index 477e110c..00000000 --- a/speech_to_text_/CHANGELOG.md +++ /dev/null @@ -1,166 +0,0 @@ -# Changelog - -## 2.3.0 - -### New - * new parameter `onDevice` on the `listen` method enforces on device recognition for sensitive content - * onSoundLevelChange now supported on iOS - * added compile troubleshooting help to README.md - * `SpeechToTextProvider` is an alternate and simpler way to interact with the `SpeechToText` plugin. - * new `provider_example.dart` example for usage of `SpeechToTextProvider`. -### Fix - * on iOS handles some conflicts with other applications better to keep speech working after calls for example - - -## 2.2.0 - -### New - * improved error handling and logging in the iOS implementation - * added general guides for iOS to the README - * moved stress testing out of the main example - * iOS now defaults to using the speaker rather than the receiver for start /stop sounds when no headphones -### Fix - * iOS now properly deactivates the audio session when no longer listening - * start and stop sounds on iOS should be more reliable when available - -## 2.1.0 -### Breaking - * `listenFor` now calls `stop` rather than `cancel` as this seems like more useful behaviour - -### Fix - * Android no longer stops or cancels the speech recognizer if it has already been shutdown by a - timeout or other platform behaviour. - * Android no longer tries to restart the listener when it is already active - * Now properly notifies errors that happen after listening stops due to platform callback rather than - client request. See https://github.com/csdcorp/speech_to_text/issues/51 - -## 2.0.1 -### Fix - * Resolves an issue with the Android implementation not handling permission requests properly on apps - that didn't use the 1.12.x plugin APIs for registration. The permission dialog would not appear and - permission was denied. - - -## 2.0.0 - -### Breaking - - * Upgraded to New Swift 1.12 plugin structure, may work with older Flutter version but not guaranteed - -### New - - * the plugin now requests both speech and microphone permission on initialize on iOS - * added `debugLogging` parameter to the `initialize` method to control native logging - -### Fix - - * The Android implementation now blocks duplicate results notifications. It appears that at least on some - Android versions the final results notification onResults is notified twice when Android automatically - terminates the session due to a pause time. The de-duplication looks for successive notifications - with < 100 ms between them and blocks the second. If you miss any onResult notifications please post - an issue. - -## 1.1.0 - -### New - - * error_timeout has been separated into error_network_timeout and error_speech_timeout - -## 1.0.0 - -### New - * hasPermission to check for the current permission without bringing up the system dialog - * `listen` has a new optional `cancelOnError` parameter to support automatically canceling - a listening session on a permanent error. - * `listen` has a new optional `partialResults` parameter that controls whether the callback - receives partial or only final results. - -## 0.8.0 - -### New - - * speech recognizer now exposes multiple possible transcriptions for each recognized speech - * alternates list on SpeechRecognitionResult exposes alternate transcriptions of voice - * confidence on SpeechRecognitionResult gives an estimate of confidence in the transcription - * isConfident on SpeechRecognitionResult supports testing confidence - * hasConfidenceRating on SpeechRecognitionResult indicates if confidence was provided from the device - * new SpeechRecognitionWords class gives details on per transcription words and confidence - -### Fix - - * speechRecognizer availabilityDidChange was crashing if invoked due to an invalid parameter type - * Added iOS platform 10 to example Podfile to resolve compilation warnings - -## 0.7.2 - -### Breaking - - * Upgrade Swift to version 5 to match Flutter. Projects using this plugin must now switch to 5. - -## 0.7.1 - -### Fix - - * Upgrade Kotlin to 1.3.5 to match the Flutter 1.12 version - * Upgrade Gradle build to 3.5.0 to match the Flutter 1.12 version - * Android version of the plugin was repeating the system default locale in the `locales` list - -## 0.7.0 - -### New - - * locales method returns the list of available languages for speech - * new optional localeId parameter on listen method supports choosing the comprehension language separately from the current system locale. - -### Breaking - - * `cancel` and `stop` are now async - -## 0.6.3 - -### Fix - - * request permission fix on Android to ensure it doesn't conflict with other requests - -## 0.6.2 - -### Fix - - * channel invoke wasn't being done on the main thread in iOS - -## 0.6.1 - -### Fix - - * listening sound was failing due to timing, now uses play and record mode on iOS. - - ## 0.6.0 -### Breaking - - * The filenames for the optional sounds for iOS have changed. - -### New - - * Added an optional listenFor parameter to set a max duration to listen for speech and then automatically cancel. - -### Fix - - * Was failing to play sounds because of record mode. Now plays sounds before going into record mode and after coming out. - * Status listener was being ignored, now properly notifies on status changes. - -## 0.5.1 - * Fixes a problem where the recognizer left the AVAudioSession in record mode which meant that subsequent sounds couldn't be played. - -## 0.5.0 -Initial draft with limited functionality, supports: - * initializing speech recognition - * asking the user for permission if required - * listening for recognized speech - * canceling the current recognition session - * stopping the current recognition session -* Android and iOS 10+ support - -Missing: - * some error handling - * testing across multiple OS versions - * and more, to be discovered... diff --git a/speech_to_text_/LICENSE b/speech_to_text_/LICENSE deleted file mode 100644 index 7c3991c8..00000000 --- a/speech_to_text_/LICENSE +++ /dev/null @@ -1,29 +0,0 @@ -BSD 3-Clause License - -Copyright (c) 2019, Corner Software Development Corp. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/speech_to_text_/README.md b/speech_to_text_/README.md deleted file mode 100644 index af726f0e..00000000 --- a/speech_to_text_/README.md +++ /dev/null @@ -1,150 +0,0 @@ -# speech_to_text - -[![pub package](https://img.shields.io/badge/pub-v2.3.0-blue)](https://pub.dartlang.org/packages/speech_to_text) [![build status](https://github.com/csdcorp/speech_to_text/workflows/build/badge.svg)](https://github.com/csdcorp/speech_to_text/actions?query=workflow%3Abuild) - -A library that exposes device specific speech recognition capability. - -This plugin contains a set of classes that make it easy to use the speech recognition -capabilities of the mobile device in Flutter. It supports both Android and iOS. The -target use cases for this library are commands and short phrases, not continuous spoken -conversion or always on listening. - -## Recent Updates - -The 2.3.0 version adds `SpeechToTextProvider` as a simpler way to interact with the plugin. Checkout -the new `provider_example.dart` for intended usage. - -The 2.2.0 version improves audio session handling and start / stop sound playback on iOS. - -*Note*: Feedback from any test devices is welcome. - -## Using - -To recognize text from the microphone import the package and call the plugin, like so: - -```dart -import 'package:speech_to_text/speech_to_text.dart' as stt; - - stt.SpeechToText speech = stt.SpeechToText(); - bool available = await speech.initialize( onStatus: statusListener, onError: errorListener ); - if ( available ) { - speech.listen( onResult: resultListener ); - } - else { - print("The user has denied the use of speech recognition."); - } - // some time later... - speech.stop() -``` - -### Initialize once -The `initialize` method only needs to be called once per application session. After that `listen`, -`start`, `stop`, and `cancel` can be used to interact with the plugin. Subsequent calls to `initialize` -are ignored which is safe but does mean that the `onStatus` and `onError` callbacks cannot be reset after -the first call to `initialize`. For that reason there should be only one instance of the plugin per -application. The `SpeechToTextProvider` is one way to create a single instance and easily reuse it in -multiple widgets. - -## Permissions - -Applications using this plugin require user permissions. -### iOS - -Add the following keys to your _Info.plist_ file, located in `/ios/Runner/Info.plist`: - -* `NSSpeechRecognitionUsageDescription` - describe why your app uses speech recognition. This is called _Privacy - Speech Recognition Usage Description_ in the visual editor. -* `NSMicrophoneUsageDescription` - describe why your app needs access to the microphone. This is called _Privacy - Microphone Usage Description_ in the visual editor. - -### Android - -Add the record audio permission to your _AndroidManifest.xml_ file, located in `/android/app/src/main/AndroidManifest.xml`. - -* `android.permission.RECORD_AUDIO` - this permission is required for microphone access. -* `android.permission.INTERNET` - this permission is required because speech recognition may use remote services. - -## Adding Sounds for iOS (optional) - -Android automatically plays system sounds when speech listening starts or stops but iOS does not. This plugin supports playing sounds to indicate listening status on iOS if sound files are available as assets in the application. To enable sounds in an application using this plugin add the sound files to the project and reference them in the assets section of the application `pubspec.yaml`. The location and filenames of the sound files must exactly match what -is shown below or they will not be found. The example application for the plugin shows the usage. *Note* These files should be very short as they delay -the start / end of the speech recognizer until the sound playback is complete. -```yaml - assets: - - assets/sounds/speech_to_text_listening.m4r - - assets/sounds/speech_to_text_cancel.m4r - - assets/sounds/speech_to_text_stop.m4r -``` -* `speech_to_text_listening.m4r` - played when the listen method is called. -* `speech_to_text_cancel.m4r` - played when the cancel method is called. -* `speech_to_text_stop.m4r` - played when the stop method is called. - -## Troubleshooting - -### SDK version error trying to compile for Android -``` -Manifest merger failed : uses-sdk:minSdkVersion 16 cannot be smaller than version 21 declared in library [:speech_to_text] -``` -The speech_to_text plugin requires at least Android SDK 21 because some of the speech functions in Android -were only introduced in that version. To fix this error you need to change the `build.gradle` entry to reflect -this version. Here's what the relevant part of that file looked like as of this writing: -``` - defaultConfig { - applicationId "com.example.app" - minSdkVersion 21 - targetSdkVersion 28 - versionCode flutterVersionCode.toInteger() - versionName flutterVersionName - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } -``` - -### Incorrect Swift version trying to compile for iOS -``` -/Users/markvandergon/flutter/.pub-cache/hosted/pub.dartlang.org/speech_to_text-1.1.0/ios/Classes/SwiftSpeechToTextPlugin.swift:224:44: error: value of type 'SwiftSpeechToTextPlugin' has no member 'AVAudioSession' - rememberedAudioCategory = self.AVAudioSession.Category - ~~~~ ^~~~~~~~~~~~~~ - /Users/markvandergon/flutter/.pub-cache/hosted/pub.dartlang.org/speech_to_text-1.1.0/ios/Classes/SwiftSpeechToTextPlugin.swift:227:63: error: type 'Int' has no member 'notifyOthersOnDeactivation' - try self.audioSession.setActive(true, withFlags: .notifyOthersOnDeactivation) -``` -This happens when the Swift language version is not set correctly. See this thread for help https://github.com/csdcorp/speech_to_text/issues/45. - -### Swift not supported trying to compile for iOS -``` -`speech_to_text` does not specify a Swift version and none of the targets (`Runner`) integrating it have the `SWIFT_VERSION` attribute set. -``` -This usually happens for older projects that only support Objective-C. See this thread for help https://github.com/csdcorp/speech_to_text/issues/88. - -### Not working on a particular Android device -The symptom for this issue is that the `initialize` method will always fail. If you turn on debug logging -using the `debugLogging: true` flag on the `initialize` method you'll see `'Speech recognition unavailable'` -in the Android log. There's a lengthy issue discussion here https://github.com/csdcorp/speech_to_text/issues/36 -about this. The issue seems to be that the recognizer is not always automatically enabled on the device. Two -key things helped resolve the issue in this case at least. - -#### First -1. Go to Google Play -2. Search for 'Google' -3. You should find this app: https://play.google.com/store/apps/details?id=com.google.android.googlequicksearchbox -If 'Disabled' enable it - -This is the SO post that helped: https://stackoverflow.com/questions/28769320/how-to-check-wether-speech-recognition-is-available-or-not - -#### Second -Ensure the app has the required permissions. The symptom for this that you get a permanent error notification - 'error_audio_error` when starting a listen session. Here's a Stack Overflow post that addresses that - https://stackoverflow.com/questions/46376193/android-speechrecognizer-audio-recording-error - Here's the important excerpt: - >You should go to system setting, Apps, Google app, then enable its permission of microphone. - -### iOS recognition guidelines -Apple has quite a good guide on the user experience for using speech, the original is here -https://developer.apple.com/documentation/speech/sfspeechrecognizer This is the section that I think is particularly relevant: - ->#### Create a Great User Experience for Speech Recognition ->Here are some tips to consider when adding speech recognition support to your app. - ->**Be prepared to handle failures caused by speech recognition limits.** Because speech recognition is a network-based service, limits are enforced so that the service can remain freely available to all apps. Individual devices may be limited in the number of recognitions that can be performed per day, and each app may be throttled globally based on the number of requests it makes per day. If a recognition request fails quickly (within a second or two of starting), check to see if the recognition service became unavailable. If it is, you may want to ask users to try again later. - ->**Plan for a one-minute limit on audio duration.** Speech recognition places a relatively high burden on battery life and network usage. To minimize this burden, the framework stops speech recognition tasks that last longer than one minute. This limit is similar to the one for keyboard-related dictation. -Remind the user when your app is recording. For example, display a visual indicator and play sounds at the beginning and end of speech recognition to help users understand that they're being actively recorded. You can also display speech as it is being recognized so that users understand what your app is doing and see any mistakes made during the recognition process. - ->**Do not perform speech recognition on private or sensitive information.** Some speech is not appropriate for recognition. Don't send passwords, health or financial data, and other sensitive speech for recognition. diff --git a/speech_to_text_/android/.classpath b/speech_to_text_/android/.classpath deleted file mode 100644 index eb19361b..00000000 --- a/speech_to_text_/android/.classpath +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/speech_to_text_/android/.gitignore b/speech_to_text_/android/.gitignore deleted file mode 100644 index c6cbe562..00000000 --- a/speech_to_text_/android/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -*.iml -.gradle -/local.properties -/.idea/workspace.xml -/.idea/libraries -.DS_Store -/build -/captures diff --git a/speech_to_text_/android/.project b/speech_to_text_/android/.project deleted file mode 100644 index 3050653c..00000000 --- a/speech_to_text_/android/.project +++ /dev/null @@ -1,23 +0,0 @@ - - - speech_to_text - Project android_____ created by Buildship. - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.buildship.core.gradleprojectbuilder - - - - - - org.eclipse.jdt.core.javanature - org.eclipse.buildship.core.gradleprojectnature - - diff --git a/speech_to_text_/android/.settings/org.eclipse.buildship.core.prefs b/speech_to_text_/android/.settings/org.eclipse.buildship.core.prefs deleted file mode 100644 index 7a23d112..00000000 --- a/speech_to_text_/android/.settings/org.eclipse.buildship.core.prefs +++ /dev/null @@ -1,13 +0,0 @@ -arguments= -auto.sync=false -build.scans.enabled=false -connection.gradle.distribution=GRADLE_DISTRIBUTION(VERSION(5.6.1)) -connection.project.dir= -eclipse.preferences.version=1 -gradle.user.home= -java.home= -jvm.arguments= -offline.mode=false -override.workspace.settings=true -show.console.view=true -show.executions.view=true diff --git a/speech_to_text_/android/build.gradle b/speech_to_text_/android/build.gradle deleted file mode 100644 index 6b23b300..00000000 --- a/speech_to_text_/android/build.gradle +++ /dev/null @@ -1,44 +0,0 @@ -group 'com.csdcorp.speech_to_text' -version '1.0-SNAPSHOT' - -buildscript { - ext.kotlin_version = '1.3.50' - repositories { - google() - jcenter() - } - - dependencies { - classpath 'com.android.tools.build:gradle:3.5.0' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - } -} - -rootProject.allprojects { - repositories { - google() - jcenter() - } -} - -apply plugin: 'com.android.library' -apply plugin: 'kotlin-android' - -android { - compileSdkVersion 28 - - sourceSets { - main.java.srcDirs += 'src/main/kotlin' - } - defaultConfig { - minSdkVersion 21 - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - lintOptions { - disable 'InvalidPackage' - } -} - -dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" -} diff --git a/speech_to_text_/android/gradle/gradle.properties b/speech_to_text_/android/gradle/gradle.properties deleted file mode 100644 index 94adc3a3..00000000 --- a/speech_to_text_/android/gradle/gradle.properties +++ /dev/null @@ -1,3 +0,0 @@ -org.gradle.jvmargs=-Xmx1536M -android.useAndroidX=true -android.enableJetifier=true diff --git a/speech_to_text_/android/gradle/local.properties b/speech_to_text_/android/gradle/local.properties deleted file mode 100644 index 71a0a2e4..00000000 --- a/speech_to_text_/android/gradle/local.properties +++ /dev/null @@ -1,3 +0,0 @@ -sdk.dir=/Users/stephen.owens/Library/Android/sdk -flutter.sdk=/Users/stephen.owens/Documents/dev/flutter/sdk/flutter -org.gradle.jvmargs=-Xmx1536m -Duser.country=US -Duser.language=en \ No newline at end of file diff --git a/speech_to_text_/android/gradle/settings.gradle b/speech_to_text_/android/gradle/settings.gradle deleted file mode 100644 index cdfc1c4b..00000000 --- a/speech_to_text_/android/gradle/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = 'speech_to_text' diff --git a/speech_to_text_/android/gradle/wrapper/gradle-wrapper.properties b/speech_to_text_/android/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 674bdda0..00000000 --- a/speech_to_text_/android/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip diff --git a/speech_to_text_/android/src/main/AndroidManifest.xml b/speech_to_text_/android/src/main/AndroidManifest.xml deleted file mode 100644 index 61a73f32..00000000 --- a/speech_to_text_/android/src/main/AndroidManifest.xml +++ /dev/null @@ -1,3 +0,0 @@ - - diff --git a/speech_to_text_/android/src/main/kotlin/com/csdcorp/speech_to_text/SpeechToTextPlugin.kt b/speech_to_text_/android/src/main/kotlin/com/csdcorp/speech_to_text/SpeechToTextPlugin.kt deleted file mode 100644 index 7954add3..00000000 --- a/speech_to_text_/android/src/main/kotlin/com/csdcorp/speech_to_text/SpeechToTextPlugin.kt +++ /dev/null @@ -1,595 +0,0 @@ -package com.csdcorp.speech_to_text - -import androidx.annotation.NonNull; -import io.flutter.embedding.engine.plugins.FlutterPlugin -import android.Manifest -import android.annotation.TargetApi -import android.app.Activity -import android.content.Intent -import android.content.pm.PackageManager -import android.os.Build -import android.os.Bundle -import android.speech.RecognitionListener -import android.speech.SpeechRecognizer.createSpeechRecognizer -import android.speech.RecognizerIntent -import android.speech.SpeechRecognizer -import androidx.core.app.ActivityCompat -import androidx.core.content.ContextCompat -import io.flutter.plugin.common.MethodCall -import io.flutter.plugin.common.MethodChannel -import io.flutter.plugin.common.MethodChannel.MethodCallHandler -import io.flutter.plugin.common.MethodChannel.Result -import io.flutter.plugin.common.PluginRegistry -import io.flutter.plugin.common.PluginRegistry.Registrar -import org.json.JSONObject -import android.content.Context -import android.content.BroadcastReceiver -import android.os.Handler -import android.os.Looper -import android.util.Log -import io.flutter.embedding.engine.plugins.activity.ActivityAware -import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding -import io.flutter.plugin.common.BinaryMessenger -import org.json.JSONArray -import java.util.* - - -enum class SpeechToTextErrors { - multipleRequests, - unimplemented, - noLanguageIntent, - recognizerNotAvailable, - missingOrInvalidArg, - unknown -} - -enum class SpeechToTextCallbackMethods { - textRecognition, - notifyStatus, - notifyError, - soundLevelChange, -} - -enum class SpeechToTextStatus { - listening, - notListening, - unavailable, - available, -} - -enum class ListenMode { - deviceDefault, - dictation, - search, - confirmation, -} - -const val pluginChannelName = "plugin.csdcorp.com/speech_to_text" - -@TargetApi(8) -/** SpeechToTextPlugin */ -public class SpeechToTextPlugin : - MethodCallHandler, RecognitionListener, - PluginRegistry.RequestPermissionsResultListener, FlutterPlugin, - ActivityAware { - private var pluginContext: Context? = null - private var channel: MethodChannel? = null - private val minSdkForSpeechSupport = 21 - private val speechToTextPermissionCode = 28521 - private val missingConfidence: Double = -1.0 - private val logTag = "SpeechToTextPlugin" - private var currentActivity: Activity? = null - private var activeResult: Result? = null - private var initializedSuccessfully: Boolean = false - private var permissionToRecordAudio: Boolean = false - private var listening = false - private var debugLogging: Boolean = false - private var speechRecognizer: SpeechRecognizer? = null - private var recognizerIntent: Intent? = null - private var previousRecognizerLang: String? = null - private var previousPartialResults: Boolean = true - private var previousListenMode: ListenMode = ListenMode.deviceDefault - private var lastFinalTime: Long = 0 - private val handler: Handler = Handler(Looper.getMainLooper()) - private val defaultLanguageTag: String = Locale.getDefault().toLanguageTag() - - override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { - - onAttachedToEngine(flutterPluginBinding.getApplicationContext(), flutterPluginBinding.getBinaryMessenger()); - } - - // This static function is optional and equivalent to onAttachedToEngine. It supports the old - // pre-Flutter-1.12 Android projects. You are encouraged to continue supporting - // plugin registration via this function while apps migrate to use the new Android APIs - // post-flutter-1.12 via https://flutter.dev/go/android-project-migration. - // - // It is encouraged to share logic between onAttachedToEngine and registerWith to keep - // them functionally equivalent. Only one of onAttachedToEngine or registerWith will be called - // depending on the user's project. onAttachedToEngine or registerWith must both be defined - // in the same class. - companion object { - @JvmStatic - fun registerWith(registrar: Registrar) { - val speechPlugin = SpeechToTextPlugin() - speechPlugin.currentActivity = registrar.activity() - registrar.addRequestPermissionsResultListener(speechPlugin) - speechPlugin.onAttachedToEngine(registrar.context(), registrar.messenger()) - } - } - - private fun onAttachedToEngine(applicationContext: Context, messenger: BinaryMessenger) { - this.pluginContext = applicationContext; - channel = MethodChannel(messenger, pluginChannelName) - channel?.setMethodCallHandler(this) - } - - override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) { - this.pluginContext = null; - channel?.setMethodCallHandler(null) - channel = null - } - - override fun onDetachedFromActivity() { - currentActivity = null - } - - override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) { - currentActivity = binding.activity - binding.addRequestPermissionsResultListener(this) - } - - override fun onAttachedToActivity(binding: ActivityPluginBinding) { - currentActivity = binding.activity - binding.addRequestPermissionsResultListener(this) - } - - override fun onDetachedFromActivityForConfigChanges() { - currentActivity = null - } - - override fun onMethodCall(@NonNull call: MethodCall, @NonNull rawrResult: Result) { - val result = ChannelResultWrapper(rawrResult) - try { - when (call.method) { - "has_permission" -> hasPermission(result) - "initialize" -> { - var dlog = call.argument("debugLogging") - if (null != dlog) { - debugLogging = dlog - } - initialize(result) - } - "listen" -> { - var localeId = call.argument("localeId") - if (null == localeId) { - localeId = defaultLanguageTag - } - var partialResults = call.argument("partialResults") - if (null == partialResults) { - partialResults = true - } - val listenModeIndex = call.argument("listenMode") - if ( null == listenModeIndex ) { - result.error(SpeechToTextErrors.missingOrInvalidArg.name, - "listenMode is required", null) - return - } - startListening(result, localeId, partialResults, listenModeIndex ) - } - "stop" -> stopListening(result) - "cancel" -> cancelListening(result) - "locales" -> locales(result) - else -> result.notImplemented() - } - } catch (exc: Exception) { - Log.e(logTag, "Unexpected exception", exc) - result.error(SpeechToTextErrors.unknown.name, - "Unexpected exception", exc.localizedMessage) - } - } - - private fun hasPermission(result: Result) { - if (sdkVersionTooLow(result)) { - return - } - debugLog("Start has_permission") - val localContext = pluginContext - if (localContext != null) { - val hasPerm = ContextCompat.checkSelfPermission(localContext, - Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED - result.success(hasPerm) - } - } - - private fun initialize(result: Result) { - if (sdkVersionTooLow(result)) { - return - } - debugLog("Start initialize") - if (null != activeResult) { - result.error(SpeechToTextErrors.multipleRequests.name, - "Only one initialize at a time", null) - return - } - activeResult = result - val localContext = pluginContext - initializeIfPermitted(pluginContext) - } - - private fun sdkVersionTooLow(result: Result): Boolean { - if (Build.VERSION.SDK_INT < minSdkForSpeechSupport) { - result.success(false) - return true; - } - return false; - } - - private fun isNotInitialized(result: Result): Boolean { - if (!initializedSuccessfully || null == pluginContext) { - result.success(false) - } - return !initializedSuccessfully - } - - private fun isListening(): Boolean { - return listening - } - - private fun isNotListening(): Boolean { - return !listening - } - - private fun startListening(result: Result, languageTag: String, partialResults: Boolean, - listenModeIndex: Int) { - if (sdkVersionTooLow(result) || isNotInitialized(result) || isListening()) { - return - } - debugLog("Start listening") - var listenMode = ListenMode.deviceDefault - if ( listenModeIndex == ListenMode.dictation.ordinal) { - listenMode = ListenMode.dictation - } - setupRecognizerIntent(languageTag, partialResults, listenMode) - handler.post { - run { - speechRecognizer?.startListening(recognizerIntent) - } - } - notifyListening(isRecording = true) - result.success(true) - debugLog("Start listening done") - } - - private fun stopListening(result: Result) { - if (sdkVersionTooLow(result) || isNotInitialized(result) || isNotListening()) { - return - } - debugLog("Stop listening") - handler.post { - run { - speechRecognizer?.stopListening() - } - } - notifyListening(isRecording = false) - result.success(true) - debugLog("Stop listening done") - } - - private fun cancelListening(result: Result) { - if (sdkVersionTooLow(result) || isNotInitialized(result) || isNotListening()) { - return - } - debugLog("Cancel listening") - handler.post { - run { - speechRecognizer?.cancel() - } - } - notifyListening(isRecording = false) - result.success(true) - debugLog("Cancel listening done") - } - - private fun locales(result: Result) { - if (sdkVersionTooLow(result) || isNotInitialized(result)) { - return - } - var detailsIntent = RecognizerIntent.getVoiceDetailsIntent(pluginContext) - if (null == detailsIntent) { - detailsIntent = Intent(RecognizerIntent.ACTION_GET_LANGUAGE_DETAILS) - } - if (null == detailsIntent) { - result.error(SpeechToTextErrors.noLanguageIntent.name, - "Could not get voice details", null) - return - } - pluginContext?.sendOrderedBroadcast( - detailsIntent, null, LanguageDetailsChecker(result), - null, Activity.RESULT_OK, null, null) - } - - private fun notifyListening(isRecording: Boolean) { - debugLog("Notify listening") - listening = isRecording - val status = when (isRecording) { - true -> SpeechToTextStatus.listening.name - false -> SpeechToTextStatus.notListening.name - } - channel?.invokeMethod(SpeechToTextCallbackMethods.notifyStatus.name, status) - debugLog("Notify listening done") - } - - private fun updateResults(speechBundle: Bundle?, isFinal: Boolean) { - if (isDuplicateFinal( isFinal )) { - debugLog("Discarding duplicate final") - return - } - val userSaid = speechBundle?.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION) - if (null != userSaid && userSaid.isNotEmpty()) { - val speechResult = JSONObject() - speechResult.put("finalResult", isFinal) - val confidence = speechBundle?.getFloatArray(SpeechRecognizer.CONFIDENCE_SCORES) - val alternates = JSONArray() - for (resultIndex in 0..userSaid.size - 1) { - val speechWords = JSONObject() - speechWords.put("recognizedWords", userSaid[resultIndex]) - if (null != confidence && confidence.size >= userSaid.size) { - speechWords.put("confidence", confidence[resultIndex]) - } else { - speechWords.put("confidence", missingConfidence) - } - alternates.put(speechWords) - } - speechResult.put("alternates", alternates) - val jsonResult = speechResult.toString() - debugLog("Calling results callback") - channel?.invokeMethod(SpeechToTextCallbackMethods.textRecognition.name, - jsonResult) - } - } - - private fun isDuplicateFinal( isFinal: Boolean ) : Boolean { - if ( !isFinal ) { - return false - } - val delta = System.currentTimeMillis() - lastFinalTime - lastFinalTime = System.currentTimeMillis() - return delta >= 0 && delta < 100 - } - - private fun initializeIfPermitted(context: Context?) { - val localContext = context - if (null == localContext) { - completeInitialize() - return - } - permissionToRecordAudio = ContextCompat.checkSelfPermission(localContext, - Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED - debugLog("Checked permission") - if (!permissionToRecordAudio) { - val localActivity = currentActivity - if (null != localActivity) { - debugLog("Requesting permission") - ActivityCompat.requestPermissions(localActivity, - arrayOf(Manifest.permission.RECORD_AUDIO), speechToTextPermissionCode) - } else { - debugLog("no permission, no activity, completing") - completeInitialize() - } - } else { - debugLog("has permission, completing") - completeInitialize() - } - debugLog("leaving initializeIfPermitted") - } - - private fun completeInitialize() { - - debugLog("completeInitialize") - if (permissionToRecordAudio) { - debugLog("Testing recognition availability") - if (!SpeechRecognizer.isRecognitionAvailable(pluginContext)) { - Log.e(logTag, "Speech recognition not available on this device") - activeResult?.error(SpeechToTextErrors.recognizerNotAvailable.name, - "Speech recognition not available on this device", "") - activeResult = null - return - } - - debugLog("Creating recognizer") - speechRecognizer = createSpeechRecognizer(pluginContext).apply { - debugLog("Setting listener") - setRecognitionListener(this@SpeechToTextPlugin) - } - if (null == speechRecognizer) { - Log.e(logTag, "Speech recognizer null") - activeResult?.error( - SpeechToTextErrors.recognizerNotAvailable.name, - "Speech recognizer null", "") - activeResult = null - } - - debugLog("before setup intent") - setupRecognizerIntent(defaultLanguageTag, true, ListenMode.deviceDefault) - debugLog("after setup intent") - } - - initializedSuccessfully = permissionToRecordAudio - debugLog("sending result") - activeResult?.success(permissionToRecordAudio) - debugLog("leaving complete") - activeResult = null - } - - private fun setupRecognizerIntent(languageTag: String, partialResults: Boolean, listenMode: ListenMode) { - debugLog("setupRecognizerIntent") - if (previousRecognizerLang == null || - previousRecognizerLang != languageTag || - partialResults != previousPartialResults || previousListenMode != listenMode ) { - previousRecognizerLang = languageTag; - previousPartialResults = partialResults - previousListenMode = listenMode - handler.post { - run { - recognizerIntent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply { - debugLog("In RecognizerIntent apply") - putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM) - debugLog("put model") - val localContext = pluginContext - if (null != localContext) { - putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, - localContext.applicationInfo.packageName) - } - debugLog("put package") - putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, partialResults) - debugLog("put partial") - if (languageTag != Locale.getDefault().toLanguageTag()) { - putExtra(RecognizerIntent.EXTRA_LANGUAGE, languageTag); - debugLog("put languageTag") - } - } - } - } - } - } - - override fun onRequestPermissionsResult(requestCode: Int, permissions: Array?, - grantResults: IntArray?): Boolean { - when (requestCode) { - speechToTextPermissionCode -> { - if (null != grantResults) { - permissionToRecordAudio = grantResults.isNotEmpty() && - grantResults.get(0) == PackageManager.PERMISSION_GRANTED - } - completeInitialize() - return true - } - } - return false - } - - - override fun onPartialResults(results: Bundle?) = updateResults(results, false) - override fun onResults(results: Bundle?) = updateResults(results, true) - override fun onEndOfSpeech() = notifyListening(isRecording = false) - - override fun onError(errorCode: Int) { - val errorMsg = when (errorCode) { - SpeechRecognizer.ERROR_AUDIO -> "error_audio_error" - SpeechRecognizer.ERROR_CLIENT -> "error_client" - SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS -> "error_permission" - SpeechRecognizer.ERROR_NETWORK -> "error_network" - SpeechRecognizer.ERROR_NETWORK_TIMEOUT -> "error_network_timeout" - SpeechRecognizer.ERROR_NO_MATCH -> "error_no_match" - SpeechRecognizer.ERROR_RECOGNIZER_BUSY -> "error_busy" - SpeechRecognizer.ERROR_SERVER -> "error_server" - SpeechRecognizer.ERROR_SPEECH_TIMEOUT -> "error_speech_timeout" - else -> "error_unknown" - } - sendError(errorMsg) - } - - private fun debugLog( msg: String ) { - if ( debugLogging ) { - Log.d( logTag, msg ) - } - } - - private fun sendError(errorMsg: String) { - val speechError = JSONObject() - speechError.put("errorMsg", errorMsg) - speechError.put("permanent", true) - handler.post { - run { - channel?.invokeMethod(SpeechToTextCallbackMethods.notifyError.name, speechError.toString()) - } - } - } - - override fun onRmsChanged(rmsdB: Float) { - handler.post { - run { - channel?.invokeMethod(SpeechToTextCallbackMethods.soundLevelChange.name, rmsdB) - } - } - } - - override fun onReadyForSpeech(p0: Bundle?) {} - override fun onBufferReceived(p0: ByteArray?) {} - override fun onEvent(p0: Int, p1: Bundle?) {} - override fun onBeginningOfSpeech() {} -} - -// See https://stackoverflow.com/questions/10538791/how-to-set-the-language-in-speech-recognition-on-android/10548680#10548680 -class LanguageDetailsChecker(flutterResult: Result) : BroadcastReceiver() { - private val result: Result = flutterResult - private var supportedLanguages: List? = null - - private var languagePreference: String? = null - - override fun onReceive(context: Context, intent: Intent) { - val results = getResultExtras(true) - if (results.containsKey(RecognizerIntent.EXTRA_LANGUAGE_PREFERENCE)) { - languagePreference = results.getString(RecognizerIntent.EXTRA_LANGUAGE_PREFERENCE) - } - if (results.containsKey(RecognizerIntent.EXTRA_SUPPORTED_LANGUAGES)) { - supportedLanguages = results.getStringArrayList( - RecognizerIntent.EXTRA_SUPPORTED_LANGUAGES) - createResponse(supportedLanguages) - } - } - - private fun createResponse(supportedLanguages: List?) { - val currentLocale = Locale.getDefault() - val localeNames = ArrayList() - localeNames.add(buildIdNameForLocale(currentLocale)) - if (null != supportedLanguages) { - for (lang in supportedLanguages) { - if (currentLocale.toLanguageTag() == lang) { - continue - } - val locale = Locale.forLanguageTag(lang) - localeNames.add(buildIdNameForLocale(locale)) - } - } - result.success(localeNames) - - } - - private fun buildIdNameForLocale(locale: Locale): String { - val name = locale.displayName.replace(':', ' ') - return "${locale.language}_${locale.country}:$name" - } -} - -private class ChannelResultWrapper(result: Result) : Result { - // Caller handler - val handler: Handler = Handler(Looper.getMainLooper()) - val result: Result = result - - // make sure to respond in the caller thread - override fun success(results: Any?) { - - handler.post { - run { - result.success(results); - } - } - } - - override fun error(errorCode: String?, errorMessage: String?, data: Any?) { - handler.post { - run { - result.error(errorCode, errorMessage, data); - } - } - } - - override fun notImplemented() { - handler.post { - run { - result.notImplemented(); - } - } - } -} diff --git a/speech_to_text_/example/.gitignore b/speech_to_text_/example/.gitignore deleted file mode 100644 index 2ddde2a5..00000000 --- a/speech_to_text_/example/.gitignore +++ /dev/null @@ -1,73 +0,0 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.buildlog/ -.history -.svn/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -**/doc/api/ -.dart_tool/ -.flutter-plugins -.packages -.pub-cache/ -.pub/ -/build/ - -# Android related -**/android/**/gradle-wrapper.jar -**/android/.gradle -**/android/captures/ -**/android/gradlew -**/android/gradlew.bat -**/android/local.properties -**/android/**/GeneratedPluginRegistrant.java - -# iOS/XCode related -**/ios/**/*.mode1v3 -**/ios/**/*.mode2v3 -**/ios/**/*.moved-aside -**/ios/**/*.pbxuser -**/ios/**/*.perspectivev3 -**/ios/**/*sync/ -**/ios/**/.sconsign.dblite -**/ios/**/.tags* -**/ios/**/.vagrant/ -**/ios/**/DerivedData/ -**/ios/**/Icon? -**/ios/**/Pods/ -**/ios/**/.symlinks/ -**/ios/**/profile -**/ios/**/xcuserdata -**/ios/.generated/ -**/ios/Flutter/App.framework -**/ios/Flutter/Flutter.framework -**/ios/Flutter/Generated.xcconfig -**/ios/Flutter/app.flx -**/ios/Flutter/app.zip -**/ios/Flutter/flutter_assets/ -**/ios/Flutter/flutter_export_environment.sh -**/ios/ServiceDefinitions.json -**/ios/Runner/GeneratedPluginRegistrant.* - -# Exceptions to above rules. -!**/ios/**/default.mode1v3 -!**/ios/**/default.mode2v3 -!**/ios/**/default.pbxuser -!**/ios/**/default.perspectivev3 -!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages diff --git a/speech_to_text_/example/.metadata b/speech_to_text_/example/.metadata deleted file mode 100644 index aeb01ee2..00000000 --- a/speech_to_text_/example/.metadata +++ /dev/null @@ -1,10 +0,0 @@ -# This file tracks properties of this Flutter project. -# Used by Flutter tool to assess capabilities and perform upgrades etc. -# -# This file should be version controlled and should not be manually edited. - -version: - revision: 2d2a1ffec95cc70a3218872a2cd3f8de4933c42f - channel: stable - -project_type: app diff --git a/speech_to_text_/example/README.md b/speech_to_text_/example/README.md deleted file mode 100644 index 92252821..00000000 --- a/speech_to_text_/example/README.md +++ /dev/null @@ -1,155 +0,0 @@ -# speech_to_text_example - -Demonstrates how to use the speech_to_text plugin. This example requires -that the plugin has been installed. It initializes speech recognition, -listens for words and prints them. - - -## Source - -```dart -import 'package:flutter/material.dart'; -import 'dart:async'; - -import 'package:speech_to_text/speech_to_text.dart'; -import 'package:speech_to_text/speech_recognition_result.dart'; -import 'package:speech_to_text/speech_recognition_error.dart'; - -void main() => runApp(MyApp()); - -class MyApp extends StatefulWidget { - @override - _MyAppState createState() => _MyAppState(); -} - -class _MyAppState extends State { - bool _hasSpeech = false; - String lastWords = ""; - String lastError = ""; - String lastStatus = ""; - final SpeechToText speech = SpeechToText(); - - @override - void initState() { - super.initState(); - initSpeechState(); - } - - Future initSpeechState() async { - bool hasSpeech = await speech.initialize(onError: errorListener, onStatus: statusListener ); - - if (!mounted) return; - setState(() { - _hasSpeech = hasSpeech; - }); - } - - @override - Widget build(BuildContext context) { - return MaterialApp( - home: Scaffold( - appBar: AppBar( - title: const Text('Speech to Text Example'), - ), - body: _hasSpeech - ? Column(children: [ - Expanded( - child: Center( - child: Text('Speech recognition available'), - ), - ), - Expanded( - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - FlatButton( - child: Text('Start'), - onPressed: startListening, - ), - FlatButton( - child: Text('Stop'), - onPressed: stopListening, - ), - FlatButton( - child: Text('Cancel'), - onPressed:cancelListening, - ), - ], - ), - ), - Expanded( - child: Column( - children: [ - Center( - child: Text('Recognized Words'), - ), - Center( - child: Text(lastWords), - ), - ], - ), - ), - Expanded( - child: Column( - children: [ - Center( - child: Text('Error'), - ), - Center( - child: Text(lastError), - ), - ], - ), - ), - Expanded( - child: Center( - child: speech.isListening ? Text("I'm listening...") : Text( 'Not listening' ), - ), - ), - ]) - : Center( child: Text('Speech recognition unavailable', style: TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold))), - ), - ); - } - - void startListening() { - lastWords = ""; - lastError = ""; - speech.listen(onResult: resultListener ); - setState(() { - - }); - } - - void stopListening() { - speech.stop( ); - setState(() { - - }); - } - - void cancelListening() { - speech.cancel( ); - setState(() { - - }); - } - - void resultListener(SpeechRecognitionResult result) { - setState(() { - lastWords = "${result.recognizedWords} - ${result.finalResult}"; - }); - } - - void errorListener(SpeechRecognitionError error ) { - setState(() { - lastError = "${error.errorMsg} - ${error.permanent}"; - }); - } - void statusListener(String status ) { - setState(() { - lastStatus = "$status"; - }); - } -} -``` \ No newline at end of file diff --git a/speech_to_text_/example/android/.project b/speech_to_text_/example/android/.project deleted file mode 100644 index d7d48141..00000000 --- a/speech_to_text_/example/android/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - android___ - Project android___ created by Buildship. - - - - - org.eclipse.buildship.core.gradleprojectbuilder - - - - - - org.eclipse.buildship.core.gradleprojectnature - - diff --git a/speech_to_text_/example/android/.settings/org.eclipse.buildship.core.prefs b/speech_to_text_/example/android/.settings/org.eclipse.buildship.core.prefs deleted file mode 100644 index e8895216..00000000 --- a/speech_to_text_/example/android/.settings/org.eclipse.buildship.core.prefs +++ /dev/null @@ -1,2 +0,0 @@ -connection.project.dir= -eclipse.preferences.version=1 diff --git a/speech_to_text_/example/android/app/build.gradle b/speech_to_text_/example/android/app/build.gradle deleted file mode 100644 index 8b616f29..00000000 --- a/speech_to_text_/example/android/app/build.gradle +++ /dev/null @@ -1,67 +0,0 @@ -def localProperties = new Properties() -def localPropertiesFile = rootProject.file('local.properties') -if (localPropertiesFile.exists()) { - localPropertiesFile.withReader('UTF-8') { reader -> - localProperties.load(reader) - } -} - -def flutterRoot = localProperties.getProperty('flutter.sdk') -if (flutterRoot == null) { - throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") -} - -def flutterVersionCode = localProperties.getProperty('flutter.versionCode') -if (flutterVersionCode == null) { - flutterVersionCode = '1' -} - -def flutterVersionName = localProperties.getProperty('flutter.versionName') -if (flutterVersionName == null) { - flutterVersionName = '1.0' -} - -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" - -android { - compileSdkVersion 28 - - sourceSets { - main.java.srcDirs += 'src/main/kotlin' - } - - lintOptions { - disable 'InvalidPackage' - } - - defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.csdcorp.speech_to_text_example" - minSdkVersion 21 - targetSdkVersion 28 - versionCode flutterVersionCode.toInteger() - versionName flutterVersionName - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - - buildTypes { - release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig signingConfigs.debug - } - } -} - -flutter { - source '../..' -} - -dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - testImplementation 'junit:junit:4.12' - androidTestImplementation 'androidx.test:runner:1.1.1' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' -} diff --git a/speech_to_text_/example/android/app/src/debug/AndroidManifest.xml b/speech_to_text_/example/android/app/src/debug/AndroidManifest.xml deleted file mode 100644 index 36edf838..00000000 --- a/speech_to_text_/example/android/app/src/debug/AndroidManifest.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/speech_to_text_/example/android/app/src/main/AndroidManifest.xml b/speech_to_text_/example/android/app/src/main/AndroidManifest.xml deleted file mode 100644 index b0912061..00000000 --- a/speech_to_text_/example/android/app/src/main/AndroidManifest.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/speech_to_text_/example/android/app/src/main/kotlin/com/csdcorp/speech_to_text_example/MainActivity.kt b/speech_to_text_/example/android/app/src/main/kotlin/com/csdcorp/speech_to_text_example/MainActivity.kt deleted file mode 100644 index f44e470e..00000000 --- a/speech_to_text_/example/android/app/src/main/kotlin/com/csdcorp/speech_to_text_example/MainActivity.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.csdcorp.speech_to_text_example - -import androidx.annotation.NonNull; -import io.flutter.embedding.android.FlutterActivity -import io.flutter.embedding.engine.FlutterEngine -import io.flutter.plugins.GeneratedPluginRegistrant - -class MainActivity: FlutterActivity() { - override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { - GeneratedPluginRegistrant.registerWith(flutterEngine); - } -} diff --git a/speech_to_text_/example/android/app/src/main/res/drawable/launch_background.xml b/speech_to_text_/example/android/app/src/main/res/drawable/launch_background.xml deleted file mode 100644 index 304732f8..00000000 --- a/speech_to_text_/example/android/app/src/main/res/drawable/launch_background.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - diff --git a/speech_to_text_/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/speech_to_text_/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index db77bb4b7b0906d62b1847e87f15cdcacf6a4f29..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 544 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAj~WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!h8bpbvhu0Wd6uZuB!w&u2PAxD2eNXD>P5D~Wn-+_Wa#27Xc zC?Zj|6r#X(-D3u$NCt}(Ms06KgJ4FxJVv{GM)!I~&n8Bnc94O7-Hd)cjDZswgC;Qs zO=b+9!WcT8F?0rF7!Uys2bs@gozCP?z~o%U|N3vA*22NaGQG zlg@K`O_XuxvZ&Ks^m&R!`&1=spLvfx7oGDKDwpwW`#iqdw@AL`7MR}m`rwr|mZgU`8P7SBkL78fFf!WnuYWm$5Z0 zNXhDbCv&49sM544K|?c)WrFfiZvCi9h0O)B3Pgg&ebxsLQ05GG~ AQ2+n{ diff --git a/speech_to_text_/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/speech_to_text_/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 17987b79bb8a35cc66c3c1fd44f5a5526c1b78be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 442 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5Xx&nMcT!A!W`0S9QKQy;}1Cl^CgaH=;G9cpY;r$Q>i*pfB zP2drbID<_#qf;rPZx^FqH)F_D#*k@@q03KywUtLX8Ua?`H+NMzkczFPK3lFz@i_kW%1NOn0|D2I9n9wzH8m|-tHjsw|9>@K=iMBhxvkv6m8Y-l zytQ?X=U+MF$@3 zt`~i=@j|6y)RWMK--}M|=T`o&^Ni>IoWKHEbBXz7?A@mgWoL>!*SXo`SZH-*HSdS+ yn*9;$7;m`l>wYBC5bq;=U}IMqLzqbYCidGC!)_gkIk_C@Uy!y&wkt5C($~2D>~)O*cj@FGjOCM)M>_ixfudOh)?xMu#Fs z#}Y=@YDTwOM)x{K_j*Q;dPdJ?Mz0n|pLRx{4n|)f>SXlmV)XB04CrSJn#dS5nK2lM zrZ9#~WelCp7&e13Y$jvaEXHskn$2V!!DN-nWS__6T*l;H&Fopn?A6HZ-6WRLFP=R` zqG+CE#d4|IbyAI+rJJ`&x9*T`+a=p|0O(+s{UBcyZdkhj=yS1>AirP+0R;mf2uMgM zC}@~JfByORAh4SyRgi&!(cja>F(l*O+nd+@4m$|6K6KDn_&uvCpV23&>G9HJp{xgg zoq1^2_p9@|WEo z*X_Uko@K)qYYv~>43eQGMdbiGbo>E~Q& zrYBH{QP^@Sti!`2)uG{irBBq@y*$B zi#&(U-*=fp74j)RyIw49+0MRPMRU)+a2r*PJ$L5roHt2$UjExCTZSbq%V!HeS7J$N zdG@vOZB4v_lF7Plrx+hxo7(fCV&}fHq)$ diff --git a/speech_to_text_/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/speech_to_text_/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index d5f1c8d34e7a88e3f88bea192c3a370d44689c3c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q8Ax83A=Cw=BuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFa`(sgt!6~Yi|1%a`XoT0ojZ}lNrNjb9xjc(B0U1_% zz5^97Xt*%oq$rQy4?0GKNfJ44uvxI)gC`h-NZ|&0-7(qS@?b!5r36oQ}zyZrNO3 zMO=Or+<~>+A&uN&E!^Sl+>xE!QC-|oJv`ApDhqC^EWD|@=#J`=d#Xzxs4ah}w&Jnc z$|q_opQ^2TrnVZ0o~wh<3t%W&flvYGe#$xqda2bR_R zvPYgMcHgjZ5nSA^lJr%;<&0do;O^tDDh~=pIxA#coaCY>&N%M2^tq^U%3DB@ynvKo}b?yu-bFc-u0JHzced$sg7S3zqI(2 z#Km{dPr7I=pQ5>FuK#)QwK?Y`E`B?nP+}U)I#c1+FM*1kNvWG|a(TpksZQ3B@sD~b zpQ2)*V*TdwjFOtHvV|;OsiDqHi=6%)o4b!)x$)%9pGTsE z-JL={-Ffv+T87W(Xpooq<`r*VzWQcgBN$$`u}f>-ZQI1BB8ykN*=e4rIsJx9>z}*o zo~|9I;xof diff --git a/speech_to_text_/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/speech_to_text_/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index 4d6372eebdb28e45604e46eeda8dd24651419bc0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1443 zcmb`G{WsKk6vsdJTdFg%tJav9_E4vzrOaqkWF|A724Nly!y+?N9`YV6wZ}5(X(D_N(?!*n3`|_r0Hc?=PQw&*vnU?QTFY zB_MsH|!j$PP;I}?dppoE_gA(4uc!jV&0!l7_;&p2^pxNo>PEcNJv za5_RT$o2Mf!<+r?&EbHH6nMoTsDOa;mN(wv8RNsHpG)`^ymG-S5By8=l9iVXzN_eG%Xg2@Xeq76tTZ*dGh~Lo9vl;Zfs+W#BydUw zCkZ$o1LqWQO$FC9aKlLl*7x9^0q%0}$OMlp@Kk_jHXOjofdePND+j!A{q!8~Jn+s3 z?~~w@4?egS02}8NuulUA=L~QQfm;MzCGd)XhiftT;+zFO&JVyp2mBww?;QByS_1w! zrQlx%{^cMj0|Bo1FjwY@Q8?Hx0cIPF*@-ZRFpPc#bBw{5@tD(5%sClzIfl8WU~V#u zm5Q;_F!wa$BSpqhN>W@2De?TKWR*!ujY;Yylk_X5#~V!L*Gw~;$%4Q8~Mad z@`-kG?yb$a9cHIApZDVZ^U6Xkp<*4rU82O7%}0jjHlK{id@?-wpN*fCHXyXh(bLt* zPc}H-x0e4E&nQ>y%B-(EL=9}RyC%MyX=upHuFhAk&MLbsF0LP-q`XnH78@fT+pKPW zu72MW`|?8ht^tz$iC}ZwLp4tB;Q49K!QCF3@!iB1qOI=?w z7In!}F~ij(18UYUjnbmC!qKhPo%24?8U1x{7o(+?^Zu0Hx81|FuS?bJ0jgBhEMzf< zCgUq7r2OCB(`XkKcN-TL>u5y#dD6D!)5W?`O5)V^>jb)P)GBdy%t$uUMpf$SNV31$ zb||OojAbvMP?T@$h_ZiFLFVHDmbyMhJF|-_)HX3%m=CDI+ID$0^C>kzxprBW)hw(v zr!Gmda);ICoQyhV_oP5+C%?jcG8v+D@9f?Dk*!BxY}dazmrT@64UrP3hlslANK)bq z$67n83eh}OeW&SV@HG95P|bjfqJ7gw$e+`Hxo!4cx`jdK1bJ>YDSpGKLPZ^1cv$ek zIB?0S<#tX?SJCLWdMd{-ME?$hc7A$zBOdIJ)4!KcAwb=VMov)nK;9z>x~rfT1>dS+ zZ6#`2v@`jgbqq)P22H)Tx2CpmM^o1$B+xT6`(v%5xJ(?j#>Q$+rx_R|7TzDZe{J6q zG1*EcU%tE?!kO%^M;3aM6JN*LAKUVb^xz8-Pxo#jR5(-KBeLJvA@-gxNHx0M-ZJLl z;#JwQoh~9V?`UVo#}{6ka@II>++D@%KqGpMdlQ}?9E*wFcf5(#XQnP$Dk5~%iX^>f z%$y;?M0BLp{O3a(-4A?ewryHrrD%cx#Q^%KY1H zNre$ve+vceSLZcNY4U(RBX&)oZn*Py()h)XkE?PL$!bNb{N5FVI2Y%LKEm%yvpyTP z(1P?z~7YxD~Rf<(a@_y` diff --git a/speech_to_text_/example/android/app/src/main/res/values/styles.xml b/speech_to_text_/example/android/app/src/main/res/values/styles.xml deleted file mode 100644 index 00fa4417..00000000 --- a/speech_to_text_/example/android/app/src/main/res/values/styles.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - diff --git a/speech_to_text_/example/android/app/src/profile/AndroidManifest.xml b/speech_to_text_/example/android/app/src/profile/AndroidManifest.xml deleted file mode 100644 index 36edf838..00000000 --- a/speech_to_text_/example/android/app/src/profile/AndroidManifest.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/speech_to_text_/example/android/build.gradle b/speech_to_text_/example/android/build.gradle deleted file mode 100644 index 13546311..00000000 --- a/speech_to_text_/example/android/build.gradle +++ /dev/null @@ -1,31 +0,0 @@ -buildscript { - ext.kotlin_version = '1.3.50' - repositories { - google() - jcenter() - } - - dependencies { - classpath 'com.android.tools.build:gradle:3.6.1' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - } -} - -allprojects { - repositories { - google() - jcenter() - } -} - -rootProject.buildDir = '../build' -subprojects { - project.buildDir = "${rootProject.buildDir}/${project.name}" -} -subprojects { - project.evaluationDependsOn(':app') -} - -task clean(type: Delete) { - delete rootProject.buildDir -} diff --git a/speech_to_text_/example/android/gradle.properties b/speech_to_text_/example/android/gradle.properties deleted file mode 100644 index a6738207..00000000 --- a/speech_to_text_/example/android/gradle.properties +++ /dev/null @@ -1,4 +0,0 @@ -org.gradle.jvmargs=-Xmx1536M -android.useAndroidX=true -android.enableJetifier=true -android.enableR8=true diff --git a/speech_to_text_/example/android/gradle/wrapper/gradle-wrapper.properties b/speech_to_text_/example/android/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 052e7951..00000000 --- a/speech_to_text_/example/android/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Mon Mar 16 08:57:32 EDT 2020 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip diff --git a/speech_to_text_/example/android/settings.gradle b/speech_to_text_/example/android/settings.gradle deleted file mode 100644 index 5a2f14fb..00000000 --- a/speech_to_text_/example/android/settings.gradle +++ /dev/null @@ -1,15 +0,0 @@ -include ':app' - -def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() - -def plugins = new Properties() -def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') -if (pluginsFile.exists()) { - pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } -} - -plugins.each { name, path -> - def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() - include ":$name" - project(":$name").projectDir = pluginDirectory -} diff --git a/speech_to_text_/example/assets/sounds/speech_to_text_cancel.m4r b/speech_to_text_/example/assets/sounds/speech_to_text_cancel.m4r deleted file mode 100644 index ccb3afe392f563a0c8205265f8953c5cb801794a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14006 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 F{x65=vylJ* diff --git a/speech_to_text_/example/ios/Flutter/AppFrameworkInfo.plist b/speech_to_text_/example/ios/Flutter/AppFrameworkInfo.plist deleted file mode 100644 index 6b4c0f78..00000000 --- a/speech_to_text_/example/ios/Flutter/AppFrameworkInfo.plist +++ /dev/null @@ -1,26 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - App - CFBundleIdentifier - io.flutter.flutter.app - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - App - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1.0 - MinimumOSVersion - 8.0 - - diff --git a/speech_to_text_/example/ios/Flutter/Debug.xcconfig b/speech_to_text_/example/ios/Flutter/Debug.xcconfig deleted file mode 100644 index e8efba11..00000000 --- a/speech_to_text_/example/ios/Flutter/Debug.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" -#include "Generated.xcconfig" diff --git a/speech_to_text_/example/ios/Flutter/Flutter.podspec b/speech_to_text_/example/ios/Flutter/Flutter.podspec deleted file mode 100644 index 5ca30416..00000000 --- a/speech_to_text_/example/ios/Flutter/Flutter.podspec +++ /dev/null @@ -1,18 +0,0 @@ -# -# NOTE: This podspec is NOT to be published. It is only used as a local source! -# - -Pod::Spec.new do |s| - s.name = 'Flutter' - s.version = '1.0.0' - s.summary = 'High-performance, high-fidelity mobile apps.' - s.description = <<-DESC -Flutter provides an easy and productive way to build and deploy high-performance mobile apps for Android and iOS. - DESC - s.homepage = 'https://flutter.io' - s.license = { :type => 'MIT' } - s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' } - s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s } - s.ios.deployment_target = '8.0' - s.vendored_frameworks = 'Flutter.framework' -end diff --git a/speech_to_text_/example/ios/Flutter/Release.xcconfig b/speech_to_text_/example/ios/Flutter/Release.xcconfig deleted file mode 100644 index 399e9340..00000000 --- a/speech_to_text_/example/ios/Flutter/Release.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" -#include "Generated.xcconfig" diff --git a/speech_to_text_/example/ios/Podfile b/speech_to_text_/example/ios/Podfile deleted file mode 100644 index ab7d5b46..00000000 --- a/speech_to_text_/example/ios/Podfile +++ /dev/null @@ -1,90 +0,0 @@ -# Uncomment this line to define a global platform for your project -platform :ios, '10.0' - -# CocoaPods analytics sends network stats synchronously affecting flutter build latency. -ENV['COCOAPODS_DISABLE_STATS'] = 'true' - -project 'Runner', { - 'Debug' => :debug, - 'Profile' => :release, - 'Release' => :release, -} - -def parse_KV_file(file, separator='=') - file_abs_path = File.expand_path(file) - if !File.exists? file_abs_path - return []; - end - generated_key_values = {} - skip_line_start_symbols = ["#", "/"] - File.foreach(file_abs_path) do |line| - next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } - plugin = line.split(pattern=separator) - if plugin.length == 2 - podname = plugin[0].strip() - path = plugin[1].strip() - podpath = File.expand_path("#{path}", file_abs_path) - generated_key_values[podname] = podpath - else - puts "Invalid plugin specification: #{line}" - end - end - generated_key_values -end - -target 'Runner' do - use_frameworks! - use_modular_headers! - - # Flutter Pod - - copied_flutter_dir = File.join(__dir__, 'Flutter') - copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework') - copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec') - unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path) - # Copy Flutter.framework and Flutter.podspec to Flutter/ to have something to link against if the xcode backend script has not run yet. - # That script will copy the correct debug/profile/release version of the framework based on the currently selected Xcode configuration. - # CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist. - - generated_xcode_build_settings_path = File.join(copied_flutter_dir, 'Generated.xcconfig') - unless File.exist?(generated_xcode_build_settings_path) - raise "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first" - end - generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path) - cached_framework_dir = generated_xcode_build_settings['FLUTTER_FRAMEWORK_DIR']; - - unless File.exist?(copied_framework_path) - FileUtils.cp_r(File.join(cached_framework_dir, 'Flutter.framework'), copied_flutter_dir) - end - unless File.exist?(copied_podspec_path) - FileUtils.cp(File.join(cached_framework_dir, 'Flutter.podspec'), copied_flutter_dir) - end - end - - # Keep pod path relative so it can be checked into Podfile.lock. - pod 'Flutter', :path => 'Flutter' - - # Plugin Pods - - # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock - # referring to absolute paths on developers' machines. - system('rm -rf .symlinks') - system('mkdir -p .symlinks/plugins') - plugin_pods = parse_KV_file('../.flutter-plugins') - plugin_pods.each do |name, path| - symlink = File.join('.symlinks', 'plugins', name) - File.symlink(path, symlink) - pod name, :path => File.join(symlink, 'ios') - end -end - -# Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system. -install! 'cocoapods', :disable_input_output_paths => true - -post_install do |installer| - installer.pods_project.targets.each do |target| - target.build_configurations.each do |config| - config.build_settings['ENABLE_BITCODE'] = 'NO' - end - end -end diff --git a/speech_to_text_/example/ios/Podfile.lock b/speech_to_text_/example/ios/Podfile.lock deleted file mode 100644 index 60c8b57d..00000000 --- a/speech_to_text_/example/ios/Podfile.lock +++ /dev/null @@ -1,29 +0,0 @@ -PODS: - - Flutter (1.0.0) - - speech_to_text (0.0.1): - - Flutter - - Try - - Try (2.1.1) - -DEPENDENCIES: - - Flutter (from `Flutter`) - - speech_to_text (from `.symlinks/plugins/speech_to_text/ios`) - -SPEC REPOS: - trunk: - - Try - -EXTERNAL SOURCES: - Flutter: - :path: Flutter - speech_to_text: - :path: ".symlinks/plugins/speech_to_text/ios" - -SPEC CHECKSUMS: - Flutter: 0e3d915762c693b495b44d77113d4970485de6ec - speech_to_text: b43a7d99aef037bd758ed8e45d79bbac035d2dfe - Try: 5ef669ae832617b3cee58cb2c6f99fb767a4ff96 - -PODFILE CHECKSUM: 0ba44ad07df4ab62269dc769727cf0f12b1e453d - -COCOAPODS: 1.9.3 diff --git a/speech_to_text_/example/ios/Runner.xcodeproj/project.pbxproj b/speech_to_text_/example/ios/Runner.xcodeproj/project.pbxproj deleted file mode 100644 index c40af650..00000000 --- a/speech_to_text_/example/ios/Runner.xcodeproj/project.pbxproj +++ /dev/null @@ -1,578 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; - 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; - 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; - 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; - 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; - 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; - 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; - C446300A034BF27D9F1ACEF9 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E76E9615C6B4FABD88067D55 /* Pods_Runner.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 9705A1C41CF9048500538489 /* Embed Frameworks */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - ); - name = "Embed Frameworks"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; - 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 59AFE6BB0B596A0E0811BDFF /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; - 6280E2A777726D2043BF80B7 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; - 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; - 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; - 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; - 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; - 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - C3909A4B7EC98A20255210E3 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; - E76E9615C6B4FABD88067D55 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 97C146EB1CF9000F007C117D /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - C446300A034BF27D9F1ACEF9 /* Pods_Runner.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 7937AF765430D66F28F7FEEF /* Frameworks */ = { - isa = PBXGroup; - children = ( - E76E9615C6B4FABD88067D55 /* Pods_Runner.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - 9740EEB11CF90186004384FC /* Flutter */ = { - isa = PBXGroup; - children = ( - 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, - 9740EEB21CF90195004384FC /* Debug.xcconfig */, - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, - 9740EEB31CF90195004384FC /* Generated.xcconfig */, - ); - name = Flutter; - sourceTree = ""; - }; - 97C146E51CF9000F007C117D = { - isa = PBXGroup; - children = ( - 9740EEB11CF90186004384FC /* Flutter */, - 97C146F01CF9000F007C117D /* Runner */, - 97C146EF1CF9000F007C117D /* Products */, - A68CCF1640763A551D35BD31 /* Pods */, - 7937AF765430D66F28F7FEEF /* Frameworks */, - ); - sourceTree = ""; - }; - 97C146EF1CF9000F007C117D /* Products */ = { - isa = PBXGroup; - children = ( - 97C146EE1CF9000F007C117D /* Runner.app */, - ); - name = Products; - sourceTree = ""; - }; - 97C146F01CF9000F007C117D /* Runner */ = { - isa = PBXGroup; - children = ( - 97C146FA1CF9000F007C117D /* Main.storyboard */, - 97C146FD1CF9000F007C117D /* Assets.xcassets */, - 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, - 97C147021CF9000F007C117D /* Info.plist */, - 97C146F11CF9000F007C117D /* Supporting Files */, - 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, - 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, - 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, - 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, - ); - path = Runner; - sourceTree = ""; - }; - 97C146F11CF9000F007C117D /* Supporting Files */ = { - isa = PBXGroup; - children = ( - ); - name = "Supporting Files"; - sourceTree = ""; - }; - A68CCF1640763A551D35BD31 /* Pods */ = { - isa = PBXGroup; - children = ( - 59AFE6BB0B596A0E0811BDFF /* Pods-Runner.debug.xcconfig */, - 6280E2A777726D2043BF80B7 /* Pods-Runner.release.xcconfig */, - C3909A4B7EC98A20255210E3 /* Pods-Runner.profile.xcconfig */, - ); - path = Pods; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 97C146ED1CF9000F007C117D /* Runner */ = { - isa = PBXNativeTarget; - buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; - buildPhases = ( - 949FCB95217187F2C022D6A9 /* [CP] Check Pods Manifest.lock */, - 9740EEB61CF901F6004384FC /* Run Script */, - 97C146EA1CF9000F007C117D /* Sources */, - 97C146EB1CF9000F007C117D /* Frameworks */, - 97C146EC1CF9000F007C117D /* Resources */, - 9705A1C41CF9048500538489 /* Embed Frameworks */, - 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - 8B0988F04B6AE44AA0304FEF /* [CP] Embed Pods Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Runner; - productName = Runner; - productReference = 97C146EE1CF9000F007C117D /* Runner.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 97C146E61CF9000F007C117D /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 1020; - ORGANIZATIONNAME = "The Chromium Authors"; - TargetAttributes = { - 97C146ED1CF9000F007C117D = { - CreatedOnToolsVersion = 7.3.1; - DevelopmentTeam = 3X949YE9K2; - LastSwiftMigration = 0910; - }; - }; - }; - buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 97C146E51CF9000F007C117D; - productRefGroup = 97C146EF1CF9000F007C117D /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 97C146ED1CF9000F007C117D /* Runner */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 97C146EC1CF9000F007C117D /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, - 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, - 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, - 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, - 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Thin Binary"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; - }; - 8B0988F04B6AE44AA0304FEF /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "[CP] Embed Pods Frameworks"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - 949FCB95217187F2C022D6A9 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 9740EEB61CF901F6004384FC /* Run Script */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Run Script"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 97C146EA1CF9000F007C117D /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, - 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 97C146FA1CF9000F007C117D /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 97C146FB1CF9000F007C117D /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 97C147001CF9000F007C117D /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 249021D3217E4FDB00AE95B9 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Profile; - }; - 249021D4217E4FDB00AE95B9 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = 3X949YE9K2; - ENABLE_BITCODE = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); - INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.csdcorp.speechToTextExample; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Profile; - }; - 97C147031CF9000F007C117D /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 97C147041CF9000F007C117D /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 97C147061CF9000F007C117D /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = 3X949YE9K2; - ENABLE_BITCODE = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); - INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.csdcorp.speechToTextExample; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Debug; - }; - 97C147071CF9000F007C117D /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = 3X949YE9K2; - ENABLE_BITCODE = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); - INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.csdcorp.speechToTextExample; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 97C147031CF9000F007C117D /* Debug */, - 97C147041CF9000F007C117D /* Release */, - 249021D3217E4FDB00AE95B9 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 97C147061CF9000F007C117D /* Debug */, - 97C147071CF9000F007C117D /* Release */, - 249021D4217E4FDB00AE95B9 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 97C146E61CF9000F007C117D /* Project object */; -} diff --git a/speech_to_text_/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/speech_to_text_/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 1d526a16..00000000 --- a/speech_to_text_/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/speech_to_text_/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/speech_to_text_/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme deleted file mode 100644 index a28140cf..00000000 --- a/speech_to_text_/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/speech_to_text_/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/speech_to_text_/example/ios/Runner.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 21a3cc14..00000000 --- a/speech_to_text_/example/ios/Runner.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/speech_to_text_/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/speech_to_text_/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d98100..00000000 --- a/speech_to_text_/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/speech_to_text_/example/ios/Runner/AppDelegate.swift b/speech_to_text_/example/ios/Runner/AppDelegate.swift deleted file mode 100644 index 70693e4a..00000000 --- a/speech_to_text_/example/ios/Runner/AppDelegate.swift +++ /dev/null @@ -1,13 +0,0 @@ -import UIKit -import Flutter - -@UIApplicationMain -@objc class AppDelegate: FlutterAppDelegate { - override func application( - _ application: UIApplication, - didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? - ) -> Bool { - GeneratedPluginRegistrant.register(with: self) - return super.application(application, didFinishLaunchingWithOptions: launchOptions) - } -} diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index d36b1fab..00000000 --- a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,122 +0,0 @@ -{ - "images" : [ - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" - }, - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@3x.png", - "scale" : "3x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@3x.png", - "scale" : "3x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@3x.png", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@2x.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@3x.png", - "scale" : "3x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@1x.png", - "scale" : "1x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@1x.png", - "scale" : "1x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@1x.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@2x.png", - "scale" : "2x" - }, - { - "size" : "83.5x83.5", - "idiom" : "ipad", - "filename" : "Icon-App-83.5x83.5@2x.png", - "scale" : "2x" - }, - { - "size" : "1024x1024", - "idiom" : "ios-marketing", - "filename" : "Icon-App-1024x1024@1x.png", - "scale" : "1x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png deleted file mode 100644 index dc9ada4725e9b0ddb1deab583e5b5102493aa332..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10932 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 diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png deleted file mode 100644 index f091b6b0bca859a3f474b03065bef75ba58a9e4c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1588 zcmV-42Fv-0P)C1SqPt}wig>|5Crh^=oyX$BK<}M8eLU3e2hGT;=G|!_SP)7zNI6fqUMB=)y zRAZ>eDe#*r`yDAVgB_R*LB*MAc)8(b{g{9McCXW!lq7r(btRoB9!8B-#AI6JMb~YFBEvdsV)`mEQO^&#eRKx@b&x- z5lZm*!WfD8oCLzfHGz#u7sT0^VLMI1MqGxF^v+`4YYnVYgk*=kU?HsSz{v({E3lb9 z>+xILjBN)t6`=g~IBOelGQ(O990@BfXf(DRI5I$qN$0Gkz-FSc$3a+2fX$AedL4u{ z4V+5Ong(9LiGcIKW?_352sR;LtDPmPJXI{YtT=O8=76o9;*n%_m|xo!i>7$IrZ-{l z-x3`7M}qzHsPV@$v#>H-TpjDh2UE$9g6sysUREDy_R(a)>=eHw-WAyfIN z*qb!_hW>G)Tu8nSw9yn#3wFMiLcfc4pY0ek1}8(NqkBR@t4{~oC>ryc-h_ByH(Cg5 z>ao-}771+xE3um9lWAY1FeQFxowa1(!J(;Jg*wrg!=6FdRX+t_<%z&d&?|Bn){>zm zZQj(aA_HeBY&OC^jj*)N`8fa^ePOU72VpInJoI1?`ty#lvlNzs(&MZX+R%2xS~5Kh zX*|AU4QE#~SgPzOXe9>tRj>hjU@c1k5Y_mW*Jp3fI;)1&g3j|zDgC+}2Q_v%YfDax z!?umcN^n}KYQ|a$Lr+51Nf9dkkYFSjZZjkma$0KOj+;aQ&721~t7QUKx61J3(P4P1 zstI~7-wOACnWP4=8oGOwz%vNDqD8w&Q`qcNGGrbbf&0s9L0De{4{mRS?o0MU+nR_! zrvshUau0G^DeMhM_v{5BuLjb#Hh@r23lDAk8oF(C+P0rsBpv85EP>4CVMx#04MOfG z;P%vktHcXwTj~+IE(~px)3*MY77e}p#|c>TD?sMatC0Tu4iKKJ0(X8jxQY*gYtxsC z(zYC$g|@+I+kY;dg_dE>scBf&bP1Nc@Hz<3R)V`=AGkc;8CXqdi=B4l2k|g;2%#m& z*jfX^%b!A8#bI!j9-0Fi0bOXl(-c^AB9|nQaE`*)Hw+o&jS9@7&Gov#HbD~#d{twV zXd^Tr^mWLfFh$@Dr$e;PBEz4(-2q1FF0}c;~B5sA}+Q>TOoP+t>wf)V9Iy=5ruQa;z)y zI9C9*oUga6=hxw6QasLPnee@3^Rr*M{CdaL5=R41nLs(AHk_=Y+A9$2&H(B7!_pURs&8aNw7?`&Z&xY_Ye z)~D5Bog^td-^QbUtkTirdyK^mTHAOuptDflut!#^lnKqU md>ggs(5nOWAqO?umG&QVYK#ibz}*4>0000U6E9hRK9^#O7(mu>ETqrXGsduA8$)?`v2seloOCza43C{NQ$$gAOH**MCn0Q?+L7dl7qnbRdqZ8LSVp1ItDxhxD?t@5_yHg6A8yI zC*%Wgg22K|8E#!~cTNYR~@Y9KepMPrrB8cABapAFa=`H+UGhkXUZV1GnwR1*lPyZ;*K(i~2gp|@bzp8}og7e*#% zEnr|^CWdVV!-4*Y_7rFvlww2Ze+>j*!Z!pQ?2l->4q#nqRu9`ELo6RMS5=br47g_X zRw}P9a7RRYQ%2Vsd0Me{_(EggTnuN6j=-?uFS6j^u69elMypu?t>op*wBx<=Wx8?( ztpe^(fwM6jJX7M-l*k3kEpWOl_Vk3@(_w4oc}4YF4|Rt=2V^XU?#Yz`8(e?aZ@#li0n*=g^qOcVpd-Wbok=@b#Yw zqn8u9a)z>l(1kEaPYZ6hwubN6i<8QHgsu0oE) ziJ(p;Wxm>sf!K+cw>R-(^Y2_bahB+&KI9y^);#0qt}t-$C|Bo71lHi{_+lg#f%RFy z0um=e3$K3i6K{U_4K!EX?F&rExl^W|G8Z8;`5z-k}OGNZ0#WVb$WCpQu-_YsiqKP?BB# vzVHS-CTUF4Ozn5G+mq_~Qqto~ahA+K`|lyv3(-e}00000NkvXXu0mjfd`9t{ diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png deleted file mode 100644 index d0ef06e7edb86cdfe0d15b4b0d98334a86163658..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1716 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 diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png deleted file mode 100644 index c8f9ed8f5cee1c98386d13b17e89f719e83555b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1895 zcmV-t2blPYP)FQtfgmafE#=YDCq`qUBt#QpG%*H6QHY765~R=q zZ6iudfM}q!Pz#~9JgOi8QJ|DSu?1-*(kSi1K4#~5?#|rh?sS)(-JQqX*}ciXJ56_H zdw=^s_srbAdqxlvGyrgGet#6T7_|j;95sL%MtM;q86vOxKM$f#puR)Bjv9Zvz9-di zXOTSsZkM83)E9PYBXC<$6(|>lNLVBb&&6y{NByFCp%6+^ALR@NCTse_wqvNmSWI-m z!$%KlHFH2omF!>#%1l3LTZg(s7eof$7*xB)ZQ0h?ejh?Ta9fDv59+u#MokW+1t8Zb zgHv%K(u9G^Lv`lh#f3<6!JVTL3(dCpxHbnbA;kKqQyd1~^Xe0VIaYBSWm6nsr;dFj z4;G-RyL?cYgsN1{L4ZFFNa;8)Rv0fM0C(~Tkit94 zz#~A)59?QjD&pAPSEQ)p8gP|DS{ng)j=2ux)_EzzJ773GmQ_Cic%3JJhC0t2cx>|v zJcVusIB!%F90{+}8hG3QU4KNeKmK%T>mN57NnCZ^56=0?&3@!j>a>B43pi{!u z7JyDj7`6d)qVp^R=%j>UIY6f+3`+qzIc!Y_=+uN^3BYV|o+$vGo-j-Wm<10%A=(Yk^beI{t%ld@yhKjq0iNjqN4XMGgQtbKubPM$JWBz}YA65k%dm*awtC^+f;a-x4+ddbH^7iDWGg&N0n#MW{kA|=8iMUiFYvMoDY@sPC#t$55gn6ykUTPAr`a@!(;np824>2xJthS z*ZdmT`g5-`BuJs`0LVhz+D9NNa3<=6m;cQLaF?tCv8)zcRSh66*Z|vXhG@$I%U~2l z?`Q zykI#*+rQ=z6Jm=Bui-SfpDYLA=|vzGE(dYm=OC8XM&MDo7ux4UF1~0J1+i%aCUpRe zt3L_uNyQ*cE(38Uy03H%I*)*Bh=Lb^Xj3?I^Hnbeq72(EOK^Y93CNp*uAA{5Lc=ky zx=~RKa4{iTm{_>_vSCm?$Ej=i6@=m%@VvAITnigVg{&@!7CDgs908761meDK5azA} z4?=NOH|PdvabgJ&fW2{Mo$Q0CcD8Qc84%{JPYt5EiG{MdLIAeX%T=D7NIP4%Hw}p9 zg)==!2Lbp#j{u_}hMiao9=!VSyx0gHbeCS`;q&vzeq|fs`y&^X-lso(Ls@-706qmA z7u*T5PMo_w3{se1t2`zWeO^hOvTsohG_;>J0wVqVe+n)AbQCx)yh9;w+J6?NF5Lmo zecS@ieAKL8%bVd@+-KT{yI|S}O>pYckUFs;ry9Ow$CD@ztz5K-*D$^{i(_1llhSh^ zEkL$}tsQt5>QA^;QgjgIfBDmcOgi5YDyu?t6vSnbp=1+@6D& z5MJ}B8q;bRlVoxasyhcUF1+)o`&3r0colr}QJ3hcSdLu;9;td>kf@Tcn<@9sIx&=m z;AD;SCh95=&p;$r{Xz3iWCO^MX83AGJ(yH&eTXgv|0=34#-&WAmw{)U7OU9!Wz^!7 zZ%jZFi@JR;>Mhi7S>V7wQ176|FdW2m?&`qa(ScO^CFPR80HucLHOTy%5s*HR0^8)i h0WYBP*#0Ks^FNSabJA*5${_#%002ovPDHLkV1oKhTl@e3 diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png deleted file mode 100644 index a6d6b8609df07bf62e5100a53a01510388bd2b22..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png deleted file mode 100644 index a6d6b8609df07bf62e5100a53a01510388bd2b22..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png deleted file mode 100644 index 75b2d164a5a98e212cca15ea7bf2ab5de5108680..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3831 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 diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png deleted file mode 100644 index c4df70d39da7941ef3f6dcb7f06a192d8dcb308d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1888 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 iW8Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png deleted file mode 100644 index 9da19eacad3b03bb08bbddbbf4ac48dd78b3d838..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png deleted file mode 100644 index 9da19eacad3b03bb08bbddbbf4ac48dd78b3d838..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md deleted file mode 100644 index 89c2725b..00000000 --- a/speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Launch Screen Assets - -You can customize the launch screen with your own desired assets by replacing the image files in this directory. - -You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/speech_to_text_/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/speech_to_text_/example/ios/Runner/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index f2e259c7..00000000 --- a/speech_to_text_/example/ios/Runner/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/speech_to_text_/example/ios/Runner/Base.lproj/Main.storyboard b/speech_to_text_/example/ios/Runner/Base.lproj/Main.storyboard deleted file mode 100644 index f3c28516..00000000 --- a/speech_to_text_/example/ios/Runner/Base.lproj/Main.storyboard +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/speech_to_text_/example/ios/Runner/Info.plist b/speech_to_text_/example/ios/Runner/Info.plist deleted file mode 100644 index a69c0fce..00000000 --- a/speech_to_text_/example/ios/Runner/Info.plist +++ /dev/null @@ -1,49 +0,0 @@ - - - - - NSMicrophoneUsageDescription - This example listens for speech on the device microphone on your request. - NSSpeechRecognitionUsageDescription - This example recognizes words as you speak them and displays them. - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - speech_to_text_example - CFBundlePackageType - APPL - CFBundleShortVersionString - $(FLUTTER_BUILD_NAME) - CFBundleSignature - ???? - CFBundleVersion - $(FLUTTER_BUILD_NUMBER) - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UIViewControllerBasedStatusBarAppearance - - - diff --git a/speech_to_text_/example/ios/Runner/Runner-Bridging-Header.h b/speech_to_text_/example/ios/Runner/Runner-Bridging-Header.h deleted file mode 100644 index 7335fdf9..00000000 --- a/speech_to_text_/example/ios/Runner/Runner-Bridging-Header.h +++ /dev/null @@ -1 +0,0 @@ -#import "GeneratedPluginRegistrant.h" \ No newline at end of file diff --git a/speech_to_text_/example/lib/main.dart b/speech_to_text_/example/lib/main.dart deleted file mode 100644 index 0115b828..00000000 --- a/speech_to_text_/example/lib/main.dart +++ /dev/null @@ -1,275 +0,0 @@ -import 'dart:async'; -import 'dart:math'; - -import 'package:flutter/material.dart'; -import 'package:permission_handler/permission_handler.dart'; -import 'package:speech_to_text/speech_recognition_error.dart'; -import 'package:speech_to_text/speech_recognition_result.dart'; -import 'package:speech_to_text/speech_to_text.dart'; - -void main() => runApp(MyApp()); - -class MyApp extends StatefulWidget { - @override - _MyAppState createState() => _MyAppState(); -} - -class _MyAppState extends State { - bool _hasSpeech = false; - double level = 0.0; - double minSoundLevel = 50000; - double maxSoundLevel = -50000; - String lastWords = ""; - String lastError = ""; - String lastStatus = ""; - String _currentLocaleId = ""; - List _localeNames = []; - final SpeechToText speech = SpeechToText(); - - @override - void initState() { - requestPermissions(); - super.initState(); - } - - Future initSpeechState() async { - bool hasSpeech = await speech.initialize( - onError: errorListener, onStatus: statusListener); - if (hasSpeech) { - _localeNames = await speech.locales(); - - var systemLocale = await speech.systemLocale(); - _currentLocaleId = systemLocale.localeId; - } - - if (!mounted) return; - - setState(() { - _hasSpeech = hasSpeech; - }); - } - - void requestPermissions() async{ - Map statuses = await [ - Permission.microphone, - ].request(); - } - - @override - Widget build(BuildContext context) { - return MaterialApp( - home: Scaffold( - appBar: AppBar( - title: const Text('Speech to Text CloudSolution'), - ), - body: Column(children: [ - Center( - child: Text( - 'Speech recognition available', - style: TextStyle(fontSize: 22.0), - ), - ), - Container( - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - FlatButton( - child: Text('Initialize'), - onPressed: _hasSpeech ? null : initSpeechState, - ), - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - FlatButton( - child: Text('Start'), - onPressed: !_hasSpeech || speech.isListening - ? null - : startListening, - ), - FlatButton( - child: Text('Stop'), - onPressed: speech.isListening ? stopListening : null, - ), - FlatButton( - child: Text('Cancel'), - onPressed: speech.isListening ? cancelListening : null, - ), - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - DropdownButton( - onChanged: (selectedVal) => _switchLang(selectedVal), - value: _currentLocaleId, - items: _localeNames - .map( - (localeName) => DropdownMenuItem( - value: localeName.localeId, - child: Text(localeName.name), - ), - ) - .toList(), - ), - ], - ) - ], - ), - ), - Expanded( - flex: 4, - child: Column( - children: [ - Center( - child: Text( - 'Recognized Words', - style: TextStyle(fontSize: 22.0), - ), - ), - Expanded( - child: Stack( - children: [ - Container( - color: Theme.of(context).selectedRowColor, - child: Center( - child: Text( - lastWords, - textAlign: TextAlign.center, - ), - ), - ), - Positioned.fill( - bottom: 10, - child: Align( - alignment: Alignment.bottomCenter, - child: Container( - width: 40, - height: 40, - alignment: Alignment.center, - decoration: BoxDecoration( - boxShadow: [ - BoxShadow( - blurRadius: .26, - spreadRadius: level * 1.5, - color: Colors.black.withOpacity(.05)) - ], - color: Colors.white, - borderRadius: - BorderRadius.all(Radius.circular(50)), - ), - child: IconButton(icon: Icon(Icons.mic)), - ), - ), - ), - ], - ), - ), - ], - ), - ), - Expanded( - flex: 1, - child: Column( - children: [ - Center( - child: Text( - 'Error Status', - style: TextStyle(fontSize: 22.0), - ), - ), - Center( - child: Text(lastError), - ), - ], - ), - ), - Container( - padding: EdgeInsets.symmetric(vertical: 20), - color: Theme.of(context).backgroundColor, - child: Center( - child: speech.isListening - ? Text( - "I'm listening...", - style: TextStyle(fontWeight: FontWeight.bold), - ) - : Text( - 'Not listening', - style: TextStyle(fontWeight: FontWeight.bold), - ), - ), - ), - ]), - ), - ); - } - - void startListening() { - lastWords = ""; - lastError = ""; - speech.listen( - onResult: resultListener, - listenFor: Duration(seconds: 10), - localeId: _currentLocaleId, - onSoundLevelChange: soundLevelListener, - cancelOnError: true, - partialResults: true, - onDevice: true, - listenMode: ListenMode.confirmation); - setState(() {}); - } - - void stopListening() { - speech.stop(); - setState(() { - level = 0.0; - }); - } - - void cancelListening() { - speech.cancel(); - setState(() { - level = 0.0; - }); - } - - void resultListener(SpeechRecognitionResult result) { - setState(() { - lastWords = "${result.recognizedWords} - ${result.finalResult}"; - }); - } - - void soundLevelListener(double level) { - minSoundLevel = min(minSoundLevel, level); - maxSoundLevel = max(maxSoundLevel, level); - // print("sound level $level: $minSoundLevel - $maxSoundLevel "); - setState(() { - this.level = level; - }); - } - - void errorListener(SpeechRecognitionError error) { - // print("Received error status: $error, listening: ${speech.isListening}"); - setState(() { - lastError = "${error.errorMsg} - ${error.permanent}"; - }); - } - - void statusListener(String status) { - // print( - // "Received listener status: $status, listening: ${speech.isListening}"); - setState(() { - lastStatus = "$status"; - }); - } - - _switchLang(selectedVal) { - setState(() { - _currentLocaleId = selectedVal; - }); - print(selectedVal); - } -} diff --git a/speech_to_text_/example/pubspec.yaml b/speech_to_text_/example/pubspec.yaml deleted file mode 100644 index d2bfcff7..00000000 --- a/speech_to_text_/example/pubspec.yaml +++ /dev/null @@ -1,33 +0,0 @@ -name: speech_to_text_example -description: Demonstrates how to use the speech_to_text plugin. -version: 1.1.0 -publish_to: 'none' - -environment: - sdk: ">=2.1.0 <3.0.0" - -dependencies: - flutter: - sdk: flutter - - cupertino_icons: ^0.1.2 - permission_handler: ^5.0.1+1 - - provider: - -dev_dependencies: - flutter_test: - sdk: flutter - - speech_to_text: - path: ../ - -# The following section is specific to Flutter. -flutter: - - uses-material-design: true - - assets: - - assets/sounds/speech_to_text_listening.m4r - - assets/sounds/speech_to_text_cancel.m4r - - assets/sounds/speech_to_text_stop.m4r diff --git a/speech_to_text_/example/test/widget_test.dart b/speech_to_text_/example/test/widget_test.dart deleted file mode 100644 index 639a52fb..00000000 --- a/speech_to_text_/example/test/widget_test.dart +++ /dev/null @@ -1,27 +0,0 @@ -// This is a basic Flutter widget test. -// -// To perform an interaction with a widget in your test, use the WidgetTester -// utility that Flutter provides. For example, you can send tap and scroll -// gestures. You can also use WidgetTester to find child widgets in the widget -// tree, read text, and verify that the values of widget properties are correct. - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import '../lib/main.dart'; - -void main() { - testWidgets('Verify Platform version', (WidgetTester tester) async { - // Build our app and trigger a frame. - await tester.pumpWidget(MyApp()); - - // Verify that platform version is retrieved. - expect( - find.byWidgetPredicate( - (Widget widget) => - widget is Text && widget.data.startsWith('Running on:'), - ), - findsOneWidget, - ); - }); -} diff --git a/speech_to_text_/ios/.gitignore b/speech_to_text_/ios/.gitignore deleted file mode 100644 index aa479fd3..00000000 --- a/speech_to_text_/ios/.gitignore +++ /dev/null @@ -1,37 +0,0 @@ -.idea/ -.vagrant/ -.sconsign.dblite -.svn/ - -.DS_Store -*.swp -profile - -DerivedData/ -build/ -GeneratedPluginRegistrant.h -GeneratedPluginRegistrant.m - -.generated/ - -*.pbxuser -*.mode1v3 -*.mode2v3 -*.perspectivev3 - -!default.pbxuser -!default.mode1v3 -!default.mode2v3 -!default.perspectivev3 - -xcuserdata - -*.moved-aside - -*.pyc -*sync/ -Icon? -.tags* - -/Flutter/Generated.xcconfig -/Flutter/flutter_export_environment.sh \ No newline at end of file diff --git a/speech_to_text_/ios/Assets/.gitkeep b/speech_to_text_/ios/Assets/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/speech_to_text_/ios/Classes/SpeechToTextPlugin.h b/speech_to_text_/ios/Classes/SpeechToTextPlugin.h deleted file mode 100644 index 1785eb8f..00000000 --- a/speech_to_text_/ios/Classes/SpeechToTextPlugin.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface SpeechToTextPlugin : NSObject -@end diff --git a/speech_to_text_/ios/Classes/SpeechToTextPlugin.m b/speech_to_text_/ios/Classes/SpeechToTextPlugin.m deleted file mode 100644 index 20d0327d..00000000 --- a/speech_to_text_/ios/Classes/SpeechToTextPlugin.m +++ /dev/null @@ -1,8 +0,0 @@ -#import "SpeechToTextPlugin.h" -#import - -@implementation SpeechToTextPlugin -+ (void)registerWithRegistrar:(NSObject*)registrar { - [SwiftSpeechToTextPlugin registerWithRegistrar:registrar]; -} -@end diff --git a/speech_to_text_/ios/Classes/SwiftSpeechToTextPlugin.swift b/speech_to_text_/ios/Classes/SwiftSpeechToTextPlugin.swift deleted file mode 100644 index 68687967..00000000 --- a/speech_to_text_/ios/Classes/SwiftSpeechToTextPlugin.swift +++ /dev/null @@ -1,580 +0,0 @@ -import Flutter -import UIKit -import Speech -import os.log -import Try - -public enum SwiftSpeechToTextMethods: String { - case has_permission - case initialize - case listen - case stop - case cancel - case locales - case unknown // just for testing -} - -public enum SwiftSpeechToTextCallbackMethods: String { - case textRecognition - case notifyStatus - case notifyError - case soundLevelChange -} - -public enum SpeechToTextStatus: String { - case listening - case notListening - case unavailable - case available -} - -public enum SpeechToTextErrors: String { - case onDeviceError - case noRecognizerError - case listenFailedError - case missingOrInvalidArg -} - -public enum ListenMode: Int { - case deviceDefault = 0 - case dictation = 1 - case search = 2 - case confirmation = 3 -} - -struct SpeechRecognitionWords : Codable { - let recognizedWords: String - let confidence: Decimal -} - -struct SpeechRecognitionResult : Codable { - let alternates: [SpeechRecognitionWords] - let finalResult: Bool -} - -struct SpeechRecognitionError : Codable { - let errorMsg: String - let permanent: Bool -} - -enum SpeechToTextError: Error { - case runtimeError(String) -} - - -@available(iOS 10.0, *) -public class SwiftSpeechToTextPlugin: NSObject, FlutterPlugin { - private var channel: FlutterMethodChannel - private var registrar: FlutterPluginRegistrar - private var recognizer: SFSpeechRecognizer? - private var currentRequest: SFSpeechAudioBufferRecognitionRequest? - private var currentTask: SFSpeechRecognitionTask? - private var listeningSound: AVAudioPlayer? - private var successSound: AVAudioPlayer? - private var cancelSound: AVAudioPlayer? - private var rememberedAudioCategory: AVAudioSession.Category? - private var previousLocale: Locale? - private var onPlayEnd: (() -> Void)? - private var returnPartialResults: Bool = true - private var failedListen: Bool = false - private var listening = false - private let audioSession = AVAudioSession.sharedInstance() - private let audioEngine = AVAudioEngine() - private let jsonEncoder = JSONEncoder() - private let busForNodeTap = 0 - private let speechBufferSize: AVAudioFrameCount = 1024 - private static var subsystem = Bundle.main.bundleIdentifier! - private let pluginLog = OSLog(subsystem: "com.csdcorp.speechToText", category: "plugin") - - public static func register(with registrar: FlutterPluginRegistrar) { - let channel = FlutterMethodChannel(name: "plugin.csdcorp.com/speech_to_text", binaryMessenger: registrar.messenger()) - let instance = SwiftSpeechToTextPlugin( channel, registrar: registrar ) - registrar.addMethodCallDelegate(instance, channel: channel ) - } - - init( _ channel: FlutterMethodChannel, registrar: FlutterPluginRegistrar ) { - self.channel = channel - self.registrar = registrar - } - - public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { - switch call.method { - case SwiftSpeechToTextMethods.has_permission.rawValue: - hasPermission( result ) - case SwiftSpeechToTextMethods.initialize.rawValue: - initialize( result ) - case SwiftSpeechToTextMethods.listen.rawValue: - guard let argsArr = call.arguments as? Dictionary, - let partialResults = argsArr["partialResults"] as? Bool, let onDevice = argsArr["onDevice"] as? Bool, let listenModeIndex = argsArr["listenMode"] as? Int - else { - DispatchQueue.main.async { - result(FlutterError( code: SpeechToTextErrors.missingOrInvalidArg.rawValue, - message:"Missing arg partialResults, onDevice, and listenMode are required", - details: nil )) - } - return - } - var localeStr: String? = nil - if let localeParam = argsArr["localeId"] as? String { - localeStr = localeParam - } - guard let listenMode = ListenMode(rawValue: listenModeIndex) else { - DispatchQueue.main.async { - result(FlutterError( code: SpeechToTextErrors.missingOrInvalidArg.rawValue, - message:"invalid value for listenMode, must be 0-2, was \(listenModeIndex)", - details: nil )) - } - return - } - - listenForSpeech( result, localeStr: localeStr, partialResults: partialResults, onDevice: onDevice, listenMode: listenMode ) - case SwiftSpeechToTextMethods.stop.rawValue: - stopSpeech( result ) - case SwiftSpeechToTextMethods.cancel.rawValue: - cancelSpeech( result ) - case SwiftSpeechToTextMethods.locales.rawValue: - locales( result ) - default: - os_log("Unrecognized method: %{PUBLIC}@", log: pluginLog, type: .error, call.method) - DispatchQueue.main.async { - result( FlutterMethodNotImplemented) - } - } - } - - private func hasPermission( _ result: @escaping FlutterResult) { - let has = SFSpeechRecognizer.authorizationStatus() == SFSpeechRecognizerAuthorizationStatus.authorized && - AVAudioSession.sharedInstance().recordPermission == AVAudioSession.RecordPermission.granted - DispatchQueue.main.async { - result( has ) - } - } - - private func initialize( _ result: @escaping FlutterResult) { - var success = false - let status = SFSpeechRecognizer.authorizationStatus() - switch status { - case SFSpeechRecognizerAuthorizationStatus.notDetermined: - SFSpeechRecognizer.requestAuthorization({(status)->Void in - success = status == SFSpeechRecognizerAuthorizationStatus.authorized - if ( success ) { - AVAudioSession.sharedInstance().requestRecordPermission({(granted: Bool)-> Void in - if granted { - self.setupSpeechRecognition(result) - } else{ - self.sendBoolResult( false, result ); - os_log("User denied permission", log: self.pluginLog, type: .info) - } - }) - } - else { - self.sendBoolResult( false, result ); - } - }); - case SFSpeechRecognizerAuthorizationStatus.denied: - os_log("Permission permanently denied", log: self.pluginLog, type: .info) - sendBoolResult( false, result ); - case SFSpeechRecognizerAuthorizationStatus.restricted: - os_log("Device restriction prevented initialize", log: self.pluginLog, type: .info) - sendBoolResult( false, result ); - default: - os_log("Has permissions continuing with setup", log: self.pluginLog, type: .debug) - setupSpeechRecognition(result) - } - } - - fileprivate func sendBoolResult( _ value: Bool, _ result: @escaping FlutterResult) { - DispatchQueue.main.async { - result( value ) - } - } - - fileprivate func setupListeningSound() { - listeningSound = loadSound("assets/sounds/speech_to_text_listening.m4r") - successSound = loadSound("assets/sounds/speech_to_text_stop.m4r") - cancelSound = loadSound("assets/sounds/speech_to_text_cancel.m4r") - } - - fileprivate func loadSound( _ assetPath: String ) -> AVAudioPlayer? { - var player: AVAudioPlayer? = nil - let soundKey = registrar.lookupKey(forAsset: assetPath ) - guard !soundKey.isEmpty else { - return player - } - if let soundPath = Bundle.main.path(forResource: soundKey, ofType:nil) { - let soundUrl = URL(fileURLWithPath: soundPath ) - do { - player = try AVAudioPlayer(contentsOf: soundUrl ) - player?.delegate = self - } catch { - // no audio - } - } - return player - } - - private func setupSpeechRecognition( _ result: @escaping FlutterResult) { - setupRecognizerForLocale( locale: Locale.current ) - guard recognizer != nil else { - sendBoolResult( false, result ); - return - } - recognizer?.delegate = self - setupListeningSound() - - sendBoolResult( true, result ); - } - - private func setupRecognizerForLocale( locale: Locale ) { - if ( previousLocale == locale ) { - return - } - previousLocale = locale - recognizer = SFSpeechRecognizer( locale: locale ) - } - - private func getLocale( _ localeStr: String? ) -> Locale { - guard let aLocaleStr = localeStr else { - return Locale.current - } - let locale = Locale(identifier: aLocaleStr) - return locale - } - - private func stopSpeech( _ result: @escaping FlutterResult) { - if ( !listening ) { - sendBoolResult( false, result ); - return - } - stopAllPlayers() - if let sound = successSound { - onPlayEnd = {() -> Void in - self.currentTask?.finish() - self.stopCurrentListen( ) - self.sendBoolResult( true, result ) - return - } - sound.play() - } - else { - stopCurrentListen( ) - sendBoolResult( true, result ); - } - } - - private func cancelSpeech( _ result: @escaping FlutterResult) { - if ( !listening ) { - sendBoolResult( false, result ); - return - } - stopAllPlayers() - if let sound = cancelSound { - onPlayEnd = {() -> Void in - self.currentTask?.cancel() - self.stopCurrentListen( ) - self.sendBoolResult( true, result ) - return - } - sound.play() - } - else { - self.currentTask?.cancel() - stopCurrentListen( ) - sendBoolResult( true, result ); - } - } - - private func stopAllPlayers() { - cancelSound?.stop() - successSound?.stop() - listeningSound?.stop() - } - - private func stopCurrentListen( ) { - stopAllPlayers() - currentRequest?.endAudio() - - do { - try trap { - self.audioEngine.stop() - } - } - catch { - os_log("Error stopping engine: %{PUBLIC}@", log: pluginLog, type: .error, error.localizedDescription) - } - do { - try trap { - let inputNode = self.audioEngine.inputNode - inputNode.removeTap(onBus: self.busForNodeTap); - } - } - catch { - os_log("Error removing trap: %{PUBLIC}@", log: pluginLog, type: .error, error.localizedDescription) - } - do { - if let rememberedAudioCategory = rememberedAudioCategory { - try self.audioSession.setCategory(rememberedAudioCategory) - } - } - catch { - os_log("Error stopping listen: %{PUBLIC}@", log: pluginLog, type: .error, error.localizedDescription) - } - do { - try self.audioSession.setActive(false, options: .notifyOthersOnDeactivation) - } - catch { - os_log("Error deactivation: %{PUBLIC}@", log: pluginLog, type: .info, error.localizedDescription) - } - currentRequest = nil - currentTask = nil - onPlayEnd = nil - listening = false - } - - private func listenForSpeech( _ result: @escaping FlutterResult, localeStr: String?, partialResults: Bool, onDevice: Bool, listenMode: ListenMode ) { - if ( nil != currentTask || listening ) { - sendBoolResult( false, result ); - return - } - do { - // let inErrorTest = true - failedListen = false - returnPartialResults = partialResults - setupRecognizerForLocale(locale: getLocale(localeStr)) - guard let localRecognizer = recognizer else { - result(FlutterError( code: SpeechToTextErrors.noRecognizerError.rawValue, - message:"Failed to create speech recognizer", - details: nil )) - return - } - if ( onDevice ) { - if #available(iOS 13.0, *), !localRecognizer.supportsOnDeviceRecognition { - result(FlutterError( code: SpeechToTextErrors.onDeviceError.rawValue, - message:"on device recognition is not supported on this device", - details: nil )) - } - } - rememberedAudioCategory = self.audioSession.category - try self.audioSession.setCategory(AVAudioSession.Category.playAndRecord, options: .defaultToSpeaker) - // try self.audioSession.setMode(AVAudioSession.Mode.measurement) - try self.audioSession.setMode(AVAudioSession.Mode.default) - try self.audioSession.setActive(true, options: .notifyOthersOnDeactivation) - if let sound = listeningSound { - self.onPlayEnd = {()->Void in - if ( !self.failedListen ) { - self.listening = true - self.invokeFlutter( SwiftSpeechToTextCallbackMethods.notifyStatus, arguments: SpeechToTextStatus.listening.rawValue ) - - } - } - sound.play() - } - self.audioEngine.reset(); - let inputNode = self.audioEngine.inputNode - if(inputNode.inputFormat(forBus: 0).channelCount == 0){ - throw SpeechToTextError.runtimeError("Not enough available inputs.") - } - self.currentRequest = SFSpeechAudioBufferRecognitionRequest() - guard let currentRequest = self.currentRequest else { - sendBoolResult( false, result ); - return - } - currentRequest.shouldReportPartialResults = true - if #available(iOS 13.0, *), onDevice { - currentRequest.requiresOnDeviceRecognition = true - } - switch listenMode { - case ListenMode.dictation: - currentRequest.taskHint = SFSpeechRecognitionTaskHint.dictation - break - case ListenMode.search: - currentRequest.taskHint = SFSpeechRecognitionTaskHint.search - break - case ListenMode.confirmation: - currentRequest.taskHint = SFSpeechRecognitionTaskHint.confirmation - break - default: - break - } - self.currentTask = self.recognizer?.recognitionTask(with: currentRequest, delegate: self ) - let recordingFormat = inputNode.outputFormat(forBus: self.busForNodeTap) - try trap { - inputNode.installTap(onBus: self.busForNodeTap, bufferSize: self.speechBufferSize, format: recordingFormat) { (buffer: AVAudioPCMBuffer, when: AVAudioTime) in - currentRequest.append(buffer) - self.updateSoundLevel( buffer: buffer ) - } - } - // if ( inErrorTest ){ - // throw SpeechToTextError.runtimeError("for testing only") - // } - self.audioEngine.prepare() - try self.audioEngine.start() - if nil == listeningSound { - listening = true - self.invokeFlutter( SwiftSpeechToTextCallbackMethods.notifyStatus, arguments: SpeechToTextStatus.listening.rawValue ) - } - sendBoolResult( true, result ); - } - catch { - failedListen = true - os_log("Error starting listen: %{PUBLIC}@", log: pluginLog, type: .error, error.localizedDescription) - stopCurrentListen() - sendBoolResult( false, result ); - invokeFlutter( SwiftSpeechToTextCallbackMethods.notifyStatus, arguments: SpeechToTextStatus.notListening.rawValue ) - let speechError = SpeechRecognitionError(errorMsg: "error_listen_failed", permanent: true ) - do { - let errorResult = try jsonEncoder.encode(speechError) - invokeFlutter( SwiftSpeechToTextCallbackMethods.notifyError, arguments: String( data:errorResult, encoding: .utf8) ) - } catch { - os_log("Could not encode JSON", log: pluginLog, type: .error) - } - } - } - - private func updateSoundLevel( buffer: AVAudioPCMBuffer) { - guard - let channelData = buffer.floatChannelData - else { - return - } - - let channelDataValue = channelData.pointee - let channelDataValueArray = stride(from: 0, - to: Int(buffer.frameLength), - by: buffer.stride).map{ channelDataValue[$0] } - let frameLength = Float(buffer.frameLength) - let rms = sqrt(channelDataValueArray.map{ $0 * $0 }.reduce(0, +) / frameLength ) - let avgPower = 20 * log10(rms) - self.invokeFlutter( SwiftSpeechToTextCallbackMethods.soundLevelChange, arguments: avgPower ) - } - - /// Build a list of localId:name with the current locale first - private func locales( _ result: @escaping FlutterResult ) { - var localeNames = [String](); - let locales = SFSpeechRecognizer.supportedLocales(); - let currentLocale = Locale.current - if let idName = buildIdNameForLocale(forIdentifier: currentLocale.identifier ) { - localeNames.append(idName) - } - for locale in locales { - if ( locale.identifier == currentLocale.identifier) { - continue - } - if let idName = buildIdNameForLocale(forIdentifier: locale.identifier ) { - localeNames.append(idName) - } - } - DispatchQueue.main.async { - result(localeNames) - } - } - - private func buildIdNameForLocale( forIdentifier: String ) -> String? { - var idName: String? - if let name = Locale.current.localizedString(forIdentifier: forIdentifier ) { - let sanitizedName = name.replacingOccurrences(of: ":", with: " ") - idName = "\(forIdentifier):\(sanitizedName)" - } - return idName - } - - private func handleResult( _ transcriptions: [SFTranscription], isFinal: Bool ) { - if ( !isFinal && !returnPartialResults ) { - return - } - var speechWords: [SpeechRecognitionWords] = [] - for transcription in transcriptions { - let words: SpeechRecognitionWords = SpeechRecognitionWords(recognizedWords: transcription.formattedString, confidence: confidenceIn( transcription)) - speechWords.append( words ) - } - let speechInfo = SpeechRecognitionResult(alternates: speechWords, finalResult: isFinal ) - do { - let speechMsg = try jsonEncoder.encode(speechInfo) - if let speechStr = String( data:speechMsg, encoding: .utf8) { - os_log("Encoded JSON result: %{PUBLIC}@", log: pluginLog, type: .debug, speechStr ) - invokeFlutter( SwiftSpeechToTextCallbackMethods.textRecognition, arguments: speechStr ) - } - } catch { - os_log("Could not encode JSON", log: pluginLog, type: .error) - } - } - - private func confidenceIn( _ transcription: SFTranscription ) -> Decimal { - guard ( transcription.segments.count > 0 ) else { - return 0; - } - var totalConfidence: Float = 0.0; - for segment in transcription.segments { - totalConfidence += segment.confidence - } - let avgConfidence: Float = totalConfidence / Float(transcription.segments.count ) - let confidence: Float = (avgConfidence * 1000).rounded() / 1000 - return Decimal( string: String( describing: confidence ) )! - } - - private func invokeFlutter( _ method: SwiftSpeechToTextCallbackMethods, arguments: Any? ) { - DispatchQueue.main.async { - self.channel.invokeMethod( method.rawValue, arguments: arguments ) - } - } - -} - -@available(iOS 10.0, *) -extension SwiftSpeechToTextPlugin : SFSpeechRecognizerDelegate { - public func speechRecognizer(_ speechRecognizer: SFSpeechRecognizer, availabilityDidChange available: Bool) { - let availability = available ? SpeechToTextStatus.available.rawValue : SpeechToTextStatus.unavailable.rawValue - os_log("Availability changed: %{PUBLIC}@", log: pluginLog, type: .debug, availability) - invokeFlutter( SwiftSpeechToTextCallbackMethods.notifyStatus, arguments: availability ) - } -} - -@available(iOS 10.0, *) -extension SwiftSpeechToTextPlugin : SFSpeechRecognitionTaskDelegate { - public func speechRecognitionDidDetectSpeech(_ task: SFSpeechRecognitionTask) { - // Do nothing for now - } - - public func speechRecognitionTaskFinishedReadingAudio(_ task: SFSpeechRecognitionTask) { - reportError(source: "FinishedReadingAudio", error: task.error) - invokeFlutter( SwiftSpeechToTextCallbackMethods.notifyStatus, arguments: SpeechToTextStatus.notListening.rawValue ) - } - - public func speechRecognitionTaskWasCancelled(_ task: SFSpeechRecognitionTask) { - reportError(source: "TaskWasCancelled", error: task.error) - invokeFlutter( SwiftSpeechToTextCallbackMethods.notifyStatus, arguments: SpeechToTextStatus.notListening.rawValue ) - } - - public func speechRecognitionTask(_ task: SFSpeechRecognitionTask, didFinishSuccessfully successfully: Bool) { - reportError(source: "FinishSuccessfully", error: task.error) - stopCurrentListen( ) - } - - public func speechRecognitionTask(_ task: SFSpeechRecognitionTask, didHypothesizeTranscription transcription: SFTranscription) { - reportError(source: "HypothesizeTranscription", error: task.error) - handleResult( [transcription], isFinal: false ) - } - - public func speechRecognitionTask(_ task: SFSpeechRecognitionTask, didFinishRecognition recognitionResult: SFSpeechRecognitionResult) { - reportError(source: "FinishRecognition", error: task.error) - let isFinal = recognitionResult.isFinal - handleResult( recognitionResult.transcriptions, isFinal: isFinal ) - } - - private func reportError( source: String, error: Error?) { - if ( nil != error) { - os_log("%{PUBLIC}@ with error: %{PUBLIC}@", log: pluginLog, type: .debug, source, error.debugDescription) - } - } -} - -@available(iOS 10.0, *) -extension SwiftSpeechToTextPlugin : AVAudioPlayerDelegate { - - public func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, - successfully flag: Bool) { - if let playEnd = self.onPlayEnd { - playEnd() - } - } -} diff --git a/speech_to_text_/ios/speech_to_text.podspec b/speech_to_text_/ios/speech_to_text.podspec deleted file mode 100644 index 1db79aa0..00000000 --- a/speech_to_text_/ios/speech_to_text.podspec +++ /dev/null @@ -1,22 +0,0 @@ -# -# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html -# -Pod::Spec.new do |s| - s.name = 'speech_to_text' - s.version = '0.0.1' - s.summary = 'A new flutter plugin project.' - s.description = <<-DESC -A new flutter plugin project. - DESC - s.homepage = 'http://example.com' - s.license = { :file => '../LICENSE' } - s.author = { 'Your Company' => 'email@example.com' } - s.source = { :path => '.' } - s.source_files = 'Classes/**/*' - s.public_header_files = 'Classes/**/*.h' - s.dependency 'Flutter' - s.dependency 'Try' - - s.ios.deployment_target = '8.0' -end - diff --git a/speech_to_text_/lib/speech_recognition_error.dart b/speech_to_text_/lib/speech_recognition_error.dart deleted file mode 100644 index 2ab6cd4d..00000000 --- a/speech_to_text_/lib/speech_recognition_error.dart +++ /dev/null @@ -1,44 +0,0 @@ -import 'package:json_annotation/json_annotation.dart'; - -part 'speech_recognition_error.g.dart'; - -/// A single error returned from the underlying speech services. -/// -/// Errors are either transient or permanent. Permanent errors -/// block speech recognition from continuing and must be -/// addressed before recogntion will work. Transient errors -/// cause individual recognition sessions to fail but subsequent -/// attempts may well succeed. -@JsonSerializable() -class SpeechRecognitionError { - /// Use this to differentiate the various error conditions. - /// - /// Not meant for display to the user. - final String errorMsg; - - /// True means that recognition cannot continue until - /// the error is resolved. - final bool permanent; - - SpeechRecognitionError(this.errorMsg, this.permanent); - - factory SpeechRecognitionError.fromJson(Map json) => - _$SpeechRecognitionErrorFromJson(json); - Map toJson() => _$SpeechRecognitionErrorToJson(this); - - @override - String toString() { - return "SpeechRecognitionError msg: $errorMsg, permanent: $permanent"; - } - - @override - bool operator ==(Object other) { - return identical(this, other) || - other is SpeechRecognitionError && - errorMsg == other.errorMsg && - permanent == other.permanent; - } - - @override - int get hashCode => errorMsg.hashCode; -} diff --git a/speech_to_text_/lib/speech_recognition_error.g.dart b/speech_to_text_/lib/speech_recognition_error.g.dart deleted file mode 100644 index 65299f6d..00000000 --- a/speech_to_text_/lib/speech_recognition_error.g.dart +++ /dev/null @@ -1,22 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'speech_recognition_error.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -SpeechRecognitionError _$SpeechRecognitionErrorFromJson( - Map json) { - return SpeechRecognitionError( - json['errorMsg'] as String, - json['permanent'] as bool, - ); -} - -Map _$SpeechRecognitionErrorToJson( - SpeechRecognitionError instance) => - { - 'errorMsg': instance.errorMsg, - 'permanent': instance.permanent, - }; diff --git a/speech_to_text_/lib/speech_recognition_event.dart b/speech_to_text_/lib/speech_recognition_event.dart deleted file mode 100644 index 71729365..00000000 --- a/speech_to_text_/lib/speech_recognition_event.dart +++ /dev/null @@ -1,30 +0,0 @@ -import 'package:speech_to_text/speech_recognition_error.dart'; -import 'package:speech_to_text/speech_recognition_result.dart'; - -enum SpeechRecognitionEventType { - finalRecognitionEvent, - partialRecognitionEvent, - errorEvent, - statusChangeEvent, - soundLevelChangeEvent, -} - -/// A single event in a stream of speech recognition events. -/// -/// Use [eventType] to determine what type of event it is and depending on that -/// use the other properties to get information about it. -class SpeechRecognitionEvent { - final SpeechRecognitionEventType eventType; - final SpeechRecognitionError _error; - final SpeechRecognitionResult _result; - final bool _listening; - final double _level; - - SpeechRecognitionEvent( - this.eventType, this._result, this._error, this._listening, this._level); - - bool get isListening => _listening; - double get level => _level; - SpeechRecognitionResult get recognitionResult => _result; - SpeechRecognitionError get error => _error; -} diff --git a/speech_to_text_/lib/speech_recognition_result.dart b/speech_to_text_/lib/speech_recognition_result.dart deleted file mode 100644 index 38509f65..00000000 --- a/speech_to_text_/lib/speech_recognition_result.dart +++ /dev/null @@ -1,140 +0,0 @@ -import 'dart:collection'; - -import 'package:json_annotation/json_annotation.dart'; - -part 'speech_recognition_result.g.dart'; - -/// A sequence of recognized words from the speech recognition -/// service. -/// -/// Depending on the platform behaviour the words may come in all -/// at once at the end or as partial results as each word is -/// recognized. Use the [finalResult] flag to determine if the -/// result is considered final by the platform. -@JsonSerializable(explicitToJson: true) -class SpeechRecognitionResult { - List _alternates; - - /// Returns a list of possible transcriptions of the speech. - /// - /// The first value is always the same as the [recognizedWords] - /// value. Use the confidence for each alternate transcription - /// to determine how likely it is. Note that not all platforms - /// do a good job with confidence, there are convenience methods - /// on [SpeechRecogntionWords] to work with possibly missing - /// confidence values. - List get alternates => - UnmodifiableListView(_alternates); - - /// The sequence of words that is the best transcription of - /// what was said. - /// - /// This is the same as the first value of [alternates]. - String get recognizedWords => - _alternates.isNotEmpty ? _alternates.first.recognizedWords : ""; - - /// False means the words are an interim result, true means - /// they are the final recognition. - final bool finalResult; - - /// The confidence that the [recognizedWords] are correct. - /// - /// Confidence is expressed as a value between 0 and 1. -1 - /// means that the confidence value was not available. - double get confidence => - _alternates.isNotEmpty ? _alternates.first.confidence : 0; - - /// true if there is confidence in this recognition, false otherwise. - /// - /// There are two separate ways for there to be confidence, the first - /// is if the confidence is missing, which is indicated by a value of - /// -1. The second is if the confidence is greater than or equal - /// [threshold]. If [threshold] is not provided it defaults to 0.8. - bool isConfident( - {double threshold = SpeechRecognitionWords.confidenceThreshold}) => - _alternates.isNotEmpty - ? _alternates.first.isConfident(threshold: threshold) - : false; - - /// true if [confidence] is not the [missingConfidence] value, false - /// otherwise. - bool get hasConfidenceRating => - _alternates.isNotEmpty ? _alternates.first.hasConfidenceRating : false; - - SpeechRecognitionResult(this._alternates, this.finalResult); - - @override - String toString() { - return "SpeechRecognitionResult words: $_alternates, final: $finalResult"; - } - - @override - bool operator ==(Object other) { - return identical(this, other) || - other is SpeechRecognitionResult && - recognizedWords == other.recognizedWords && - finalResult == other.finalResult; - } - - @override - int get hashCode => recognizedWords.hashCode; - - factory SpeechRecognitionResult.fromJson(Map json) => - _$SpeechRecognitionResultFromJson(json); - Map toJson() => _$SpeechRecognitionResultToJson(this); -} - -/// A set of words recognized in a [SpeechRecognitionResult]. -/// -/// Each result will have one or more [SpeechRecognitionWords] -/// with a varying degree of confidence about each set of words. -@JsonSerializable() -class SpeechRecognitionWords { - /// The sequence of words recognized - final String recognizedWords; - - /// The confidence that the [recognizedWords] are correct. - /// - /// Confidence is expressed as a value between 0 and 1. 0 - /// means that the confidence value was not available. Use - /// [isConfident] which will ignore 0 values automatically. - final double confidence; - - static const double confidenceThreshold = 0.8; - static const double missingConfidence = -1; - - const SpeechRecognitionWords(this.recognizedWords, this.confidence); - - /// true if there is confidence in this recognition, false otherwise. - /// - /// There are two separate ways for there to be confidence, the first - /// is if the confidence is missing, which is indicated by a value of - /// -1. The second is if the confidence is greater than or equal - /// [threshold]. If [threshold] is not provided it defaults to 0.8. - bool isConfident({double threshold = confidenceThreshold}) => - confidence == missingConfidence || confidence >= threshold; - - /// true if [confidence] is not the [missingConfidence] value, false - /// otherwise. - bool get hasConfidenceRating => confidence != missingConfidence; - - @override - String toString() { - return "SpeechRecognitionWords words: $recognizedWords, confidence: $confidence"; - } - - @override - bool operator ==(Object other) { - return identical(this, other) || - other is SpeechRecognitionWords && - recognizedWords == other.recognizedWords && - confidence == other.confidence; - } - - @override - int get hashCode => recognizedWords.hashCode; - - factory SpeechRecognitionWords.fromJson(Map json) => - _$SpeechRecognitionWordsFromJson(json); - Map toJson() => _$SpeechRecognitionWordsToJson(this); -} diff --git a/speech_to_text_/lib/speech_recognition_result.g.dart b/speech_to_text_/lib/speech_recognition_result.g.dart deleted file mode 100644 index 023e5485..00000000 --- a/speech_to_text_/lib/speech_recognition_result.g.dart +++ /dev/null @@ -1,41 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'speech_recognition_result.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -SpeechRecognitionResult _$SpeechRecognitionResultFromJson( - Map json) { - return SpeechRecognitionResult( - (json['alternates'] as List) - ?.map((e) => e == null - ? null - : SpeechRecognitionWords.fromJson(e as Map)) - ?.toList(), - json['finalResult'] as bool, - ); -} - -Map _$SpeechRecognitionResultToJson( - SpeechRecognitionResult instance) => - { - 'alternates': instance.alternates?.map((e) => e?.toJson())?.toList(), - 'finalResult': instance.finalResult, - }; - -SpeechRecognitionWords _$SpeechRecognitionWordsFromJson( - Map json) { - return SpeechRecognitionWords( - json['recognizedWords'] as String, - (json['confidence'] as num)?.toDouble(), - ); -} - -Map _$SpeechRecognitionWordsToJson( - SpeechRecognitionWords instance) => - { - 'recognizedWords': instance.recognizedWords, - 'confidence': instance.confidence, - }; diff --git a/speech_to_text_/lib/speech_to_text.dart b/speech_to_text_/lib/speech_to_text.dart deleted file mode 100644 index 343706e6..00000000 --- a/speech_to_text_/lib/speech_to_text.dart +++ /dev/null @@ -1,511 +0,0 @@ -import 'dart:async'; -import 'dart:convert'; -import 'dart:math'; - -import 'package:clock/clock.dart'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/services.dart'; -import 'package:speech_to_text/speech_recognition_error.dart'; -import 'package:speech_to_text/speech_recognition_result.dart'; - -enum ListenMode { - deviceDefault, - dictation, - search, - confirmation, -} - -/// Notified as words are recognized with the current set of recognized words. -/// -/// See the [onResult] argument on the [listen] method for use. -typedef SpeechResultListener = void Function(SpeechRecognitionResult result); - -/// Notified if errors occur during recognition or intialization. -/// -/// Possible errors per the Android docs are described here: -/// https://developer.android.com/reference/android/speech/SpeechRecognizer -/// "error_audio_error" -/// "error_client" -/// "error_permission" -/// "error_network" -/// "error_network_timeout" -/// "error_no_match" -/// "error_busy" -/// "error_server" -/// "error_speech_timeout" -/// See the [onError] argument on the [initialize] method for use. -typedef SpeechErrorListener = void Function( - SpeechRecognitionError errorNotification); - -/// Notified when recognition status changes. -/// -/// See the [onStatus] argument on the [initialize] method for use. -typedef SpeechStatusListener = void Function(String status); - -/// Notified when the sound level changes during a listen method. -/// -/// [level] is a measure of the decibels of the current sound on -/// the recognition input. See the [onSoundLevelChange] argument on -/// the [listen] method for use. -typedef SpeechSoundLevelChange = Function(double level); - -/// An interface to device specific speech recognition services. -/// -/// The general flow of a speech recognition session is as follows: -/// ```Dart -/// SpeechToText speech = SpeechToText(); -/// bool isReady = await speech.initialize(); -/// if ( isReady ) { -/// await speech.listen( resultListener: resultListener ); -/// } -/// ... -/// // At some point later -/// speech.stop(); -/// ``` -class SpeechToText { - static const String listenMethod = 'listen'; - static const String textRecognitionMethod = 'textRecognition'; - static const String notifyErrorMethod = 'notifyError'; - static const String notifyStatusMethod = 'notifyStatus'; - static const String soundLevelChangeMethod = "soundLevelChange"; - static const String notListeningStatus = "notListening"; - static const String listeningStatus = "listening"; - - static const MethodChannel speechChannel = - const MethodChannel('plugin.csdcorp.com/speech_to_text'); - static final SpeechToText _instance = - SpeechToText.withMethodChannel(speechChannel); - bool _initWorked = false; - bool _recognized = false; - bool _listening = false; - bool _cancelOnError = false; - bool _partialResults = false; - int _listenStartedAt = 0; - int _lastSpeechEventAt = 0; - Duration _pauseFor; - Duration _listenFor; - - /// True if not listening or the user called cancel / stop, false - /// if cancel/stop were invoked by timeout or error condition. - bool _userEnded = false; - String _lastRecognized = ""; - String _lastStatus = ""; - double _lastSoundLevel = 0; - Timer _listenTimer; - LocaleName _systemLocale; - SpeechRecognitionError _lastError; - SpeechResultListener _resultListener; - SpeechErrorListener errorListener; - SpeechStatusListener statusListener; - SpeechSoundLevelChange _soundLevelChange; - - final MethodChannel channel; - factory SpeechToText() => _instance; - - @visibleForTesting - SpeechToText.withMethodChannel(this.channel); - - /// True if words have been recognized during the current [listen] call. - /// - /// Goes false as soon as [cancel] is called. - bool get hasRecognized => _recognized; - - /// The last set of recognized words received. - /// - /// This is maintained across [cancel] calls but cleared on the next - /// [listen]. - String get lastRecognizedWords => _lastRecognized; - - /// The last status update received, see [initialize] to register - /// an optional listener to be notified when this changes. - String get lastStatus => _lastStatus; - - /// The last sound level received during a listen event. - /// - /// The sound level is a measure of how loud the current - /// input is during listening. Use the [onSoundLevelChange] - /// argument in the [listen] method to get notified of - /// changes. - double get lastSoundLevel => _lastSoundLevel; - - /// True if [initialize] succeeded - bool get isAvailable => _initWorked; - - /// True if [listen] succeeded and [stop] or [cancel] has not been called. - /// - /// Also goes false when listening times out if listenFor was set. - bool get isListening => _listening; - bool get isNotListening => !isListening; - - /// The last error received or null if none, see [initialize] to - /// register an optional listener to be notified of errors. - SpeechRecognitionError get lastError => _lastError; - - /// True if an error has been received, see [lastError] for details - bool get hasError => null != lastError; - - /// Returns true if the user has already granted permission to access the - /// microphone, does not prompt the user. - /// - /// This method can be called before [initialize] to check if permission - /// has already been granted. If this returns false then the [initialize] - /// call will prompt the user for permission if it is allowed to do so. - /// Note that applications cannot ask for permission again if the user has - /// denied them permission in the past. - Future get hasPermission async { - bool hasPermission = await channel.invokeMethod('has_permission'); - return hasPermission; - } - - /// Initialize speech recognition services, returns true if - /// successful, false if failed. - /// - /// This method must be called before any other speech functions. - /// If this method returns false no further [SpeechToText] methods - /// should be used. Should only be called once if successful but does protect - /// itself if called repeatedly. False usually means that the user has denied - /// permission to use speech. The usual option in that case is to give them - /// instructions on how to open system settings and grant permission. - /// - /// [onError] is an optional listener for errors like - /// timeout, or failure of the device speech recognition. - /// [onStatus] is an optional listener for status changes from - /// listening to not listening. - /// [debugLogging] controls whether there is detailed logging from the underlying - /// plugins. It is off by default, usually only useful for troubleshooting issues - /// with a paritcular OS version or device, fairly verbose - Future initialize( - {SpeechErrorListener onError, - SpeechStatusListener onStatus, - debugLogging = false}) async { - if (_initWorked) { - return Future.value(_initWorked); - } - errorListener = onError; - statusListener = onStatus; - channel.setMethodCallHandler(_handleCallbacks); - _initWorked = await channel - .invokeMethod('initialize', {"debugLogging": debugLogging}); - return _initWorked; - } - - /// Stops the current listen for speech if active, does nothing if not. - /// - /// Stopping a listen session will cause a final result to be sent. Each - /// listen session should be ended with either [stop] or [cancel], for - /// example in the dispose method of a Widget. [cancel] is automatically - /// invoked by a permanent error if [cancelOnError] is set to true in the - /// [listen] call. - /// - /// *Note:* Cannot be used until a successful [initialize] call. Should - /// only be used after a successful [listen] call. - Future stop() async { - _userEnded = true; - return _stop(); - } - - Future _stop() async { - if (!_initWorked) { - return; - } - _shutdownListener(); - await channel.invokeMethod('stop'); - } - - /// Cancels the current listen for speech if active, does nothing if not. - /// - /// Canceling means that there will be no final result returned from the - /// recognizer. Each listen session should be ended with either [stop] or - /// [cancel], for example in the dispose method of a Widget. [cancel] is - /// automatically invoked by a permanent error if [cancelOnError] is set - /// to true in the [listen] call. - /// - /// *Note* Cannot be used until a successful [initialize] call. Should only - /// be used after a successful [listen] call. - Future cancel() async { - _userEnded = true; - return _cancel(); - } - - Future _cancel() async { - if (!_initWorked) { - return; - } - _shutdownListener(); - await channel.invokeMethod('cancel'); - } - - /// Starts a listening session for speech and converts it to text, - /// invoking the provided [onResult] method as words are recognized. - /// - /// Cannot be used until a successful [initialize] call. There is a - /// time limit on listening imposed by both Android and iOS. The time - /// depends on the device, network, etc. Android is usually quite short, - /// especially if there is no active speech event detected, on the order - /// of ten seconds or so. - /// - /// When listening is done always invoke either [cancel] or [stop] to - /// end the session, even if it times out. [cancelOnError] provides an - /// automatic way to ensure this happens. - /// - /// [onResult] is an optional listener that is notified when words - /// are recognized. - /// - /// [listenFor] sets the maximum duration that it will listen for, after - /// that it automatically stops the listen for you. - /// - /// [pauseFor] sets the maximum duration of a pause in speech with no words - /// detected, after that it automatically stops the listen for you. - /// - /// [localeId] is an optional locale that can be used to listen in a language - /// other than the current system default. See [locales] to find the list of - /// supported languages for listening. - /// - /// [onSoundLevelChange] is an optional listener that is notified when the - /// sound level of the input changes. Use this to update the UI in response to - /// more or less input. The values currently differ between Ancroid and iOS, - /// haven't yet been able to determine from the Android documentation what the - /// value means. On iOS the value returned is in decibels. - /// - /// [cancelOnError] if true then listening is automatically canceled on a - /// permanent error. This defaults to false. When false cancel should be - /// called from the error handler. - /// - /// [partialResults] if true the listen reports results as they are recognized, - /// when false only final results are reported. Defaults to true. - /// - /// [onDevice] if true the listen attempts to recognize locally with speech never - /// leaving the device. If it cannot do this the listen attempt will fail. This is - /// usually only needed for sensitive content where privacy or security is a concern. - Future listen( - {SpeechResultListener onResult, - Duration listenFor, - Duration pauseFor, - String localeId, - SpeechSoundLevelChange onSoundLevelChange, - cancelOnError = false, - partialResults = true, - onDevice = false, - ListenMode listenMode = ListenMode.confirmation}) async { - if (!_initWorked) { - throw SpeechToTextNotInitializedException(); - } - _userEnded = false; - _cancelOnError = cancelOnError; - _recognized = false; - _resultListener = onResult; - _soundLevelChange = onSoundLevelChange; - _partialResults = partialResults; - Map listenParams = { - "partialResults": partialResults || null != pauseFor, - "onDevice": onDevice, - "listenMode": listenMode.index, - }; - if (null != localeId) { - listenParams["localeId"] = localeId; - } - try { - bool started = await channel.invokeMethod(listenMethod, listenParams); - if (started) { - _listenStartedAt = clock.now().millisecondsSinceEpoch; - _setupListenAndPause(pauseFor, listenFor); - } - } on PlatformException catch (e) { - throw ListenFailedException(e.details); - } - } - - void _setupListenAndPause(Duration pauseFor, Duration listenFor) { - _pauseFor = null; - _listenFor = null; - if (null == pauseFor && null == listenFor) { - return; - } - var minDuration; - if (null == pauseFor) { - _listenFor = Duration(milliseconds: listenFor.inMilliseconds); - minDuration = listenFor; - } else if (null == listenFor) { - _pauseFor = Duration(milliseconds: pauseFor.inMilliseconds); - minDuration = pauseFor; - } else { - _listenFor = Duration(milliseconds: listenFor.inMilliseconds); - _pauseFor = Duration(milliseconds: pauseFor.inMilliseconds); - var minMillis = min(listenFor.inMilliseconds - _elapsedListenMillis, - pauseFor.inMilliseconds); - minDuration = Duration(milliseconds: minMillis); - } - _listenTimer = Timer(minDuration, _stopOnPauseOrListen); - } - - int get _elapsedListenMillis => - clock.now().millisecondsSinceEpoch - _listenStartedAt; - int get _elapsedSinceSpeechEvent => - clock.now().millisecondsSinceEpoch - _lastSpeechEventAt; - - void _stopOnPauseOrListen() { - if (null != _listenFor && - _elapsedListenMillis >= _listenFor.inMilliseconds) { - _stop(); - } else if (null != _pauseFor && - _elapsedSinceSpeechEvent >= _pauseFor.inMilliseconds) { - _stop(); - } else { - _setupListenAndPause(_pauseFor, _listenFor); - } - } - - /// returns the list of speech locales available on the device. - /// - /// This method is useful to find the identifier to use - /// for the [listen] method, it is the [localeId] member of the - /// [LocaleName]. - /// - /// Each [LocaleName] in the returned list has the - /// identifier for the locale as well as a name for - /// display. The name is localized for the system locale on - /// the device. - Future> locales() async { - if (!_initWorked) { - throw SpeechToTextNotInitializedException(); - } - final List locales = await channel.invokeMethod('locales'); - List filteredLocales = locales - .map((locale) { - var components = locale.split(":"); - if (components.length != 2) { - return null; - } - return LocaleName(components[0], components[1]); - }) - .where((item) => item != null) - .toList(); - if (filteredLocales.isNotEmpty) { - _systemLocale = filteredLocales.first; - } else { - _systemLocale = null; - } - filteredLocales.sort((ln1, ln2) => ln1.name.compareTo(ln2.name)); - return filteredLocales; - } - - /// returns the locale that will be used if no localeId is passed - /// to the [listen] method. - Future systemLocale() async { - if (null == _systemLocale) { - await locales(); - } - return Future.value(_systemLocale); - } - - Future _handleCallbacks(MethodCall call) async { - // print("SpeechToText call: ${call.method} ${call.arguments}"); - switch (call.method) { - case textRecognitionMethod: - if (call.arguments is String) { - _onTextRecognition(call.arguments); - } - break; - case notifyErrorMethod: - if (call.arguments is String) { - await _onNotifyError(call.arguments); - } - break; - case notifyStatusMethod: - if (call.arguments is String) { - _onNotifyStatus(call.arguments); - } - break; - case soundLevelChangeMethod: - if (call.arguments is double) { - _onSoundLevelChange(call.arguments); - } - break; - default: - } - } - - void _onTextRecognition(String resultJson) { - _lastSpeechEventAt = clock.now().millisecondsSinceEpoch; - Map resultMap = jsonDecode(resultJson); - SpeechRecognitionResult speechResult = - SpeechRecognitionResult.fromJson(resultMap); - if (!_partialResults && !speechResult.finalResult) { - return; - } - _recognized = true; - // print("Recognized text $resultJson"); - - _lastRecognized = speechResult.recognizedWords; - if (null != _resultListener) { - _resultListener(speechResult); - } - } - - Future _onNotifyError(String errorJson) async { - if (isNotListening && _userEnded) { - return; - } - Map errorMap = jsonDecode(errorJson); - SpeechRecognitionError speechError = - SpeechRecognitionError.fromJson(errorMap); - _lastError = speechError; - if (null != errorListener) { - errorListener(speechError); - } - if (_cancelOnError && speechError.permanent) { - await _cancel(); - } - } - - void _onNotifyStatus(String status) { - _lastStatus = status; - _listening = status == listeningStatus; - // print(status); - if (null != statusListener) { - statusListener(status); - } - } - - void _onSoundLevelChange(double level) { - if (isNotListening) { - return; - } - _lastSoundLevel = level; - if (null != _soundLevelChange) { - _soundLevelChange(level); - } - } - - _shutdownListener() { - _listening = false; - _recognized = false; - _listenTimer?.cancel(); - _listenTimer = null; - } - - @visibleForTesting - Future processMethodCall(MethodCall call) async { - return await _handleCallbacks(call); - } -} - -/// A single locale with a [name], localized to the current system locale, -/// and a [localeId] which can be used in the [listen] method to choose a -/// locale for speech recognition. -class LocaleName { - final String localeId; - final String name; - LocaleName(this.localeId, this.name); -} - -/// Thrown when a method is called that requires successful -/// initialization first. -class SpeechToTextNotInitializedException implements Exception {} - -/// Thrown when listen fails to properly start a speech listening session -/// on the device -class ListenFailedException implements Exception { - final String details; - ListenFailedException(this.details); -} diff --git a/speech_to_text_/lib/speech_to_text_provider.dart b/speech_to_text_/lib/speech_to_text_provider.dart deleted file mode 100644 index 91adf3b4..00000000 --- a/speech_to_text_/lib/speech_to_text_provider.dart +++ /dev/null @@ -1,201 +0,0 @@ -import 'dart:async'; - -import 'package:flutter/material.dart'; -import 'package:speech_to_text/speech_recognition_error.dart'; -import 'package:speech_to_text/speech_recognition_event.dart'; -import 'package:speech_to_text/speech_recognition_result.dart'; -import 'package:speech_to_text/speech_to_text.dart'; - -/// Simplifies interaction with [SpeechToText] by handling all the callbacks and notifying -/// listeners as events happen. -/// -/// Here's an example of using the [SpeechToTextProvider] -/// ``` -/// var speechProvider = SpeechToTextProvider( SpeechToText()); -/// var available = await speechProvider.initialize(); -/// StreamSubscription _subscription; -/// _subscription = speechProvider.recognitionController.stream.listen((recognitionEvent) { -/// if (recognitionEvent.eventType == SpeechRecognitionEventType.finalRecognitionEvent ) { -/// print("I heard: ${recognitionEvent.recognitionResult.recognizedWords}"); -/// } -/// }); -/// speechProvider.addListener(() { -/// var words = speechProvider.lastWords; -/// }); -class SpeechToTextProvider extends ChangeNotifier { - final StreamController _recognitionController = - StreamController.broadcast(); - final SpeechToText _speechToText; - SpeechRecognitionResult _lastResult; - double _lastLevel = 0; - List _locales = []; - LocaleName _systemLocale; - - /// Only construct one instance in an application. - /// - /// Do not call `initialize` on the [SpeechToText] that is passed as a parameter, instead - /// call the [initialize] method on this class. - SpeechToTextProvider(this._speechToText); - - Stream get stream => _recognitionController.stream; - - /// Returns the last result received, may be null. - SpeechRecognitionResult get lastResult => _lastResult; - - /// Returns the last error received, may be null. - SpeechRecognitionError get lastError => _speechToText.lastError; - - /// Returns the last sound level received. - /// - /// Note this is only available when the `soundLevel` is set to true on - /// a call to [listen], will be 0 at all other times. - double get lastLevel => _lastLevel; - - /// Initializes the provider and the contained [SpeechToText] instance. - /// - /// Returns true if [SpeechToText] was initialized successful and can now - /// be used, false otherwse. - Future initialize() async { - if (isAvailable) { - return isAvailable; - } - bool availableBefore = _speechToText.isAvailable; - bool available = - await _speechToText.initialize(onStatus: _onStatus, onError: _onError); - if (available) { - _locales = []; - _locales.addAll(await _speechToText.locales()); - _systemLocale = await _speechToText.systemLocale(); - } - if (availableBefore != available) { - notifyListeners(); - } - return available; - } - - /// Returns true if the provider has been initialized and can be used to recognize speech. - bool get isAvailable => _speechToText.isAvailable; - - /// Returns true if the provider cannot be used to recognize speech, either because it has not - /// yet been initialized or because initialization failed. - bool get isNotAvailable => !_speechToText.isAvailable; - - /// Returns true if [SpeechToText] is listening for new speech. - bool get isListening => _speechToText.isListening; - - /// Returns true if [SpeechToText] is not listening for new speech. - bool get isNotListening => _speechToText.isNotListening; - - /// Returns true if [SpeechToText] has a previous error. - bool get hasError => _speechToText.hasError; - - /// Returns true if [lastResult] has a last result. - bool get hasResults => null != _lastResult; - - /// Returns the list of locales that are available on the device for speech recognition. - List get locales => _locales; - - /// Returns the locale that is currently set as active on the device. - LocaleName get systemLocale => _systemLocale; - - /// Start listening for new events, set [partialResults] to true to receive interim - /// recognition results. - /// - /// [soundLevel] set to true to be notified on changes to the input sound level - /// on the microphone. - /// - /// [listenFor] sets the maximum duration that it will listen for, after - /// that it automatically stops the listen for you. - /// - /// [pauseFor] sets the maximum duration of a pause in speech with no words - /// detected, after that it automatically stops the listen for you. - /// - /// Call this only after a successful [initialize] call - void listen( - {bool partialResults = false, - bool soundLevel = false, - Duration listenFor, - Duration pauseFor}) { - _lastLevel = 0; - _lastResult = null; - if (soundLevel) { - _speechToText.listen( - partialResults: partialResults, - listenFor: listenFor, - pauseFor: pauseFor, - cancelOnError: true, - onResult: _onListenResult, - // onSoundLevelChange: _onSoundLevelChange); - ); - } else { - _speechToText.listen( - partialResults: partialResults, - listenFor: listenFor, - pauseFor: pauseFor, - cancelOnError: true, - onResult: _onListenResult); - } - } - - /// Stops a current active listening session. - /// - /// Call this after calling [listen] to stop the recognizer from listening further - /// and return the current result as final. - void stop() { - _speechToText.stop(); - notifyListeners(); - } - - /// Cancel a current active listening session. - /// - /// Call this after calling [listen] to stop the recognizer from listening further - /// and ignore any results recognized so far. - void cancel() { - _speechToText.cancel(); - notifyListeners(); - } - - void _onError(SpeechRecognitionError errorNotification) { - _recognitionController.add(SpeechRecognitionEvent( - SpeechRecognitionEventType.errorEvent, - null, - errorNotification, - isListening, - null)); - notifyListeners(); - } - - void _onStatus(String status) { - _recognitionController.add(SpeechRecognitionEvent( - SpeechRecognitionEventType.statusChangeEvent, - null, - null, - isListening, - null)); - notifyListeners(); - } - - void _onListenResult(SpeechRecognitionResult result) { - _lastResult = result; - _recognitionController.add(SpeechRecognitionEvent( - result.finalResult - ? SpeechRecognitionEventType.finalRecognitionEvent - : SpeechRecognitionEventType.partialRecognitionEvent, - result, - null, - isListening, - null)); - notifyListeners(); - } - - // void _onSoundLevelChange(double level) { - // _lastLevel = level; - // _recognitionController.add(SpeechRecognitionEvent( - // SpeechRecognitionEventType.soundLevelChangeEvent, - // null, - // null, - // null, - // level)); - // notifyListeners(); - // } -} diff --git a/speech_to_text_/pubspec.yaml b/speech_to_text_/pubspec.yaml deleted file mode 100644 index 34b3da29..00000000 --- a/speech_to_text_/pubspec.yaml +++ /dev/null @@ -1,31 +0,0 @@ -name: speech_to_text -description: A Flutter plugin that exposes device specific speech to text recognition capability. - - - -environment: - sdk: ">=2.1.0 <3.0.0" - flutter: ">=1.10.0" - -dependencies: - flutter: - sdk: flutter - json_annotation: ^3.0.0 - clock: ^1.0.1 - -dev_dependencies: - flutter_test: - sdk: flutter - build_runner: ^1.0.0 - json_serializable: ^3.0.0 - fake_async: ^1.0.1 - -flutter: - plugin: - platforms: - android: - package: com.csdcorp.speech_to_text - pluginClass: SpeechToTextPlugin - ios: - pluginClass: SpeechToTextPlugin - diff --git a/speech_to_text_/test/speech_recognition_error_test.dart b/speech_to_text_/test/speech_recognition_error_test.dart deleted file mode 100644 index 202ae4cd..00000000 --- a/speech_to_text_/test/speech_recognition_error_test.dart +++ /dev/null @@ -1,65 +0,0 @@ -import 'dart:convert'; - -import 'package:flutter_test/flutter_test.dart'; -import 'package:speech_to_text/speech_recognition_error.dart'; - -void main() { - const String msg1 = "msg1"; - - setUp(() {}); - - group('properties', () { - test('equals true for same object', () { - SpeechRecognitionError error = SpeechRecognitionError(msg1, false); - expect(error, error); - }); - test('equals true for different object same values', () { - SpeechRecognitionError error1 = SpeechRecognitionError(msg1, false); - SpeechRecognitionError error2 = SpeechRecognitionError(msg1, false); - expect(error1, error2); - }); - test('equals false for different object', () { - SpeechRecognitionError error1 = SpeechRecognitionError(msg1, false); - SpeechRecognitionError error2 = SpeechRecognitionError("msg2", false); - expect(error1, isNot(error2)); - }); - test('hash same for same object', () { - SpeechRecognitionError error = SpeechRecognitionError(msg1, false); - expect(error.hashCode, error.hashCode); - }); - test('hash same for different object same values', () { - SpeechRecognitionError error1 = SpeechRecognitionError(msg1, false); - SpeechRecognitionError error2 = SpeechRecognitionError(msg1, false); - expect(error1.hashCode, error2.hashCode); - }); - test('hash different for different object', () { - SpeechRecognitionError error1 = SpeechRecognitionError(msg1, false); - SpeechRecognitionError error2 = SpeechRecognitionError("msg2", false); - expect(error1.hashCode, isNot(error2.hashCode)); - }); - test('toString as expected', () { - SpeechRecognitionError error1 = SpeechRecognitionError(msg1, false); - expect(error1.toString(), - "SpeechRecognitionError msg: $msg1, permanent: false"); - }); - }); - group('json', () { - test('loads properly', () { - var json = jsonDecode('{"errorMsg":"$msg1","permanent":true}'); - SpeechRecognitionError error = SpeechRecognitionError.fromJson(json); - expect(error.errorMsg, msg1); - expect(error.permanent, isTrue); - json = jsonDecode('{"errorMsg":"$msg1","permanent":false}'); - error = SpeechRecognitionError.fromJson(json); - expect(error.permanent, isFalse); - }); - test('roundtrips properly', () { - var json = jsonDecode('{"errorMsg":"$msg1","permanent":true}'); - SpeechRecognitionError error = SpeechRecognitionError.fromJson(json); - var roundtripJson = error.toJson(); - SpeechRecognitionError roundtripError = - SpeechRecognitionError.fromJson(roundtripJson); - expect(error, roundtripError); - }); - }); -} diff --git a/speech_to_text_/test/speech_recognition_event_test.dart b/speech_to_text_/test/speech_recognition_event_test.dart deleted file mode 100644 index ceaaab8a..00000000 --- a/speech_to_text_/test/speech_recognition_event_test.dart +++ /dev/null @@ -1,42 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:speech_to_text/speech_recognition_event.dart'; - -import 'test_speech_channel_handler.dart'; - -void main() { - group('properties', () { - test('status listening matches', () { - var event = SpeechRecognitionEvent( - SpeechRecognitionEventType.statusChangeEvent, null, null, true, null); - expect(event.eventType, SpeechRecognitionEventType.statusChangeEvent); - expect(event.isListening, isTrue); - }); - test('result matches', () { - var event = SpeechRecognitionEvent( - SpeechRecognitionEventType.finalRecognitionEvent, - TestSpeechChannelHandler.firstRecognizedResult, - null, - null, - null); - expect(event.eventType, SpeechRecognitionEventType.finalRecognitionEvent); - expect(event.recognitionResult, - TestSpeechChannelHandler.firstRecognizedResult); - }); - test('error matches', () { - var event = SpeechRecognitionEvent(SpeechRecognitionEventType.errorEvent, - null, TestSpeechChannelHandler.firstError, null, null); - expect(event.eventType, SpeechRecognitionEventType.errorEvent); - expect(event.error, TestSpeechChannelHandler.firstError); - }); - test('sound level matches', () { - var event = SpeechRecognitionEvent( - SpeechRecognitionEventType.soundLevelChangeEvent, - null, - null, - null, - TestSpeechChannelHandler.level1); - expect(event.eventType, SpeechRecognitionEventType.soundLevelChangeEvent); - expect(event.level, TestSpeechChannelHandler.level1); - }); - }); -} diff --git a/speech_to_text_/test/speech_recognition_result_test.dart b/speech_to_text_/test/speech_recognition_result_test.dart deleted file mode 100644 index 1516779a..00000000 --- a/speech_to_text_/test/speech_recognition_result_test.dart +++ /dev/null @@ -1,134 +0,0 @@ -import 'dart:convert'; - -import 'package:flutter_test/flutter_test.dart'; -import 'package:speech_to_text/speech_recognition_result.dart'; - -void main() { - final String firstRecognizedWords = 'hello'; - final String secondRecognizedWords = 'hello there'; - final double firstConfidence = 0.85; - final double secondConfidence = 0.62; - final String firstRecognizedJson = - '{"alternates":[{"recognizedWords":"$firstRecognizedWords","confidence":$firstConfidence}],"finalResult":false}'; - final String secondRecognizedJson = - '{"alternates":[{"recognizedWords":"$secondRecognizedWords","confidence":$secondConfidence}],"finalResult":false}'; - final SpeechRecognitionWords firstWords = - SpeechRecognitionWords(firstRecognizedWords, firstConfidence); - final SpeechRecognitionWords secondWords = - SpeechRecognitionWords(secondRecognizedWords, secondConfidence); - - setUp(() {}); - - group('recognizedWords', () { - test('empty if no alternates', () { - SpeechRecognitionResult result = SpeechRecognitionResult([], true); - expect(result.recognizedWords, isEmpty); - }); - test('matches first alternate', () { - SpeechRecognitionResult result = - SpeechRecognitionResult([firstWords, secondWords], true); - expect(result.recognizedWords, firstRecognizedWords); - }); - }); - group('alternates', () { - test('empty if no alternates', () { - SpeechRecognitionResult result = SpeechRecognitionResult([], true); - expect(result.alternates, isEmpty); - }); - test('expected contents', () { - SpeechRecognitionResult result = - SpeechRecognitionResult([firstWords, secondWords], true); - expect(result.alternates, contains(firstWords)); - expect(result.alternates, contains(secondWords)); - }); - test('in order', () { - SpeechRecognitionResult result = - SpeechRecognitionResult([firstWords, secondWords], true); - expect(result.alternates.first, firstWords); - }); - }); - group('confidence', () { - test('0 if no alternates', () { - SpeechRecognitionResult result = SpeechRecognitionResult([], true); - expect(result.confidence, 0); - }); - test('isConfident false if no alternates', () { - SpeechRecognitionResult result = SpeechRecognitionResult([], true); - expect(result.isConfident(), isFalse); - }); - test('isConfident matches first alternate', () { - SpeechRecognitionResult result = - SpeechRecognitionResult([firstWords, secondWords], true); - expect(result.isConfident(), firstWords.isConfident()); - }); - test('hasConfidenceRating false if no alternates', () { - SpeechRecognitionResult result = SpeechRecognitionResult([], true); - expect(result.hasConfidenceRating, isFalse); - }); - test('hasConfidenceRating matches first alternate', () { - SpeechRecognitionResult result = - SpeechRecognitionResult([firstWords, secondWords], true); - expect(result.hasConfidenceRating, firstWords.hasConfidenceRating); - }); - }); - group('json', () { - test('loads correctly', () { - var json = jsonDecode(firstRecognizedJson); - SpeechRecognitionResult result = SpeechRecognitionResult.fromJson(json); - expect(result.recognizedWords, firstRecognizedWords); - expect(result.confidence, firstConfidence); - }); - test('roundtrips correctly', () { - var json = jsonDecode(firstRecognizedJson); - SpeechRecognitionResult result = SpeechRecognitionResult.fromJson(json); - var roundTripJson = result.toJson(); - SpeechRecognitionResult roundtripResult = - SpeechRecognitionResult.fromJson(roundTripJson); - expect(result, roundtripResult); - }); - }); - group('overrides', () { - test('toString works with no alternates', () { - SpeechRecognitionResult result = SpeechRecognitionResult([], true); - expect( - result.toString(), "SpeechRecognitionResult words: [], final: true"); - }); - test('toString works with alternates', () { - SpeechRecognitionResult result = - SpeechRecognitionResult([firstWords], true); - expect(result.toString(), - "SpeechRecognitionResult words: [SpeechRecognitionWords words: hello, confidence: 0.85], final: true"); - }); - test('hash same for same object', () { - SpeechRecognitionResult result = - SpeechRecognitionResult([firstWords], true); - expect(result.hashCode, result.hashCode); - }); - test('hash differs for different objects', () { - SpeechRecognitionResult result1 = - SpeechRecognitionResult([firstWords], true); - SpeechRecognitionResult result2 = - SpeechRecognitionResult([secondWords], true); - expect(result1.hashCode, isNot(result2.hashCode)); - }); - test('equals same for same object', () { - SpeechRecognitionResult result = - SpeechRecognitionResult([firstWords], true); - expect(result, result); - }); - test('equals same for different object same values', () { - SpeechRecognitionResult result1 = - SpeechRecognitionResult([firstWords], true); - SpeechRecognitionResult result1a = - SpeechRecognitionResult([firstWords], true); - expect(result1, result1a); - }); - test('equals differs for different objects', () { - SpeechRecognitionResult result1 = - SpeechRecognitionResult([firstWords], true); - SpeechRecognitionResult result2 = - SpeechRecognitionResult([secondWords], true); - expect(result1, isNot(result2)); - }); - }); -} diff --git a/speech_to_text_/test/speech_recognitions_words_test.dart b/speech_to_text_/test/speech_recognitions_words_test.dart deleted file mode 100644 index 36a9ef0e..00000000 --- a/speech_to_text_/test/speech_recognitions_words_test.dart +++ /dev/null @@ -1,86 +0,0 @@ -import 'dart:convert'; - -import 'package:flutter_test/flutter_test.dart'; -import 'package:speech_to_text/speech_recognition_result.dart'; - -void main() { - final String firstRecognizedWords = 'hello'; - final String secondRecognizedWords = 'hello there'; - final double firstConfidence = 0.85; - final double secondConfidence = 0.62; - final String firstRecognizedJson = - '{"recognizedWords":"$firstRecognizedWords","confidence":$firstConfidence}'; - final SpeechRecognitionWords firstWords = - SpeechRecognitionWords(firstRecognizedWords, firstConfidence); - final SpeechRecognitionWords secondWords = - SpeechRecognitionWords(secondRecognizedWords, secondConfidence); - - setUp(() {}); - - group('properties', () { - test('words', () { - expect(firstWords.recognizedWords, firstRecognizedWords); - expect(secondWords.recognizedWords, secondRecognizedWords); - }); - test('confidence', () { - expect(firstWords.confidence, firstConfidence); - expect(secondWords.confidence, secondConfidence); - expect(firstWords.hasConfidenceRating, isTrue); - }); - test('equals true for same object', () { - expect(firstWords, firstWords); - }); - test('equals true for different object with same values', () { - SpeechRecognitionWords firstWordsA = - SpeechRecognitionWords(firstRecognizedWords, firstConfidence); - expect(firstWords, firstWordsA); - }); - test('equals false for different results', () { - expect(firstWords, isNot(secondWords)); - }); - test('hash same for same object', () { - expect(firstWords.hashCode, firstWords.hashCode); - }); - test('hash same for different object with same values', () { - SpeechRecognitionWords firstWordsA = - SpeechRecognitionWords(firstRecognizedWords, firstConfidence); - expect(firstWords.hashCode, firstWordsA.hashCode); - }); - test('hash different for different results', () { - expect(firstWords.hashCode, isNot(secondWords.hashCode)); - }); - }); - group('isConfident', () { - test('true when >= 0.8', () { - expect(firstWords.isConfident(), isTrue); - }); - test('false when < 0.8', () { - expect(secondWords.isConfident(), isFalse); - }); - test('respects threshold', () { - expect(secondWords.isConfident(threshold: 0.5), isTrue); - }); - test('true when missing', () { - SpeechRecognitionWords words = SpeechRecognitionWords( - firstRecognizedWords, SpeechRecognitionWords.missingConfidence); - expect(words.isConfident(), isTrue); - expect(words.hasConfidenceRating, isFalse); - }); - }); - group('json', () { - test('loads correctly', () { - var json = jsonDecode(firstRecognizedJson); - SpeechRecognitionWords words = SpeechRecognitionWords.fromJson(json); - expect(words.recognizedWords, firstRecognizedWords); - expect(words.confidence, firstConfidence); - }); - test('roundtrips correctly', () { - var json = jsonDecode(firstRecognizedJson); - SpeechRecognitionWords words = SpeechRecognitionWords.fromJson(json); - var roundTripJson = words.toJson(); - SpeechRecognitionWords roundtripWords = - SpeechRecognitionWords.fromJson(roundTripJson); - expect(words, roundtripWords); - }); - }); -} diff --git a/speech_to_text_/test/speech_to_text_provider_test.dart b/speech_to_text_/test/speech_to_text_provider_test.dart deleted file mode 100644 index 25366b6f..00000000 --- a/speech_to_text_/test/speech_to_text_provider_test.dart +++ /dev/null @@ -1,196 +0,0 @@ -import 'package:fake_async/fake_async.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:speech_to_text/speech_to_text.dart'; -import 'package:speech_to_text/speech_to_text_provider.dart'; - -import 'test_speech_channel_handler.dart'; -import 'test_speech_listener.dart'; - -void main() { - SpeechToTextProvider provider; - SpeechToText speechToText; - TestSpeechChannelHandler speechHandler; - TestSpeechListener speechListener; - - TestWidgetsFlutterBinding.ensureInitialized(); - - setUp(() { - speechToText = SpeechToText.withMethodChannel(SpeechToText.speechChannel); - speechHandler = TestSpeechChannelHandler(speechToText); - speechToText.channel - .setMockMethodCallHandler(speechHandler.methodCallHandler); - provider = SpeechToTextProvider(speechToText); - speechListener = TestSpeechListener(provider); - provider.addListener(speechListener.onNotify); - }); - - tearDown(() { - speechToText.channel.setMockMethodCallHandler(null); - }); - - group('delegates', () { - test('isListening matches delegate defaults', () { - expect(provider.isListening, speechToText.isListening); - expect(provider.isNotListening, speechToText.isNotListening); - }); - test('isAvailable matches delegate defaults', () { - expect(provider.isAvailable, speechToText.isAvailable); - expect(provider.isNotAvailable, !speechToText.isAvailable); - }); - test('isAvailable matches delegate after init', () async { - expect(await provider.initialize(), isTrue); - expect(provider.isAvailable, speechToText.isAvailable); - expect(provider.isNotAvailable, !speechToText.isAvailable); - }); - test('hasError matches delegate after error', () async { - expect(await provider.initialize(), isTrue); - expect(provider.hasError, speechToText.hasError); - }); - }); - group('listening', () { - test('notifies on initialize', () async { - fakeAsync((fa) { - provider.initialize(); - fa.flushMicrotasks(); - expect(speechListener.notified, isTrue); - expect(speechListener.isAvailable, isTrue); - }); - }); - test('notifies on listening', () async { - fakeAsync((fa) { - setupForListen(provider, fa, speechListener); - expect(speechListener.notified, isTrue); - expect(speechListener.isListening, isTrue); - expect(provider.hasResults, isFalse); - }); - }); - test('notifies on final words', () async { - fakeAsync((fa) { - setupForListen(provider, fa, speechListener); - speechListener.reset(); - speechHandler.notifyFinalWords(); - fa.flushMicrotasks(); - expect(speechListener.notified, isTrue); - expect(provider.hasResults, isTrue); - var result = speechListener.recognitionResult; - expect(result.recognizedWords, - TestSpeechChannelHandler.secondRecognizedWords); - expect(result.finalResult, isTrue); - }); - }); - test('hasResult false after listening before new results', () async { - fakeAsync((fa) { - setupForListen(provider, fa, speechListener); - speechHandler.notifyFinalWords(); - provider.stop(); - setupForListen(provider, fa, speechListener); - fa.flushMicrotasks(); - expect(provider.hasResults, isFalse); - }); - }); - test('notifies on partial words', () async { - fakeAsync((fa) { - setupForListen(provider, fa, speechListener, partialResults: true); - speechListener.reset(); - speechHandler.notifyPartialWords(); - fa.flushMicrotasks(); - expect(speechListener.notified, isTrue); - expect(provider.hasResults, isTrue); - var result = speechListener.recognitionResult; - expect(result.recognizedWords, - TestSpeechChannelHandler.firstRecognizedWords); - expect(result.finalResult, isFalse); - }); - }); - }); - group('soundLevel', () { - test('notifies when requested', () async { - fakeAsync((fa) { - setupForListen(provider, fa, speechListener, - partialResults: true, soundLevel: true); - speechListener.reset(); - speechHandler.notifySoundLevel(); - fa.flushMicrotasks(); - expect(speechListener.notified, isTrue); - expect(speechListener.soundLevel, TestSpeechChannelHandler.level2); - }); - }); - test('no notification by default', () async { - fakeAsync((fa) { - setupForListen(provider, fa, speechListener, - partialResults: true, soundLevel: false); - speechListener.reset(); - speechHandler.notifySoundLevel(); - fa.flushMicrotasks(); - expect(speechListener.notified, isFalse); - expect(speechListener.soundLevel, 0); - }); - }); - }); - group('stop/cancel', () { - test('notifies on stop', () async { - fakeAsync((fa) { - provider.initialize(); - setupForListen(provider, fa, speechListener); - speechListener.reset(); - provider.stop(); - fa.flushMicrotasks(); - expect(speechListener.notified, isTrue); - expect(speechListener.isListening, isFalse); - }); - }); - test('notifies on cancel', () async { - fakeAsync((fa) { - provider.initialize(); - setupForListen(provider, fa, speechListener); - speechListener.reset(); - provider.cancel(); - fa.flushMicrotasks(); - expect(speechListener.notified, isTrue); - expect(speechListener.isListening, isFalse); - }); - }); - }); - group('error handling', () { - test('hasError matches delegate default', () async { - expect(await provider.initialize(), isTrue); - expect(provider.hasError, speechToText.hasError); - }); - test('notifies on error', () async { - fakeAsync((fa) { - provider.initialize(); - setupForListen(provider, fa, speechListener); - speechListener.reset(); - speechHandler.notifyPermanentError(); - expect(speechListener.notified, isTrue); - expect(speechListener.hasError, isTrue); - }); - }); - }); - group('locale', () { - test('locales empty before init', () async { - expect(provider.systemLocale, isNull); - expect(provider.locales, isEmpty); - }); - test('set from SpeechToText after init', () async { - fakeAsync((fa) { - speechHandler.setupLocales(); - provider.initialize(); - fa.flushMicrotasks(); - expect( - provider.systemLocale.localeId, TestSpeechChannelHandler.localeId1); - expect(provider.locales, hasLength(speechHandler.locales.length)); - }); - }); - }); -} - -void setupForListen(SpeechToTextProvider provider, FakeAsync fa, - TestSpeechListener speechListener, - {bool partialResults = false, bool soundLevel = false}) { - provider.initialize(); - fa.flushMicrotasks(); - speechListener.reset(); - provider.listen(partialResults: partialResults, soundLevel: soundLevel); - fa.flushMicrotasks(); -} diff --git a/speech_to_text_/test/speech_to_text_test.dart b/speech_to_text_/test/speech_to_text_test.dart deleted file mode 100644 index 7b4701ff..00000000 --- a/speech_to_text_/test/speech_to_text_test.dart +++ /dev/null @@ -1,425 +0,0 @@ -import 'package:fake_async/fake_async.dart'; -import 'package:flutter/services.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:speech_to_text/speech_recognition_error.dart'; -import 'package:speech_to_text/speech_recognition_result.dart'; -import 'package:speech_to_text/speech_to_text.dart'; - -import 'test_speech_channel_handler.dart'; - -void main() { - TestWidgetsFlutterBinding.ensureInitialized(); - - TestSpeechListener listener; - TestSpeechChannelHandler speechHandler; - SpeechToText speech; - - setUp(() { - listener = TestSpeechListener(); - speech = SpeechToText.withMethodChannel(SpeechToText.speechChannel); - speechHandler = TestSpeechChannelHandler(speech); - speech.channel.setMockMethodCallHandler(speechHandler.methodCallHandler); - }); - - tearDown(() { - speech.channel.setMockMethodCallHandler(null); - }); - - group('hasPermission', () { - test('true if platform reports true', () async { - expect(await speech.hasPermission, true); - }); - test('false if platform reports false', () async { - speechHandler.hasPermissionResult = false; - expect(await speech.hasPermission, false); - }); - }); - group('init', () { - test('succeeds on platform success', () async { - expect(await speech.initialize(), true); - expect(speechHandler.initInvoked, true); - expect(speech.isAvailable, true); - }); - test('only invokes once', () async { - expect(await speech.initialize(), true); - speechHandler.initInvoked = false; - expect(await speech.initialize(), true); - expect(speechHandler.initInvoked, false); - }); - test('fails on platform failure', () async { - speechHandler.initResult = false; - expect(await speech.initialize(), false); - expect(speech.isAvailable, false); - }); - }); - - group('listen', () { - test('fails with exception if not initialized', () async { - try { - await speech.listen(); - fail("Expected an exception."); - } on SpeechToTextNotInitializedException { - // This is a good result - } - }); - test('fails with exception if init fails', () async { - try { - speechHandler.initResult = false; - await speech.initialize(); - await speech.listen(); - fail("Expected an exception."); - } on SpeechToTextNotInitializedException { - // This is a good result - } - }); - test('invokes listen after successful init', () async { - await speech.initialize(); - await speech.listen(); - expect(speechHandler.listenLocale, isNull); - expect(speechHandler.listenInvoked, true); - }); - test('converts platformException to listenFailed', () async { - await speech.initialize(); - speechHandler.listenException = true; - try { - await speech.listen(); - fail("Should have thrown"); - } on ListenFailedException catch (e) { - expect(e.details, TestSpeechChannelHandler.listenExceptionDetails); - } catch (wrongE) { - fail("Should have been ListenFailedException"); - } - }); - test('stops listen after listenFor duration', () async { - fakeAsync((fa) { - speech.initialize(); - fa.flushMicrotasks(); - speech.listen(listenFor: Duration(seconds: 2)); - fa.flushMicrotasks(); - expect(speech.isListening, isTrue); - fa.elapse(Duration(seconds: 2)); - expect(speech.isListening, isFalse); - }); - }); - test('stops listen after listenFor duration even with speech event', - () async { - fakeAsync((fa) { - speech.initialize(); - fa.flushMicrotasks(); - speech.listen(listenFor: Duration(seconds: 1)); - speech.processMethodCall(MethodCall(SpeechToText.textRecognitionMethod, - TestSpeechChannelHandler.firstRecognizedJson)); - fa.flushMicrotasks(); - expect(speech.isListening, isTrue); - fa.elapse(Duration(seconds: 1)); - expect(speech.isListening, isFalse); - }); - }); - test('stops listen after pauseFor duration with no speech', () async { - fakeAsync((fa) { - speech.initialize(); - fa.flushMicrotasks(); - speech.listen(pauseFor: Duration(seconds: 2)); - fa.flushMicrotasks(); - expect(speech.isListening, isTrue); - fa.elapse(Duration(seconds: 2)); - expect(speech.isListening, isFalse); - }); - }); - test('stops listen after pauseFor with longer listenFor duration', - () async { - fakeAsync((fa) { - speech.initialize(); - fa.flushMicrotasks(); - speech.listen( - pauseFor: Duration(seconds: 1), listenFor: Duration(seconds: 5)); - fa.flushMicrotasks(); - expect(speech.isListening, isTrue); - fa.elapse(Duration(seconds: 1)); - expect(speech.isListening, isFalse); - }); - }); - test('stops listen after listenFor with longer pauseFor duration', - () async { - fakeAsync((fa) { - speech.initialize(); - fa.flushMicrotasks(); - speech.listen( - listenFor: Duration(seconds: 1), pauseFor: Duration(seconds: 5)); - fa.flushMicrotasks(); - expect(speech.isListening, isTrue); - fa.elapse(Duration(seconds: 1)); - expect(speech.isListening, isFalse); - }); - }); - test('keeps listening after pauseFor with speech event', () async { - fakeAsync((fa) { - speech.initialize(); - fa.flushMicrotasks(); - speech.listen(pauseFor: Duration(seconds: 2)); - fa.flushMicrotasks(); - fa.elapse(Duration(seconds: 1)); - speech.processMethodCall(MethodCall(SpeechToText.textRecognitionMethod, - TestSpeechChannelHandler.firstRecognizedJson)); - fa.flushMicrotasks(); - fa.elapse(Duration(seconds: 1)); - expect(speech.isListening, isTrue); - }); - }); - test('uses localeId if provided', () async { - await speech.initialize(); - await speech.listen(localeId: TestSpeechChannelHandler.localeId1); - expect(speechHandler.listenInvoked, true); - expect(speechHandler.listenLocale, TestSpeechChannelHandler.localeId1); - }); - test('calls speech listener', () async { - await speech.initialize(); - await speech.listen(onResult: listener.onSpeechResult); - await speech.processMethodCall(MethodCall( - SpeechToText.textRecognitionMethod, - TestSpeechChannelHandler.firstRecognizedJson)); - expect(listener.speechResults, 1); - expect( - listener.results, [TestSpeechChannelHandler.firstRecognizedResult]); - expect(speech.lastRecognizedWords, - TestSpeechChannelHandler.firstRecognizedWords); - }); - test('calls speech listener with multiple', () async { - await speech.initialize(); - await speech.listen(onResult: listener.onSpeechResult); - await speech.processMethodCall(MethodCall( - SpeechToText.textRecognitionMethod, - TestSpeechChannelHandler.firstRecognizedJson)); - await speech.processMethodCall(MethodCall( - SpeechToText.textRecognitionMethod, - TestSpeechChannelHandler.secondRecognizedJson)); - expect(listener.speechResults, 2); - expect(listener.results, [ - TestSpeechChannelHandler.firstRecognizedResult, - TestSpeechChannelHandler.secondRecognizedResult - ]); - expect(speech.lastRecognizedWords, - TestSpeechChannelHandler.secondRecognizedWords); - }); - }); - - group('status callback', () { - test('invoked on listen', () async { - await speech.initialize( - onError: listener.onSpeechError, onStatus: listener.onSpeechStatus); - await speech.processMethodCall(MethodCall( - SpeechToText.notifyStatusMethod, SpeechToText.listeningStatus)); - expect(listener.speechStatus, 1); - expect(listener.statuses.contains(SpeechToText.listeningStatus), true); - }); - }); - - group('soundLevel callback', () { - test('invoked on listen', () async { - await speech.initialize(); - await speech.listen(onSoundLevelChange: listener.onSoundLevel); - await speech.processMethodCall(MethodCall( - SpeechToText.soundLevelChangeMethod, - TestSpeechChannelHandler.level1)); - expect(listener.soundLevel, 1); - expect(listener.soundLevels, contains(TestSpeechChannelHandler.level1)); - }); - test('sets lastLevel', () async { - await speech.initialize(); - await speech.listen(onSoundLevelChange: listener.onSoundLevel); - await speech.processMethodCall(MethodCall( - SpeechToText.soundLevelChangeMethod, - TestSpeechChannelHandler.level1)); - expect(speech.lastSoundLevel, TestSpeechChannelHandler.level1); - }); - }); - - group('cancel', () { - test('does nothing if not initialized', () async { - speech.cancel(); - expect(speechHandler.cancelInvoked, false); - }); - test('cancels an active listen', () async { - await speech.initialize(); - await speech.listen(); - await speech.cancel(); - expect(speechHandler.cancelInvoked, true); - expect(speech.isListening, isFalse); - }); - }); - group('stop', () { - test('does nothing if not initialized', () async { - speech.stop(); - expect(speechHandler.cancelInvoked, false); - }); - test('stops an active listen', () async { - await speech.initialize(); - speech.listen(); - speech.stop(); - expect(speechHandler.stopInvoked, true); - }); - }); - group('error', () { - test('notifies handler with transient', () async { - await speech.initialize(onError: listener.onSpeechError); - await speech.listen(); - await speech.processMethodCall(MethodCall(SpeechToText.notifyErrorMethod, - TestSpeechChannelHandler.transientErrorJson)); - expect(listener.speechErrors, 1); - expect(listener.errors.first.permanent, isFalse); - }); - test('notifies handler with permanent', () async { - await speech.initialize(onError: listener.onSpeechError); - await speech.listen(); - await speech.processMethodCall(MethodCall(SpeechToText.notifyErrorMethod, - TestSpeechChannelHandler.permanentErrorJson)); - expect(listener.speechErrors, 1); - expect(listener.errors.first.permanent, isTrue); - }); - test('continues listening on transient', () async { - await speech.initialize(onError: listener.onSpeechError); - await speech.listen(); - await speech.processMethodCall(MethodCall(SpeechToText.notifyErrorMethod, - TestSpeechChannelHandler.transientErrorJson)); - expect(speech.isListening, isTrue); - }); - test('continues listening on permanent if cancel not explicitly requested', - () async { - await speech.initialize(onError: listener.onSpeechError); - await speech.listen(); - await speech.processMethodCall(MethodCall(SpeechToText.notifyErrorMethod, - TestSpeechChannelHandler.permanentErrorJson)); - expect(speech.isListening, isTrue); - }); - test('stops listening on permanent if cancel explicitly requested', - () async { - await speech.initialize(onError: listener.onSpeechError); - await speech.listen(cancelOnError: true); - await speech.processMethodCall(MethodCall(SpeechToText.notifyErrorMethod, - TestSpeechChannelHandler.permanentErrorJson)); - expect(speech.isListening, isFalse); - }); - test('Error not sent after cancel', () async { - await speech.initialize(onError: listener.onSpeechError); - await speech.listen(); - await speech.cancel(); - await speech.processMethodCall(MethodCall(SpeechToText.notifyErrorMethod, - TestSpeechChannelHandler.permanentErrorJson)); - expect(speech.isListening, isFalse); - expect(listener.speechErrors, 0); - }); - test('Error still sent after implicit cancel', () async { - await speech.initialize(onError: listener.onSpeechError); - await speech.listen(cancelOnError: true); - await speech.processMethodCall(MethodCall(SpeechToText.notifyErrorMethod, - TestSpeechChannelHandler.permanentErrorJson)); - await speech.processMethodCall(MethodCall(SpeechToText.notifyErrorMethod, - TestSpeechChannelHandler.permanentErrorJson)); - expect(speech.isListening, isFalse); - expect(listener.speechErrors, 2); - }); - }); - group('locales', () { - test('fails with exception if not initialized', () async { - try { - await speech.locales(); - fail("Expected an exception."); - } on SpeechToTextNotInitializedException { - // This is a good result - } - }); - test('system locale null if not initialized', () async { - LocaleName current; - try { - current = await speech.systemLocale(); - fail("Expected an exception."); - } on SpeechToTextNotInitializedException { - expect(current, isNull); - } - }); - test('handles an empty list', () async { - await speech.initialize(onError: listener.onSpeechError); - List localeNames = await speech.locales(); - expect(speechHandler.localesInvoked, isTrue); - expect(localeNames, isEmpty); - }); - test('returns expected locales', () async { - await speech.initialize(onError: listener.onSpeechError); - speechHandler.locales.add(TestSpeechChannelHandler.locale1); - speechHandler.locales.add(TestSpeechChannelHandler.locale2); - List localeNames = await speech.locales(); - expect(localeNames, hasLength(speechHandler.locales.length)); - expect(localeNames[0].localeId, TestSpeechChannelHandler.localeId1); - expect(localeNames[0].name, TestSpeechChannelHandler.name1); - expect(localeNames[1].localeId, TestSpeechChannelHandler.localeId2); - expect(localeNames[1].name, TestSpeechChannelHandler.name2); - }); - test('skips incorrect locales', () async { - await speech.initialize(onError: listener.onSpeechError); - speechHandler.locales.add("InvalidJunk"); - speechHandler.locales.add(TestSpeechChannelHandler.locale1); - List localeNames = await speech.locales(); - expect(localeNames, hasLength(1)); - expect(localeNames[0].localeId, TestSpeechChannelHandler.localeId1); - expect(localeNames[0].name, TestSpeechChannelHandler.name1); - }); - test('system locale matches first returned locale', () async { - await speech.initialize(onError: listener.onSpeechError); - speechHandler.locales.add(TestSpeechChannelHandler.locale1); - speechHandler.locales.add(TestSpeechChannelHandler.locale2); - LocaleName current = await speech.systemLocale(); - expect(current.localeId, TestSpeechChannelHandler.localeId1); - }); - }); - group('status', () { - test('recognized false at start', () async { - expect(speech.hasRecognized, isFalse); - }); - test('listening false at start', () async { - expect(speech.isListening, isFalse); - }); - }); - test('available false at start', () async { - expect(speech.isAvailable, isFalse); - }); - test('hasError false at start', () async { - expect(speech.hasError, isFalse); - }); - test('lastError null at start', () async { - expect(speech.lastError, isNull); - }); - test('status empty at start', () async { - expect(speech.lastStatus, isEmpty); - }); -} - -class TestSpeechListener { - int speechResults = 0; - List results = []; - int speechErrors = 0; - List errors = []; - int speechStatus = 0; - List statuses = []; - int soundLevel = 0; - List soundLevels = []; - - void onSpeechResult(SpeechRecognitionResult result) { - ++speechResults; - results.add(result); - } - - void onSpeechError(SpeechRecognitionError errorResult) { - ++speechErrors; - errors.add(errorResult); - } - - void onSpeechStatus(String status) { - ++speechStatus; - statuses.add(status); - } - - void onSoundLevel(double level) { - ++soundLevel; - soundLevels.add(level); - } -} diff --git a/speech_to_text_/test/test_speech_channel_handler.dart b/speech_to_text_/test/test_speech_channel_handler.dart deleted file mode 100644 index a55f0670..00000000 --- a/speech_to_text_/test/test_speech_channel_handler.dart +++ /dev/null @@ -1,134 +0,0 @@ -import 'package:flutter/services.dart'; -import 'package:speech_to_text/speech_recognition_error.dart'; -import 'package:speech_to_text/speech_recognition_result.dart'; -import 'package:speech_to_text/speech_to_text.dart'; - -/// Holds a set of responses and acts as a mock for the platform specific -/// implementations allowing test cases to determine what the result of -/// a call should be. -class TestSpeechChannelHandler { - final SpeechToText _speech; - - bool listenException = false; - - static const String listenExceptionCode = "listenFailedError"; - static const String listenExceptionMessage = "Failed"; - static const String listenExceptionDetails = "Device Listen Failure"; - - TestSpeechChannelHandler(this._speech); - - bool initResult = true; - bool initInvoked = false; - bool listenInvoked = false; - bool cancelInvoked = false; - bool stopInvoked = false; - bool localesInvoked = false; - bool hasPermissionResult = true; - String listeningStatusResponse = SpeechToText.listeningStatus; - String listenLocale; - List locales = []; - static const String localeId1 = "en_US"; - static const String localeId2 = "fr_CA"; - static const String name1 = "English US"; - static const String name2 = "French Canada"; - static const String locale1 = "$localeId1:$name1"; - static const String locale2 = "$localeId2:$name2"; - static const String firstRecognizedWords = 'hello'; - static const String secondRecognizedWords = 'hello there'; - static const double firstConfidence = 0.85; - static const double secondConfidence = 0.62; - static const String firstRecognizedJson = - '{"alternates":[{"recognizedWords":"$firstRecognizedWords","confidence":$firstConfidence}],"finalResult":false}'; - static const String secondRecognizedJson = - '{"alternates":[{"recognizedWords":"$secondRecognizedWords","confidence":$secondConfidence}],"finalResult":false}'; - static const String finalRecognizedJson = - '{"alternates":[{"recognizedWords":"$secondRecognizedWords","confidence":$secondConfidence}],"finalResult":true}'; - static const SpeechRecognitionWords firstWords = - SpeechRecognitionWords(firstRecognizedWords, firstConfidence); - static const SpeechRecognitionWords secondWords = - SpeechRecognitionWords(secondRecognizedWords, secondConfidence); - static final SpeechRecognitionResult firstRecognizedResult = - SpeechRecognitionResult([firstWords], false); - static final SpeechRecognitionResult secondRecognizedResult = - SpeechRecognitionResult([secondWords], false); - static final SpeechRecognitionResult finalRecognizedResult = - SpeechRecognitionResult([secondWords], true); - static const String transientErrorJson = - '{"errorMsg":"network","permanent":false}'; - static const String permanentErrorJson = - '{"errorMsg":"network","permanent":true}'; - static final SpeechRecognitionError firstError = - SpeechRecognitionError("network", true); - static const double level1 = 0.5; - static const double level2 = 10; - - Future methodCallHandler(MethodCall methodCall) async { - switch (methodCall.method) { - case "has_permission": - return hasPermissionResult; - break; - case "initialize": - initInvoked = true; - return initResult; - break; - case "cancel": - cancelInvoked = true; - return true; - break; - case "stop": - stopInvoked = true; - return true; - break; - case SpeechToText.listenMethod: - listenInvoked = true; - if (listenException) { - throw PlatformException( - code: listenExceptionCode, - message: listenExceptionMessage, - details: listenExceptionDetails); - } - listenLocale = methodCall.arguments["localeId"]; - await _speech.processMethodCall(MethodCall( - SpeechToText.notifyStatusMethod, listeningStatusResponse)); - return initResult; - break; - case "locales": - localesInvoked = true; - return locales; - break; - default: - } - return initResult; - } - - void notifyFinalWords() { - _speech.processMethodCall( - MethodCall(SpeechToText.textRecognitionMethod, finalRecognizedJson)); - } - - void notifyPartialWords() { - _speech.processMethodCall( - MethodCall(SpeechToText.textRecognitionMethod, firstRecognizedJson)); - } - - void notifyPermanentError() { - _speech.processMethodCall( - MethodCall(SpeechToText.notifyErrorMethod, permanentErrorJson)); - } - - void notifyTransientError() { - _speech.processMethodCall( - MethodCall(SpeechToText.notifyErrorMethod, transientErrorJson)); - } - - void notifySoundLevel() { - _speech.processMethodCall( - MethodCall(SpeechToText.soundLevelChangeMethod, level2)); - } - - void setupLocales() { - locales.clear(); - locales.add(locale1); - locales.add(locale2); - } -} diff --git a/speech_to_text_/test/test_speech_listener.dart b/speech_to_text_/test/test_speech_listener.dart deleted file mode 100644 index 1efcd81c..00000000 --- a/speech_to_text_/test/test_speech_listener.dart +++ /dev/null @@ -1,36 +0,0 @@ -import 'package:speech_to_text/speech_recognition_error.dart'; -import 'package:speech_to_text/speech_recognition_result.dart'; -import 'package:speech_to_text/speech_to_text_provider.dart'; - -/// Holds the results of notification by the [SpeechToTextProvider] -class TestSpeechListener { - final SpeechToTextProvider _speechProvider; - - bool isListening = false; - bool isFinal = false; - bool isAvailable = false; - bool notified = false; - bool hasError = false; - SpeechRecognitionResult recognitionResult; - SpeechRecognitionError lastError; - double soundLevel; - - TestSpeechListener(this._speechProvider); - - void reset() { - isListening = false; - isFinal = false; - isAvailable = false; - notified = false; - } - - void onNotify() { - notified = true; - isAvailable = _speechProvider.isAvailable; - isListening = _speechProvider.isListening; - recognitionResult = _speechProvider.lastResult; - hasError = _speechProvider.hasError; - lastError = _speechProvider.lastError; - soundLevel = _speechProvider.lastLevel; - } -} From 7f446772423ff9d0a01ec38350eb161fceaea5f3 Mon Sep 17 00:00:00 2001 From: Sultan Khan Date: Wed, 9 Dec 2020 11:54:23 +0300 Subject: [PATCH 21/71] voice command priv --- lib/pages/landing/landing_page.dart | 102 +++++++++--------- lib/widgets/others/app_scaffold_widget.dart | 2 +- .../others/floating_button_search.dart | 2 + 3 files changed, 56 insertions(+), 50 deletions(-) diff --git a/lib/pages/landing/landing_page.dart b/lib/pages/landing/landing_page.dart index e08f1773..7be7c4e6 100644 --- a/lib/pages/landing/landing_page.dart +++ b/lib/pages/landing/landing_page.dart @@ -52,6 +52,7 @@ class _LandingPageState extends State with WidgetsBindingObserver { ProjectViewModel projectViewModel; var notificationCount = ''; var themeNotifier; + ///inject the user data AuthenticatedUserObject authenticatedUserObject = locator(); @@ -75,8 +76,9 @@ class _LandingPageState extends State with WidgetsBindingObserver { LocationUtils locationUtils; _changeCurrentTab(int tab) { setState(() { - currentTab = tab; - pageController.jumpToPage(tab); + currentTab = tab; + pageController.jumpToPage(tab); + }); } @@ -140,18 +142,17 @@ class _LandingPageState extends State with WidgetsBindingObserver { _firebaseMessaging.setAutoInitEnabled(true); locationUtils = - new LocationUtils(isShowConfirmDialog: true, context: context); + new LocationUtils(isShowConfirmDialog: true, context: context); WidgetsBinding.instance .addPostFrameCallback((_) => locationUtils.getCurrentLocation()); - if (Platform.isIOS) { _firebaseMessaging.requestNotificationPermissions(); } _firebaseMessaging.getToken().then((String token) async { sharedPref.setString(PUSH_TOKEN, token); - if (token != null && await sharedPref.getObject(USER_PROFILE) ==null) { + if (token != null && await sharedPref.getObject(USER_PROFILE) == null) { DEVICE_TOKEN = token; checkUserStatus(token); } @@ -392,7 +393,7 @@ class _LandingPageState extends State with WidgetsBindingObserver { notificationCount, style: new TextStyle( color: Colors.white, - fontSize: projectViewModel.isArabic ? 8 : 9, + fontSize: projectViewModel.isArabic ? 8 : 9, ), textAlign: TextAlign.center, ), @@ -416,7 +417,7 @@ class _LandingPageState extends State with WidgetsBindingObserver { SETTINGS, ); else - login(); + login(); }, //do something, ) ], @@ -430,7 +431,7 @@ class _LandingPageState extends State with WidgetsBindingObserver { children: [ HomePage( goToMyProfile: () { - _changeCurrentTab(1); + // _changeCurrentTab(1); }, ), MedicalProfilePage(), @@ -471,45 +472,46 @@ class _LandingPageState extends State with WidgetsBindingObserver { return TranslationBase.of(context).bookAppo; } } - setTheme() async{ - // - // defaultTheme = - // ThemeData( - // fontFamily:projectViewModel.isArabic ? 'Cairo' : 'WorkSans', - // primarySwatch: Colors.blue, - // visualDensity: VisualDensity.adaptivePlatformDensity, - // brightness: Brightness.light, - // pageTransitionsTheme: const PageTransitionsTheme( - // builders: { - // TargetPlatform.android: ZoomPageTransitionsBuilder(), - // TargetPlatform.iOS: CupertinoPageTransitionsBuilder(), - // }, - // ), - // hintColor: Colors.grey[400], - // disabledColor: Colors.grey[300], - // errorColor: Color.fromRGBO(235, 80, 60, 1.0), - // scaffoldBackgroundColor: Color(0xffEEEEEE), - // textSelectionColor: Color.fromRGBO(80, 100, 253, 0.5), - // textSelectionHandleColor: Colors.grey, - // canvasColor: Colors.white, - // backgroundColor: Colors.white, - // highlightColor: Colors.grey[100].withOpacity(0.4), - // splashColor: Colors.transparent, - // primaryColor: Color(0xff40ACC9), - // bottomSheetTheme: BottomSheetThemeData(backgroundColor: Color(0xffE0E0E0)), - // cursorColor: Colors.grey, - // cardColor: Colors.white, - // iconTheme: IconThemeData(), - // appBarTheme: AppBarTheme( - // color: Color(0xff40ACC9), - // brightness: Brightness.dark, - // elevation: 10.0, - // actionsIconTheme: IconThemeData( - // color: Color(0xff40ACC9), - // ), - // ), - // ); - // themeNotifier.setTheme(defaultTheme); + + setTheme() async { + // + // defaultTheme = + // ThemeData( + // fontFamily:projectViewModel.isArabic ? 'Cairo' : 'WorkSans', + // primarySwatch: Colors.blue, + // visualDensity: VisualDensity.adaptivePlatformDensity, + // brightness: Brightness.light, + // pageTransitionsTheme: const PageTransitionsTheme( + // builders: { + // TargetPlatform.android: ZoomPageTransitionsBuilder(), + // TargetPlatform.iOS: CupertinoPageTransitionsBuilder(), + // }, + // ), + // hintColor: Colors.grey[400], + // disabledColor: Colors.grey[300], + // errorColor: Color.fromRGBO(235, 80, 60, 1.0), + // scaffoldBackgroundColor: Color(0xffEEEEEE), + // textSelectionColor: Color.fromRGBO(80, 100, 253, 0.5), + // textSelectionHandleColor: Colors.grey, + // canvasColor: Colors.white, + // backgroundColor: Colors.white, + // highlightColor: Colors.grey[100].withOpacity(0.4), + // splashColor: Colors.transparent, + // primaryColor: Color(0xff40ACC9), + // bottomSheetTheme: BottomSheetThemeData(backgroundColor: Color(0xffE0E0E0)), + // cursorColor: Colors.grey, + // cardColor: Colors.white, + // iconTheme: IconThemeData(), + // appBarTheme: AppBarTheme( + // color: Color(0xff40ACC9), + // brightness: Brightness.dark, + // elevation: 10.0, + // actionsIconTheme: IconThemeData( + // color: Color(0xff40ACC9), + // ), + // ), + // ); + // themeNotifier.setTheme(defaultTheme); } void checkUserStatus(token) async { authService @@ -524,8 +526,9 @@ class _LandingPageState extends State with WidgetsBindingObserver { .then((res) => {print(res)}); authService.getDashboard().then((value) => { setState(() { - notificationCount = value['List_PatientDashboard'] - [0]['UnreadPatientNotificationCount'].toString(); + notificationCount = value['List_PatientDashboard'][0] + ['UnreadPatientNotificationCount'] + .toString(); }) }); } @@ -557,6 +560,7 @@ class _LandingPageState extends State with WidgetsBindingObserver { _changeCurrentTab(2); } } + login() async { var data = await sharedPref.getObject(IMEI_USER_DATA); sharedPref.remove(REGISTER_DATA_FOR_LOGIIN); diff --git a/lib/widgets/others/app_scaffold_widget.dart b/lib/widgets/others/app_scaffold_widget.dart index 6f3481eb..d15cde99 100644 --- a/lib/widgets/others/app_scaffold_widget.dart +++ b/lib/widgets/others/app_scaffold_widget.dart @@ -135,7 +135,7 @@ class AppScaffold extends StatelessWidget { // return body; //Stack(children: [body, buildAppLoaderWidget(isLoading)]); return Stack(children: [ body, - isHelp==true ? RobotIcon() : Container() + isHelp==true && Provider.of(context, listen: false).havePrivilege(77) ? RobotIcon() : Container() ]); } } diff --git a/lib/widgets/others/floating_button_search.dart b/lib/widgets/others/floating_button_search.dart index 5608f517..1b474339 100644 --- a/lib/widgets/others/floating_button_search.dart +++ b/lib/widgets/others/floating_button_search.dart @@ -221,6 +221,8 @@ class _FloatingSearchButton extends State reconizedWord = result.recognizedWords; event.setValue({"searchText": reconizedWord}); if (result.finalResult == true) { + RoboSearch.closeAlertDialog(context); + // setState(() { // setState(() { From 77423139235dfa8986508705c9d5e7893b19fd72 Mon Sep 17 00:00:00 2001 From: Sultan Khan Date: Wed, 9 Dec 2020 20:56:48 +0300 Subject: [PATCH 22/71] voice command --- lib/locator.dart | 2 + lib/widgets/others/app_scaffold_widget.dart | 57 +++++++++---------- .../others/floating_button_search.dart | 14 +++-- 3 files changed, 40 insertions(+), 33 deletions(-) diff --git a/lib/locator.dart b/lib/locator.dart index b0b999be..68557d01 100644 --- a/lib/locator.dart +++ b/lib/locator.dart @@ -50,6 +50,7 @@ import 'core/service/medical/reports_monthly_service.dart'; import 'core/service/medical/vital_sign_service.dart'; import 'core/service/parmacyModule/order-preview-service.dart'; import 'core/service/notifications_service.dart'; +import 'core/service/privilege_service.dart'; import 'core/viewModels/AlHabibMedicalService/cmc_view_model.dart'; import 'core/service/parmacyModule/parmacy_module_service.dart'; @@ -153,6 +154,7 @@ void setupLocator() { locator.registerLazySingleton(() => OrderPreviewService()); locator.registerLazySingleton(() => CustomerAddressesService()); // locator.registerLazySingleton(() => TermsConditionService()); + locator.registerLazySingleton(() => PrivilegeService()); /// View Model locator.registerFactory(() => HospitalViewModel()); diff --git a/lib/widgets/others/app_scaffold_widget.dart b/lib/widgets/others/app_scaffold_widget.dart index d15cde99..228407b5 100644 --- a/lib/widgets/others/app_scaffold_widget.dart +++ b/lib/widgets/others/app_scaffold_widget.dart @@ -94,37 +94,37 @@ class AppScaffold extends StatelessWidget { appBar = preferredSize == 0 ? appBarWidget : PreferredSize( - child: appBarWidget, - preferredSize: Size.fromHeight(preferredSize)); + child: appBarWidget, + preferredSize: Size.fromHeight(preferredSize)); } else { appBar = this.appBarWidget; } return Scaffold( - backgroundColor: - backgroundColor ?? Theme.of(context).scaffoldBackgroundColor, - appBar: appBar, - body: (!Provider.of(context, listen: false).isLogin && - isShowDecPage) - ? NotAutPage( - title: appBarTitle, - description: description, - infoList: infoList, - imagesInfo: imagesInfo, - ) - : baseViewModel != null - ? NetworkBaseView( - child: buildBodyWidget(context), - baseViewModel: baseViewModel, - ) - : buildBodyWidget(context), - bottomSheet: bottomSheet + backgroundColor: + backgroundColor ?? Theme.of(context).scaffoldBackgroundColor, + appBar: appBar, + body: (!Provider.of(context, listen: false).isLogin && + isShowDecPage) + ? NotAutPage( + title: appBarTitle, + description: description, + infoList: infoList, + imagesInfo: imagesInfo, + ) + : baseViewModel != null + ? NetworkBaseView( + child: buildBodyWidget(context), + baseViewModel: baseViewModel, + ) + : buildBodyWidget(context), + bottomSheet: bottomSheet - //floatingActionButton: floatingActionButton ?? floatingActionButton, - // bottomNavigationBar: - // this.isBottomBar == true ? BottomBarSearch() : SizedBox() - //floatingActionButton: FloatingSearchButton(), - ); + //floatingActionButton: floatingActionButton ?? floatingActionButton, + // bottomNavigationBar: + // this.isBottomBar == true ? BottomBarSearch() : SizedBox() + //floatingActionButton: FloatingSearchButton(), + ); } buildAppLoaderWidget(bool isLoading) { @@ -133,10 +133,9 @@ class AppScaffold extends StatelessWidget { buildBodyWidget(context) { // return body; //Stack(children: [body, buildAppLoaderWidget(isLoading)]); - return Stack(children: [ - body, - isHelp==true && Provider.of(context, listen: false).havePrivilege(77) ? RobotIcon() : Container() - ]); + //&& Provider.of(context, listen: false).havePrivilege(77) need to added + return Stack( + children: [body, isHelp == true ? RobotIcon() : Container()]); } } diff --git a/lib/widgets/others/floating_button_search.dart b/lib/widgets/others/floating_button_search.dart index 1b474339..f2ffb2d2 100644 --- a/lib/widgets/others/floating_button_search.dart +++ b/lib/widgets/others/floating_button_search.dart @@ -217,11 +217,11 @@ class _FloatingSearchButton extends State void resultListener(SpeechRecognitionResult result) { // lastWords = "${result.recognizedWords} - ${result.finalResult}"; - print(result); reconizedWord = result.recognizedWords; event.setValue({"searchText": reconizedWord}); if (result.finalResult == true) { - RoboSearch.closeAlertDialog(context); + + // setState(() { @@ -230,6 +230,7 @@ class _FloatingSearchButton extends State // }); Future.delayed(const Duration(seconds: 1), () { _speak(reconizedWord); + RoboSearch.closeAlertDialog(context); }); } //}); @@ -942,9 +943,14 @@ class RoboSearch { Expanded( flex: 1, child: Center( - child: Text(searchText != null + child: Text(searchText != null && searchText != 'null' ? searchText - : 'Try saying something'))) + : 'Try saying something'))), + + // searchText == 'null' ? Center(child:RaisedButton(child: Text('Retry'), onPressed: (){ + // //RoboSearch.closeAlertDialog(context); + // new FloatingSearchButton().createState().startVoiceSearch(); + // }, )) :SizedBox() ]), )); }), From 188b72bb90cbfae190cdba7f71a4f17c00651ce0 Mon Sep 17 00:00:00 2001 From: Sultan Khan Date: Thu, 10 Dec 2020 11:13:54 +0300 Subject: [PATCH 23/71] voice command --- lib/pages/landing/landing_page.dart | 23 +++++---- lib/pages/medical/medical_profile_page.dart | 47 ++++++++++--------- .../bottom_navigation/bottom_nav_bar.dart | 2 +- 3 files changed, 40 insertions(+), 32 deletions(-) diff --git a/lib/pages/landing/landing_page.dart b/lib/pages/landing/landing_page.dart index e8f9a923..43d345e0 100644 --- a/lib/pages/landing/landing_page.dart +++ b/lib/pages/landing/landing_page.dart @@ -76,9 +76,11 @@ class _LandingPageState extends State with WidgetsBindingObserver { LocationUtils locationUtils; _changeCurrentTab(int tab) { setState(() { - currentTab = tab; + currentTab = tab; + if (tab != 0) pageController.jumpToPage(tab); - + else + this.triggerRobot(); }); } @@ -431,7 +433,7 @@ class _LandingPageState extends State with WidgetsBindingObserver { children: [ HomePage( goToMyProfile: () { - // _changeCurrentTab(1); + // _changeCurrentTab(1); }, ), MedicalProfilePage(), @@ -445,13 +447,14 @@ class _LandingPageState extends State with WidgetsBindingObserver { index: currentTab, ), floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, - floatingActionButton: (projectViewModel.havePrivilege(34) && currentTab == 0) - ? FloatingButton( - elevation: true, - onTap: () { - _changeCurrentTab(2); - }) - : null); + floatingActionButton: + (projectViewModel.havePrivilege(34) && currentTab == 0) + ? FloatingButton( + elevation: true, + onTap: () { + _changeCurrentTab(2); + }) + : null); } triggerRobot() { diff --git a/lib/pages/medical/medical_profile_page.dart b/lib/pages/medical/medical_profile_page.dart index d7c479d6..ff2d4587 100644 --- a/lib/pages/medical/medical_profile_page.dart +++ b/lib/pages/medical/medical_profile_page.dart @@ -48,15 +48,19 @@ class MedicalProfilePage extends StatefulWidget { class _MedicalProfilePageState extends State { var authProvider = new AuthProvider(); - List medical=List(); + List medical = List(); ProjectViewModel projectViewModel; @override Widget build(BuildContext context) { - projectViewModel = Provider.of(context); + projectViewModel = Provider.of(context); var appoCountProvider = Provider.of(context); - List myMedicalList = Utils.myMedicalList(projectViewModel: projectViewModel,context: context,count: appoCountProvider.count,isLogin: projectViewModel.isLogin); - return BaseView( + List myMedicalList = Utils.myMedicalList( + projectViewModel: projectViewModel, + context: context, + count: appoCountProvider.count, + isLogin: projectViewModel.isLogin); + return BaseView( onModelReady: (model) => model.getAppointmentHistory(), builder: (_, model, widget) => AppScaffold( isShowDecPage: false, @@ -96,20 +100,25 @@ class _MedicalProfilePageState extends State { ], ), ), - SizedBox(height: 50,), + SizedBox( + height: 50, + ), Padding( padding: EdgeInsets.symmetric(vertical: 5.0), child: GridView.builder( shrinkWrap: true, primary: false, physics: NeverScrollableScrollPhysics(), - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + gridDelegate: + SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, - childAspectRatio: MediaQuery.of(context).size.width / (MediaQuery.of(context).size.height / 2.40), + childAspectRatio: MediaQuery.of(context) + .size + .width / + (MediaQuery.of(context).size.height / 2.40), ), itemCount: myMedicalList.length, itemBuilder: (BuildContext context, int index) { - return myMedicalList[index]; }, ), @@ -117,8 +126,7 @@ class _MedicalProfilePageState extends State { ], ), SizedBox( - height: - MediaQuery.of(context).size.height * 0.12, + height: MediaQuery.of(context).size.height * 0.12, ), if (model.user != null && model.isLogin) Positioned( @@ -182,19 +190,16 @@ class _MedicalProfilePageState extends State { ); } - fullMedicalData(){ - if(projectViewModel.havePrivilege(5)) - {} + fullMedicalData() { + if (projectViewModel.havePrivilege(5)) {} } } -class Medical{ - - final String title; - final String imagePath; - final String subTitle; - final Widget page; - - Medical({this.title, this.imagePath, this.subTitle, this.page}); +class Medical { + final String title; + final String imagePath; + final String subTitle; + final Widget page; + Medical({this.title, this.imagePath, this.subTitle, this.page}); } diff --git a/lib/widgets/bottom_navigation/bottom_nav_bar.dart b/lib/widgets/bottom_navigation/bottom_nav_bar.dart index f0b9ea03..3bc7d0f1 100644 --- a/lib/widgets/bottom_navigation/bottom_nav_bar.dart +++ b/lib/widgets/bottom_navigation/bottom_nav_bar.dart @@ -93,7 +93,7 @@ class _BottomNavBarState extends State { currentIndex: 4, name: TranslationBase.of(context).todoList, ), - if (widget.index == 0 && projectViewModel.havePrivilege(77)) + if (projectViewModel.havePrivilege(77)) BottomNavigationItem( icon: DQIcons.roboticon, activeIcon: DQIcons.roboticon, From 557b8e814f34164f880671b495ee52ceb5d5c637 Mon Sep 17 00:00:00 2001 From: Sultan Khan Date: Sun, 13 Dec 2020 10:01:16 +0300 Subject: [PATCH 24/71] voice command --- lib/config/shared_pref_kay.dart | 2 + lib/pages/landing/landing_page.dart | 5 +- lib/pages/medical/medical_profile_page.dart | 1 + .../bottom_navigation/bottom_nav_bar.dart | 4 +- lib/widgets/drawer/app_drawer_widget.dart | 4 +- lib/widgets/others/app_scaffold_widget.dart | 18 +++- .../others/floating_button_search.dart | 91 ++++++++++--------- 7 files changed, 75 insertions(+), 50 deletions(-) diff --git a/lib/config/shared_pref_kay.dart b/lib/config/shared_pref_kay.dart index e64e7ef4..39e2649d 100644 --- a/lib/config/shared_pref_kay.dart +++ b/lib/config/shared_pref_kay.dart @@ -22,3 +22,5 @@ const MAIN_USER = 'main-user'; const WEATHER = 'weather'; const PHARMACY_LAST_VISITED_PRODUCTS = 'last-visited'; const PHARMACY_CUSTOMER_ID = 'costumer-id'; +const IS_ROBOT_VISIBLE = 'robot-visible'; +const IS_ROBOT_INIT = 'robot-init'; diff --git a/lib/pages/landing/landing_page.dart b/lib/pages/landing/landing_page.dart index 43d345e0..2773aac3 100644 --- a/lib/pages/landing/landing_page.dart +++ b/lib/pages/landing/landing_page.dart @@ -77,10 +77,7 @@ class _LandingPageState extends State with WidgetsBindingObserver { _changeCurrentTab(int tab) { setState(() { currentTab = tab; - if (tab != 0) - pageController.jumpToPage(tab); - else - this.triggerRobot(); + if (tab != 0) pageController.jumpToPage(tab); }); } diff --git a/lib/pages/medical/medical_profile_page.dart b/lib/pages/medical/medical_profile_page.dart index ff2d4587..73e60ce6 100644 --- a/lib/pages/medical/medical_profile_page.dart +++ b/lib/pages/medical/medical_profile_page.dart @@ -65,6 +65,7 @@ class _MedicalProfilePageState extends State { builder: (_, model, widget) => AppScaffold( isShowDecPage: false, baseViewModel: model, + isHelp: true, body: Container( child: SingleChildScrollView( child: Column( diff --git a/lib/widgets/bottom_navigation/bottom_nav_bar.dart b/lib/widgets/bottom_navigation/bottom_nav_bar.dart index 3bc7d0f1..a6b61717 100644 --- a/lib/widgets/bottom_navigation/bottom_nav_bar.dart +++ b/lib/widgets/bottom_navigation/bottom_nav_bar.dart @@ -11,6 +11,8 @@ import 'package:provider/provider.dart'; import '../../d_q_icons_icons.dart'; import 'bottom_navigation_item.dart'; +import 'package:diplomaticquarterapp/services/authentication/auth_provider.dart'; +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; class BottomNavBar extends StatefulWidget { final ValueChanged changeIndex; @@ -24,7 +26,7 @@ class BottomNavBar extends StatefulWidget { class _BottomNavBarState extends State { int _index = 0; var event = RobotProvider(); - _changeIndex(int index) { + _changeIndex(int index) async { widget.changeIndex(index); if (_index == 0) { event.setValue({'isRobotVisible': 'true'}); diff --git a/lib/widgets/drawer/app_drawer_widget.dart b/lib/widgets/drawer/app_drawer_widget.dart index 9a4e3d1f..379c4cc8 100644 --- a/lib/widgets/drawer/app_drawer_widget.dart +++ b/lib/widgets/drawer/app_drawer_widget.dart @@ -141,9 +141,7 @@ class _AppDrawerState extends State { TranslationBase.of(context).arabicChange, Icons.translate), onTap: () { - // Navigator.of(context).pushNamed( - // WELCOME_LOGIN, - // ); + sharedPref.setBool(IS_ROBOT_INIT, null); if (projectProvider.isArabic) { projectProvider.changeLanguage('en'); } else { diff --git a/lib/widgets/others/app_scaffold_widget.dart b/lib/widgets/others/app_scaffold_widget.dart index 228407b5..4f94baa4 100644 --- a/lib/widgets/others/app_scaffold_widget.dart +++ b/lib/widgets/others/app_scaffold_widget.dart @@ -26,6 +26,8 @@ import '../progress_indicator/app_loader_widget.dart'; import 'arrow_back.dart'; import 'network_base_view.dart'; import 'not_auh_page.dart'; +import 'package:diplomaticquarterapp/services/authentication/auth_provider.dart'; +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; class AppScaffold extends StatelessWidget { final String appBarTitle; @@ -240,7 +242,7 @@ class RobotIcon extends StatefulWidget { class _RobotIcon extends State { var event = RobotProvider(); - bool isAnimation = true; + bool isAnimation = false; @override void initState() { @@ -253,6 +255,10 @@ class _RobotIcon extends State { }); } }); + + setState(() { + setAnimation(); + }); super.initState(); } @@ -312,4 +318,14 @@ class _RobotIcon extends State { right: -30, bottom: 50); } + + setAnimation() async { + //await sharedPref.getBool(IS_ROBOT_VISIBLE) || + var animation = + await sharedPref.getBool(IS_ROBOT_INIT) == null ? true : false; + + setState(() { + this.isAnimation = animation; + }); + } } diff --git a/lib/widgets/others/floating_button_search.dart b/lib/widgets/others/floating_button_search.dart index f2ffb2d2..b954069f 100644 --- a/lib/widgets/others/floating_button_search.dart +++ b/lib/widgets/others/floating_button_search.dart @@ -101,7 +101,7 @@ class _FloatingSearchButton extends State var sharedPref = new AppSharedPreferences(); bool _hasSpeech = false; ProjectViewModel projectProvider; - bool isAnimationEnable = true; + bool isAnimationEnable = false; AnimationController controller; Animation offset; String networkImage; @@ -111,29 +111,37 @@ class _FloatingSearchButton extends State AnimationController(vsync: this, duration: Duration(seconds: 1)); offset = Tween(begin: Offset.zero, end: Offset(0.0, 1.0)) .animate(controller); - controller.reverse(); initialSpeak(); Future.delayed(const Duration(seconds: 2), () { requestPermissions(); getUserData(); }); - controller.reverse(); + event.controller.stream.listen((p) { if (p['isRobotVisible'] == 'true') { if (this.mounted) { setState(() { + sharedPref.setBool(IS_ROBOT_VISIBLE, true); controller.reverse(); }); } } }); + event.controller.stream.listen((p) { + if (p['startPopUp'] == 'true') { + if (this.mounted) { + new RoboSearch(context: context).showAlertDialog(context); + initSpeechState().then((value) => {startVoiceSearch()}); + } + } + }); super.initState(); } @override void didUpdateWidget(FloatingSearchButton oldWidget) { - // super.didUpdateWidget(oldWidget); + // super.didUpdateWidget(oldWidget); // event.controller.stream.listen((p) { // if (p['animationEnable'] != 'false') { // initialSpeak(); @@ -171,7 +179,6 @@ class _FloatingSearchButton extends State : 'assets/images/gif/robot-idle.gif'), ), onTap: () { - new RoboSearch(context: context).showAlertDialog(context); initSpeechState().then((value) => {startVoiceSearch()}); }, @@ -184,7 +191,7 @@ class _FloatingSearchButton extends State setState(() { if (this.mounted) { controller.forward(); - //isShow = false; + sharedPref.setBool(IS_ROBOT_VISIBLE, false); } }); }, @@ -220,26 +227,14 @@ class _FloatingSearchButton extends State reconizedWord = result.recognizedWords; event.setValue({"searchText": reconizedWord}); if (result.finalResult == true) { - - - - // setState(() { - - // setState(() { - // searchText = reconizedWord; - // }); Future.delayed(const Duration(seconds: 1), () { _speak(reconizedWord); RoboSearch.closeAlertDialog(context); }); } - //}); } Future _speak(reconizedWord) async { - // Navigator.of(AppGlobal.context).pop(); - //await flutterTts.speak(reconizedWord); - //RoboSearch.closeAlertDialog(context); getPages(reconizedWord); } @@ -799,13 +794,15 @@ class _FloatingSearchButton extends State ); } - speak() async { + speak({isInit}) async { setState(() { this.networkImage = results['AnimationURL']; this.isAnimationEnable = true; }); - if (_currentLocaleId == 'en' && results['ReturnMessage'] != null) { + if (Provider.of(context, listen: false).isArabic == + false && + results['ReturnMessage'] != null) { await flutterTts .setVoice({"name": "en-au-x-aub-network", "locale": "en-AU"}); await flutterTts.speak(results['ReturnMessage']); @@ -815,7 +812,7 @@ class _FloatingSearchButton extends State await flutterTts.speak(results['ReturnMessage_Ar']); } - stopAnimation(); + stopAnimation(isInit: isInit); } goToClinic(List ids) { @@ -847,25 +844,32 @@ class _FloatingSearchButton extends State 'ReturnMessage': "Through this service, you will be able to link your family medical files to your medical file so that you can manage their records by login to your medical file." }; - this.speak(); - - if (Provider.of(context, listen: false).isArabic == - false && - results['ReturnMessage'] != null) { - await flutterTts - .setVoice({"name": "en-au-x-aub-network", "locale": "en-AU"}); - await flutterTts.speak(results['ReturnMessage']); - } else if (results['ReturnMessage_Ar'] != null) { - await flutterTts - .setVoice({"name": "ar-xa-x-ard-network", "locale": "ar"}); - await flutterTts.speak(results['ReturnMessage_Ar']); + if (await sharedPref.getBool(IS_ROBOT_INIT) == null) { + this.speak(isInit: true); + controller.reverse(); + } else { + controller.forward(); } + // if (Provider.of(context, listen: false).isArabic == + // false && + // results['ReturnMessage'] != null) { + // await flutterTts + // .setVoice({"name": "en-au-x-aub-network", "locale": "en-AU"}); + // await flutterTts.speak(results['ReturnMessage']); + // } else if (results['ReturnMessage_Ar'] != null) { + // await flutterTts + // .setVoice({"name": "ar-xa-x-ard-network", "locale": "ar"}); + // await flutterTts.speak(results['ReturnMessage_Ar']); + // } - this.isAnimationEnable = true; - stopAnimation(); + //this.isAnimationEnable = true; + //stopAnimation(); } - stopAnimation() { + stopAnimation({isInit}) async { + if (isInit && (await sharedPref.getBool(IS_ROBOT_INIT) == null)) { + sharedPref.setBool(IS_ROBOT_INIT, isInit); + } flutterTts.setCompletionHandler(() => { event.setValue({"animationEnable": 'false'}), setState(() { @@ -946,11 +950,16 @@ class RoboSearch { child: Text(searchText != null && searchText != 'null' ? searchText : 'Try saying something'))), - - // searchText == 'null' ? Center(child:RaisedButton(child: Text('Retry'), onPressed: (){ - // //RoboSearch.closeAlertDialog(context); - // new FloatingSearchButton().createState().startVoiceSearch(); - // }, )) :SizedBox() + searchText == 'null' + ? Center( + child: RaisedButton( + child: Text('Retry'), + onPressed: () { + RoboSearch.closeAlertDialog(context); + event.setValue({'startPopUp': 'true'}); + }, + )) + : SizedBox() ]), )); }), From 2c50402aa8b17a9ca9ee0c7d5f60248ecd3390b2 Mon Sep 17 00:00:00 2001 From: Sultan Khan Date: Sun, 13 Dec 2020 17:25:44 +0300 Subject: [PATCH 25/71] language issue fixed --- lib/core/service/client/base_app_client.dart | 3 ++- lib/pages/DrawerPages/family/my-family.dart | 20 ++------------------ lib/widgets/drawer/app_drawer_widget.dart | 3 +++ 3 files changed, 7 insertions(+), 19 deletions(-) diff --git a/lib/core/service/client/base_app_client.dart b/lib/core/service/client/base_app_client.dart index e7d69a31..89c0775c 100644 --- a/lib/core/service/client/base_app_client.dart +++ b/lib/core/service/client/base_app_client.dart @@ -45,7 +45,8 @@ class BaseAppClient { //Map profile = await sharedPref.getObj(DOCTOR_PROFILE); if (!isExternal) { String token = await sharedPref.getString(TOKEN); - var languageID = await sharedPref.getString(APP_LANGUAGE)?? 'ar'; + print(await sharedPref.getString(APP_LANGUAGE)); + var languageID = await sharedPref.getString(APP_LANGUAGE) ?? 'ar'; var user = await sharedPref.getObject(USER_PROFILE); if (body.containsKey('SetupID')) { body['SetupID'] = body.containsKey('SetupID') diff --git a/lib/pages/DrawerPages/family/my-family.dart b/lib/pages/DrawerPages/family/my-family.dart index 7fc0c546..791c33b3 100644 --- a/lib/pages/DrawerPages/family/my-family.dart +++ b/lib/pages/DrawerPages/family/my-family.dart @@ -666,24 +666,7 @@ class _MyFamily extends State with TickerProviderStateMixin { loginAfter(result, context) async { GifLoaderDialogUtils.hideDialog(context); - // var familyFile = await sharedPref.getObject(FAMILY_FILE); - // var mainUser = await sharedPref.getObject(MAIN_USER); - // result = CheckActivationCode.fromJson(result); - // this.sharedPref.clear(); - // this.sharedPref.setObject(FAMILY_FILE, familyFile); - // this.sharedPref.setObject(MAIN_USER, mainUser); - // result.list.isFamily = true; - // this.sharedPref.setObject(USER_PROFILE, result.list); - // this.sharedPref.setObject(LOGIN_TOKEN_ID, result.logInTokenID); - // this.sharedPref.setString(TOKEN, result.authenticationTokenID); - // - // authenticatedUserObject.isLogin = true; - // appointmentRateViewModel.isLogin = true; - // projectViewModel.isLogin = true; - // //this.checkIfUserAgreedBefore(result), - // Navigator.of(context).pushNamed( - // HOME, - // ); + var currentLang = await sharedPref.getString(APP_LANGUAGE); result = list.CheckActivationCode.fromJson(result); var familyFile = await sharedPref.getObject(FAMILY_FILE); Provider.of(context, listen: false) @@ -695,6 +678,7 @@ class _MyFamily extends State with TickerProviderStateMixin { result.list.isFamily = true; } this.sharedPref.setObject(MAIN_USER, mainUser); + this.sharedPref.setString(APP_LANGUAGE, currentLang); this.sharedPref.setObject(USER_PROFILE, result.list); this.sharedPref.setObject(FAMILY_FILE, familyFile); this.sharedPref.setObject(LOGIN_TOKEN_ID, result.logInTokenID); diff --git a/lib/widgets/drawer/app_drawer_widget.dart b/lib/widgets/drawer/app_drawer_widget.dart index 379c4cc8..5b8f4d5e 100644 --- a/lib/widgets/drawer/app_drawer_widget.dart +++ b/lib/widgets/drawer/app_drawer_widget.dart @@ -463,11 +463,14 @@ class _AppDrawerState extends State { Utils.hideProgressDialog(); result = CheckActivationCode.fromJson(result); var familyFile = await sharedPref.getObject(FAMILY_FILE); + var currentLang = await sharedPref.getString(APP_LANGUAGE); var mainUser = await sharedPref.getObject(MAIN_USER); this.sharedPref.clear(); if (mainUser["PatientID"] != result.list.patientID) { result.list.isFamily = true; } + this.sharedPref.setString(APP_LANGUAGE, currentLang); + this.sharedPref.setObject(MAIN_USER, mainUser); this.sharedPref.setObject(USER_PROFILE, result.list); this.sharedPref.setObject(FAMILY_FILE, familyFile); From c65983bfdbbf89b81943513a5ecd5efa6ba2a957 Mon Sep 17 00:00:00 2001 From: Sultan Khan Date: Tue, 19 Jan 2021 12:29:10 +0300 Subject: [PATCH 26/71] code merged --- .gitignore | 1 + DQKey.jks | Bin 2269 -> 0 bytes Keystore Pass.rtf | 9 - android/app/build.gradle | 57 +- android/app/google-services.json | 28 +- android/app/src/debug/AndroidManifest.xml | 1 - android/app/src/main/AndroidManifest.xml | 31 +- .../diplomaticquarterapp/MainActivity.kt | 22 +- .../geofence/GeoZoneModel.kt | 56 + .../geofence/GeofenceBroadcastReceiver.kt | 13 + .../geofence/GeofenceErrorMessages.kt | 34 + .../GeofenceTransitionsJobIntentService.kt | 106 + .../GeofencingRebootBroadcastReceiver.kt | 27 + .../geofence/HMG_Geofence.kt | 165 ++ .../diplomaticquarterapp/hmgwifi/HMG_Guest.kt | 172 ++ .../hmgwifi/HMG_Internet.kt | 110 + .../cloud/diplomaticquarterapp/hmgwifi/WPA.kt | 105 + .../cloud/diplomaticquarterapp/utils/API.kt | 11 + .../diplomaticquarterapp/utils/FlutterText.kt | 36 + .../diplomaticquarterapp/utils/HMGUtils.kt | 160 ++ .../diplomaticquarterapp/utils/HMG_Wifi_.kt | 351 +++ .../utils/PlatformBridge.kt | 127 ++ .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 3287 -> 544 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 1957 -> 442 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 4315 -> 721 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 7926 -> 1031 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 11608 -> 1443 bytes android/app/src/main/res/values/strings.xml | 16 + android/app/src/profile/AndroidManifest.xml | 1 - android/build.gradle | 4 +- android/gradle.properties | 3 +- .../gradle/wrapper/gradle-wrapper.properties | 4 +- assets/images/DQ/logo.png | Bin 0 -> 6505 bytes assets/images/DQ/logo_big.png | Bin 0 -> 38890 bytes assets/images/appointment_booking.png | Bin 0 -> 6175 bytes assets/images/appointment_booking_en.png | Bin 0 -> 6175 bytes assets/images/book_appointment_ar.png | Bin 0 -> 5709 bytes assets/images/book_appointment_arabic.png | Bin 0 -> 5709 bytes assets/images/booking_ar.png | Bin 0 -> 7967 bytes assets/images/booking_en.png | Bin 0 -> 8589 bytes assets/images/check-in.png | Bin 0 -> 2050 bytes assets/images/comments.png | Bin 0 -> 11678 bytes assets/images/device_icon.png | Bin 0 -> 21635 bytes .../images/{ => medical}/vital_sign_icon.png | Bin assets/images/new-design/check-in.png | Bin 1326 -> 2050 bytes assets/images/new-design/covid-19-car.svg | 26 + assets/images/new-design/empty_box.png | Bin 0 -> 4247 bytes .../images/new-design/liveCare_white_logo.svg | 40 + .../new-design/livecare_arabic_logo.svg | 39 + .../images/new-design/livecare_white_logo.png | Bin 0 -> 9986 bytes assets/images/no-data-found.png | Bin 0 -> 1647 bytes assets/images/no_image.png | Bin 0 -> 18755 bytes assets/images/offer.png | Bin 0 -> 2631 bytes assets/images/offer_ar.png | Bin 0 -> 2626 bytes assets/images/online_payment_icon.png | Bin 3166 -> 10046 bytes assets/images/pharmacy/Group 1206.svg | 14 + assets/images/pharmacy/Group 1207.svg | 17 + assets/images/pharmacy/Logo Parmacy-green.png | Bin 0 -> 38549 bytes .../images/pharmacy/aramex_shipping_logo.svg | 14 + assets/images/pharmacy/arrow-left-png.png | Bin 0 -> 2208 bytes assets/images/pharmacy/arrow-left.png | Bin 0 -> 2208 bytes assets/images/pharmacy/arrow-right-png.png | Bin 0 -> 2214 bytes assets/images/pharmacy/arrow.png | Bin 0 -> 2214 bytes assets/images/pharmacy/arrow_lef.png | Bin 0 -> 2214 bytes assets/images/pharmacy/arrow_left.svg | 6 + assets/images/pharmacy/arrow_right.svg | 6 + assets/images/pharmacy/check_icon.svg | 6 + assets/images/pharmacy/compare.png | Bin 0 -> 704 bytes assets/images/pharmacy/contact_us_icon.svg | 10 + assets/images/pharmacy/credit_card_icon.svg | 6 + assets/images/pharmacy/delete_red_icon.svg | 8 + assets/images/pharmacy/edit_icon.svg | 3 + assets/images/pharmacy/empty_box.svg | 18 + .../pharmacy/hmg_shipping_greenlogo.svg | 25 + assets/images/pharmacy/hmg_shipping_logo.svg | 17 + assets/images/pharmacy/lakum_icon.svg | 8 + .../pharmacy/medication_refill_icon.svg | 32 + assets/images/pharmacy/mobile_number_icon.svg | 3 + assets/images/pharmacy/my_family_icon.svg | 19 + .../images/pharmacy/my_prescription_icon.svg | 54 + assets/images/pharmacy/orders_icon.svg | 8 + assets/images/pharmacy/our_locations_icon.svg | 10 + assets/images/pharmacy/pill_reminder_icon.svg | 49 + assets/images/pharmacy/quote_end.svg | 8 + assets/images/pharmacy/quote_start.svg | 8 + assets/images/pharmacy/review_icon.svg | 6 + .../pharmacy/shipping_addresses_icon.svg | 6 + assets/images/pharmacy/shipping_mark_icon.svg | 16 + .../images/pharmacy/shipping_truck_icon.svg | 34 + assets/images/pharmacy/success_check_icon.svg | 6 + .../images/pharmacy/success_review_icon.svg | 24 + assets/images/pharmacy/terms.png | Bin 0 -> 1782 bytes assets/images/pharmacy/user.svg | 3 + assets/images/pharmacy/user_icon.svg | 3 + assets/images/pharmacy/wishklist_icon.svg | 3 + assets/images/pharmacy/wishlist_icon.svg | 6 + .../pharmacy_module/ic_payment_option.png | Bin 0 -> 447 bytes .../pharmacy_module/ic_shipping_address.png | Bin 0 -> 383 bytes .../pharmacy_module/ic_shipping_mark.png | Bin 0 -> 782 bytes .../pharmacy_module/ic_shipping_truck.png | Bin 0 -> 503 bytes .../lakum/Account_activation_icon.png | Bin 0 -> 1123 bytes .../lakum/Lakum_transfer_icon.png | Bin 0 -> 1572 bytes .../pharmacy_module/lakum/expired_icon.png | Bin 0 -> 737 bytes .../pharmacy_module/lakum/inactive_cross.png | Bin 0 -> 387 bytes .../lakum/lakum_card_front_bg.png | Bin 0 -> 89083 bytes .../pharmacy_module/lakum/lakum_checkout.png | Bin 0 -> 534 bytes .../lakum/waiting_gained_icon.png | Bin 0 -> 373 bytes .../lakum/will_be_expired_icon.png | Bin 0 -> 648 bytes .../payment/LogoParmacyGreen.png | Bin 0 -> 38549 bytes .../payment/aramex_shipping_logo.png | Bin 0 -> 1385 bytes .../payment/hmg_shipping_logo.png | Bin 0 -> 1821 bytes .../pharmacy_module/payment/installment.png | Bin 0 -> 41513 bytes .../images/pharmacy_module/payment/mada.png | Bin 0 -> 17068 bytes .../pharmacy_module/payment/mastercard.png | Bin 0 -> 59419 bytes .../images/pharmacy_module/payment/sadad.png | Bin 0 -> 23578 bytes .../images/pharmacy_module/payment/visa.png | Bin 0 -> 83030 bytes .../images/pharmacy_module/payment_image.png | Bin 0 -> 4982 bytes assets/images/powerd-by.jpg | Bin 0 -> 150482 bytes assets/images/progress-loading-red.gif | Bin 0 -> 142880 bytes help/.gitignore | 41 + help/.metadata | 10 + help/README.md | 16 + help/android/.gitignore | 11 + help/android/app/build.gradle | 63 + .../android/app/src/debug/AndroidManifest.xml | 7 + help/android/app/src/main/AndroidManifest.xml | 47 + .../kotlin/com/example/help/MainActivity.kt | 6 + .../main/res/drawable/launch_background.xml | 12 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 544 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 442 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 721 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 1031 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 1443 bytes .../app/src/main/res/values/styles.xml | 18 + .../app/src/profile/AndroidManifest.xml | 7 + help/android/build.gradle | 31 + help/android/gradle.properties | 3 + .../gradle/wrapper/gradle-wrapper.properties | 6 + help/android/settings.gradle | 11 + help/ios/.gitignore | 32 + help/ios/Flutter/AppFrameworkInfo.plist | 26 + help/ios/Flutter/Debug.xcconfig | 1 + help/ios/Flutter/Release.xcconfig | 1 + help/ios/Runner.xcodeproj/project.pbxproj | 495 +++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../xcshareddata/xcschemes/Runner.xcscheme | 91 + .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + help/ios/Runner/AppDelegate.swift | 13 + .../AppIcon.appiconset/Contents.json | 122 ++ .../Icon-App-1024x1024@1x.png | Bin 0 -> 10932 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 0 -> 564 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 0 -> 1283 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 0 -> 1588 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 0 -> 1025 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 0 -> 1716 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 0 -> 1920 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 0 -> 1283 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 0 -> 1895 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 0 -> 2665 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 0 -> 2665 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 0 -> 3831 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 0 -> 1888 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 0 -> 3294 bytes .../Icon-App-83.5x83.5@2x.png | Bin 0 -> 3612 bytes .../LaunchImage.imageset/Contents.json | 23 + .../LaunchImage.imageset/LaunchImage.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/README.md | 5 + .../Runner/Base.lproj/LaunchScreen.storyboard | 37 + help/ios/Runner/Base.lproj/Main.storyboard | 26 + help/ios/Runner/Info.plist | 48 + help/ios/Runner/Runner-Bridging-Header.h | 1 + help/lib/main.dart | 117 + help/pubspec.yaml | 76 + help/test/widget_test.dart | 32 + ios/.gitignore | 2 - ios/Flutter/.last_build_id | 2 +- ios/Flutter/AppFrameworkInfo.plist | 2 +- ios/GoogleService-Info.plist | 36 + ios/Podfile | 87 +- ios/Podfile.lock | 455 ++++ ios/Runner.xcodeproj/project.pbxproj | 697 ++++++ .../xcshareddata/xcschemes/Runner.xcscheme | 2 +- .../contents.xcworkspacedata | 10 + .../xcshareddata/WorkspaceSettings.xcsettings | 2 - ios/Runner/AppDelegate.swift | 46 +- .../AppIcon.appiconset/Contents.json | 123 +- .../Icon-App-1024x1024@1x.png | Bin 0 -> 10932 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 0 -> 564 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 0 -> 1283 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 0 -> 1588 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 0 -> 1025 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 0 -> 1716 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 0 -> 1920 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 0 -> 1283 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 0 -> 1895 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 0 -> 2665 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 0 -> 2665 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 0 -> 3831 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 0 -> 1888 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 0 -> 3294 bytes .../Icon-App-83.5x83.5@2x.png | Bin 0 -> 3612 bytes .../LaunchImage.imageset/Contents.json | 23 + .../LaunchImage.imageset/LaunchImage.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/README.md | 5 + ios/Runner/Base.lproj/Main.storyboard | 17 +- ios/Runner/Base.lproj/Main_Custom.storyboard | 102 + ios/Runner/Controllers/MainFlutterVC.swift | 118 + ios/Runner/GoogleService-Info.plist | 36 + ios/Runner/GuestPOC_Certificate.cer | Bin 0 -> 1596 bytes ios/Runner/GuestPOC_Certificate.p12 | Bin 0 -> 5413 bytes ios/Runner/Helper/API.swift | 17 + ios/Runner/Helper/Extensions.swift | 132 ++ ios/Runner/Helper/GeoZoneModel.swift | 67 + ios/Runner/Helper/GlobalHelper.swift | 85 + ios/Runner/Helper/HMGPlatformBridge.swift | 137 ++ ios/Runner/Helper/HMG_Geofence.swift | 189 ++ ios/Runner/Helper/LocalizedFromFlutter.swift | 22 + ios/Runner/Info.plist | 48 +- ios/Runner/Runner.entitlements | 6 + ios/Runner/WifiConnect/HMG_GUEST.swift | 77 + ios/Runner/WifiConnect/HMG_GUEST_bkp.swift | 129 ++ ios/Runner/WifiConnect/HMG_Internet.swift | 193 ++ ios/Runner/WifiConnect/HMG_Wifi.swift | 172 ++ ios/gpx.gpx | 1 + lib/Constants.dart | 3 + lib/config/config.dart | 113 +- lib/config/localized_values.dart | 449 +++- lib/config/shared_pref_kay.dart | 6 +- lib/core/model/ImagesInfo.dart | 3 +- lib/core/model/er/PickUpRequestPresOrder.dart | 4 +- .../requests/GeoZonesRequestModel.dart | 11 + .../requests/LogGeoZoneRequestModel.dart | 12 + .../responses/GeoZonesResponseModel.dart | 62 + .../responses/LogGeoZoneResponseModel.dart | 26 + .../insurance/Insurance_card_details.dart | 88 + ....dart => insurance_card_update_model.dart} | 0 lib/core/model/labs/LabOrderResult.dart | 88 + lib/core/model/labs/lab_result.dart | 11 +- lib/core/model/labs/patient_lab_orders.dart | 6 +- .../OffersCategoriesRequestModel.dart | 11 + .../requests/OffersProductsRequestModel.dart | 12 + .../OfferCategoriesResponseModel.dart | 65 + .../responses/OfferProductsResponseModel.dart | 235 ++ lib/core/model/pharmacies/Addresses.dart | 6 +- lib/core/model/pharmacies/BillingAddress.dart | 84 + lib/core/model/pharmacies/Country.dart | 32 + lib/core/model/pharmacies/Customer.dart | 106 +- .../pharmacies/LacumAccountInformation.dart | 1926 +++++++++++++++++ .../LakumInquiryInformationObjVersion.dart | 179 ++ .../model/pharmacies/ListUserAgreement.dart | 28 + .../pharmacies/PharmacyAddressesModel.dart | 170 ++ .../model/pharmacies/PharmacyProduct.dart | 487 ++++- .../pharmacies/PointsAmountPerMonth.dart | 42 + .../model/pharmacies/PointsAmountPerYear.dart | 38 + .../model/pharmacies/PointsAmountPerday.dart | 42 + lib/core/model/pharmacies/PointsDetails.dart | 57 + lib/core/model/pharmacies/ShippingOption.dart | 97 + lib/core/model/pharmacies/ShoppingCart.dart | 115 + .../pharmacies/ShoppingCartResponse.dart | 55 + lib/core/model/pharmacies/Specifications.dart | 36 + lib/core/model/pharmacies/order_model.dart | 1456 +++++++++++++ .../pharmacies/payment-checkout-data.dart | 21 + .../pharmacies/pharmacies_list_model.dart | 4 +- lib/core/model/pharmacy/brands_model.dart | 24 + .../pharmacy/categorise_parent_model.dart | 75 + .../model/pharmacy/final_products_model.dart | 184 ++ .../model/pharmacy/offer_products_model.dart | 579 +++++ lib/core/model/pharmacy/offers_model.dart | 175 ++ .../model/pharmacy/parent_products_model.dart | 566 +++++ .../model/pharmacy/pharmacy_categorise.dart | 103 + lib/core/model/pharmacy/scan_qr_model.dart | 584 +++++ .../model/pharmacy/sub_categories_model.dart | 75 + .../model/pharmacy/sub_products_model.dart | 562 +++++ .../model/prescriptions/Prescriptions.dart | 5 +- .../request_prescription_report.dart | 2 +- lib/core/model/radiology/final_radiology.dart | 5 +- lib/core/model/reports/Reports.dart | 76 +- lib/core/model/search_products_model.dart | 185 ++ lib/core/model/sick_leave/sick_leave.dart | 4 +- lib/core/model/weahter/weather_model.dart | 103 +- .../customer_addresses_service.dart | 25 +- .../e_referral_service.dart | 120 +- lib/core/service/AuthenticatedUserObject.dart | 10 +- .../childvaccines/add_new_child_service.dart | 7 + .../childvaccines/delete_baby_service.dart | 43 +- .../get_vaccinations_item_services.dart | 27 + .../user_information_service.dart | 40 +- .../vaccination_table_service.dart | 15 +- lib/core/service/client/base_app_client.dart | 138 +- .../service/contactus/livechat_service.dart | 1 + .../geofencing/GeofencingServices.dart | 66 + lib/core/service/hospital_service.dart | 5 +- lib/core/service/insurance_service.dart | 45 +- .../medical/PatientSickLeaveService.dart | 10 +- lib/core/service/medical/labs_service.dart | 35 +- .../service/medical/my_balance_service.dart | 6 + .../medical/prescriptions_service.dart | 1 + .../service/medical/radiology_service.dart | 2 +- lib/core/service/medical/reports_service.dart | 69 +- .../service/medical/vital_sign_service.dart | 16 +- lib/core/service/offers_service.dart | 56 + .../PackagesOffersServices.dart | 51 + .../lacum-registration-service.dart | 50 + .../service/parmacyModule/lacum-service.dart | 133 ++ .../parmacyModule/lacum-transfer-service.dart | 57 + .../parmacyModule/order-preview-service.dart | 237 +- .../parmacyModule/parmacy_module_service.dart | 72 +- .../terms-condition-service.dart | 33 + lib/core/service/pharmacies_service.dart | 46 +- .../service/pharmacy_categorise_service.dart | 225 ++ lib/core/service/weather_service.dart | 7 +- .../AlHabibMedicalService/cmc_view_model.dart | 1 + .../e_referral_view_model.dart | 65 +- .../appointment_rate_view_model.dart | 2 +- lib/core/viewModels/base_view_model.dart | 7 +- .../add_new_child_view_model.dart | 7 + .../child_vaccines_view_model.dart | 23 +- .../user_information_view_model.dart | 14 +- .../vaccination_table_view_model.dart | 25 +- lib/core/viewModels/dashboard_view_model.dart | 13 +- .../feedback/feedback_view_model.dart | 53 - .../viewModels/insurance_card_View_model.dart | 11 +- .../viewModels/medical/labs_view_model.dart | 50 +- .../medical/my_balance_view_model.dart | 8 +- .../medical/prescriptions_view_model.dart | 3 +- .../medical/radiology_view_model.dart | 4 +- .../medical/reports_monthly_view_model.dart | 32 +- .../medical/reports_view_model.dart | 4 +- .../medical/vital_sign_view_model.dart | 46 +- .../offers_Categorise_view_model.dart | 48 + .../PackagesOffersViewModel.dart | 19 + .../viewModels/pharmacies_view_model.dart | 4 +- .../pharmacyModule/OrderPreviewViewModel.dart | 187 ++ .../PharmacyAddressesViewModel.dart | 117 + .../pharmacyModule/brand_view_model.dart | 57 + .../lacum-registration-viewModel.dart | 55 + .../lacum-trasnfer-viewModel.dart | 42 + .../pharmacyModule/lacum-viewmodel.dart | 111 + .../order_model_view_model.dart | 127 ++ .../pharmacy_module_view_model.dart | 35 + .../product_detail_view_model.dart | 110 + .../pharmacyModule/review_view_model.dart | 26 + .../tems-condition-viewmodel.dart | 24 + .../pharmacyModule/wishlist_view_model.dart | 36 + .../pharmacy_categorise_view_model.dart | 158 ++ lib/core/viewModels/project_view_model.dart | 11 +- .../json/GeoZonesResponseModel_helper.dart | 50 + .../OfferCategoriesResponseModel_helper.dart | 172 ++ .../OfferProductsResponseModel_helper.dart | 569 +++++ .../json/base/json_convert_content.dart | 128 ++ lib/generated/json/base/json_field.dart | 21 + ...geo_zone_response_model_entity_helper.dart | 54 + lib/locator.dart | 92 +- lib/main.dart | 41 +- .../AppoimentAllHistoryResultList.dart | 3 + .../Appointments/toDoCountProviderModel.dart | 6 +- .../check_activation_code_response.dart | 6 +- .../GetAllSharedRecordByStatusResponse.dart | 4 +- lib/models/id-name-pair.dart | 12 + lib/models/pharmacy/Wishlist.dart | 881 ++++++++ lib/models/pharmacy/addToCartModel.dart | 924 ++++++++ lib/models/pharmacy/brandModel.dart | 137 ++ lib/models/pharmacy/locationModel.dart | 159 ++ lib/models/pharmacy/productDetailModel.dart | 249 +++ lib/models/pharmacy/products.dart | 835 +++++++ lib/models/pharmacy/reviewModel.dart | 803 +++++++ lib/models/pharmacy/specification.dart | 61 + lib/models/pharmacy/topBrandsModel.dart | 137 ++ .../NewCMC/cmc_location_page.dart | 180 +- .../NewCMC/new_cmc_page.dart | 15 +- .../ComprehensiveMedicalCheckup/cmc_page.dart | 11 +- .../new_e_referral_index_page.dart | 54 +- .../new_e_referral_step_one_page.dart | 79 +- .../new_e_referral_step_three_page.dart | 64 +- .../new_e_referral_step_two_page.dart | 5 +- .../dialogs/select_project_dialog.dart | 129 -- .../E-Referral/e_referral_page.dart | 6 +- .../E-Referral/referral_details.dart | 100 - .../E-Referral/search_for_referrals_page.dart | 220 +- .../NewHomeHealthCare/location_page.dart | 178 +- .../home_health_care_index_page.dart | 69 + .../HomeHealthCare/home_health_care_page.dart | 2 +- .../all_habib_medical_service_page.dart | 106 +- .../AlHabibMedicalService/h2o/h2o_page.dart | 2 +- .../health-weather-indicator.dart | 7 +- .../AlHabibMedicalService/parking_page.dart | 1 - lib/pages/Blood/blood_donation.dart | 1 + lib/pages/Blood/dialogs/ConfirmSMSDialog.dart | 46 +- lib/pages/BookAppointment/BookConfirm.dart | 12 +- lib/pages/BookAppointment/BookSuccess.dart | 335 +-- lib/pages/BookAppointment/BookingOptions.dart | 9 +- .../BookAppointment/DentalComplaints.dart | 19 +- lib/pages/BookAppointment/DoctorProfile.dart | 15 +- lib/pages/BookAppointment/QRCode.dart | 9 +- lib/pages/BookAppointment/Search.dart | 73 +- lib/pages/BookAppointment/SearchResults.dart | 3 +- .../components/DocAvailableAppointments.dart | 6 +- .../BookAppointment/components/DocInfo.dart | 91 +- .../components/SearchByClinic.dart | 85 +- .../components/SearchByDoctor.dart | 4 +- .../BookAppointment/widgets/CardCommon.dart | 19 +- .../widgets/DentalComplaintCard.dart | 21 +- .../BookAppointment/widgets/DoctorView.dart | 1 + .../ChildVaccines/ChidDetailsWidget.dart | 120 - .../ChildVaccines/add_newchild_page.dart | 253 ++- lib/pages/ChildVaccines/child_page.dart | 256 ++- .../ChildVaccines/child_vaccines_page.dart | 304 ++- ...ailDialog.dart => SelectGenderDialog.dart} | 42 +- .../ChildVaccines/dialogs/delete_child.dart | 27 +- .../ChildVaccines/vaccinationtable_page.dart | 222 +- .../LiveChat/hospitalsLivechat_page.dart | 57 +- .../ContactUs/LiveChat/livechat_page.dart | 24 +- .../LiveChat/pharmaciesLivechat_page.dart | 21 +- lib/pages/ContactUs/findus/findus_page.dart | 10 +- .../ContactUs/findus/hospitrals_page.dart | 12 +- .../ContactUs/findus/pharmacies_page.dart | 18 +- .../ContactUs/widgets/card_common_contat.dart | 20 +- .../Covid-DriveThru/Covid-TimeSlots.dart | 43 +- .../covid-drivethru-location.dart | 35 +- .../DrawerPages/family/add-family-member.dart | 30 +- .../DrawerPages/family/add-family_type.dart | 7 +- lib/pages/DrawerPages/family/my-family.dart | 103 +- lib/pages/ErService/AmbulanceReq.dart | 3 +- .../AmbulanceRequestIndex.dart | 14 +- .../BillAmount.dart | 8 +- .../PickupLocation.dart | 8 +- .../SelectTransportationMethod.dart | 10 +- .../AmbulanceRequestIndexPages/Summary.dart | 4 +- lib/pages/ErService/ErOptions.dart | 2 +- lib/pages/ErService/NearestEr.dart | 352 +-- lib/pages/ErService/widgets/StepsWidget.dart | 2 +- lib/pages/ErService/widgets/card_common.dart | 24 +- .../ErService/widgets/card_position.dart | 19 +- .../MyAppointments/AppointmentDetails.dart | 394 +++- lib/pages/MyAppointments/MyAppointments.dart | 313 ++- .../MyAppointments/models/ArrivedButtons.dart | 14 +- .../MyAppointments/models/BookedButtons.dart | 2 +- .../models/BookedButtonsAllowCheckIn.dart | 2 +- .../models/ConfirmedButtons.dart | 2 +- .../models/ConfirmedButtonsAllowCheckIn.dart | 2 +- .../widgets/AppointmentActions.dart | 168 +- .../widgets/AppointmentCardView.dart | 236 +- .../MyAppointments/widgets/custom_radio.dart | 31 +- .../widgets/reminder_dialog.dart | 15 +- lib/pages/ToDoList/ToDo.dart | 81 +- lib/pages/ToDoList/payment_method_select.dart | 80 +- lib/pages/base/base_view.dart | 2 +- lib/pages/feedback/feedback_home_page.dart | 3 +- lib/pages/feedback/send_feedback_page.dart | 151 +- lib/pages/feedback/status_feedback_page.dart | 119 +- lib/pages/final_products_page.dart | 480 ++++ .../AttachInsuranceCardImageDialog.dart | 147 ++ .../insurance/insurance_approval_screen.dart | 142 +- .../insurance/insurance_card_screen.dart | 134 +- .../insurance_card_update_details.dart | 346 +++ lib/pages/insurance/insurance_details.dart | 26 +- lib/pages/insurance/insurance_page.dart | 261 +++ .../insurance/insurance_update_screen.dart | 195 +- lib/pages/landing/home_page.dart | 841 ++++--- lib/pages/landing/landing_page_pharmcy.dart | 175 ++ lib/pages/livecare/livecare_home.dart | 66 +- .../livecare/widgets/LiveCareHistoryCard.dart | 8 +- .../widgets/LiveCarePendingRequest.dart | 12 +- lib/pages/livecare/widgets/clinic_card.dart | 9 +- lib/pages/login/confirm-login.dart | 412 ++-- lib/pages/login/login-type.dart | 295 +-- lib/pages/login/login.dart | 72 +- lib/pages/login/register-info.dart | 69 +- lib/pages/login/register.dart | 215 +- lib/pages/login/welcome.dart | 5 +- .../ask_doctor/ask_doctor_home_page.dart | 2 - .../medical/ask_doctor/ask_doctor_page.dart | 3 + .../medical/balance/advance_payment_page.dart | 10 +- .../medical/balance/confirm_payment_page.dart | 3 +- .../balance/dialogs/ConfirmSMSDialog.dart | 8 +- .../dialogs/SelectBeneficiaryDialog.dart | 3 +- .../balance/dialogs/SelectHospitalDialog.dart | 4 +- .../dialogs/SelectPatientFamilyDialog.dart | 8 +- .../dialogs/SelectPatientInfoDialog.dart | 4 +- .../medical/balance/my_balance_page.dart | 103 +- .../medical/doctor/doctor_home_page.dart | 2 - lib/pages/medical/eye/EyeHomePage.dart | 3 +- .../medical/labs/laboratory_result_page.dart | 35 +- lib/pages/medical/labs/labs_home_page.dart | 12 +- lib/pages/medical/medical_profile_page.dart | 6 + .../my_trackers/Weight/WeightHomePage.dart | 2 +- .../blood_pressure/BloodPressureHomePage.dart | 3 +- .../blood_suger/blood_sugar_home_page.dart | 3 +- .../medical/patient_sick_leave_page.dart | 50 +- .../prescription_details_page.dart | 20 +- .../prescription_items_page.dart | 275 ++- .../prescriptions_history_details_page.dart | 22 +- .../prescriptions_history_page.dart | 8 +- .../prescriptions_home_page.dart | 11 +- .../prescriptions/prescriptions_page.dart | 11 +- .../radiology/radiology_details_page.dart | 98 +- .../radiology/radiology_home_page.dart | 12 +- .../medical/reports/monthly_reports.dart | 266 ++- .../medical/reports/report_home_page.dart | 51 +- .../medical/reports/report_list_widget.dart | 91 +- lib/pages/medical/reports/reports_page.dart | 24 +- .../health_data_list.dart | 38 +- .../smart_watch_instructions.dart | 27 +- .../medical/vital_sign/LineChartCurved.dart | 217 ++ .../LineChartCurvedBloodPressure.dart | 257 +++ ...al_sign_details_blood_pressurewideget.dart | 146 ++ .../vital_sign/vital_sign_details_screen.dart | 77 +- .../vital_sign_details_wideget.dart | 62 +- .../medical/vital_sign/vital_sign_item.dart | 6 +- .../vital_sign_item_details_screen.dart | 96 +- .../vital_sing_chart_and_detials.dart | 45 +- .../vital_sing_chart_blood_pressure.dart | 85 + lib/pages/offers_categorise_page.dart | 620 ++++++ lib/pages/parent_categorise_page.dart | 1074 +++++++++ lib/pages/paymentService/payment_service.dart | 152 +- .../pharmacies/ProductCheckTypeWidget.dart | 70 + lib/pages/pharmacies/compare-list.dart | 36 + lib/pages/pharmacies/compare.dart | 328 +++ .../pharmacies/medicine_search_screen.dart | 61 +- lib/pages/pharmacies/my_reviews.dart | 248 +++ .../pharmacies/pharmacies_list_screen.dart | 6 +- lib/pages/pharmacies/product-brands.dart | 254 +++ lib/pages/pharmacies/product_detail.dart | 1862 ++++++++++++++++ .../screens/address-select-page.dart | 34 + .../pharmacies/screens/cart-order-page.dart | 382 ++++ .../screens/cart-order-preview.dart | 832 +++++++ .../screens/lacum-activitaion-vida-page.dart | 101 + .../screens/lacum-registration-page.dart | 234 ++ .../screens/lacum-setting-page.dart | 238 ++ .../screens/lacum-transfer-page.dart | 315 +++ .../pharmacies/screens/lakum-main-page.dart | 555 +++++ .../screens/lakum-points-month-page.dart | 271 +++ .../screens/lakum-points-year-page.dart | 201 ++ .../screens/lakum-terms-conditions-page.dart | 77 + .../screens/payment-method-select-page.dart | 202 ++ .../pharmacy-terms-conditions-page.dart | 51 + .../screens/pharmacy_module_page.dart | 82 +- lib/pages/pharmacies/search_brands_page.dart | 145 ++ .../pharmacies/widgets/ProductOrderItem.dart | 238 +- .../widgets/ProductOrderPreviewItem.dart | 111 + .../pharmacies/widgets/ProductTileItem.dart | 41 +- .../widgets/lacum-banner-widget.dart | 289 +++ .../widgets/lakum-banner-widget.dart | 289 +++ .../widgets/lakum-point-table-row-widget.dart | 116 + .../widgets/lakum_point_table_row_widget.dart | 116 + lib/pages/pharmacies/wishlist.dart | 69 + lib/pages/pharmacy/order/Order.dart | 1148 ++++++++++ lib/pages/pharmacy/order/OrderDetails.dart | 650 ++++++ lib/pages/pharmacy/order/ProductReview.dart | 367 ++++ .../pharmacyAddresses/AddAddress.dart | 79 + .../pharmacyAddresses/PharmacyAddresses.dart | 313 +++ lib/pages/pharmacy/profile/profile.dart | 626 ++++++ lib/pages/pharmacy_categorise.dart | 239 ++ .../rate_appointment_clinic.dart | 15 +- .../rate_appointment_doctor.dart | 32 +- lib/pages/search_products_page.dart | 287 +++ lib/pages/settings/general_setting.dart | 263 ++- lib/pages/settings/profile_setting.dart | 395 ++-- lib/pages/settings/settings.dart | 12 + lib/pages/sub_categorise_page.dart | 944 ++++++++ lib/pages/vaccine/my_vaccines_screen.dart | 1 + lib/routes.dart | 3 +- .../appointment_services/GetDoctorsList.dart | 38 + .../authentication/auth_provider.dart | 26 +- .../family_files/family_files_provider.dart | 2 +- .../permission/permission_service.dart | 2 - .../pharmacy_services/brands_service.dart | 73 + .../cancelOrder_service.dart | 44 + .../orderDetails_service.dart | 75 + .../pharmacy_services/order_service.dart | 81 + .../pharmacyAddress_service.dart | 102 + .../product_detail_service.dart | 178 ++ .../pharmacy_services/review_service.dart | 38 + .../pharmacy_services/wishList_service.dart | 72 + .../writeReview_service.dart | 40 + lib/splashPage.dart | 33 +- lib/theme/theme_value.dart | 3 +- lib/uitl/HMGNetworkConnectivity.dart | 120 + lib/uitl/HMG_Geofence.dart | 189 ++ lib/uitl/LocalNotification.dart | 86 +- lib/uitl/PlatformBridge.dart | 152 ++ lib/uitl/app_toast.dart | 4 +- lib/uitl/date_uitl.dart | 59 +- lib/uitl/location_util.dart | 12 +- lib/uitl/translations_delegate_base.dart | 268 ++- lib/uitl/utils.dart | 3 +- lib/widgets/Loader/gif_loader_container.dart | 2 +- lib/widgets/avatar/large_avatar.dart | 2 +- .../bottom_navigation/bottom_nav_bar.dart | 10 +- .../bottom_navigation_item.dart | 17 +- lib/widgets/bottom_options/BottomSheet.dart | 19 +- lib/widgets/buttons/borderedButton.dart | 96 +- lib/widgets/buttons/button.dart | 7 +- lib/widgets/buttons/defaultButton.dart | 2 +- lib/widgets/buttons/floatingActionButton.dart | 40 +- lib/widgets/buttons/mini_button.dart | 2 +- lib/widgets/buttons/secondary_button.dart | 10 +- lib/widgets/charts/app_time_series_chart.dart | 7 + .../medical/LabResult/FlowChartPage.dart | 42 + .../{ => LabResult}/LabResultWidget.dart | 21 +- .../LabResult/Lab_Result_details_wideget.dart | 119 + .../medical/LabResult/LineChartCurved.dart | 229 ++ .../lab_result_chart_and_detials.dart | 42 + .../laboratory_result_widget.dart | 191 +- .../data_display/medical/doctor_card.dart | 56 +- .../medical/medical_profile_item.dart | 8 +- .../medical/time_line_widget.dart | 36 +- lib/widgets/data_display/text.dart | 2 +- lib/widgets/dialogs/confirm_dialog.dart | 4 +- .../dialogs/confirm_send_email_dialog.dart | 120 + lib/widgets/dialogs/radio-group-dialog.dart | 101 + .../dialogs/select_location_dialog.dart | 2 +- lib/widgets/drawer/drawer_item_widget.dart | 17 +- lib/widgets/input/text_field.dart | 6 +- lib/widgets/loadings/ShimmerLoading.dart | 62 + lib/widgets/mobile-no/mobile_no.dart | 73 +- .../offers_packages/offers_packages.dart | 282 +++ .../others/app_expandable_notifier.dart | 42 +- .../others/app_scaffold_pharmacy_widget.dart | 114 + lib/widgets/others/app_scaffold_widget.dart | 6 +- .../others/app_scafold_detail_page.dart | 241 +++ .../others/floating_button_search.dart | 10 +- lib/widgets/others/not_auh_page.dart | 9 +- .../others/points-expandable-notifier.dart | 77 + lib/widgets/otp/sms-popup.dart | 207 +- .../pharmacy/bottom_nav_pharmacy_bar.dart | 108 + .../bottom_nav_pharmacy_home_item.dart | 74 + .../pharmacy/bottom_nav_pharmacy_item.dart | 76 + lib/widgets/pharmacy/drug_item.dart | 2 +- lib/widgets/pharmacy/product_tile.dart | 312 +++ .../pickupLocation/PickupLocationFromMap.dart | 60 +- .../weather_slider/weather_slider.dart | 150 +- pubspec.yaml | 25 +- 641 files changed, 49974 insertions(+), 6453 deletions(-) delete mode 100644 DQKey.jks delete mode 100644 Keystore Pass.rtf create mode 100644 android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/GeoZoneModel.kt create mode 100644 android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/GeofenceBroadcastReceiver.kt create mode 100644 android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/GeofenceErrorMessages.kt create mode 100644 android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/GeofenceTransitionsJobIntentService.kt create mode 100644 android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/GeofencingRebootBroadcastReceiver.kt create mode 100644 android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/HMG_Geofence.kt create mode 100644 android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/hmgwifi/HMG_Guest.kt create mode 100644 android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/hmgwifi/HMG_Internet.kt create mode 100644 android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/hmgwifi/WPA.kt create mode 100644 android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/API.kt create mode 100644 android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/FlutterText.kt create mode 100644 android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/HMGUtils.kt create mode 100644 android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/HMG_Wifi_.kt create mode 100644 android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/PlatformBridge.kt create mode 100644 android/app/src/main/res/values/strings.xml create mode 100644 assets/images/DQ/logo.png create mode 100644 assets/images/DQ/logo_big.png create mode 100644 assets/images/appointment_booking.png create mode 100644 assets/images/appointment_booking_en.png create mode 100644 assets/images/book_appointment_ar.png create mode 100644 assets/images/book_appointment_arabic.png create mode 100644 assets/images/booking_ar.png create mode 100644 assets/images/booking_en.png create mode 100644 assets/images/check-in.png create mode 100644 assets/images/comments.png create mode 100644 assets/images/device_icon.png rename assets/images/{ => medical}/vital_sign_icon.png (100%) create mode 100644 assets/images/new-design/covid-19-car.svg create mode 100644 assets/images/new-design/empty_box.png create mode 100644 assets/images/new-design/liveCare_white_logo.svg create mode 100644 assets/images/new-design/livecare_arabic_logo.svg create mode 100644 assets/images/new-design/livecare_white_logo.png create mode 100644 assets/images/no-data-found.png create mode 100644 assets/images/no_image.png create mode 100644 assets/images/offer.png create mode 100644 assets/images/offer_ar.png create mode 100644 assets/images/pharmacy/Group 1206.svg create mode 100644 assets/images/pharmacy/Group 1207.svg create mode 100644 assets/images/pharmacy/Logo Parmacy-green.png create mode 100644 assets/images/pharmacy/aramex_shipping_logo.svg create mode 100644 assets/images/pharmacy/arrow-left-png.png create mode 100644 assets/images/pharmacy/arrow-left.png create mode 100644 assets/images/pharmacy/arrow-right-png.png create mode 100644 assets/images/pharmacy/arrow.png create mode 100644 assets/images/pharmacy/arrow_lef.png create mode 100644 assets/images/pharmacy/arrow_left.svg create mode 100644 assets/images/pharmacy/arrow_right.svg create mode 100644 assets/images/pharmacy/check_icon.svg create mode 100644 assets/images/pharmacy/compare.png create mode 100644 assets/images/pharmacy/contact_us_icon.svg create mode 100644 assets/images/pharmacy/credit_card_icon.svg create mode 100644 assets/images/pharmacy/delete_red_icon.svg create mode 100644 assets/images/pharmacy/edit_icon.svg create mode 100644 assets/images/pharmacy/empty_box.svg create mode 100644 assets/images/pharmacy/hmg_shipping_greenlogo.svg create mode 100644 assets/images/pharmacy/hmg_shipping_logo.svg create mode 100644 assets/images/pharmacy/lakum_icon.svg create mode 100644 assets/images/pharmacy/medication_refill_icon.svg create mode 100644 assets/images/pharmacy/mobile_number_icon.svg create mode 100644 assets/images/pharmacy/my_family_icon.svg create mode 100644 assets/images/pharmacy/my_prescription_icon.svg create mode 100644 assets/images/pharmacy/orders_icon.svg create mode 100644 assets/images/pharmacy/our_locations_icon.svg create mode 100644 assets/images/pharmacy/pill_reminder_icon.svg create mode 100644 assets/images/pharmacy/quote_end.svg create mode 100644 assets/images/pharmacy/quote_start.svg create mode 100644 assets/images/pharmacy/review_icon.svg create mode 100644 assets/images/pharmacy/shipping_addresses_icon.svg create mode 100644 assets/images/pharmacy/shipping_mark_icon.svg create mode 100644 assets/images/pharmacy/shipping_truck_icon.svg create mode 100644 assets/images/pharmacy/success_check_icon.svg create mode 100644 assets/images/pharmacy/success_review_icon.svg create mode 100644 assets/images/pharmacy/terms.png create mode 100644 assets/images/pharmacy/user.svg create mode 100644 assets/images/pharmacy/user_icon.svg create mode 100644 assets/images/pharmacy/wishklist_icon.svg create mode 100644 assets/images/pharmacy/wishlist_icon.svg create mode 100644 assets/images/pharmacy_module/ic_payment_option.png create mode 100644 assets/images/pharmacy_module/ic_shipping_address.png create mode 100644 assets/images/pharmacy_module/ic_shipping_mark.png create mode 100644 assets/images/pharmacy_module/ic_shipping_truck.png create mode 100644 assets/images/pharmacy_module/lakum/Account_activation_icon.png create mode 100644 assets/images/pharmacy_module/lakum/Lakum_transfer_icon.png create mode 100644 assets/images/pharmacy_module/lakum/expired_icon.png create mode 100644 assets/images/pharmacy_module/lakum/inactive_cross.png create mode 100644 assets/images/pharmacy_module/lakum/lakum_card_front_bg.png create mode 100644 assets/images/pharmacy_module/lakum/lakum_checkout.png create mode 100644 assets/images/pharmacy_module/lakum/waiting_gained_icon.png create mode 100644 assets/images/pharmacy_module/lakum/will_be_expired_icon.png create mode 100644 assets/images/pharmacy_module/payment/LogoParmacyGreen.png create mode 100644 assets/images/pharmacy_module/payment/aramex_shipping_logo.png create mode 100644 assets/images/pharmacy_module/payment/hmg_shipping_logo.png create mode 100644 assets/images/pharmacy_module/payment/installment.png create mode 100644 assets/images/pharmacy_module/payment/mada.png create mode 100644 assets/images/pharmacy_module/payment/mastercard.png create mode 100644 assets/images/pharmacy_module/payment/sadad.png create mode 100644 assets/images/pharmacy_module/payment/visa.png create mode 100644 assets/images/pharmacy_module/payment_image.png create mode 100644 assets/images/powerd-by.jpg create mode 100644 assets/images/progress-loading-red.gif create mode 100644 help/.gitignore create mode 100644 help/.metadata create mode 100644 help/README.md create mode 100644 help/android/.gitignore create mode 100644 help/android/app/build.gradle create mode 100644 help/android/app/src/debug/AndroidManifest.xml create mode 100644 help/android/app/src/main/AndroidManifest.xml create mode 100644 help/android/app/src/main/kotlin/com/example/help/MainActivity.kt create mode 100644 help/android/app/src/main/res/drawable/launch_background.xml create mode 100644 help/android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 help/android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 help/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 help/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 help/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 help/android/app/src/main/res/values/styles.xml create mode 100644 help/android/app/src/profile/AndroidManifest.xml create mode 100644 help/android/build.gradle create mode 100644 help/android/gradle.properties create mode 100644 help/android/gradle/wrapper/gradle-wrapper.properties create mode 100644 help/android/settings.gradle create mode 100644 help/ios/.gitignore create mode 100644 help/ios/Flutter/AppFrameworkInfo.plist create mode 100644 help/ios/Flutter/Debug.xcconfig create mode 100644 help/ios/Flutter/Release.xcconfig create mode 100644 help/ios/Runner.xcodeproj/project.pbxproj create mode 100644 help/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 help/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 help/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 help/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 help/ios/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 help/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 help/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 help/ios/Runner/AppDelegate.swift create mode 100644 help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png create mode 100644 help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png create mode 100644 help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png create mode 100644 help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png create mode 100644 help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png create mode 100644 help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png create mode 100644 help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png create mode 100644 help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png create mode 100644 help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png create mode 100644 help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png create mode 100644 help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png create mode 100644 help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png create mode 100644 help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png create mode 100644 help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png create mode 100644 help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png create mode 100644 help/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json create mode 100644 help/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png create mode 100644 help/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png create mode 100644 help/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png create mode 100644 help/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md create mode 100644 help/ios/Runner/Base.lproj/LaunchScreen.storyboard create mode 100644 help/ios/Runner/Base.lproj/Main.storyboard create mode 100644 help/ios/Runner/Info.plist create mode 100644 help/ios/Runner/Runner-Bridging-Header.h create mode 100644 help/lib/main.dart create mode 100644 help/pubspec.yaml create mode 100644 help/test/widget_test.dart create mode 100644 ios/GoogleService-Info.plist create mode 100644 ios/Podfile.lock create mode 100644 ios/Runner.xcodeproj/project.pbxproj create mode 100644 ios/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md create mode 100644 ios/Runner/Base.lproj/Main_Custom.storyboard create mode 100644 ios/Runner/Controllers/MainFlutterVC.swift create mode 100644 ios/Runner/GoogleService-Info.plist create mode 100644 ios/Runner/GuestPOC_Certificate.cer create mode 100644 ios/Runner/GuestPOC_Certificate.p12 create mode 100644 ios/Runner/Helper/API.swift create mode 100644 ios/Runner/Helper/Extensions.swift create mode 100644 ios/Runner/Helper/GeoZoneModel.swift create mode 100644 ios/Runner/Helper/GlobalHelper.swift create mode 100644 ios/Runner/Helper/HMGPlatformBridge.swift create mode 100644 ios/Runner/Helper/HMG_Geofence.swift create mode 100644 ios/Runner/Helper/LocalizedFromFlutter.swift create mode 100644 ios/Runner/WifiConnect/HMG_GUEST.swift create mode 100644 ios/Runner/WifiConnect/HMG_GUEST_bkp.swift create mode 100644 ios/Runner/WifiConnect/HMG_Internet.swift create mode 100644 ios/Runner/WifiConnect/HMG_Wifi.swift create mode 100644 ios/gpx.gpx create mode 100644 lib/Constants.dart create mode 100644 lib/core/model/geofencing/requests/GeoZonesRequestModel.dart create mode 100644 lib/core/model/geofencing/requests/LogGeoZoneRequestModel.dart create mode 100644 lib/core/model/geofencing/responses/GeoZonesResponseModel.dart create mode 100644 lib/core/model/geofencing/responses/LogGeoZoneResponseModel.dart create mode 100644 lib/core/model/insurance/Insurance_card_details.dart rename lib/core/model/insurance/{insurance_card_update.dart => insurance_card_update_model.dart} (100%) create mode 100644 lib/core/model/labs/LabOrderResult.dart create mode 100644 lib/core/model/packages_offers/requests/OffersCategoriesRequestModel.dart create mode 100644 lib/core/model/packages_offers/requests/OffersProductsRequestModel.dart create mode 100644 lib/core/model/packages_offers/responses/OfferCategoriesResponseModel.dart create mode 100644 lib/core/model/packages_offers/responses/OfferProductsResponseModel.dart create mode 100644 lib/core/model/pharmacies/BillingAddress.dart create mode 100644 lib/core/model/pharmacies/Country.dart create mode 100644 lib/core/model/pharmacies/LacumAccountInformation.dart create mode 100644 lib/core/model/pharmacies/LakumInquiryInformationObjVersion.dart create mode 100644 lib/core/model/pharmacies/ListUserAgreement.dart create mode 100644 lib/core/model/pharmacies/PharmacyAddressesModel.dart create mode 100644 lib/core/model/pharmacies/PointsAmountPerMonth.dart create mode 100644 lib/core/model/pharmacies/PointsAmountPerYear.dart create mode 100644 lib/core/model/pharmacies/PointsAmountPerday.dart create mode 100644 lib/core/model/pharmacies/PointsDetails.dart create mode 100644 lib/core/model/pharmacies/ShippingOption.dart create mode 100644 lib/core/model/pharmacies/ShoppingCart.dart create mode 100644 lib/core/model/pharmacies/ShoppingCartResponse.dart create mode 100644 lib/core/model/pharmacies/Specifications.dart create mode 100644 lib/core/model/pharmacies/order_model.dart create mode 100644 lib/core/model/pharmacies/payment-checkout-data.dart create mode 100644 lib/core/model/pharmacy/brands_model.dart create mode 100644 lib/core/model/pharmacy/categorise_parent_model.dart create mode 100644 lib/core/model/pharmacy/final_products_model.dart create mode 100644 lib/core/model/pharmacy/offer_products_model.dart create mode 100644 lib/core/model/pharmacy/offers_model.dart create mode 100644 lib/core/model/pharmacy/parent_products_model.dart create mode 100644 lib/core/model/pharmacy/pharmacy_categorise.dart create mode 100644 lib/core/model/pharmacy/scan_qr_model.dart create mode 100644 lib/core/model/pharmacy/sub_categories_model.dart create mode 100644 lib/core/model/pharmacy/sub_products_model.dart create mode 100644 lib/core/model/search_products_model.dart create mode 100644 lib/core/service/childvaccines/get_vaccinations_item_services.dart create mode 100644 lib/core/service/geofencing/GeofencingServices.dart create mode 100644 lib/core/service/offers_service.dart create mode 100644 lib/core/service/packages_offers/PackagesOffersServices.dart create mode 100644 lib/core/service/parmacyModule/lacum-registration-service.dart create mode 100644 lib/core/service/parmacyModule/lacum-service.dart create mode 100644 lib/core/service/parmacyModule/lacum-transfer-service.dart create mode 100644 lib/core/service/parmacyModule/terms-condition-service.dart create mode 100644 lib/core/service/pharmacy_categorise_service.dart create mode 100644 lib/core/viewModels/offers_Categorise_view_model.dart create mode 100644 lib/core/viewModels/packages_offers/PackagesOffersViewModel.dart create mode 100644 lib/core/viewModels/pharmacyModule/PharmacyAddressesViewModel.dart create mode 100644 lib/core/viewModels/pharmacyModule/brand_view_model.dart create mode 100644 lib/core/viewModels/pharmacyModule/lacum-registration-viewModel.dart create mode 100644 lib/core/viewModels/pharmacyModule/lacum-trasnfer-viewModel.dart create mode 100644 lib/core/viewModels/pharmacyModule/lacum-viewmodel.dart create mode 100644 lib/core/viewModels/pharmacyModule/order_model_view_model.dart create mode 100644 lib/core/viewModels/pharmacyModule/product_detail_view_model.dart create mode 100644 lib/core/viewModels/pharmacyModule/review_view_model.dart create mode 100644 lib/core/viewModels/pharmacyModule/tems-condition-viewmodel.dart create mode 100644 lib/core/viewModels/pharmacyModule/wishlist_view_model.dart create mode 100644 lib/core/viewModels/pharmacy_categorise_view_model.dart create mode 100644 lib/generated/json/GeoZonesResponseModel_helper.dart create mode 100644 lib/generated/json/OfferCategoriesResponseModel_helper.dart create mode 100644 lib/generated/json/OfferProductsResponseModel_helper.dart create mode 100644 lib/generated/json/base/json_convert_content.dart create mode 100644 lib/generated/json/base/json_field.dart create mode 100644 lib/generated/json/log_geo_zone_response_model_entity_helper.dart create mode 100644 lib/models/id-name-pair.dart create mode 100644 lib/models/pharmacy/Wishlist.dart create mode 100644 lib/models/pharmacy/addToCartModel.dart create mode 100644 lib/models/pharmacy/brandModel.dart create mode 100644 lib/models/pharmacy/locationModel.dart create mode 100644 lib/models/pharmacy/productDetailModel.dart create mode 100644 lib/models/pharmacy/products.dart create mode 100644 lib/models/pharmacy/reviewModel.dart create mode 100644 lib/models/pharmacy/specification.dart create mode 100644 lib/models/pharmacy/topBrandsModel.dart delete mode 100644 lib/pages/AlHabibMedicalService/E-Referral/dialogs/select_project_dialog.dart delete mode 100644 lib/pages/AlHabibMedicalService/E-Referral/referral_details.dart create mode 100644 lib/pages/AlHabibMedicalService/HomeHealthCare/home_health_care_index_page.dart delete mode 100644 lib/pages/ChildVaccines/ChidDetailsWidget.dart rename lib/pages/ChildVaccines/dialogs/{ConfirmSendEmailDialog.dart => SelectGenderDialog.dart} (70%) create mode 100644 lib/pages/final_products_page.dart create mode 100644 lib/pages/insurance/AttachInsuranceCardImageDialog.dart create mode 100644 lib/pages/insurance/insurance_card_update_details.dart create mode 100644 lib/pages/insurance/insurance_page.dart create mode 100644 lib/pages/landing/landing_page_pharmcy.dart create mode 100644 lib/pages/medical/vital_sign/LineChartCurved.dart create mode 100644 lib/pages/medical/vital_sign/LineChartCurvedBloodPressure.dart create mode 100644 lib/pages/medical/vital_sign/vital_sign_details_blood_pressurewideget.dart create mode 100644 lib/pages/medical/vital_sign/vital_sing_chart_blood_pressure.dart create mode 100644 lib/pages/offers_categorise_page.dart create mode 100644 lib/pages/parent_categorise_page.dart create mode 100644 lib/pages/pharmacies/ProductCheckTypeWidget.dart create mode 100644 lib/pages/pharmacies/compare-list.dart create mode 100644 lib/pages/pharmacies/compare.dart create mode 100644 lib/pages/pharmacies/my_reviews.dart create mode 100644 lib/pages/pharmacies/product-brands.dart create mode 100644 lib/pages/pharmacies/product_detail.dart create mode 100644 lib/pages/pharmacies/screens/address-select-page.dart create mode 100644 lib/pages/pharmacies/screens/cart-order-page.dart create mode 100644 lib/pages/pharmacies/screens/cart-order-preview.dart create mode 100644 lib/pages/pharmacies/screens/lacum-activitaion-vida-page.dart create mode 100644 lib/pages/pharmacies/screens/lacum-registration-page.dart create mode 100644 lib/pages/pharmacies/screens/lacum-setting-page.dart create mode 100644 lib/pages/pharmacies/screens/lacum-transfer-page.dart create mode 100644 lib/pages/pharmacies/screens/lakum-main-page.dart create mode 100644 lib/pages/pharmacies/screens/lakum-points-month-page.dart create mode 100644 lib/pages/pharmacies/screens/lakum-points-year-page.dart create mode 100644 lib/pages/pharmacies/screens/lakum-terms-conditions-page.dart create mode 100644 lib/pages/pharmacies/screens/payment-method-select-page.dart create mode 100644 lib/pages/pharmacies/screens/pharmacy-terms-conditions-page.dart create mode 100644 lib/pages/pharmacies/search_brands_page.dart create mode 100644 lib/pages/pharmacies/widgets/ProductOrderPreviewItem.dart create mode 100644 lib/pages/pharmacies/widgets/lacum-banner-widget.dart create mode 100644 lib/pages/pharmacies/widgets/lakum-banner-widget.dart create mode 100644 lib/pages/pharmacies/widgets/lakum-point-table-row-widget.dart create mode 100644 lib/pages/pharmacies/widgets/lakum_point_table_row_widget.dart create mode 100644 lib/pages/pharmacies/wishlist.dart create mode 100644 lib/pages/pharmacy/order/Order.dart create mode 100644 lib/pages/pharmacy/order/OrderDetails.dart create mode 100644 lib/pages/pharmacy/order/ProductReview.dart create mode 100644 lib/pages/pharmacy/pharmacyAddresses/AddAddress.dart create mode 100644 lib/pages/pharmacy/pharmacyAddresses/PharmacyAddresses.dart create mode 100644 lib/pages/pharmacy/profile/profile.dart create mode 100644 lib/pages/pharmacy_categorise.dart create mode 100644 lib/pages/search_products_page.dart create mode 100644 lib/pages/sub_categorise_page.dart create mode 100644 lib/services/pharmacy_services/brands_service.dart create mode 100644 lib/services/pharmacy_services/cancelOrder_service.dart create mode 100644 lib/services/pharmacy_services/orderDetails_service.dart create mode 100644 lib/services/pharmacy_services/order_service.dart create mode 100644 lib/services/pharmacy_services/pharmacyAddress_service.dart create mode 100644 lib/services/pharmacy_services/product_detail_service.dart create mode 100644 lib/services/pharmacy_services/review_service.dart create mode 100644 lib/services/pharmacy_services/wishList_service.dart create mode 100644 lib/services/pharmacy_services/writeReview_service.dart create mode 100644 lib/uitl/HMGNetworkConnectivity.dart create mode 100644 lib/uitl/HMG_Geofence.dart create mode 100644 lib/uitl/PlatformBridge.dart create mode 100644 lib/widgets/data_display/medical/LabResult/FlowChartPage.dart rename lib/widgets/data_display/medical/{ => LabResult}/LabResultWidget.dart (87%) create mode 100644 lib/widgets/data_display/medical/LabResult/Lab_Result_details_wideget.dart create mode 100644 lib/widgets/data_display/medical/LabResult/LineChartCurved.dart create mode 100644 lib/widgets/data_display/medical/LabResult/lab_result_chart_and_detials.dart rename lib/widgets/data_display/medical/{ => LabResult}/laboratory_result_widget.dart (64%) create mode 100644 lib/widgets/dialogs/confirm_send_email_dialog.dart create mode 100644 lib/widgets/dialogs/radio-group-dialog.dart create mode 100644 lib/widgets/loadings/ShimmerLoading.dart create mode 100644 lib/widgets/offers_packages/offers_packages.dart create mode 100644 lib/widgets/others/app_scaffold_pharmacy_widget.dart create mode 100644 lib/widgets/others/app_scafold_detail_page.dart create mode 100644 lib/widgets/others/points-expandable-notifier.dart create mode 100644 lib/widgets/pharmacy/bottom_nav_pharmacy_bar.dart create mode 100644 lib/widgets/pharmacy/bottom_nav_pharmacy_home_item.dart create mode 100644 lib/widgets/pharmacy/bottom_nav_pharmacy_item.dart create mode 100644 lib/widgets/pharmacy/product_tile.dart diff --git a/.gitignore b/.gitignore index 4b016310..fd4aca5a 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,4 @@ app.*.map.json # Exceptions to above rules. !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages +health_calculators.dart diff --git a/DQKey.jks b/DQKey.jks deleted file mode 100644 index 7c844584b4958f6b20b4ce3b3ceae1fac4b8e2a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2269 zcmc&#X*AT08lTNrCPv1-PL{4>_>agwMpyn_2+KK&FXhJJrNE71Td@6`#HtaCvKiP~NBk(~Ym&tw7B zDr`jY6{=}N%<8nH`w2q_K1q$i5#I)svs6gSw)J~iK5%Z56ZiK3aoegi*) z3`3nVbF01*8>Djj*?d9-S^Kcll~N-9E~gf-ySk6y1k?N8K|>+Yp}hiMEFuz*CZ}2$ zu9?T($|UtEuWQ5i;p3`o>k`w0IXz`;jW0RHLvcMydW!M<14gRXo6Fl7Rjn}Q z^@TR2*Jm1>$MUOp?A|~wF@LmA&9l7P3$ct~KT3&PVbElN89vkP0djqC9u!CGJ{O>s zrr?8;k-mR3DLE>CIm0=~pZLMWlp~BHE5PTKujol>z`q%%==~xQ?s{*~9IiH@X>yz4 z(C17%yW@6=5<*yqN-GGVy?q*d6cY>K==*I>u7&GI2-{|twp%p2D%TG~{6D;yY6(mI zwQN{rsxxq?P4<&)tb>H6;ZM5)BHvJKo>1OxO4du+wJZ!SKnabhu3yysmad8X5tXtLhbMH@|Ru{n`W!K@3*=hQN9i*eV8BY+zqI>pbYDF`B zDfPosx#+FXf|Ko*es*O0{Qzob;pa7@sV?$BU`Qxe{OFsT@onWH{A=aQr^<2H!TlJY z`YraLH_^3<6B^d?zP(fPbx%QR?`#)*N&=Hf5OnurkAYM3@^v<;3Fh%%N*}(Dm{klf zla>4xbwX*-emb>{1|ApU@D>LDxPiXCiz;EgQAril;h+4Nq1ucy5T5C0uIR;?PguE^ zIW2!`%_r6E!jgE8uUp^2q6po+qf#yS zQAWN*8AId8kJ3){I0?jm;%}?)aJgfiWZhX=1fA$H$!}b4oloNNS?~8bi5%3tLGYi} zjQKoM=Sn`AUyX=jn$@>JE0e13=jnUSdF+~GnzhX7T(}uvpkGyZ7kMk zon(cjcYLP=vd|Sd>UGXMTWFog@{x(8N*Fe>I5~{t&yHlYZ9cO)9F(%WJG#K?60=Bi z`Ia1olh9UC9c7@XHiej}^l8kKoi3$@K`F|o?BoP|XqF7#tnXL9HDhH%yK`tVtU1oX z>R3%HYuMhQ?W?FDp5D+EuC-c-tAiUDOKlb3)i{nTpT!SYg4pxHBelTL%-w_J%!+DR#or&Az2ZIq@ARq#Z0C?e02N)a$u`|XZ5BvkdgMt&u z;hx@p{}#CaBZvVa|LWjF3D{8rJjsEcLFhA{USu!qUk2iT8PNYW09i494FHSPIG9#T z6RY7Y#;>UZ9Du**|8+JxSpM%(9efff9gGA4bTA);4hDnX`C{3|AB|$gysA#IpCx44 z)cy{a+R?8|?9SR7TJOao8G6(A*BLEYH318ds zGpZ)Nr5LM){+2nWj^BQkT=(}75BBXKL@)@cAe?{p?m~dqip%FSgp>1i31r3mD~R*h ztqmeAKBdoqRCMJ6k2%teDbBgru-aYHbw~8!#qCMu2iLg_p)ak3p2jzA@7vP)8RpxET~w8Gd+W;gaE(|^J656;a83~a zSao4Gipof(*7p4^LW~h+@{C-uQ3^U6 u=Y4|ex!K@;hfDFe9jB)G4MlxPULqI0$>&F0+9;UbO<1zo0k&Orfqw#)pyOiz diff --git a/Keystore Pass.rtf b/Keystore Pass.rtf deleted file mode 100644 index cd33f08e..00000000 --- a/Keystore Pass.rtf +++ /dev/null @@ -1,9 +0,0 @@ -{\rtf1\ansi\ansicpg1252\cocoartf2513 -\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -{\*\expandedcolortbl;;} -\paperw11900\paperh16840\margl1440\margr1440\vieww10800\viewh8400\viewkind0 -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural\partightenfactor0 - -\f0\fs24 \cf0 keyPassword=HmGsa123\ -storePassword=HmGsa123} \ No newline at end of file diff --git a/android/app/build.gradle b/android/app/build.gradle index e4d2cb78..7a09b3ca 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -26,12 +26,6 @@ apply plugin: 'kotlin-android' apply plugin: 'com.google.gms.google-services' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" -def keystoreProperties = new Properties() -def keystorePropertiesFile = rootProject.file('key.properties') -if (keystorePropertiesFile.exists()) { - keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) -} - android { compileSdkVersion 30 @@ -40,9 +34,7 @@ android { } lintOptions { -// disable 'InvalidPackage' - checkReleaseBuilds false - abortOnError false + disable 'InvalidPackage' } defaultConfig { @@ -56,35 +48,21 @@ android { } - signingConfigs { - release { - keyAlias keystoreProperties['keyAlias'] - keyPassword keystoreProperties['keyPassword'] - storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null - storePassword keystoreProperties['storePassword'] - } - } - buildTypes { debug {} release { // TODO: Add your own signing config for the release build. // Signing with the debug keys for now, so `flutter run --release` works. -// signingConfig signingConfigs.debug -// useProguard true - -// proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - - signingConfigs.release + signingConfig signingConfigs.debug + } + staging { + // Specifies a sorted list of fallback build types that the + // plugin should try to use when a dependency does not include a + // "staging" build type. You may specify as many fallbacks as you + // like, and the plugin selects the first build type that's + // available in the dependency. + matchingFallbacks = ['debug', 'qa', 'release'] } -// staging { -// // Specifies a sorted list of fallback build types that the -// // plugin should try to use when a dependency does not include a -// // "staging" build type. You may specify as many fallbacks as you -// // like, and the plugin selects the first build type that's -// // available in the dependency. -// matchingFallbacks = ['debug', 'qa', 'release'] -// } } } @@ -94,15 +72,28 @@ flutter { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - implementation "com.google.firebase:firebase-messaging:20.3.0" + implementation "com.google.firebase:firebase-messaging:21.0.0" +// implementation ('com.google.firebase:firebase-inappmessaging-display:19.1.2',{ +// exclude group: 'com.google.protobuf',module: 'protobuf-javalite' +// exclude group: 'com.google.protobuf',module: 'protobuf-lite' +// }) implementation 'pub.devrel:easypermissions:0.4.0' // implementation 'com.google.firebase:firebase-inappmessaging-display:17.2.0' + // implementation 'com.google.firebase:firebase-inappmessaging-display:17.2.0' implementation 'com.google.guava:guava:27.0.1-android' // Dependency on local binaries implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'com.google.code.gson:gson:2.8.6' // Dependency on a remote binary // implementation 'com.example.android:app-magic:12.3' + // Native Dependency + implementation "org.jetbrains.anko:anko-commons:0.10.4" + implementation 'com.github.kittinunf.fuel:fuel:2.3.0' //for JVM + implementation 'com.github.kittinunf.fuel:fuel-android:2.3.0' + implementation 'com.google.android.gms:play-services-location:17.1.0'//for Android + + } diff --git a/android/app/google-services.json b/android/app/google-services.json index a4655794..f86832ad 100644 --- a/android/app/google-services.json +++ b/android/app/google-services.json @@ -1,37 +1,39 @@ { "project_info": { - "project_number": "864393916058", - "firebase_url": "https://diplomaticquarter-d2385.firebaseio.com", - "project_id": "diplomaticquarter-d2385", - "storage_bucket": "diplomaticquarter-d2385.appspot.com" + "project_number": "815750722565", + "firebase_url": "https://api-project-815750722565.firebaseio.com", + "project_id": "api-project-815750722565", + "storage_bucket": "api-project-815750722565.appspot.com" }, "client": [ { "client_info": { - "mobilesdk_app_id": "1:864393916058:android:5b5a65cd6d8c18b4b97923", + "mobilesdk_app_id": "1:815750722565:android:62281cd3e5df4063", "android_client_info": { "package_name": "com.cloud.diplomaticquarterapp" } }, "oauth_client": [ { - "client_id": "864393916058-tphjrn8j39ntevt32ekcvmll8aue7qql.apps.googleusercontent.com", + "client_id": "815750722565-3a0gc7neins0eoahdrimrfksk0sqice8.apps.googleusercontent.com", "client_type": 3 } ], "api_key": [ { - "current_key": "AIzaSyBdV3mos1BPhUzNKCj2KANJtiO3o2zh9IM" + "current_key": "AIzaSyDUfg6AKM1-00WyzpvLImUBC46wFrq9-qw" } ], "services": { + "analytics_service": { + "status": 1 + }, "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "864393916058-tphjrn8j39ntevt32ekcvmll8aue7qql.apps.googleusercontent.com", - "client_type": 3 - } - ] + "status": 1, + "other_platform_oauth_client": [] + }, + "ads_service": { + "status": 2 } } } diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml index beeadd9e..d8fd4e88 100644 --- a/android/app/src/debug/AndroidManifest.xml +++ b/android/app/src/debug/AndroidManifest.xml @@ -3,6 +3,5 @@ - diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 12ced804..1032b29b 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -7,6 +7,7 @@ FlutterApplication and put your custom class here. --> + @@ -20,11 +21,19 @@ + + + + + + + + + android:label="diplomaticquarterapp"> - @@ -68,13 +75,25 @@ - + + + + + + + + + + + + diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/MainActivity.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/MainActivity.kt index b8a87c8c..8b73b0c7 100644 --- a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/MainActivity.kt +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/MainActivity.kt @@ -1,11 +1,23 @@ package com.cloud.diplomaticquarterapp +import android.os.Bundle +import android.util.Log import androidx.annotation.NonNull; - import io.flutter.embedding.android.FlutterFragmentActivity +import com.cloud.diplomaticquarterapp.utils.FlutterText +import com.cloud.diplomaticquarterapp.utils.PlatformBridge +import io.flutter.embedding.android.FlutterFragmentActivity import io.flutter.embedding.engine.FlutterEngine - import io.flutter.plugins.GeneratedPluginRegistrant +import io.flutter.plugin.common.MethodChannel +import io.flutter.plugins.GeneratedPluginRegistrant class MainActivity: FlutterFragmentActivity() { - override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { - GeneratedPluginRegistrant.registerWith(flutterEngine); - } + override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { + GeneratedPluginRegistrant.registerWith(flutterEngine); + // Create Flutter Platform Bridge + PlatformBridge(flutterEngine.dartExecutor.binaryMessenger, this).create() + + } + + override fun onResume() { + super.onResume() + } } \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/GeoZoneModel.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/GeoZoneModel.kt new file mode 100644 index 00000000..7eba1ead --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/GeoZoneModel.kt @@ -0,0 +1,56 @@ +package com.cloud.diplomaticquarterapp.geofence + +import com.google.android.gms.location.Geofence +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class GeoZoneModel { + var GEOF_ID:Int = 0 + var Radius:Int = 0 + var Type:Int = 0 + var ProjectID:Int = 0 + + var Description:String? = null + var DescriptionN:String? = null + var Latitude:String? = null + var Longitude:String? = null + var ImageURL:String? = null + var IsCity:String? = null + + fun identifier():String{ + return "$GEOF_ID" + "_hmg" + } + + fun message():String{ + return Description ?: "nil" + } + + fun listFrom(jsonString: String) : List{ + val type = object : TypeToken?>() {}.getType() + return Gson().fromJson(jsonString, type) + } + + fun toGeofence() : Geofence?{ + if (!Latitude.isNullOrEmpty() && !Longitude.isNullOrEmpty() && Radius > 50) { + val lat = Latitude!!.trim().toDoubleOrNull() + val long = Longitude!!.trim().toDoubleOrNull() + val rad = Radius.toFloat() + if(lat != null && long != null){ + + return Geofence.Builder() + .setRequestId(identifier()) + .setCircularRegion( + lat, + long, + rad + ) + .setTransitionTypes(GeofenceTransition.ENTER_EXIT.value) +// .setNotificationResponsiveness(0) + .setExpirationDuration(Geofence.NEVER_EXPIRE) + .build() + } + } + return null + } + +} diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/GeofenceBroadcastReceiver.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/GeofenceBroadcastReceiver.kt new file mode 100644 index 00000000..8fc1faae --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/GeofenceBroadcastReceiver.kt @@ -0,0 +1,13 @@ + + +package com.cloud.diplomaticquarterapp.geofence + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent + +class GeofenceBroadcastReceiver : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + GeofenceTransitionsJobIntentService.enqueueWork(context, intent) + } +} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/GeofenceErrorMessages.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/GeofenceErrorMessages.kt new file mode 100644 index 00000000..4890f7cb --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/GeofenceErrorMessages.kt @@ -0,0 +1,34 @@ + + +package com.cloud.diplomaticquarterapp.geofence + +import android.content.Context +import com.cloud.diplomaticquarterapp.R +import com.google.android.gms.common.api.ApiException +import com.google.android.gms.location.GeofenceStatusCodes + +object GeofenceErrorMessages { + fun getErrorString(context: Context, e: Exception): String { + return if (e is ApiException) { + getErrorString(context, e.statusCode) + } else { + context.resources.getString(R.string.geofence_unknown_error) + } + } + + fun getErrorString(context: Context, errorCode: Int): String { + val resources = context.resources + return when (errorCode) { + GeofenceStatusCodes.GEOFENCE_NOT_AVAILABLE -> + resources.getString(R.string.geofence_not_available) + + GeofenceStatusCodes.GEOFENCE_TOO_MANY_GEOFENCES -> + resources.getString(R.string.geofence_too_many_geofences) + + GeofenceStatusCodes.GEOFENCE_TOO_MANY_PENDING_INTENTS -> + resources.getString(R.string.geofence_too_many_pending_intents) + + else -> resources.getString(R.string.geofence_unknown_error) + } + } +} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/GeofenceTransitionsJobIntentService.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/GeofenceTransitionsJobIntentService.kt new file mode 100644 index 00000000..f28e1720 --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/GeofenceTransitionsJobIntentService.kt @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2018 Razeware LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish, + * distribute, sublicense, create a derivative work, and/or sell copies of the + * Software in any work that is designed, intended, or marketed for pedagogical or + * instructional purposes related to programming, coding, application development, + * or information technology. Permission for such use, copying, modification, + * merger, publication, distribution, sublicensing, creation of derivative works, + * or sale is expressly withheld. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + +package com.cloud.diplomaticquarterapp.geofence + +import android.content.Context +import android.content.Intent +import android.location.Location +import android.util.Log +import androidx.core.app.JobIntentService +import com.cloud.diplomaticquarterapp.utils.API +import com.cloud.diplomaticquarterapp.utils.httpPost +import com.cloud.diplomaticquarterapp.utils.sendNotification +import com.github.kittinunf.fuel.core.extensions.jsonBody +import com.github.kittinunf.fuel.core.isSuccessful +import com.github.kittinunf.fuel.httpPost +import com.google.android.gms.location.Geofence +import com.google.android.gms.location.GeofencingEvent +import com.google.gson.Gson + +class GeofenceTransitionsJobIntentService : JobIntentService() { + + companion object { + private const val LOG_TAG = "GeoTrIntentService" + + private const val JOB_ID = 573 + + fun enqueueWork(context: Context, intent: Intent) { + enqueueWork( + context, + GeofenceTransitionsJobIntentService::class.java, JOB_ID, + intent) + } + } + + override fun onHandleWork(intent: Intent) { + val geofencingEvent = GeofencingEvent.fromIntent(intent) + if (geofencingEvent.hasError()) { + val errorMessage = GeofenceErrorMessages.getErrorString(this, geofencingEvent.errorCode) + Log.e(LOG_TAG, errorMessage) + return + } + + if (geofencingEvent.geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER || geofencingEvent.geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) { + handleEvent(geofencingEvent.triggeringGeofences,geofencingEvent.triggeringLocation, GeofenceTransition.fromInt(geofencingEvent.geofenceTransition)); + } + } + + private fun handleEvent(triggerGeofences: List, location:Location, transition:GeofenceTransition) { + val hmg = HMG_Geofence.shared(this) + hmg.getPatientID()?.let { patientId -> + + hmg.getActiveGeofences({ activeGeofences -> + + triggerGeofences.forEach { geofence -> + // Extract PointID from 'geofence.requestId' and find from active geofences + val pointID = activeGeofences.firstOrNull {it == geofence.requestId}?.split('_')?.first() + if(!pointID.isNullOrEmpty() && pointID.toIntOrNull() != null){ + + val body = mapOf( + "PointsID" to pointID.toIntOrNull(), + "GeoType" to transition.value, + "PatientID" to patientId + ) + + httpPost>(API.LOG_GEOFENCE, body, { response -> + sendNotification(this, transition.named(), geofence.requestId, "Notified to server.😎") + },{ exception -> + sendNotification(this, transition.named(), geofence.requestId, "Failed to notify server.😔") + }) + + } + } + + },null) + } + } +} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/GeofencingRebootBroadcastReceiver.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/GeofencingRebootBroadcastReceiver.kt new file mode 100644 index 00000000..08a0c93f --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/GeofencingRebootBroadcastReceiver.kt @@ -0,0 +1,27 @@ + + +package com.cloud.diplomaticquarterapp.geofence + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Message +import com.cloud.diplomaticquarterapp.geofence.HMG_Geofence +import com.cloud.diplomaticquarterapp.utils.HMGUtils + +class GeofencingRebootBroadcastReceiver : BroadcastReceiver(){ + override fun onReceive(context: Context, intent: Intent) { + + if (Intent.ACTION_BOOT_COMPLETED.equals(intent.action)) { + val pref = context.getSharedPreferences(PREFS_STORAGE, Context.MODE_PRIVATE) + pref.edit().putString("REBOOT_DETECTED","YES").apply() + + HMG_Geofence.shared(context).unRegisterAll { status, exception -> + val geoZones = HMGUtils.getGeoZonesFromPreference(context) + HMG_Geofence.shared(context).register(geoZones) + } + } + } + +} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/HMG_Geofence.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/HMG_Geofence.kt new file mode 100644 index 00000000..4d2c48b3 --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/HMG_Geofence.kt @@ -0,0 +1,165 @@ +package com.cloud.diplomaticquarterapp.geofence + +import android.Manifest +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import android.content.SharedPreferences +import android.content.pm.PackageManager +import androidx.core.content.ContextCompat +import com.google.android.gms.location.Geofence +import com.google.android.gms.location.GeofencingClient +import com.google.android.gms.location.GeofencingRequest +import com.google.android.gms.location.LocationServices +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +enum class GeofenceTransition(val value: Int) { + ENTER(1), + EXIT(2), + ENTER_EXIT((ENTER.value or EXIT.value)), + DWELL(4); + + companion object { + fun fromInt(value: Int) = GeofenceTransition.values().first { it.value == value } + } + + fun named():String{ + if (value == 1)return "Enter" + if (value == 2)return "Exit" + if (value == (ENTER.value or EXIT.value))return "Enter or Exit" + if (value == 4)return "dWell" + return "unknown" + } +} + +const val PREFS_STORAGE = "FlutterSharedPreferences" +const val PREF_KEY_SUCCESS = "HMG_GEOFENCE_SUCCESS" +const val PREF_KEY_FAILED = "HMG_GEOFENCE_FAILED" +const val PREF_KEY_HMG_ZONES = "flutter.hmg-geo-fences" + +class HMG_Geofence { + // https://developer.android.com/training/location/geofencing#java + + private lateinit var context: Context + private lateinit var preferences:SharedPreferences + private val gson = Gson() + + private lateinit var geofencingClient:GeofencingClient + private val geofencePendingIntent: PendingIntent by lazy { + val intent = Intent(context, GeofenceBroadcastReceiver::class.java) + PendingIntent.getBroadcast( + context, + 0, + intent, + PendingIntent.FLAG_UPDATE_CURRENT) + } + + companion object{ + + var instance: HMG_Geofence? = null + fun shared(context: Context) : HMG_Geofence { + if (instance == null) { + instance = HMG_Geofence() + instance?.context = context + instance?.geofencingClient = LocationServices.getGeofencingClient(context) + instance?.preferences = context.getSharedPreferences(PREFS_STORAGE, Context.MODE_PRIVATE) + } + return instance!! + } + } + + fun register(geoZones: List){ + if (geoZones.isEmpty()) + return + + fun buildGeofencingRequest(geofences: List): GeofencingRequest { + return GeofencingRequest.Builder() + .setInitialTrigger(0) + .addGeofences(geofences) + .build() + } + + getActiveGeofences({ active -> + + val geofences = mutableListOf() + geoZones.forEach { + it.toGeofence()?.let { geof -> + if(!active.contains(geof.requestId)){ // if not already registered then register + geofences.add(geof) + } + } + } + + if (checkPermission() && geofences.isNotEmpty()) { + geofencingClient + .addGeofences(buildGeofencingRequest(geofences), geofencePendingIntent) + .addOnSuccessListener { + saveActiveGeofence(geofences.map { it.requestId }, listOf()) + } + .addOnFailureListener { + print(it.localizedMessage) + } + } + },null) + } + + fun unRegisterAll(completion: (status: Boolean, exception:Exception?) -> Unit){ + getActiveGeofences({ success -> + val mList = success.toMutableList() + mList.add("12345") + geofencingClient + .removeGeofences(success) + .addOnSuccessListener { + completion(true, null) + } + .addOnFailureListener { + completion(false, it) + } + removeActiveGeofences() + }, { failed -> + // Nothing to do with failed geofences. + }) + } + + fun saveActiveGeofence(success: List, failed: List){ + val jsonSuccess = gson.toJson(success) + val jsonFailure = gson.toJson(failed) + preferences.edit().putString(PREF_KEY_SUCCESS, jsonSuccess).apply() + preferences.edit().putString(PREF_KEY_FAILED, jsonFailure).apply() + } + + fun removeActiveGeofences(){ + preferences.edit().putString(PREF_KEY_SUCCESS,"[]").apply() + preferences.edit().putString(PREF_KEY_FAILED,"[]").apply() + } + + fun getActiveGeofences(success: (success: List) -> Unit, failure: ((failed: List) -> Unit)?){ + val type = object : TypeToken?>() {}.type + + val jsonSuccess = preferences.getString(PREF_KEY_SUCCESS, "[]") + val success = gson.fromJson>(jsonSuccess, type) + success(success) + + if(failure != null){ + val jsonFailure = preferences.getString(PREF_KEY_FAILED, "[]") + val failed = gson.fromJson>(jsonFailure, type) + failure(failed) + } + + } + + private fun checkPermission() : Boolean{ + return ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED + } + + fun getPatientID():Int?{ + val profileJson = preferences.getString("flutter.imei-user-data", "{}") + val type = object : TypeToken?>() {}.type + return gson.fromJson?>(profileJson,type) + ?.get("PatientID") + .toString() + .toDoubleOrNull() + ?.toInt() + } +} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/hmgwifi/HMG_Guest.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/hmgwifi/HMG_Guest.kt new file mode 100644 index 00000000..61433596 --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/hmgwifi/HMG_Guest.kt @@ -0,0 +1,172 @@ +package com.cloud.diplomaticquarterapp.hmgwifi + +import android.content.Context +import android.net.ConnectivityManager +import android.net.wifi.WifiConfiguration +import android.net.wifi.WifiInfo +import android.net.wifi.WifiManager +import android.os.Build +import android.util.Log +import android.widget.Toast +import com.cloud.diplomaticquarterapp.MainActivity +import com.cloud.diplomaticquarterapp.utils.FlutterText +import com.cloud.diplomaticquarterapp.utils.HMGUtils + + +class HMG_Guest(context: MainActivity) { + private var wifiManager: WifiManager? = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager? + private var connectivityManager: ConnectivityManager? = context.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + private var context = context + + private val TAG = "HMG_Guest" + private val TEST = false + private var SSID = """"HMG-MobileApp"""" + + private lateinit var completionListener: ((status: Boolean, message: String) -> Unit) + + fun completionOnUiThread(status: Boolean, message: String){ + completionListener(status, message) + } + + /* + * Helpful: + * http://stackoverflow.com/questions/8818290/how-to-connect-to-a-specific-wifi-network-in-android-programmatically + */ + fun connectToHMGGuestNetwork(completion: (status: Boolean, message: String) -> Unit) { + wifiManager?.let { wm -> + completionListener = completion + + if (!wm.isWifiEnabled){ + wm.isWifiEnabled = true + HMGUtils.popFlutterText(context,"enablingWifi"); + HMGUtils.timer(2000,false){ + connect() + } + }else{ + connect() + } + + } + + } + + + private fun connect(){ + val security = "OPEN" + val networkPass = "" + Log.d(TAG, "Connecting to SSID \"$SSID\" with password \"$networkPass\" and with security \"$security\" ...") + + // You need to create WifiConfiguration instance like this: + val conf = WifiConfiguration() + conf.SSID = SSID + conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE) + conf.networkId = ssidToNetworkId(SSID) + + val wm = wifiManager!! + + if (conf.networkId == -1) { + wm.addNetwork(conf) + } else { + Log.v(TAG, "WiFi found - updating it.\n") + wm.updateNetwork(conf) + } + + conf.networkId = ssidToNetworkId(SSID) + Log.d(TAG, "Network ID: ${conf.networkId}") + + val networkIdToConnect = conf.networkId + if (networkIdToConnect >= 0) { + Log.v(TAG, "Start connecting to $SSID Wifi...") + + // We disable the network before connecting, because if this was the last connection before + // a disconnect(), this will not reconnect. + wm.disableNetwork(networkIdToConnect) + val result = wm.enableNetwork(networkIdToConnect, true) + if(result){ + HMGUtils.timer(8000,false){ + if(wm.getConnectionInfo().getSSID() == SSID){ + completionOnUiThread(true, "successConnectingHmgNetwork") + + }else{ + errorConnecting() + } + } + + }else{ + errorConnecting() + } + + + + }else{ + Log.v(TAG, "Cannot connect to $SSID network") + errorConnecting() + } + } + + private fun errorConnecting(){ + completionOnUiThread(false, "errorConnectingHmgNetwork") + } + + // If CompileSDK is greater and equals to APILevel 29 + private fun connectNewer(wm:WifiManager){ + +// Log.e(TAG, "connection wifi Q") +// +// val wifiNetworkSpecifier: WifiNetworkSpecifier = WifiNetworkSpecifier.Builder() +// .setSsid(ssid) +// .setWpa2Passphrase(password) +// .build() +// +// val networkRequest: NetworkRequest = NetworkRequest.Builder() +// .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) +// .setNetworkSpecifier(wifiNetworkSpecifier) +// .build() +// +// var connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager +// var networkCallback = object : ConnectivityManager.NetworkCallback() { +// override fun onAvailable(network: Network) { +// super.onAvailable(network) +// connectivityManager.bindProcessToNetwork(network) +// Log.e(TAG, "onAvailable") +// } +// +// override fun onLosing(network: Network, maxMsToLive: Int) { +// super.onLosing(network, maxMsToLive) +// Log.e(TAG, "onLosing") +// } +// +// override fun onLost(network: Network) { +// super.onLost(network) +// Log.e(TAG, "onLosing") +// Log.e(TAG, "losing active connection") +// } +// +// override fun onUnavailable() { +// super.onUnavailable() +// Log.e(TAG, "onUnavailable") +// } +// } +// connectivityManager.requestNetwork(networkRequest, networkCallback) + } + + + /** + * This method takes a given String, searches the current list of configured WiFi + * networks, and returns the networkId for the network if the SSID matches. If not, + * it returns -1. + */ + private fun ssidToNetworkId(ssid: String): Int { + val currentNetworks = wifiManager!!.configuredNetworks + var networkId = -1 + + // For each network in the list, compare the SSID with the given one + for (test in currentNetworks) { + if (test.SSID == ssid) { + networkId = test.networkId + break + } + } + return networkId + } +} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/hmgwifi/HMG_Internet.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/hmgwifi/HMG_Internet.kt new file mode 100644 index 00000000..332e60a5 --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/hmgwifi/HMG_Internet.kt @@ -0,0 +1,110 @@ +package com.cloud.diplomaticquarterapp.hmgwifi + +import android.annotation.SuppressLint +import com.cloud.diplomaticquarterapp.utils.API +import com.cloud.diplomaticquarterapp.MainActivity +import com.cloud.diplomaticquarterapp.utils.FlutterText +import com.github.kittinunf.fuel.core.extensions.jsonBody +import com.github.kittinunf.fuel.httpGet +import com.github.kittinunf.fuel.httpPost +import org.json.JSONObject +import java.util.* + + +@SuppressLint("MissingPermission") +class HMG_Internet(flutterMainActivity: MainActivity) { + private val TAG = "HMG_Wifi" + private val TEST = false + + private var context = flutterMainActivity; + + private lateinit var completionListener: ((status: Boolean, message: String) -> Unit) + + private var SSID = "GUEST-POC" + private var USER_NAME = "" + private var PASSWORD = "" + + fun completionOnUiThread(status: Boolean, message: String){ + completionListener(status, message) +// context.runOnUiThread { +// +// FlutterText.with(message){localized -> +// completionListener(status, localized) +// } +// } + } + + /* + * Helpful: + * http://stackoverflow.com/questions/8818290/how-to-connect-to-a-specific-wifi-network-in-android-programmatically + */ + fun connectToHMGGuestNetwork(patientId: String, completion: (status: Boolean, message: String) -> Unit): HMG_Internet { + completionListener = completion + getWifiCredentials(patientId) { + WPA(context,SSID).connect(USER_NAME,PASSWORD) { status, message -> + completionOnUiThread(status,message) + } + } + return this + } + + private fun haveInternet(completion: ((status: Boolean) -> Unit)){ + if (TEST) + completion(true) + + "https://captive.apple.com".httpGet().response { request, response, result -> + result.fold(success = { + val html = String(it).toLowerCase(Locale.ENGLISH) + .replace(" ", "", true) + .replace("\n","",true) + val have = html.contains("success", true) + completion(have) + + },failure = { + completion(false) + }) + } + } + + private fun getWifiCredentials(patientId:String, success: (() -> Unit)){ + if (TEST){ + SSID = "GUEST-POC" + USER_NAME = "0696" + PASSWORD = "0000" + success() + return + } + + val jsonBody = """{"PatientID":$patientId}""" + API.WIFI_CREDENTIALS. + httpPost() + .jsonBody(jsonBody, Charsets.UTF_8) + .response { request, response, result -> + + result.fold(success = { data -> + val jsonString = String(data) + val jsonObject = JSONObject(jsonString) + if(!jsonObject.getString("ErrorMessage").equals("null")){ + val errorMsg = jsonObject.getString("ErrorMessage") + completionOnUiThread(false, errorMsg) + + }else{ + jsonObject.getJSONArray("Hmg_SMS_Get_By_ProjectID_And_PatientIDList").let { array -> + array.getJSONObject(0).let { object_ -> + if (object_.has("UserName") && object_.has("UserName")){ + USER_NAME = object_.getString("UserName") + PASSWORD = object_.getString("Password") + success() + }else{ + completionOnUiThread(false, "somethingWentWrong") + } + } + } + } + + },failure = { error -> + completionOnUiThread(false, "somethingWentWrong" ) + }) + } + } +} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/hmgwifi/WPA.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/hmgwifi/WPA.kt new file mode 100644 index 00000000..86e67def --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/hmgwifi/WPA.kt @@ -0,0 +1,105 @@ +package com.cloud.diplomaticquarterapp.hmgwifi + +import android.annotation.SuppressLint +import android.content.Context +import android.net.ConnectivityManager +import android.net.wifi.* +import android.net.wifi.SupplicantState.ASSOCIATED +import android.net.wifi.SupplicantState.COMPLETED +import android.util.Log +import com.cloud.diplomaticquarterapp.MainActivity +import com.cloud.diplomaticquarterapp.utils.HMGUtils + +class WPA(mainActivity: MainActivity, SSID:String) { + private var TAG = "WPA" + private var SSID = "GUEST-POC" + private var wifiManager_: WifiManager? = null + private var connectivityManager_: ConnectivityManager? = null + + init { + wifiManager_ = mainActivity.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager? + connectivityManager_ = mainActivity.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + } + + fun connect(identity:String, password:String, completion: (status: Boolean, message: String) -> Unit) { + if(wifiManager_ == null || connectivityManager_ == null){ + completion(false,"errorConnectingHmgNetwork") + return + } + + val wifiManager = wifiManager_!! + val connectivityManager = connectivityManager_!! + + // Initialize the WifiConfiguration object + val enterpriseConfig = WifiEnterpriseConfig() + val wifi = WifiConfiguration() + wifi.SSID = """"$SSID"""" + wifi.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP) + wifi.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X) + enterpriseConfig.eapMethod = WifiEnterpriseConfig.Eap.PEAP + enterpriseConfig.identity = identity + enterpriseConfig.password = password + wifi.enterpriseConfig = enterpriseConfig + wifi.networkId = ssidToNetworkId(wifi.SSID) + if (wifi.networkId == -1) { + wifiManager.addNetwork(wifi) + } else { + Log.v(TAG, "WiFi found - updating it.\n") + wifiManager.updateNetwork(wifi) + } + Log.v(TAG, "saving config.\n") + wifiManager.saveConfiguration() + wifi.networkId = ssidToNetworkId(wifi.SSID) + + Log.v(TAG, "wifi ID in device = " + wifi.networkId) + + var supState: SupplicantState + val networkIdToConnect = wifi.networkId + if (networkIdToConnect >= 0) { + Log.v(TAG, "Start connecting...\n") + + // We disable the network before connecting, because if this was the last connection before + // a disconnect(), this will not reconnect. + wifiManager.disableNetwork(networkIdToConnect) + wifiManager.enableNetwork(networkIdToConnect, true) + + val wifiInfo: WifiInfo = wifiManager.connectionInfo + + HMGUtils.timer(5000,false){ + supState = wifiInfo.supplicantState + Log.i(TAG, "WifiWizard: Done connect to network : status = $supState") + val successStates = listOf(COMPLETED, ASSOCIATED) + if (successStates.contains(COMPLETED /*supState*/)) + + completion(true,"Connected to internet Wifi") + + else + completion(false,"errorConnectingHmgNetwork") + } + + } else { + Log.v(TAG, "WifiWizard: cannot connect to network") + completion(false,"errorConnectingHmgNetwork") + } + } + + /** + * This method takes a given String, searches the current list of configured WiFi + * networks, and returns the networkId for the network if the SSID matches. If not, + * it returns -1. + */ + @SuppressLint("MissingPermission") + private fun ssidToNetworkId(ssid: String): Int { + val currentNetworks = wifiManager_!!.configuredNetworks + var networkId = -1 + + // For each network in the list, compare the SSID with the given one + for (test in currentNetworks) { + if (test.SSID == ssid) { + networkId = test.networkId + break + } + } + return networkId + } +} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/API.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/API.kt new file mode 100644 index 00000000..30f57dde --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/API.kt @@ -0,0 +1,11 @@ +package com.cloud.diplomaticquarterapp.utils + +class API { + companion object{ + private val BASE = "https://uat.hmgwebservices.com" + private val SERVICE = "Services/Patients.svc/REST" + + val WIFI_CREDENTIALS = "$BASE/$SERVICE/Hmg_SMS_Get_By_ProjectID_And_PatientID" + val LOG_GEOFENCE = "$BASE/$SERVICE/GeoF_InsertPatientFileInfo" + } +} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/FlutterText.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/FlutterText.kt new file mode 100644 index 00000000..419eb340 --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/FlutterText.kt @@ -0,0 +1,36 @@ +package com.cloud.diplomaticquarterapp.utils + +import io.flutter.plugin.common.MethodChannel +import io.flutter.plugin.common.MethodChannel.Result + +class FlutterText{ + + companion object{ + fun with(key:String, completion:(String)->Unit){ + HMGUtils.getPlatformChannel().invokeMethod("localizedValue",key, object:MethodChannel.Result{ + override fun success(result: Any?) { + val localized = result as String? + if (localized != null){ + completion(localized) + }else{ + completion(key) + } + } + + override fun error(errorCode: String?, errorMessage: String?, errorDetails: Any?) { + completion(key) + require(false){ + "'localizedValue' $errorMessage" + } + } + + override fun notImplemented() { + require(false){ + "'localizedValue' method not implemented at flutter" + } + } + + }) + } + } +} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/HMGUtils.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/HMGUtils.kt new file mode 100644 index 00000000..ceecd65b --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/HMGUtils.kt @@ -0,0 +1,160 @@ +package com.cloud.diplomaticquarterapp.utils + +import android.app.NotificationChannel +import android.app.NotificationManager +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import android.os.Build +import android.widget.Toast +import androidx.annotation.Nullable +import androidx.core.app.NotificationCompat +import androidx.core.app.TaskStackBuilder +import com.cloud.diplomaticquarterapp.BuildConfig +import com.cloud.diplomaticquarterapp.MainActivity +import com.cloud.diplomaticquarterapp.R +import com.cloud.diplomaticquarterapp.geofence.GeoZoneModel +import com.cloud.diplomaticquarterapp.geofence.PREFS_STORAGE +import com.cloud.diplomaticquarterapp.geofence.PREF_KEY_HMG_ZONES +import com.github.kittinunf.fuel.core.extensions.jsonBody +import com.github.kittinunf.fuel.httpPost +import com.google.android.gms.location.Geofence +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import io.flutter.plugin.common.MethodChannel +import org.json.JSONArray +import org.json.JSONException +import org.json.JSONObject +import java.util.* +import kotlin.concurrent.timerTask + + +class HMGUtils { + + companion object{ + private lateinit var platformChannel: MethodChannel + fun getPlatformChannel():MethodChannel{ + return platformChannel + } + fun setPlatformChannel(channel: MethodChannel){ + platformChannel = channel + } + + fun timer(delay: Long, repeat: Boolean, tick: (Timer) -> Unit) : Timer{ + val timer = Timer() + if(repeat) + timer.schedule(timerTask { + tick(timer) + }, delay, delay) + else + timer.schedule(timerTask { + tick(timer) + }, delay) + + return timer + } + + fun popMessage(context: MainActivity, message: String){ + context.runOnUiThread { + Toast.makeText(context, message, Toast.LENGTH_LONG).show() + } + } + + fun popFlutterText(context: MainActivity, key: String){ + context.runOnUiThread { + FlutterText.with(key){ + Toast.makeText(context, it, Toast.LENGTH_LONG).show() + } + } + } + + fun getGeoZonesFromPreference(context: Context): List { + val pref = context.getSharedPreferences(PREFS_STORAGE, Context.MODE_PRIVATE) + val json = pref.getString(PREF_KEY_HMG_ZONES,"[]") + + val geoZones = json?.let { GeoZoneModel().listFrom(it) } + return geoZones!! + } + + } + +} + +private fun Timer.schedule(timerTask: TimerTask) { + +} +private const val NOTIFICATION_CHANNEL_ID = BuildConfig.APPLICATION_ID + ".channel" + +fun sendNotification(context: Context, title:String, @Nullable subtitle:String?, message:String?) { + val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O + && notificationManager.getNotificationChannel(NOTIFICATION_CHANNEL_ID) == null) { + val name = context.getString(R.string.app_name) + val channel = NotificationChannel(NOTIFICATION_CHANNEL_ID, + name, + NotificationManager.IMPORTANCE_DEFAULT) + + notificationManager.createNotificationChannel(channel) + } + + val intent = Intent(context, MainActivity::class.java) + + val stackBuilder = TaskStackBuilder.create(context) + .addParentStack(MainActivity::class.java) + .addNextIntent(intent) + val notificationPendingIntent = stackBuilder.getPendingIntent(getUniqueId(), PendingIntent.FLAG_UPDATE_CURRENT) + + val notification = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) + .setSmallIcon(R.mipmap.ic_launcher) + .setContentIntent(notificationPendingIntent) + .setAutoCancel(true) + .setContentTitle(title) + + subtitle.let { notification.setContentText(it) } + message.let { notification.setSubText(it) } + + notificationManager.notify(getUniqueId(), notification.build()) +} + + +private fun getUniqueId() = ((System.currentTimeMillis() % 10000).toInt()) + +fun isJSONValid(jsonString: String?): Boolean { + try { JSONObject(jsonString) } catch (ex: JSONException) { + try { JSONArray(jsonString) } catch (ex1: JSONException) { + return false + } + } + return true +} + +class HTTPResponse(data: T){ + final var data:T = data +} +fun httpPost(url: String, body: Map, onSuccess: (response: HTTPResponse) -> Unit, onError: (error: Exception) -> Unit){ + + val gson = Gson() + val type = object : TypeToken() {}.type + val jsonBody = gson.toJson(body) + url.httpPost() + .jsonBody(jsonBody, Charsets.UTF_8) + .timeout(10000) + .header("Content-Type","application/json") + .header("Allow","*/*") + .response { request, response, result -> + result.fold({ data -> + val dataString = String(data) + if(isJSONValid(dataString)){ + val responseData = gson.fromJson(dataString,type) + onSuccess(HTTPResponse(responseData)) + }else{ + onError(Exception("Invalid response from server (Not a valid JSON)")) + } + }, { + onError(it) + it.localizedMessage + }) + + } +} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/HMG_Wifi_.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/HMG_Wifi_.kt new file mode 100644 index 00000000..decc9bdf --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/HMG_Wifi_.kt @@ -0,0 +1,351 @@ +//package com.cloud.diplomaticquarterapp.utils +// +//import android.annotation.SuppressLint +//import android.content.Context +//import android.net.ConnectivityManager +//import android.net.Network +//import android.net.NetworkCapabilities +//import android.net.NetworkRequest +//import android.net.wifi.ScanResult +//import android.net.wifi.WifiConfiguration +//import android.net.wifi.WifiManager +//import android.util.Log +//import com.cloud.diplomaticquarterapp.utils.API +//import com.cloud.diplomaticquarterapp.FlutterMainActivity +//import com.github.kittinunf.fuel.core.extensions.jsonBody +//import com.github.kittinunf.fuel.httpGet +//import com.github.kittinunf.fuel.httpPost +//import org.json.JSONObject +//import java.util.* +// +// +//@SuppressLint("MissingPermission") +//class HMG_Wifi_(flutterMainActivity: FlutterMainActivity) { +// val TAG = "WIFI" +// val TEST = true +// +// var context = flutterMainActivity; +// var completionListener: ((status: Boolean, message: String) -> Unit)? = null +// +// +// private var SSID = "HMG-GUEST" +// private var USER_NAME = "" +// private var PASSWORD = "" +// var NETWORK_ID = -1 // HMG-GUEST Assigned Network ID by Android +// private lateinit var PATIENT_ID:String +// /* +// * Helpful: +// * http://stackoverflow.com/questions/5452940/how-can-i-get-android-wifi-scan-results-into-a-list +// */ +// fun triggerWifiScan(context: Context) { +// val wifi = context.getSystemService(Context.WIFI_SERVICE) as WifiManager +// wifi.startScan() +// } +// +// /* +// * Helpful: +// * http://stackoverflow.com/questions/8818290/how-to-connect-to-a-specific-wifi-network-in-android-programmatically +// */ +// fun connectToWifiNetworkWith(patientId: String): HMG_Wifi_ { +// +// val connectivityManager = context.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager +// +// PATIENT_ID = patientId +// +// val security = "OPEN" +// val networkPass = "" +// Log.d(TAG, "Connecting to SSID \"$SSID\" with password \"$networkPass\" and with security \"$security\" ...") +// +// // You need to create WifiConfiguration instance like this: +// val conf = WifiConfiguration() +// conf.SSID = "\"" + SSID + "\"" +// +// if (security == "OPEN") { +// conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE) +// } else if (security == "WEP") { +// conf.wepKeys[0] = "\"" + networkPass + "\"" +// conf.wepTxKeyIndex = 0 +// conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE) +// conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40) +// } else { +// conf.preSharedKey = "\"" + networkPass + "\"" +// } +// +// // Then, you need to add it to Android wifi manager settings: +// val wifiManager = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager +// +// NETWORK_ID = wifiManager.addNetwork(conf) +// Log.d(TAG, "Network ID: $NETWORK_ID") +// +// //wifiManager.disconnect(); +// val result = wifiManager.enableNetwork(NETWORK_ID, true) +// //wifiManager.reconnect(); +// wifiManager.saveConfiguration() +// +// if(result == true){ +// authNetworkConnection(NETWORK_ID); +// }else{ +// completionListener?.let { it(false, "Error connecting to HMG network") } +// } +// return this +// } +// +// private var authTimer:Timer? = null +// fun authNetworkConnection(networkId: Int){ +// authTimer = Timer() +// authTimer?.scheduleAtFixedRate(object : TimerTask() { +// override fun run() { +// if (connectedNetworkId() == networkId && connectedNetworkIPAddress() > 0) { +// authServerCall() +// authTimer?.cancel() +// } +// } +// +// }, 2000, 1000) +// +// // If wifi not connected in 5 sec terminate with fail status +// Timer().schedule(object : TimerTask() { +// override fun run() { +// if (null != authTimer) { +// authTimer?.cancel() +// completionListener?.let { it(false, "Error connecting to HMG network") } +// } +// } +// }, 5000) +// +// } +// +// fun authServerCall(){ +// +// fun call(){ +// +// forceNetworkCallOverWifi() +// +// val params = listOf("cmd" to "authenticate", "password" to PASSWORD, "user" to USER_NAME) +// val serverUrl = "https://captiveportal-login.hmg.com/cgi-bin/login" +//// val serverUrl = "http://192.168.102.223/cgi-bin/login" +// serverUrl +// .httpPost(params) +// .timeout(10000) +// .response { request, response, result -> +// Log.v(TAG, response.statusCode.toString()) +// +// haveInternet { have -> +// if(have){ +// Log.v(TAG, "Connected to internet via $SSID network at HMG") +// completionListener?.let { it(true, "Successfully connected to the internet") } +// }else{ +// Log.e(TAG, "failed to connect to internet via $SSID network at HMG") +// completionListener?.let { it(false, "Authentication failed or you are already using your credentials on another device") } +// } +// } +// } +// } +// +// haveInternet { has -> +// if (has){ +// getAuthCredentials { +// call() +// } +// }else{ +// completionListener?.let { it(false, "You must have active internet connection to connect with HMG Network") } +// } +// } +// } +// +// fun haveInternet(completion: ((status: Boolean) -> Unit)){ +// if (TEST) +// completion(true) +// +// "https://captive.apple.com".httpGet().response { request, response, result -> +// val have = response.statusCode == 200 && String(response.data).contains("Success", true) +// completion(have) +// } +// } +// +// fun getAuthCredentials(completion: (() -> Unit)){ +// if (TEST){ +// USER_NAME = "2300" +// PASSWORD = "1820" +// completion() +// return +// } +// +// val jsonBody = """{"PatientID":$PATIENT_ID}""" +// API.WIFI_CREDENTIALS +// .httpPost() +// .jsonBody(jsonBody, Charsets.UTF_8) +// .response { request, response, result -> +// val jsonString = String(response.data) +// Log.d(TAG, "JSON $jsonString") +// +// if (response.statusCode == 200){ +// +// val jsonObject = JSONObject(jsonString) +// if(!jsonObject.getString("ErrorMessage").equals("null")){ +// val errorMsg = jsonObject.getString("ErrorMessage") +// completionListener?.let { it(false, errorMsg) } +// +// }else{ +// jsonObject.getJSONArray("Hmg_SMS_Get_By_ProjectID_And_PatientIDList").let { array -> +// array.getJSONObject(0).let { object_ -> +// if (object_.has("UserName") && object_.has("UserName")){ +// USER_NAME = object_.getString("UserName") +// PASSWORD = object_.getString("Password") +// completion() +// }else{ +// completionListener?.let { it(false, "Failed to get your internet credentials") } +// } +// } +// } +// } +// +// }else{ +// completionListener?.let { it(false, "Failed to get your internet credentials") } +// } +// } +// } +// +// fun forceNetworkCallOverWifi(){ +// val connectivityManager = context.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager +//// val network = Network +//// connectivityManager.activeNetwork +// // Exit app if Network disappears. +// // Exit app if Network disappears. +//// val networkCapabilities: NetworkCapabilities = ConnectivityManager.from(context).getNetworkCapabilities(network) +//// val networkCapabilities: NetworkCapabilities = connectivityManager.getNetworkCapabilities(network) +// +//// if (networkCapabilities == null) { +//// return +//// } +// +// val mNetworkCallback = object : ConnectivityManager.NetworkCallback() { +// override fun onLost(lostNetwork: Network?) { +//// if (network.equals(lostNetwork)){ +//// //GlyphLayout.done(false) +//// } +// } +// } +// val builder: NetworkRequest.Builder = NetworkRequest.Builder() +//// for (transportType in networkCapabilities.getTransportTypes()) { +//// builder.addTransportType(transportType) +//// } +// connectivityManager.registerNetworkCallback(builder.build(), mNetworkCallback) +// } +// +// /* +// * Helpful: +// * http://stackoverflow.com/questions/6517314/android-wifi-connection-programmatically +// */ +// fun getScanResultSecurity(result: ScanResult): String? { +// val capabilities: String = result.capabilities +// val securityModes = arrayOf("WEP", "PSK", "EAP") +// for (securityMode in securityModes) { +// if (capabilities.contains(securityMode)) { +// return securityMode +// } +// } +// return "OPEN" +// } +// +// //connects to the given ssid +// fun connectToWPAWiFi(ssid: String, password: String){ +// +// WifiUtils.withContext(context) +// .connectWith(ssid, "") +// .setTimeout(40000) +// .onConnectionResult(object : ConnectionSuccessListener { +// override fun success() { +// Log.v(TAG,"Success") +// } +// +// override fun failed(@NonNull errorCode: ConnectionErrorCode) { +// Log.v(TAG,"Failed") +// } +// }) +// .start() +// if(isConnectedTo(ssid)){ //see if we are already connected to the given ssid +// return +// } +// +// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { +// Log.e(TAG, "connection wifi Q") +// +// val wifiNetworkSpecifier: WifiNetworkSpecifier = WifiNetworkSpecifier.Builder() +// .setSsid(ssid) +// .setWpa2Passphrase(password) +// .build() +// +// val networkRequest: NetworkRequest = NetworkRequest.Builder() +// .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) +// .setNetworkSpecifier(wifiNetworkSpecifier) +// .build() +// +// var connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager +// var networkCallback = object : ConnectivityManager.NetworkCallback() { +// override fun onAvailable(network: Network) { +// super.onAvailable(network) +// connectivityManager.bindProcessToNetwork(network) +// Log.e(TAG, "onAvailable") +// } +// +// override fun onLosing(network: Network, maxMsToLive: Int) { +// super.onLosing(network, maxMsToLive) +// Log.e(TAG, "onLosing") +// } +// +// override fun onLost(network: Network) { +// super.onLost(network) +// Log.e(TAG, "onLosing") +// Log.e(TAG, "losing active connection") +// } +// +// override fun onUnavailable() { +// super.onUnavailable() +// Log.e(TAG, "onUnavailable") +// } +// } +// connectivityManager.requestNetwork(networkRequest, networkCallback) +// +// }else{ +// +// try { +// val wm:WifiManager= context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager +// +// Log.e(TAG, "connection wifi pre Q") +// +// var netId: Int = wm.addNetwork(getWifiConfig(ssid)) +// if (netId == -1) netId = getExistingNetworkId(ssid); +// wm.saveConfiguration() +// if(wm.enableNetwork(netId, true)){ +// Log.v(TAG,"HMG-GUEST Connected") +// }else{ +// Log.v(TAG,"HMG-GUEST failed to connect") +// } +// } catch (e: Exception) { +// e.printStackTrace() +// Log.v(TAG,"HMG-GUEST failed to connect") +// } +// } +// +// } +// +// fun connectedNetworkId():Int{ +// val wm:WifiManager= context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager +// return wm.connectionInfo.networkId +// } +// +// fun connectedNetworkIPAddress():Int{ +// val wm:WifiManager= context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager +// return wm.connectionInfo.ipAddress +// } +// +// fun isConnectedTo(bssid: String):Boolean{ +// val wm:WifiManager= context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager +// if(wm.connectionInfo.bssid == bssid){ +// return true +// } +// return false +// } +// +//} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/PlatformBridge.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/PlatformBridge.kt new file mode 100644 index 00000000..ed1a62c8 --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/PlatformBridge.kt @@ -0,0 +1,127 @@ +package com.cloud.diplomaticquarterapp.utils + +import android.content.Context +import android.net.wifi.WifiManager +import android.util.Log +import com.cloud.diplomaticquarterapp.MainActivity +import com.cloud.diplomaticquarterapp.hmgwifi.HMG_Guest +import com.cloud.diplomaticquarterapp.hmgwifi.HMG_Internet +import com.cloud.diplomaticquarterapp.geofence.GeoZoneModel +import com.cloud.diplomaticquarterapp.geofence.HMG_Geofence +import io.flutter.plugin.common.BinaryMessenger +import io.flutter.plugin.common.MethodCall +import io.flutter.plugin.common.MethodChannel + +class PlatformBridge(binaryMessenger: BinaryMessenger, flutterMainActivity: MainActivity) { + private var binaryMessenger = binaryMessenger + private var mainActivity = flutterMainActivity + + private lateinit var channel: MethodChannel + + companion object { + private const val CHANNEL = "HMG-Platform-Bridge" + private const val HMG_INTERNET_WIFI_CONNECT_METHOD = "connectHMGInternetWifi" + private const val HMG_GUEST_WIFI_CONNECT_METHOD = "connectHMGGuestWifi" + private const val ENABLE_WIFI_IF_NOT = "enableWifiIfNot" + private const val REGISTER_HMG_GEOFENCES = "registerHmgGeofences" + private const val UN_REGISTER_HMG_GEOFENCES = "unRegisterHmgGeofences" + } + + fun create(){ + channel = MethodChannel(binaryMessenger, CHANNEL) + HMGUtils.setPlatformChannel(channel) + channel.setMethodCallHandler { methodCall: MethodCall, result: MethodChannel.Result -> + + if (methodCall.method == HMG_INTERNET_WIFI_CONNECT_METHOD) { + connectHMGInternetWifi(methodCall,result) + + }else if (methodCall.method == HMG_GUEST_WIFI_CONNECT_METHOD) { + connectHMGGuestWifi(methodCall,result) + + }else if (methodCall.method == ENABLE_WIFI_IF_NOT) { + enableWifiIfNot(methodCall,result) + }else if (methodCall.method == REGISTER_HMG_GEOFENCES) { + registerHmgGeofences(methodCall,result) + }else if (methodCall.method == UN_REGISTER_HMG_GEOFENCES) { + unRegisterHmgGeofences(methodCall,result) + }else{ + + result.notImplemented() + } + + } + + val res = channel.invokeMethod("localizedValue","errorConnectingHmgNetwork") + print(res) + } + + private fun connectHMGInternetWifi(methodCall: MethodCall, result: MethodChannel.Result){ + (methodCall.arguments as ArrayList<*>).let { + require(it.size > 0 && (it[0] is String),lazyMessage = { + "Missing or invalid arguments (Must have one argument 'String at 0'" + }) + + val patientId = it[0].toString() + HMG_Internet(mainActivity) + .connectToHMGGuestNetwork(patientId){ status, message -> + + mainActivity.runOnUiThread { + result.success(if(status) 1 else 0) + + HMGUtils.popFlutterText(mainActivity, message) + Log.v(this.javaClass.simpleName, "$status | $message") + } + + } + } + } + + + private fun connectHMGGuestWifi(methodCall: MethodCall, result: MethodChannel.Result){ + HMG_Guest(mainActivity).connectToHMGGuestNetwork { status, message -> + mainActivity.runOnUiThread { + result.success(if(status) 1 else 0) + + HMGUtils.popFlutterText(mainActivity, message) + Log.v(this.javaClass.simpleName, "$status | $message") + } + } + } + + private fun enableWifiIfNot(methodCall: MethodCall, result: MethodChannel.Result) { + val wm = mainActivity.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager? + if (wm != null){ + if (!wm.isWifiEnabled) + wm.isWifiEnabled = true + result.success(true) + }else + result.error("101","Error while opening wifi, Please try to open wifi yourself and try again","'WifiManager' service failed"); + } + + + private fun registerHmgGeofences(methodCall: MethodCall, result: MethodChannel.Result) { + + channel.invokeMethod("getGeoZones",null, object : MethodChannel.Result{ + override fun success(result: Any?) { + if(result is String) { + val geoZones = GeoZoneModel().listFrom(result) + HMG_Geofence.shared(mainActivity).register(geoZones) + } + } + + override fun error(errorCode: String?, errorMessage: String?, errorDetails: Any?) { print(result) } + override fun notImplemented() { print(result) } + }) + + } + + private fun unRegisterHmgGeofences(methodCall: MethodCall, result: MethodChannel.Result) { + HMG_Geofence.shared(mainActivity).unRegisterAll { status, exception -> + if(status) + result.success(true) + else + result.error("101", exception?.localizedMessage, exception); + } + } + +} diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png index 81bc6ebbc58a6bb19f39e1301241dcbf83146b9f..db77bb4b7b0906d62b1847e87f15cdcacf6a4f29 100644 GIT binary patch literal 544 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAj~WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!h8bpbvhu0Wd6uZuB!w&u2PAxD2eNXD>P5D~Wn-+_Wa#27Xc zC?Zj|6r#X(-D3u$NCt}(Ms06KgJ4FxJVv{GM)!I~&n8Bnc94O7-Hd)cjDZswgC;Qs zO=b+9!WcT8F?0rF7!Uys2bs@gozCP?z~o%U|N3vA*22NaGQG zlg@K`O_XuxvZ&Ks^m&R!`&1=spLvfx7oGDKDwpwW`#iqdw@AL`7MR}m`rwr|mZgU`8P7SBkL78fFf!WnuYWm$5Z0 zNXhDbCv&49sM544K|?c)WrFfiZvCi9h0O)B3Pgg&ebxsLQ05GG~ AQ2+n{ literal 3287 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 Vd9uLGJ)-~s002ovPDHLkV1ljaHBbNm diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png index a35f0ed789cd85017f50cff69ef39c384dbb7d4f..17987b79bb8a35cc66c3c1fd44f5a5526c1b78be 100644 GIT binary patch literal 442 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5Xx&nMcT!A!W`0S9QKQy;}1Cl^CgaH=;G9cpY;r$Q>i*pfB zP2drbID<_#qf;rPZx^FqH)F_D#*k@@q03KywUtLX8Ua?`H+NMzkczFPK3lFz@i_kW%1NOn0|D2I9n9wzH8m|-tHjsw|9>@K=iMBhxvkv6m8Y-l zytQ?X=U+MF$@3 zt`~i=@j|6y)RWMK--}M|=T`o&^Ni>IoWKHEbBXz7?A@mgWoL>!*SXo`SZH-*HSdS+ yn*9;$7;m`l>wYBC5bq;=U}IMqLzqbYCidGC!)_gkIk_C@U6?>1YX@$pE5i39wiXjY0Mnb*kX{R04e(iCN)o+ipnzxYWl zpXWJnjSm0758IYz{zNjh0QCS^3(EfZu8%iA&4d0)7eBc2Dg~t*SuNqO>KP+XkgWqi z8c#|N;d~oQmw(QD1ppaGxwHUGPi*-u-xr^>NfsY=VbY1Qe!wGv1!4h!WRRlPuJ&bn zpI=Y}g%9F$_Od@-QdP>^9rIQ03}JmTS~$xE=pc;>>BYcmp}h!jp8mc2mt{Q$z%47S z1rYb>_9Hc%%{E~$>Ih5fSzm`L3d{%qh{jRJ9q;Ksb$@VK)(il>dH@Jad|pXa4QF?Z zXCq24a0jzKYg0XAsGqUE0;Y^eK&RV_3!Qz88a(`NSN);<*#w|ljwsdx^f_TkNmaGU zCIVm;PqbN-dyWG*=1X=QE$ro);Fn3pi+oMATS4>v@)(AO4vQI&j7>tp#L;-I;tbBU z_c1yc1%FUnRc*36#xdG7LLq4>tBFHV4goM$xIeCLKt)Tt;6pi!rN%q(_1sBeD<^9cEdU{< z8=_EgRkaL2whwtA5&#=c{Ds|3S5*KW7?p^%Gk@<2={fBeY5<}k_WqXW>USf9j11K@0j7{szC4FOopctB18M4{qb;}jA-5CA~dn;xMDUf5rU3!Sb2 z019@Z&|n@=05I8sJW!lF#c&J|fU>4GRqGHv0Hz2U0#HO0vWsms&Ou_4?kbHf<782yPN}#w05AmTWx)z4j2W%NxhKP zTI{Q`hwhZQM9?LlKcJJyIj&DR3TD?uN~JZvI}8h?OV z@qkF#LsTQ;tQJG`UUKQ2Y!WFcGGva}T+r$_MR$8MtW11}s@5e0;YeWEO zFOgeX1CLK!NpJI`er}LL1VG))se5(JYQn->qX0m17VoS315U*;SVZ1$$3mK-twvxycBH<`ac99x!tp zb}X3+vbd3JeQgs;rDjeZPtDv1I#dfKZ~3n$gS=qK16ly&32NpD00A*_eNo$lT?_!K zvNKX513;DhY`gOIL`;50J%0d=2ciYQzB0XG0On~a!~-^S;1A6H;<^Zw_DTvkWG*M`0Ub^uZkN~im?0*G7 z*{3uD0G}UM2QgKH=_!f$D08Bb93YH|nnKxy<<;6CrhdMR02oZ8?|&XSkKbE6nC2Kr zOK{@b?EC(E0CNhr3YRuYSdtp>&fdqSarA_KKA{n#3g#Mm8sKGu;OG{ zFCRP|T^f}Eu)8r@AY8M?I;Pj_6O^xBM678N3V)63O3UG+s|pI>al0AJBhuZSn1B761SM07*qoM6N<$g8A5c?f?J) diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png index 4bfdccb83767609cda095e74875f6bff50e914a8..09d4391482be68e9e4a07fab769b5de337d16eb1 100644 GIT binary patch literal 721 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD3?#3*wSy!iOI#yLg7ec#$`gxH85~pclTsBt za}(23gHjVyDhp4h+5i=O3-AeX1=1l$e`s#|#^}+&7(N@w0CIr{$Oe+Uk^K-ZP~83C zcc@hG6rikF&NPT(23>y!y&wkt5C($~2D>~)O*cj@FGjOCM)M>_ixfudOh)?xMu#Fs z#}Y=@YDTwOM)x{K_j*Q;dPdJ?Mz0n|pLRx{4n|)f>SXlmV)XB04CrSJn#dS5nK2lM zrZ9#~WelCp7&e13Y$jvaEXHskn$2V!!DN-nWS__6T*l;H&Fopn?A6HZ-6WRLFP=R` zqG+CE#d4|IbyAI+rJJ`&x9*T`+a=p|0O(+s{UBcyZdkhj=yS1>AirP+0R;mf2uMgM zC}@~JfByORAh4SyRgi&!(cja>F(l*O+nd+@4m$|6K6KDn_&uvCpV23&>G9HJp{xgg zoq1^2_p9@|WEo z*X_Uko@K)qYYv~>43eQGMdbiGbo>E~Q& zrYBH{QP^@Sti!`2)uG{irBBq@y*$B zi#&(U-*=fp74j)RyIw49+0MRPMRU)+a2r*PJ$L5roHt2$UjExCTZSbq%V!HeS7J$N zdG@vOZB4v_lF7Plrx+hxo7(fCV&}fHq)$ literal 4315 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 JPDHLkV1l(q`MLlA diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index fc595a387b91d6c5bc60f062c8b9a684efbc5ccb..d5f1c8d34e7a88e3f88bea192c3a370d44689c3c 100644 GIT binary patch literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q8Ax83A=Cw=BuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFa`(sgt!6~Yi|1%a`XoT0ojZ}lNrNjb9xjc(B0U1_% zz5^97Xt*%oq$rQy4?0GKNfJ44uvxI)gC`h-NZ|&0-7(qS@?b!5r36oQ}zyZrNO3 zMO=Or+<~>+A&uN&E!^Sl+>xE!QC-|oJv`ApDhqC^EWD|@=#J`=d#Xzxs4ah}w&Jnc z$|q_opQ^2TrnVZ0o~wh<3t%W&flvYGe#$xqda2bR_R zvPYgMcHgjZ5nSA^lJr%;<&0do;O^tDDh~=pIxA#coaCY>&N%M2^tq^U%3DB@ynvKo}b?yu-bFc-u0JHzced$sg7S3zqI(2 z#Km{dPr7I=pQ5>FuK#)QwK?Y`E`B?nP+}U)I#c1+FM*1kNvWG|a(TpksZQ3B@sD~b zpQ2)*V*TdwjFOtHvV|;OsiDqHi=6%)o4b!)x$)%9pGTsE z-JL={-Ffv+T87W(Xpooq<`r*VzWQcgBN$$`u}f>-ZQI1BB8ykN*=e4rIsJx9>z}*o zo~|9I;xof literal 7926 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 diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index 605c7e4a7772aba3eca43f602084b513da944907..4d6372eebdb28e45604e46eeda8dd24651419bc0 100644 GIT binary patch literal 1443 zcmb`G{WsKk6vsdJTdFg%tJav9_E4vzrOaqkWF|A724Nly!y+?N9`YV6wZ}5(X(D_N(?!*n3`|_r0Hc?=PQw&*vnU?QTFY zB_MsH|!j$PP;I}?dppoE_gA(4uc!jV&0!l7_;&p2^pxNo>PEcNJv za5_RT$o2Mf!<+r?&EbHH6nMoTsDOa;mN(wv8RNsHpG)`^ymG-S5By8=l9iVXzN_eG%Xg2@Xeq76tTZ*dGh~Lo9vl;Zfs+W#BydUw zCkZ$o1LqWQO$FC9aKlLl*7x9^0q%0}$OMlp@Kk_jHXOjofdePND+j!A{q!8~Jn+s3 z?~~w@4?egS02}8NuulUA=L~QQfm;MzCGd)XhiftT;+zFO&JVyp2mBww?;QByS_1w! zrQlx%{^cMj0|Bo1FjwY@Q8?Hx0cIPF*@-ZRFpPc#bBw{5@tD(5%sClzIfl8WU~V#u zm5Q;_F!wa$BSpqhN>W@2De?TKWR*!ujY;Yylk_X5#~V!L*Gw~;$%4Q8~Mad z@`-kG?yb$a9cHIApZDVZ^U6Xkp<*4rU82O7%}0jjHlK{id@?-wpN*fCHXyXh(bLt* zPc}H-x0e4E&nQ>y%B-(EL=9}RyC%MyX=upHuFhAk&MLbsF0LP-q`XnH78@fT+pKPW zu72MW`|?8ht^tz$iC}ZwLp4tB;Q49K!QCF3@!iB1qOI=?w z7In!}F~ij(18UYUjnbmC!qKhPo%24?8U1x{7o(+?^Zu0Hx81|FuS?bJ0jgBhEMzf< zCgUq7r2OCB(`XkKcN-TL>u5y#dD6D!)5W?`O5)V^>jb)P)GBdy%t$uUMpf$SNV31$ zb||OojAbvMP?T@$h_ZiFLFVHDmbyMhJF|-_)HX3%m=CDI+ID$0^C>kzxprBW)hw(v zr!Gmda);ICoQyhV_oP5+C%?jcG8v+D@9f?Dk*!BxY}dazmrT@64UrP3hlslANK)bq z$67n83eh}OeW&SV@HG95P|bjfqJ7gw$e+`Hxo!4cx`jdK1bJ>YDSpGKLPZ^1cv$ek zIB?0S<#tX?SJCLWdMd{-ME?$hc7A$zBOdIJ)4!KcAwb=VMov)nK;9z>x~rfT1>dS+ zZ6#`2v@`jgbqq)P22H)Tx2CpmM^o1$B+xT6`(v%5xJ(?j#>Q$+rx_R|7TzDZe{J6q zG1*EcU%tE?!kO%^M;3aM6JN*LAKUVb^xz8-Pxo#jR5(-KBeLJvA@-gxNHx0M-ZJLl z;#JwQoh~9V?`UVo#}{6ka@II>++D@%KqGpMdlQ}?9E*wFcf5(#XQnP$Dk5~%iX^>f z%$y;?M0BLp{O3a(-4A?ewryHrrD%cx#Q^%KY1H zNre$ve+vceSLZcNY4U(RBX&)oZn*Py()h)XkE?PL$!bNb{N5FVI2Y%LKEm%yvpyTP z(1P?z~7YxD~Rf<(a@_y` literal 11608 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 + HMG Patient App + + + Unknown error: the Geofence service is not available now. + + + Geofence service is not available now. Go to Settings>Location>Mode and choose High accuracy. + + + Your app has registered too many geofences. + + + You have provided too many PendingIntents to the addGeofences() call. + + diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml index 71c11607..d8fd4e88 100644 --- a/android/app/src/profile/AndroidManifest.xml +++ b/android/app/src/profile/AndroidManifest.xml @@ -4,5 +4,4 @@ to allow setting breakpoints, to provide hot reload, etc. --> - diff --git a/android/build.gradle b/android/build.gradle index 8c57e18a..433bc8ad 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -6,9 +6,9 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.6.2' + classpath 'com.android.tools.build:gradle:4.0.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath 'com.google.gms:google-services:4.3.2' + classpath 'com.google.gms:google-services:4.3.4' } } diff --git a/android/gradle.properties b/android/gradle.properties index 9c0729c9..38c8d454 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,5 +1,4 @@ - +org.gradle.jvmargs=-Xmx1536M android.enableR8=true android.useAndroidX=true android.enableJetifier=true -org.gradle.jvmargs=-Xmx4608m diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 5ffeb56f..c935be88 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Nov 25 14:25:50 AST 2020 +#Thu Sep 03 16:26:30 EEST 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip diff --git a/assets/images/DQ/logo.png b/assets/images/DQ/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..29719b35936faa70f760fbfde6456629ac401f29 GIT binary patch literal 6505 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 P#}G|bU6n#5o1p&#+wM@@ literal 0 HcmV?d00001 diff --git a/assets/images/DQ/logo_big.png b/assets/images/DQ/logo_big.png new file mode 100644 index 0000000000000000000000000000000000000000..0d9e4a56026c52e0ca2cf096a4dadcee98c27155 GIT binary patch literal 38890 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

%S1Pd9nP81ZiB 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 Eg3P3x_W%F@ literal 0 HcmV?d00001 diff --git a/assets/images/appointment_booking.png b/assets/images/appointment_booking.png new file mode 100644 index 0000000000000000000000000000000000000000..14db8d895d749640278bdaea77858403230fafc9 GIT binary patch literal 6175 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 literal 0 HcmV?d00001 diff --git a/assets/images/appointment_booking_en.png b/assets/images/appointment_booking_en.png new file mode 100644 index 0000000000000000000000000000000000000000..14db8d895d749640278bdaea77858403230fafc9 GIT binary patch literal 6175 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 literal 0 HcmV?d00001 diff --git a/assets/images/book_appointment_ar.png b/assets/images/book_appointment_ar.png new file mode 100644 index 0000000000000000000000000000000000000000..f0bc5aff59a36356b346c5e8f2698f2c08765009 GIT binary patch literal 5709 zcmV-T7P9GyP)005u}1^@s6i_d2*000&gNkl z34B!5y~lqu31qU6g@k~BY(YT8D2o_Su=s?kttf&*U8+UYC)%f06fFW4d9`(`U9=CY zxYbv1Yt`206PKz8E;LF66f_93ldvX05|WvI{wM!C-c0Vy+?lz{xp(gO^SK|AaOd3r zJ?A%P{h$BweK7Duc!bFUPzIn6Uwr{|1yIaa34lTXegK&OI`IeV05k�@w#&kLub5 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�@w#&kLub5 z;2Qv&_^Jlb=w*2;nKBq*69oW90~iLNoUh{mWF%ouC)Lj+)c!H0T|3RnG8_PxsHYSHh^US_DW)#skmK$B(e(uoC{!NlC_&1 zP%Zf}fY$)L#Nu=%ZWJK(;idtY3cxKd_c?&20G4nc(lxk6fB^uL0bC7WEWMWmHkm;P zzwg@mgLnxCKB*32bs2 z9Xap5;=Gjd%PXS*2l7=lSJ!zptGF%m(lTfTsZD+h|9+ zLV5l)mqE5&d0>|Sdjt3Yz?C*V-{U*3~#mi|Paxj$3`5^ zjmHynLU^NfdFy`4Ma}=GWaqx5ef!1?;~;K4{hCGmer#>x=p=E2-264T2KW_H}AwD zfX|2QvVQ0~k z(9xsFIj%p7&-p&~z55;xuBt>vPENaf$X*(Sce`{NG7Agv%{}+YD#8(5_A^pRBvk=k zF8g##mx(_>>BJvm{|75jJ#PUTw{4I6nY{8LC_Vo?)P4FHc0B#8VYcK99Dt&6-@}2G zA7SVJQm7YgvW__h{pQa>$q&v!{n{_Eeesiq*SYi^TFT%OiXl@n5ymu%Rfsdp@%J^cK@4M)duNqVJ7G-#hO>pl1)!&l4hy zgJN$;hgc^_$AiLMG;!`wD)3jr!A?XHs_d=jY_ttbn zAvEo-vFeqqWNtG1juRE2k7Luh(y4U+ij~;5_$f5)+=X4wzlfbnpEo4kn!mm*1|5{{ z&S(FEegAydkaQ&@z}iS?AtKQx_-fwZ>`Ged>apc_4`cTWFQIAIZo?*mn-A7u(|r$O z`_q3GA`CXVHb_2c;~Ms!(M2LPU?Fd6b{4$usw}U?BiPi0BbzoGz6ud+Xh6f}Z*_|= zq|;srxjT`7NQu;d^JrSlaoIuBDL$H8>xRIwJ)JPB6k;WNA=)#?Ev=JA=Iix{(ksA0 z0B%UlE_?8I%mVy=bid+qbiHUYe3|kG$`3WSz@MEh<_vuXx`SEB_1p}98SjyL1-QVe z(MUy877B^=)gzlXiv@qV9d<%u1WvVeW~V%-HpLxSGjX?g>JcD?#hqe|UDgw10oJ_o zcWhnsn5b2x7hp?Jcw_gx?pi0iZcSnBtd4b)9sw?JvX5VDjn_K3pjyx=2;V`p_F)~0 zkF^tX|3SP_FokS5_}#z@zCEAVA?bg=fqoEI+yOFRM2a?57&usgg{aIV|F8Xt!V zj!G;6_Od!oh=(hg%39JSmH>a6=Eu2u7(*s&Nt0*-%Xad=WmTJ}tQh2|^I@#! zDqhHFx4aas2BafSi(Hij9(Gd1nrcTh0bc7BmxsYa#|1bC?z z$IrtAd|FWzv<4y5yxea~I~i9n;uTCQM`vI7F+O^zbl<0j#m80-WUKw1>%D zpiVwgfD^pj_b{37tCLsv0XsWotEJUw_2o>Th<3+Xuok0OYkLt<1CCF2bFqi`NM~bns4L$yWJ{2g<()N!QPsY6|}U7QEg;&RuPqJ!8{Sa zn#5N{eTDzNr%LgoHN0mT9DdaelFE`8}C|}?&2f5k^s9(V2G*Exf`4Be@H|= z?Q~Lk%(LRmM4S=QF$+8YvNRp$`SegqXT?><3n1g+VG^JC6N%^R;bAbvB)}XmS3PVZ z&+pbVKRg^kmfwqjVJp=99`b5I_mVemEPCHCQ@r1y>S}Dd zZH`RuT2BIW)Hwj%ZoD3u`JKeiwJ-l24OMGww@GF)3ky+j!eCh~Y#{+Q(81yo7^92g zv17s+TEAwUCqQS@NPWP=>7EN7wjr9}{Z7jNJ@37b1D|~+er~AVXuCZgDX}M0iP7N{ zcK-HZugKlQUTT7Or+Y4V*v4+E0k=6R|4(>vNq7*l?v6XL|F5s4lwP2G2m)pOkT<0L zNRduDZ}@gg%Fl3u4K}fh1h~nKZx#zG@NSp=2*smDA*)MC{14o-5PLuV1pEJ0X;>FP z1{)+`Q(6fy^O$bvGxrXZo|$+cu+Ae-5m%2Xld*a66R1rxW{V6qNJRPwkX8f+F1V{r zZPR@CF!p}<5o(vcrP;)hSPIV`kHS+%pmW8k$jr$RpC2&$R`Iv5XWr;I8ze&rkmfR4 z+#Z}Vul&R|1y9Y{*R$uKdB@JEpP~PwT81tXLeHCjitZCzPp=g<*dxD9NB}a}AQ7aw z>Wr&Oy3$hIB>;4EMC_+@>J$V@y9hgK-g+AiI`>x8fAk6JwrxYv=nB-nzZ@H8T!&zN zz3%s+d-pGU8%HzzC_1GzmQ!xuzR2j+Q~X_48v@4|n9QWwKX*4quaf~hGScZTH_$zVg01X*)o0qz6vg;T7Tfyic5@lmuA8Ei@w#6zLY)FC+l#i$d_>L1S_izQ_IV1I!%w8)W~g_ zZ^)i^4*bS@wB`TRzfp87_3uM?RYXb(Cr!lQdlrUGtGxIUZ&Q-Pi;zN|UFiQZ;lj+rHhQDn7oyhIedeRWNFm1Z~9#fu09@h$M zCr>lw8EMRt$XC}A;IjbcwmnY8dT0ZB;qYO|DlH8Q55l9P7VGET71M<&6(ruo?Q}w{ ztu|;0a05?DkFoQG)f>>kwchSG-@?}4{N6P2d6>#_t?pg4&}@tB79hnjA!rY9!`5xs z|N1gZghv~lJWOGcR-%!kV1;bnEm!1~g@*yqx^E8vMydJ|M|Jwcq@BpNlpP6A88B7uozm0<{1mp+epEr^Vt*1rprgCms#gda<5I zXV66xKBd!p)=lVo@syb9kPz43G)tuCB3{s=8NC7=#9KEz*quMI1gJpG8hQy zD1UKDT=A)?nmn!Dv-FBsfy7sN*12vGA)OLl4j}G9$a;@ypoAO~l8KtRL<(OGHMv@! zBVk1A_w~NzCf(^og9JP9p_u*ks8ADMwqTz4;?NhAu3^hw6X`|kLYT}Wdc=nWYC!Oz zhP0N~#p<_FLz%5W1x#1**%LJHO|({_f*SVbYwZe*`g%&UPU0T$(EVX?QS-U;xfj~> z&&on(K|c1q^R6y)i^iRS((~I6_^HrHfC^&p zu<}FX^e+>~?Qi+RA93XC>NcOD!AoI;D5!~EbIBFrvt)P8%dd(w=u#7EY}941(!@u; zvlf&OoyVPlrrkAS1aC68B(lRY(UX!E$+&$}e8W|>lo}cUC?n5!Xx+D8qc)$~x4x*8$0BLAVZpn>izD2T7fok>B z^cJd?0F4?H&{R>oziHU2r@uyaYK^Sv{XZUgI#vuSN9Fi)H3wlmXG~AX?gVILZ6vgC zk<3|f)VW-!<33x^>gOag7?ByRFBH8uwE)T&hQz(@C)c$50#OZU(x7Ca-hqdjWDhI6 zhqu>BhgP$wH^a4Rq-4aaRcmTB%gLf;6E*Q#c4$p<=NiA4nzZn%WImXz0BLjaWjrX6 z3aw^GZ-#4$H__=7M6rR=i8mpw7p*T;v^h_szEm-&V=W}*IhD#`)fC$I1^`c`kVaf+ zjxE&;qXIi&@uO}2Mop2P=??lV&9B9~SG_DpwUO5R8w~YE4k<`7$MAE2XPd3u+Cll3gLv zU@>bTX^c3q`g$+GWqU|~Ryr9_%^C@bPiw$(XpJEPq%xnGY9dAmkS3@nQ_OG!(sC8# zV34X~gkGqBNzJ}e<57)CD>jkc0BXt&m|CjgGEaFrF4ZPjfjnL(aoDYn2Bql=sBcJ9 zBqR{EUm;YZWuvA=sL9uA_SI~CEafjm6M*w$c{wLSB5T2VxD>!MviJ_l4vDe+#kRo$ zsDD?d zM+-e8dAipC@qx?MF!8~J8c^Xk0AjZVX$tkzVl|VrgqEngKMgd<<2v_*!EHvpB+mUS zKh#`@P6ArEzS-zfGpY|5$utE?6vc;CQq&w)WIR&kkFzTd|V0fN^N z$9ORarQmTc3q#g+6U8n8g8LgY09*mURWT_X!a>ga8Fu!|?G&H_IW!KHb&rWlS;2Xp zk~66h$RI$lOZQkl9zx13pDv-1^Z1NZ+~|!&76F1cwb0hSlf1KwO<_6b?LwJCFUurA zh4ow;{--xxV+ggJmt#3^r9wslf@k0tagdt_*bCPqF`78iT26hMggj!UEmi2 zI2XW3-lO6KDEipP0AAyo&h)stcHwpbs_D%BZfDYI4=heu`oKXJ*$R#>v5fn8t|y%Y z7)cQeaVXE3(beCAT9RtFuld}SDn80;MVbzz(prF8Wb??nFMvLL(J=zWe3hsU@y-H} z!#^KZIZ^E6<*z+_?E|ZIrp*5Y&_M|z3aA(*I{0UB z8*50J$jJd1{^>{nV2C*Y{=bxe0RIC30G9>#|2$b)p#QJ`7YwB0s|5f^5~RdMR9t~4 zP!vy`nPwqVPO88=LU=brw?Q#Kz)u51)uMW48uFQrY3<6H*;xt|b4%NqTiprE%BaQu z^7hwjcWaIhKR=fDLK4rBfg(8Y@FF5R%p!2_sap45J6B|Xr>8Ic?>K|}p5s}27(I}4r_i}0i0hind|$_@^{*lamY>I1U|9uTZKq1z?eI*saL9gk;APn_9_ z9yYs*nNJB1>z_lSS=EodcF$aomkVcf9mlL$U=mjYRkZv#8 zXdYei!m}2v9+Xr;t3~wb9V_6z(XCh~fH-Ld#Ba={9H|<4w08%fn{hR5BSA4i0q>)1 zcOmLcS9y5zbC7nV$Ju?p46yz&fv~mV-hXES#A`i|)HRv|)5VT;&4#j`oh<+))IsN$ zC2|2`Id0?#7+kysLWRGGkJfV5LV)YdGXU$^>)?O(=tef;UCvRqqm1m8VS|WhaWy zM?UDac|OArgWIy?fVg?Urk7XG^xHuEjhqBPQqIP^D#oInAbGMqsX`PaS|)hJ$fT{! zyHT}itz|QXF03VSCH0&+u<~F&n4J_#j;0tlLVa*3d=OtAOre1zSrZyX&e^N#)GIhT zM^S|+C39y+|KrJ~LI> z0FTFHXOm6Giqs;qu+ci^e2IXC3(fK7S|zK{$YLaT{8KXX&T#LaBH`C5r3?m>2H<#S zo(=idW`D_b8)VMhmjx*)U+%{eobcP`;!)Mf1u)gKAs#I=iJyNKhL5!>|fg);(InXpB8@iChNvkK~wdYY4+IaXy~?Xoqd$aJbMR!Fk6NuRJZQ$Pj=>oI^xwN#`-pYlew66%CFEx z($_%Yv9`PS9`1b4?+CKO+DDD|PAD@8Lk;*tM_M0^->l&i*n#6O5L-coC`A(<7~v%eeA&eze6JrF1FOR!o#?x``ev(VgDkoO zCK#vI&63z2E}#ECtrveu9FAcV8|@5Uh>R~>P=eEU9VhSUEKDN^`JAPS+}u~ERYwT9 zYy8zXQ$w>!i|;eg=^7yPt;uyQ4uNdp+MwqNZe%}h7gM21*4xr7a<#XqxBE5IogwJa z#fCcGi?7dr3>!E0uh@@uKe5fecCloANU-3Cy&#+mzS{5j%#I= zzyM4I3h6)lz5{H)G81^zIus5;j3`v8zeQ9W$ie0x)p(lL4%@hcNN<`ep89cR{T##i zMCBxOQ^s0%&ukaE`3T&~LIcc`u_E4i6X+l7);`P5`F=^Pc!PT;D_nkHXEdYf?oTC= zQYGPYD`e1Cy5P~)P--^FTWBhOe9idvUt8$ht=Vp!~h&RPGpi&h4*Z}AoUzard;^X;5!ajo@H!<3bhQwe%H}w9>KXnP@2`eA1gS{#r54 z&rsyo?)GPl?6_S5o|7GEFyAi(GvCbs%M8}z+w%c%CA#TNb+G6Mfpc=pET01)P<1^; zRLLR1HmU3Je7_}Qn&{#yfRNGRp^uvduRl%yE(HSO;rmDF8Z+y&lU>g8%fahzCn;mA z33Opi0nx)HoEfyD%xhh;E);@1FJ2GowAGR2ySjC=Pan%1T?3&a{wterOS>Lh&3@t9 zphu19+iP6+p@>Q#fhW$;C&rX}Ebc2yd_HE=t%{TbxM=w}9CG{cFSWZ;JGf};fId>p z#Ov*ucVv9-`)Xv|-}@`@mOReP$@~zy@!=A${mtQ`(;(j^o@m`;+U_zCWG(c82GWd? zG=QjW>n5xLIqtyO@B8gn>>qN0qliQsge>81QFx2F>(RcZps0B8{v3Jcihx_wWx}bz ziO_7$ngL|VrtIq;)y4R)0T&? z2$cD(X3YYMpBqGq|NN$Dx?1=kpJgOJ|5O-1)#}oW(2b6AKWI6<5DFwS!D!!AFQ-0R zU_k59XDoSt+gVqgWQMF8xgt+e%r5M~lQD5oWCtRWV~}E5E+r-ThA`ahVYStk;yg~@ zegOeSbJTmHDWj9$Qm;%mDHkxll(DQY7?zNe(Fl|5- zKQ)sdq6&x8PzYpBZO!-kq^t3k4Z_Qygp#qJ98z6?Kz2p@bI)sT76xuoIEt^lXSPHP zcjq${j%r9b>p%CD&b6W*1SG6s-q)DnoIpBA^4o&ycW>S#KMqa_962XPGLZsBBBQQh zw4@j@#_NArw{(P9`H^oQeF`oNwc(q0hqcbXvg4g1PFf$aN6fv|qJ5*m-$S~m0EbyW)|^!qG#{m81M zeo<4!C*!wELb>b7hc@==CA?wX85?ZOQNgz8kD^>nIPth6`5ij9^f2TtKSh17kosI zbKe1w8NSH&{cy6=8Xd}^W>!ynXQ0rXJvn-q&9A_hJlK_5|j;NCJ{n^}| zNH*+do7&)WDO)~eec%B`TL|w(`Li4^gnhiHm`XhJ`gbwfqUg#6S3MU}X=q2_3+9_< z%9roTXmpAoUQ(ZV9Kne6wPLTPcw09^#-)5Vy&t+49$3_~09yqwm}D^x`bp3^yM8$W zJP2@+S+65tlYtOn;hUm=8Ywamr+rt8?uLmd6QbkUoi~v)7-k0}`3q|Cw-DrUv1nq1 zzYS#11G0DJtSU;fL>B@}|J(k16FIf3`hc}%l*j5%<%B*1RqKJ2g&&Ux+;FepZ_U63 zgJ@H%dc?DZ)?kxf2t*l9|E$}S^QFz^cvBFnF?Rb<<{`p2TTh0edmviYQJhRHG&N#Y zQGL4pz5%4pXF|l6BgEHitIk=kr#?$MC9@JOIEd*Fl@yq)6q@S3g(a;Ai_vyN!egv7 zAutjPVGDmKE2f#>ZU1++rw01~d}w_rQ=CVAR8wCvoL%%79^96m3yD69w_RvDwPT(n z{Hu09no;lGoxU5dZWdC6xKX<@Z;mbZ%8mzm?Vhvukl-H-DodpK-2A4pGZ5~s)bVI| za1CQ@m4CL@!P6FE^-q?xeq8H&-*%__tGwYiLdr42HDJ-sN8;Rw%jz5v;pfZo)#GAo z(pu?Xa>o*GJd8w$fFNP)v~~_MxfOnPLnGO8h%!&*2_M*IGm<^Sxc__(^!H-?Q;-#1 zVr8)70qm0~HuGGlqnBA9-EFIj;CC4pQZ{I$i!9N|E@~7fKP}@)LZ)Y*#kmVWZ3#k{ zs@Z|T*CUCLr%)4dve0bJ^UK$R&>Qv7#^e^)e38x9Usk-7i4t}bWK;{DZ&pK9bm!l) zUw~vholU07(7U@J6T#-$Q;@0Z(W2@CswZmzG%y>u{Y{a)TtTup^WrI&AJq*6vXL-D5 zw+l5)_}+3F-$S0ACKU52St94kKyJnV&sgYUHiJ%RO1+befff7=A>5*K)k5N9DriGTTmd^^A)igA{n(zPk=->8(Pn_ z)S&QI!3%tMtJ;bFTY!jojku7nP+M&!a|?#ooo(cgEBjC607ZrYcYsn@y2bm3k2*D6 z+wSV->UY0lc9A zI|qBVm}**L{WzOP?8kbxZ!TF#4v7_%v`@HCxynnghKWh(Tpjt+7a%w{Z#z;l9Au^~MM z%927O=?9;ffAy&`H86S98zL1gFk&s{RXvw1B?Rh+wwF8}3iM6D`hR1^6l;6$0wpbn zjF#6Ku#|ka(Lk)MEC`7?H8E1N{$G=of~BdM;Sq(yY@shbiO z!f6Y>ss*Z2Y%(6~?>k+!+ST5^nM|J@yN=pIv2r7nPYfa8FjrjtWJM|WM2;cW$Y#9n z`AjlBr?i(iupP@w#6qaCp-Sx0L1`b41b<3^M{U`_=gTJXXkVti=FD%FsZ2h0lL=+Q z@c_qIs|+S7Ghx4aP5^H+={%xD8j0~QgvCdn_*@4$)*BGsoRZME{oix=Ua6hBJWiJf z6NzChlHNH$@=cP;OfN?KY30vXQtA~oQ1H(Bvi;QO!*_RcRir&2y_Ro=2JQ?IUxDXk z)86!`pNMJ?d?ozXh&{aH2V)4t6u(&Hwu7gqr%3aUVs5}>R`0}4O5)QD9Z&RhT2UoR z2&{t#vE1;}T-M+i*DrqNe_F)2U^+fH&iXhf|9PR{# zBss~!3+7;(*>BwkxPOYRwsMS$+{-g>r^I${h2h2hzUwAIvwN*ev1bB&-P`fcPUx5-J5{g_8j^kKr#)lueAL;135=+f~9)KoI z)67mnP+kuAvsU8@{czaH@~}oY5T}XQfs%f#_&lLqlGhSyPF80NQ@%hneZuaHgdOD& z%Xhz0g1^1f$aB9X5kRBL2Y%|Yy`eY+RjIEDb&DT0>58AV7XkyoMW(P=T@5GzK{}Yz zfa>{w{bJw`$Dh0ZClE}zy(9EfYy4T>rhU5YuDQVPk$=O3O1EGOF1q2bfyt)A1-|PV zKia;9Z|$3R`}ZHq%$@c?$%p{{GZ7*a>@PmKsYQ2PQvmi4Har2(6XHXXNHA67I1JeM zOS5=H%?%#`eFUt9y8IO3au{i-KmK*N5RXfP=Ju9w2ajvax?xYxw+lw6_E zk&Tx?v~N-snlvUg)CI#0lCF~c17}Z zzvdl9@jgDmAZUIWAlVc`i^n5KfpDV2suPwjJuZU(-it&@73ORL6%zxjazRf~T^n11 zw*;QNv|{ibLVBMgZ#edkcIYCgY&;wY`AW8GAC_{TY6<((Dr@d%5+hunf2>qg{d?sf zY}^^0iQYS9RF!`}<_Y;}-@~H&`mg z6vvaQa|5h6%EV+mVC9qeY;~8=Ah3#T7yT5rdcGm6{xI;VyzVYNf;*3089R3FdF`>k zhc19fIhF(cM6AG&__?GYS^iiDkm)0xWL*~!)q?smF{h0EfXy4`;L+NU;ga(zkISpgs{$INKa7t!5ZAIaC8LFHGyjRLu0!`Gyc zYjlw4VEF0a7Y2gqNiqxJLbwLIOFIcuGR81~`^lx;H(xbx^|d%#7-`poTN`N}QAnD$ zVAK|kl6^G&)ns!_f%Fq8&C_X9Cc8}VGaor1INiOp@g zdL!!(Xla3rqBh#$vhIu4U9v=>MNW!B``PK8oy}_{cj<2n0p@eeC`^2w(y-;jSAwPY zNS@+UUtWXm;FBK`u5pmn z4D8CGicQRMi)*3Dfi?xG;zbo$v!95rn)BY_iuJ&@Fy(~=MtUoP(z;^m7-OK%HOm@y~Tzx#i$#SNl8e?gX?-^+ET5t{52M-ibNE{$r)pAei0OvL0*=adPW z!=#DbD4uOMAhAt^K4ZeI8FBmn0?uWR71Ho3=e7dJRJZrP2^2452C)kpe#n*=J9^0K zw$FQpS_+G<`R^wc7mxd<*2jQT8_Wdj9=FU8O{cFJp~%DLUfJ5m1uPG#52a@<_4(N7 zsZn@gG5?OxJMyNp*fqLJ{ufHl56g(t7_6E~!T0pUKV4~Wq6guy#40LR=h-c#r^4g^kHO#gM|Ax&F_zrilZlnX{Er<(`|2Q4%}smx_D` z4|6hgVv)P2X7q|QhlTm%OJCGI^ zR_#y@i0anKnyQ=vCn$GvO<;t(T413!=G8R7dG_d4F0)TX-qp0!nNh~R#>76O;&6j(@GOF&C28A&BmO5P-zuK6qm(?lM)WI0kDn^Yl>NN|6EvKAC1+M zSDWwlq`oa)8@Se_wH+1)?CWf;K?P|%;rPl!qPi_G%g<$x@Rk@$f;WOSk(20$ICc6= zDEr^r4v?_QKmS&+6TITT#kmvvgXh8`EZf86DPjt=?W@+Rdt`-^qv8k&XsLrJP;Yu= zzw;7+i&SNAav;}sJQ!#?w)o88t;_+%<`O-Eus^L8)^K3W%Ho%w1}5LP7`&(+;bn8S zX>$oj`p}8Lohqp742-ImcSl=i&1&{pI88|2l4y)a#{_=Mc|CB^^GJ&6Bz7=b?ieFl zqbf5Pp#lsi3z0pSn`|06Xb=UHWTX;>D34c)m%G}ZefqYLKVjZGoa$tanhUq(XMw>x z@JPryA}OwN^{r9Z?bJSpd*duk0G}=u+0e*ipaHCiJNJ)-7A&J8Nz8P3c$_itnr{ma z-Y@Z$m(EnLh2FKUh8*ngdA*NYF^Z**N-M_p21sCd2nrE%&T=drZ}$7<^7XU{Kd@`# zfvph9=>K-QzWfD{TZq}XWhz%HrrisY0L=g1BF-!=%DX72c`yDE^--BB-s3~N!l4L# zh&j?;}(P^Or9 zCH5dx#&LR2L(Finwh}B^4UTVR+}tu){FO!Q{WB zC+bg7y?-mpwM-K<1vM0F zAe~m0JSERjHJbNa5&|j-s5|WbG4Yhi7C&Z^f1m@jsTpl@i2%m*rfM^ZRUdpPRyxeKuWR=hoCBM#1r86nKPwQNfez`7jTh=H zR*$aXud%$r8R>H<`|Wen0E@P<>_)z7Tf;QvE{H#01A>ahjAdfNqNJz7U+db+my=?v zB-yl|9OODcVV+XfvlLm*;Cthw9CK%@6XxO6QAT0B?$z_oYBRW@O(V z5;6>25jgzUC>p2}kX}`+#hGWaHon+7t`r~hlKQe|!O79K4#5|b=Uy`%b#=!UQ3Hwm)P@hlJ zk#G4X@-aLZiEP**y0z%O(gKYs-YbDFbCkJZT=I03ruQUXtzKrjZ$nMjK1L$(2KH7m zf~COu0uH9Dk8kD9@l<&-id9Mam4B%HFJcDTC@&S{7}HYQF@!uUzfF|~9Yxlc?#c&I zj&JK^)bA|4005u}1^@s6i_d2*00001b5ch_0Itp) z=>Px#IAvH#W=%~1DgXcg2mk?xX#fNO00031000^Q000000-yo_1ONa40RR91pr8W) z1ONa40RR91pa1{>0E8qvvj6}g14%?dRCodHT?v>J)wRC2XBbvx8x~mvTv=q3U16AU z#VslW6MfM{Uwny1pG!0eN%SSg7ng(=aLJ;H#xEvOfkBOmxK6V=44@J~a77lCMPQI+ z24<%3`~RA$p}M-NySlr&yL!6L$I#VPx6VEH)Zgdcd+xcXr0^+B0~6*fZ`(Rh&`&8f zKnVN=RBxd~XQ@I;c{l7bV1(V7*Byu?ZmkM5)lS zKw*!?!IA;BDXP-bY;y*H)90wX?PArafNVHh3VAlH)R_QV8&5nPr2sy;ObPX-2n62f z-Z18!xn;7!6SAdPh!zdNqWNzRk_~}#q)-5yEQY=Bm|}gp!(NGfkhKEL-V6moZ!VrX zVS_u2y~m}+0T5%jF0J$OE>|H@CZ#$Hz{~fZ+T)Q()hi|6Qc^uz5XvuqqipoPc<%Ok z*%kr7bLOn-SfAH0t>u8u8a7IaBY0r1tAKj8RYU&2S^^le8h~e&ztbSkc_aE)ii zbJo~#|18Fhn9w`{>o{|9*|<&aSCAf#SqZ>Nb1DZ10`g9{M#=!Zy!5EbqqQi7$%=d? zr1BnETsC^GN2RnCE2{ulTwXaI-Oyc_#a?LJqFlb9#LMUn?hlrYUz#my$O-@!Jzv#V z)~lHiwk%r|n@Ks*HP2D`@{Yxqjoq3_Ih@q(X#ifZ;G@=u4(_=fE{UH*&~{E5%p19l9GC_>cz7FoLpX6B9;6z6nCOmm6r{2VaW16mJ@GUR64%Gi}HF7 zfPQzI8kl&sTlNe9{q8n3z%z37Vz=xG0G=^_P4`v}wNFVY&NC{^KTeGX&@I0v^9#Ni zynG}gcQQ*E2VhD0$}?4{p*+=5D4A8W_iBeV+!~O9D=SLJEX$;H83Q1rQ+5Vc{2XCP z|C961$p`@15;s)rOT%d-)T6T zmcz6IkjrR!0r@Ig*C#D4^eb_s0d~nU5V$Znb<8?PH@H+N;1VB4Y>LXOit?mfj>10p z9BC|lg8n+Uv;nYqe$|wKQmnlo>PGndQ>g(pGdOMhk5W}b$}C{6ptxpGZ`bQQsZ%?R_muwKT<7gR zLvhR(-8`opUnoX&J64pQ+|%`{Cmz>X<2~j0uCDV=2}2or za`L>YOWfw|ss${WUo}~U)V%E93K_2E4y|%~+exD~WWH3PId1z2T>~IjI6|S&i)5l+ytN=-O!JMLJ3;1Rg4az$3 z@d5J(!`V0|M4lljFNL=wX&-M=7Lb#UP=k64k<3X0In|2QAK(sHllvW76S`l%Gq}+O zQ&L{#s)#!8HLz;8F5YO%o1nXC`0?Vzj_m|3;gzqfu`QeK3y7?)!=pbhIDJeo(Yg}` z4rBUML+IIT03Vg3TaQQ9Z1GlC7URjW+kNtVcouEC!}P&$gY=Ns^@@|#52SO_!7(oevt@^ zxB)nE{)$tO2RZ4%XClI;>z;|nbqcGB<3_h=M7ON)RK?$1DQ1++S$S%_H^vRX{E&DE zm3U_$5^swglz;E5{b8lv+ZFyj>|&f>KHeAZ({qz|oT9j0ytN919*mc1Y;UZAWAVHd z^!uD|IMpH#=Y6ytU1WhcNt<~d5s$3d>{>hZ2?co*jPpL;?iz0oFgl+Y2~HdLyi-{m z1F(3``VLAQcqpNfrc-G=RF1RdR1haYsp6dqdE@1Y%}oytnX`Vu`m!NMoZRcY3(h-m zC&1U&2~)pJ?rMM-=_U{S%&7((SwL;#5o#F|j~j;_4_Az5vz0l0Zr(1}I3anuqHN3u zu>^Gl!2FQ<72GZ@V&cK|V4qU10Zd35?nW&LOpZ=50a!Gz@?@|mjm{=}uD-hYE3y5c zdv29Xq9;B+Cl)(Q&A-jm6Lq{ zl=-ddj{F$Si|R9uItiInzUnxJb>tWGH4vr&1S@>6__=q(z4~D#V(baY6Aj$c z+tzfC|JB!kBMoTSsXvmK1?1Z#vA^Scj%xA?`5Lg%0D91yi6xuMQO0&(?YJHY#(Qyn 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 Trk48;00000NkvXXu0mjf?opzu literal 0 HcmV?d00001 diff --git a/assets/images/check-in.png b/assets/images/check-in.png new file mode 100644 index 0000000000000000000000000000000000000000..f6effbeb6b8a17f264f78658d198744e3e213a81 GIT binary patch literal 2050 zcmV+d2>thoP)Px+yh%hsRCodHoN1_4RTRfH%?2|qEr-$+wK*)aG^C7zqNMr~krV}mNLf(!p&}wP zhz2MOBKr_YMK%y+l!DM`4j&Q=D=WW@--g`^!0Ty59TVS?8T~&wlUi1;2OC z-FFXbueH}6&VA>0>lUTMTi_ph5XonQr>x#S#9AQc_q9NDh_8LkwMU1TP3Bu5I>gt$ z=Gvn}%qH_K5FO%cUvurzA!d{L7Kjeh(ILL}HP;>;Vm6s?f#?ul`-M7r;d516@*z{7;sm;8i%w$zmE<*Ml5fL_e=G=KsqoVjrvWYiMLlk%kJC=}wtx zplQ#lr$_$a9HPh=0nL`XY0$&K);i4&@!n;r1Kw@abN23fi5(%$+gPf95qPZ~^=v$q z#M$*e=&WhhuvPxO@DgY@qEt;C3I+$0q+c^Scd`%@fGt{=Zm9(|+1N;b$4u*aC zY-EPRxX#KB-YkH}U|@31OQrHOt!vP@igm=zL7U!*M#u4b3%m$Am1`GftuM{5sQ3&X zhs&WCNHhSHp609aHMj_ofh3xy?uXYv>q#m{bD^n69F-)>usVqkfy0wDO+#B?6MPS! z!z$PZsr2XK_5_s=L4u5s>-Lat1#qPw+s zf)?*GN3YhQl`spA1&Jc2%r=VFWsZ;o+8h5^mD8Qv>5$!BX^y`T?uCW02DDDJRkxz& zOPCL{;a1Q_Ar(c_JZP()W_=!{L((PFKyUjB8| zBZn7>c#7qcbIA2N)N8*{T98wgdb=4OhPkjCQc;9z>#D8na5xksilX7L4_ZJYUC|@M zuYr@`O^`eaGhq)jL$0C`wVh`zG*4MYI?!k|G7_@{EjT=2?klbf#&BoI)eZA#eZ85mKZRd6j8)zGZagHc%9nDZQ!eT6hbzrdj&c zZMY9Eg6zPR(`%!qQT^r!$##Txa)}xbO_rk2 z6QEOi?JlhkY1(3^BVTKRqG2$khTh4wrawiTc758O*UBgo9s(Ue^NOa;8F@1o&DUr& zgpj_SPU$o~4P?OfikzlfKl7nTq?scm9U<*iJe2bK8u+>d>9h^jW@t&$lrFN-t_5A^ z8f^mP%rT%dPgA9{Ii%Kj{YV&>Q2SYs?=>o-1Z08ekbs;aRiZ`2#F2}%mRU_6C)%rhj@G+qOU^r zOOh>#9t0B2=u zpH*qIx#*BKP1LRoy7O%kk10z}Bk5_TP-HTSly*)qc4~_;|9_8kSq1E{#BK}i-z@Gdt5`R@<2_y&lYip>WC3iW62WU?x2ogphvLH;<1L9mFQ#z z?w~(~oKe&cA^c)Ps5Q!2mjIZtMR@e;h gz$>7ib#jw`0VqW(eEQLBr2qf`07*qoM6N<$f{>Kj9smFU literal 0 HcmV?d00001 diff --git a/assets/images/comments.png b/assets/images/comments.png new file mode 100644 index 0000000000000000000000000000000000000000..353edf4ef5274f7a1f8d20b7f31ac1adc8390bc9 GIT binary patch literal 11678 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 literal 0 HcmV?d00001 diff --git a/assets/images/device_icon.png b/assets/images/device_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..8ad55c09420faa5b2b03b7ce260fce9b76cc0c8f GIT binary patch literal 21635 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

{D8%XnKl}+ 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 delta 1320 zcmV+@1=sq55UvW47k^|31^@s6aN?Cz00001b5ch_0Itp)=>Px(=t)FDRCodHUEQlp zQ545jzI7#`sJSUZq;4UEC-QP3{pEGN%z4q^SX3xx-Gk<$phWND+=xzEvqtVY@z!svq{S}WN0puA(bIiawyI+n0azh4<43GgbKnBP_ z;TWiO@qcYAMzJ1fE!=2|Rd5f=y#SPfnzjH(?*Zmr2e*E>=mh8go%|&n{6H~sI~nDP z&@YO)d*eI~$TNhN4+C<0(|4dOuOTJi2|&x2fgW_9@%|K7y1+afIKnBQw zf&safH5*u_h@q=H20G+LeFbpFT_4P>V4#a{dlhW?aHSwVSXT5wK@?>9aHSwVSXT5w zK@?>9aHSwVSXT5QZ+qnjk`ELybalsoEaXNb17v^?4BUpq+1fQ=i9f z0)Hup8(vdqr68%Pa}!8G-0+$@D+NhSotr=k;)d7MSt&?r>f8iU5I4N0&PqX2Q|Bg- zg1F%|byfuL^}D;D`T<_<6tYx$>Z0IGqw`H z%i6DQ%9nhyS=fItdxQtemP5PM zuGRdAgJtW1lGRS!$d;Jif-M~8IjO{e5 zU8^|{2g}w2saB?oNsz@BSxK5R;3P5`Rq9 zd#js?%&K5nZfRfDvAVml31WW^sY^~qhZ5q|f^f>p$a{6zs6lIziTe1YjW4}mG9KmrV(T+vUjR`2q!?k zpbFkNWd$Y?1)(5;F%Vce@(hu`Po;&yK(7eW9Y!tDS0OjrJr+T_fTz*Zkv{ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/new-design/empty_box.png b/assets/images/new-design/empty_box.png new file mode 100644 index 0000000000000000000000000000000000000000..af3551fdbd3930209898c0ab4149d3172db686d5 GIT binary patch literal 4247 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 literal 0 HcmV?d00001 diff --git a/assets/images/new-design/liveCare_white_logo.svg b/assets/images/new-design/liveCare_white_logo.svg new file mode 100644 index 00000000..494b3671 --- /dev/null +++ b/assets/images/new-design/liveCare_white_logo.svg @@ -0,0 +1,40 @@ + + + + + + Online Consultation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/new-design/livecare_arabic_logo.svg b/assets/images/new-design/livecare_arabic_logo.svg new file mode 100644 index 00000000..c524a803 --- /dev/null +++ b/assets/images/new-design/livecare_arabic_logo.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + استشارة مباشرة + + diff --git a/assets/images/new-design/livecare_white_logo.png b/assets/images/new-design/livecare_white_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..dc223965d895a23bafa20008261bfbaccaddc329 GIT binary patch literal 9986 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 E6oU9fw7_*MNN7{I&bPYj>`x>Uy{1Sl)| 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 literal 0 HcmV?d00001 diff --git a/assets/images/offer.png b/assets/images/offer.png new file mode 100644 index 0000000000000000000000000000000000000000..b9977670cc0f532b5704938259829151d67ed875 GIT binary patch literal 2631 zcmV-N3b^%&P)q$q3BLTds|Vv;z-O}rJ3 z78#THx)<9!)jvLGIXgbPJ7>ckC*62w9*jdAKQ3|bzKw|PH063t*>A3M&E|Ye9h`NRD9^oR>WFufOa*`90C4N7uM-g!=b$?gFea~IUhg+dtGmW7 zd1o$@9t!#(sg8IjF*Y^)rXY`}eI0=a#UAo=A92e)9yYBT5Tmmz9UoggoPY1CuM=^Z z@0KpAx+*9UQp8CSC-7An1X3OGHkZNU9*w>L=WlK~`?C+@YTjhn?aAr?SAGm>HQ=mctXPx!KL8iwKRHk z)74;XTn9}{mq6^sbyvQ%3gWweb3u3`|U$8dhiM1XhjB&g0HF3aitq~Uk{5` zuY~5GY=qdlA3LjkeD^MxK6$w0b~F8bkp1ja$WKf<+o3n0h~2W$*SVy!Ir>y75rB|k zh>)S`<5xPSZLxcQ1hKB`AlB6d#!c&C(V82C_mTbNFkHHSSK;+E9EKJDT;pqBERLQz zM_(x?0+25rJws2BeSaMlJkP~1-}`bP$C@2Z7KkvH{L0rp1_$SfVB2;eL;ymDBZg`H zhNK|UU=(~@2c!FS@f5hqX9iBg+{F}RKN%2G{&;LW9>vswH-*pt{LL-2hL9BAxCF{& z4f{yH`gxHZR=e@y1zugeJuz8wZy4vtp4|l~sBVCv!VeJ`G?qs|_Zn%nU~XvCmwQ&>;)4Q) z0BUR$hAaO5T0tzLN2?TCc-Z&ud(OMIZ7WOhRS`irGid(xdNA+$IaphNS@b@xpz*zX zAp82svfHar@o0qDP1i!SYd*wG{Qi}S+vG2g!p!L}oTkyt*$Xh+=l%F7472|_QuH@t zGfL!dm|7mCsiRUz6M<9&Jp;e|rH^jo3Me3}r2V-UV0`tivToC_i;rHt2HM|vYQgc* ztFUmpcqHDXC!dk_Hcp7x`u%IvI{@Cp!}(4VV1AACN}Y%cDlU2ROavss4_oqXjb=Zmq&(vFLy zN}8hO-mNfpaF3^bi@JCUD&}&>J}>(@)F3K=E$95xqlNDQACd50ThSL571plO7C_aA z(Ejv}A`*P}=O6GvAm;rwAq~*SQ zie6(nDGQxkJZto!**px4dOvmcRuo219cI=f)@CtwSIAG5QJiqE*$|0!8p1!PR6zW4AnBT#3Vi6I))! z)NpF=2SJ~jQs6-8`Bno?=Of=6U7UX>sKJTRt9A!DsmtP19r21AV>y=X!Bb!X2*5J$*J_w`2ayA*-O-`X>=ZZ6M3h**Cpl};uifNNd#SPoxcDm=DuueE>7F(NWs?vRrLr#fUDrejh=MH z^oBM%4>Cj$8d_BWw}O{2y4DK57LXxApjR||XuNoVTfrwnqx0d52%;nGmB3Z-ANvxO zz4ey1=>oqVL5c`e!JnFuYP>Y8g0BVq62Y@jQuK}dGkC8|uA#j5XR>6lx*9@{mxLjh2xh@+oS2ARYKsOE* ze4RsfLTN*2^u~a%%i{4)YY@QIHX&*UAtK-nybaSjUW-0Mh+yHF2*e82i{zg}?RVWQOUeD2L+FJ{9-)V$2g0z>fbdjD pAo>9B*W8)Qq_vn#3ZW1H@PD47K5?G}_gVk|002ovPDHLkV1hU-3I6~9 literal 0 HcmV?d00001 diff --git a/assets/images/offer_ar.png b/assets/images/offer_ar.png new file mode 100644 index 0000000000000000000000000000000000000000..1fdbf749c13f25315123508b1935dc771cc382d6 GIT binary patch literal 2626 zcmV-I3cdA-P) z1bk^6nOes7o$dR{ZS|I!&D`GJ-R|w|?%a7l$(1%7t3;@G&_hW$g5tgO#v(xX20hhm4YczUV}tqyJH&)H}$r^*;7#m)ldqcvqYnn;L$dg^xKx!{iajG|@{)akN>~Ix#x? zx5;J`cilKPfF5#MRaIMF3cV|a!$|CgOekSU*@&_GcvrmJ;NI;Ty$suLlV<;R?06dz zLRD4Eo=TDx98f60`*WFeZ;)AZ2}I1r8KbW!QyW*@I5wa)r>bhmO1n6S2mu};hh}n_ zbS%g$asZ>?*?E1n+t;028UYxyemcR z&Sj(2Gb{)qn1pSvD0r_ip3TuKntFs> zCT)3rrs;^_mxA{LW7A1`RmV9MEssF*_ol289YoAEz0u8JH-}IS)FbSmDO`~=b|Ncy zuQ7g;L~{rU9+##>=q6&RUy_x$2xKrQ`1nFLx)~;75GFTD`15TqJ?cZGM65BLEFv`pLFdyNVd*Beb5qH zT5=o-(b=~TCR2|={vQ{)UpJL6&`mCSE<(z_Op82lda%(}f3pZWBvI>~YoM5#t2&}1 zn^x&$146jM*vBB9(^o5FbnPlwuTdz(TKfo1^1D_2<>J?NTC_E#v{bbus4FK~71lV$TZ z?$7?^Aap$O^!015xdi~qiNKjT-%TIlo}g7jF))%&3|71PB!jis0Cg` zaFjue?fiu{l5mvOgZ5wlK+^=3NI;Q4_p!d+vZQvVTiI+bIBNmFN9N=^P#F0TvhSXE z^3#-oDPf=C*{)+EkVT}rfuk+dVJ&ty1AbPy_q&>UpW69!RRv$1n%B3(U%07e+m!?- z3p9G}+z{kPMj$_O844%IT#X`_5_YZ&f;>EeGa@hwydKccruP5V){0*xwcoO&&Gb0c z1TZT5|0yu#MJl z+;zP#)00}HAqoK~m=bob&xmM9j}YomO7`0x`W{60++lf&K@T$jYH7rPB)~9`wlRD7 zd0|L!>9$31Ce{k0*8pA`JWCG?M+DE)%NS~w>{kijYKb`{K-f#5s>id`g zNU?uYCaz(p!Z8)8)X7nhs?24Wd^2IKa?=Zy-#tA;hmBI3q`QJ{A`{W{loxG`q;q$bGI@Y-P1eIoD#vY zM?j>HzNOF8DA<<$^#x6}U;Ffmc1+sv)e

^SEDPjv5^m{DoxddfwmuBIarK7Im+U zZU#rsP#W)wB1}8-Dv`&##@PkuH9$}lX3f>P0Ndy}UFV&DR#Oi_3tH5_6 zm@4>Vb&0wDMhx3Tfu}@Z6+EYfm!?$ke!w-cXu9y?JO|$&7~LH>Awo$#xT%7-Z}iiK zk-i`mydS8G2&9Dl@aV0|ncqSFnLxoeJ{)BhL!l6^KK{$XsR@IS3ydxp+*ovK*oBvc z3?79ko>kEVa1X&dodRg6>y^Ngtn4B$g$U3ju;mfR!#R(VcLj>{2KN9CVc8?#^O=bb zSSRq?+XK`IOGF@VYJY`EA~}93bpWwYb!s4Q2s1uWH4#h;%?B$U;aS6b1%qj!31L|* k5}`<6&>gG+G!p>e|HhcBcl3n_`Tzg`07*qoM6N<$g2Wg0G5`Po literal 0 HcmV?d00001 diff --git a/assets/images/online_payment_icon.png b/assets/images/online_payment_icon.png index a6e0150af3d2fe2804bbf58a258a6f8ffdbe9d68..6e167aced001bc568fc6c448c7e3bed4d1d3bca7 100644 GIT binary patch literal 10046 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 Eg6yB|NdN!< diff --git a/assets/images/pharmacy/Group 1206.svg b/assets/images/pharmacy/Group 1206.svg new file mode 100644 index 00000000..ef8f7473 --- /dev/null +++ b/assets/images/pharmacy/Group 1206.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/assets/images/pharmacy/Group 1207.svg b/assets/images/pharmacy/Group 1207.svg new file mode 100644 index 00000000..fd2ffd41 --- /dev/null +++ b/assets/images/pharmacy/Group 1207.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/assets/images/pharmacy/Logo Parmacy-green.png b/assets/images/pharmacy/Logo Parmacy-green.png new file mode 100644 index 0000000000000000000000000000000000000000..72862b330df17999c5094e379a72e46bb0c558ff GIT binary patch literal 38549 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 + + + + + + + diff --git a/assets/images/pharmacy/arrow-left-png.png b/assets/images/pharmacy/arrow-left-png.png new file mode 100644 index 0000000000000000000000000000000000000000..18d58c8789d9d62cf07226a8667a3040ca9dc413 GIT binary patch literal 2208 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 iH)cLYqehJym85^pV00xQrb2T70000j literal 0 HcmV?d00001 diff --git a/assets/images/pharmacy/arrow-left.png b/assets/images/pharmacy/arrow-left.png new file mode 100644 index 0000000000000000000000000000000000000000..18d58c8789d9d62cf07226a8667a3040ca9dc413 GIT binary patch literal 2208 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 iH)cLYqehJym85^pV00xQrb2T70000j literal 0 HcmV?d00001 diff --git a/assets/images/pharmacy/arrow-right-png.png b/assets/images/pharmacy/arrow-right-png.png new file mode 100644 index 0000000000000000000000000000000000000000..19af7c0bac23d17d77e5bd6d791c729609adba9b GIT binary patch literal 2214 zcmV;X2wC@uP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+SQj^lJYnVh2OP`SwiHS?B)2Ts@cITe~wHVXrO5b z|2#}m#KCbS>pSu#H2?Wq=`S3vq>Vz9oJvX?j!;5z6*qZ19jB7Fu&(O}`y>4SR!`># z4pkndKmAQ}Z(mU#FE7ac0=Mt=Bz?D&cSHMwFN5AZJKXH;@@~kxQ$6qhsqF97a23w} z)9%*e*iMgb{|5n#5n<0ea?`Wla82gLqX)kDiqhlCo}JY&?t_oGdY>P&qx0^Q$gntYiZP}rF~<^X@+qX4Qj%nIR245lq9hT?Qlw^|LykFR$vKx? ziz^;eSS+asm0U`x6;3NmSG--(qSoe`Z=uDOnzYA9C)hZ}xi_>VM% zMjmC<$rGtG!;CXcnR%936}hHfgGNm%nzd*>tG289T{XT@?zw8bt7eLY)lM#|p<3k2 z1lx2HO*1Iw0z+{z1(49rG}|(V;7mEwY%30fB08wX(Zm^Sib26J*+u2Eb{FNI>P9iV zrJMUnIWp<~gmPrk?aJNj_CU2!*NWnoKsE}E>E;y^8yd`9U9Pq!9WLop1HT(;HR~p# zy-n2>jcQ7G*xO(YqH`qm4MEQ+fZY(ihb+FR@Wi;0I59@C7(=DV5zu?eW@;25R9Njp zJ!I4^jh;NuDI+y3kXRP#>dHqYz19$&>^!VrPMZ~wuhfRjg7mC0E6rY3q&$Cy&Nj@y@8E2nk~gGqHQC5K?5H%0xiN0<= zEuR=-2nMgL7Kg~3e#Mb2G@cfSpM4KR9nCYY&uG!(tazUmU2uI?(kl&Lp+y&5pV6Y< z#?Y&@=uvVVDe1izex^l_lIsX9dOj3ir$x_);_D?H#d}MOo)5*>Y0;|_*Kf4w)rsqa z`RF}b^y$>rSo#?OH#yvb_I>MwVb9{v0rM~kY|Li*m5EK(XnTkF-@I*jM8z< zQqiM0?4#Ry`AJDXH;5}gvTf3arN`RbAQ9S1kS)zVAp`nj;Z!R7W@k?hJtv1h4W%Vn zEjMsa`C&N-C&&)u(eeR=NDO%3+06rhSmt3TW%ur2rhupG7Kd!XkmE?G0d_FA#H;Y zScKpEMy5aXk^LVTvJX}I7h!|UJ5_~sTL1t624YJ`L;wH)0002_L%V+f000SaNLh0L z04^f{04^f|c%?sf00007bV*G`2jc?^2rVWsk+Amw00PEIL_t(|+U=UlZqq;%hQGwA zDzQVN7s{=o66gp-D<~V@VxDx~p`wDq5`@kMmIx%EnV|56t5 zSTpl~Gd^=p9B9?5RjXFz${5pKmbrFHHogk%0c$`Ce6rSlj~PJOEA;}n1)KvnfS1OY z?dt^K=G^yl;AzYd$_9`vxE3{pvH^VbT)%+uFg5^5nVqR>Dk2kL({szZh@7eFaU%gZ z2m=vG9fU=v%vwwkk}5h?)uD(Cf!nb|NUG{sRYwINoQ8&wRM~j}225sO0V~#-vP#$C%|J*a|V2A><+lZ zd7f#(#m)0?tUSRW!GQ9V7nXetdB}ZNAR(@LNoO(5ye}(^dz98mnONEUw zdpYJuF5uN}z7_z^yzl>kL$~r{0;v<&{9#D*l>%4>^OXTG#ykhMbIiXktDcVzfLr-{ zp601DKPD3ON;WUR9pKM`<_tKB$$S-gzyr_q%oR2%k*SV6AX@WP0QkI2=1VV!RrQyM ooB*r9SKvcz&wQ&^ty<0MFCu`1o^i+R`v3p{07*qoM6N<$f*QIMG5`Po literal 0 HcmV?d00001 diff --git a/assets/images/pharmacy/arrow.png b/assets/images/pharmacy/arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..19af7c0bac23d17d77e5bd6d791c729609adba9b GIT binary patch literal 2214 zcmV;X2wC@uP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+SQj^lJYnVh2OP`SwiHS?B)2Ts@cITe~wHVXrO5b z|2#}m#KCbS>pSu#H2?Wq=`S3vq>Vz9oJvX?j!;5z6*qZ19jB7Fu&(O}`y>4SR!`># z4pkndKmAQ}Z(mU#FE7ac0=Mt=Bz?D&cSHMwFN5AZJKXH;@@~kxQ$6qhsqF97a23w} z)9%*e*iMgb{|5n#5n<0ea?`Wla82gLqX)kDiqhlCo}JY&?t_oGdY>P&qx0^Q$gntYiZP}rF~<^X@+qX4Qj%nIR245lq9hT?Qlw^|LykFR$vKx? ziz^;eSS+asm0U`x6;3NmSG--(qSoe`Z=uDOnzYA9C)hZ}xi_>VM% zMjmC<$rGtG!;CXcnR%936}hHfgGNm%nzd*>tG289T{XT@?zw8bt7eLY)lM#|p<3k2 z1lx2HO*1Iw0z+{z1(49rG}|(V;7mEwY%30fB08wX(Zm^Sib26J*+u2Eb{FNI>P9iV zrJMUnIWp<~gmPrk?aJNj_CU2!*NWnoKsE}E>E;y^8yd`9U9Pq!9WLop1HT(;HR~p# zy-n2>jcQ7G*xO(YqH`qm4MEQ+fZY(ihb+FR@Wi;0I59@C7(=DV5zu?eW@;25R9Njp zJ!I4^jh;NuDI+y3kXRP#>dHqYz19$&>^!VrPMZ~wuhfRjg7mC0E6rY3q&$Cy&Nj@y@8E2nk~gGqHQC5K?5H%0xiN0<= zEuR=-2nMgL7Kg~3e#Mb2G@cfSpM4KR9nCYY&uG!(tazUmU2uI?(kl&Lp+y&5pV6Y< z#?Y&@=uvVVDe1izex^l_lIsX9dOj3ir$x_);_D?H#d}MOo)5*>Y0;|_*Kf4w)rsqa z`RF}b^y$>rSo#?OH#yvb_I>MwVb9{v0rM~kY|Li*m5EK(XnTkF-@I*jM8z< zQqiM0?4#Ry`AJDXH;5}gvTf3arN`RbAQ9S1kS)zVAp`nj;Z!R7W@k?hJtv1h4W%Vn zEjMsa`C&N-C&&)u(eeR=NDO%3+06rhSmt3TW%ur2rhupG7Kd!XkmE?G0d_FA#H;Y zScKpEMy5aXk^LVTvJX}I7h!|UJ5_~sTL1t624YJ`L;wH)0002_L%V+f000SaNLh0L z04^f{04^f|c%?sf00007bV*G`2jc?^2rVWsk+Amw00PEIL_t(|+U=UlZqq;%hQGwA zDzQVN7s{=o66gp-D<~V@VxDx~p`wDq5`@kMmIx%EnV|56t5 zSTpl~Gd^=p9B9?5RjXFz${5pKmbrFHHogk%0c$`Ce6rSlj~PJOEA;}n1)KvnfS1OY z?dt^K=G^yl;AzYd$_9`vxE3{pvH^VbT)%+uFg5^5nVqR>Dk2kL({szZh@7eFaU%gZ z2m=vG9fU=v%vwwkk}5h?)uD(Cf!nb|NUG{sRYwINoQ8&wRM~j}225sO0V~#-vP#$C%|J*a|V2A><+lZ zd7f#(#m)0?tUSRW!GQ9V7nXetdB}ZNAR(@LNoO(5ye}(^dz98mnONEUw zdpYJuF5uN}z7_z^yzl>kL$~r{0;v<&{9#D*l>%4>^OXTG#ykhMbIiXktDcVzfLr-{ zp601DKPD3ON;WUR9pKM`<_tKB$$S-gzyr_q%oR2%k*SV6AX@WP0QkI2=1VV!RrQyM ooB*r9SKvcz&wQ&^ty<0MFCu`1o^i+R`v3p{07*qoM6N<$f*QIMG5`Po literal 0 HcmV?d00001 diff --git a/assets/images/pharmacy/arrow_lef.png b/assets/images/pharmacy/arrow_lef.png new file mode 100644 index 0000000000000000000000000000000000000000..19af7c0bac23d17d77e5bd6d791c729609adba9b GIT binary patch literal 2214 zcmV;X2wC@uP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+SQj^lJYnVh2OP`SwiHS?B)2Ts@cITe~wHVXrO5b z|2#}m#KCbS>pSu#H2?Wq=`S3vq>Vz9oJvX?j!;5z6*qZ19jB7Fu&(O}`y>4SR!`># z4pkndKmAQ}Z(mU#FE7ac0=Mt=Bz?D&cSHMwFN5AZJKXH;@@~kxQ$6qhsqF97a23w} z)9%*e*iMgb{|5n#5n<0ea?`Wla82gLqX)kDiqhlCo}JY&?t_oGdY>P&qx0^Q$gntYiZP}rF~<^X@+qX4Qj%nIR245lq9hT?Qlw^|LykFR$vKx? ziz^;eSS+asm0U`x6;3NmSG--(qSoe`Z=uDOnzYA9C)hZ}xi_>VM% zMjmC<$rGtG!;CXcnR%936}hHfgGNm%nzd*>tG289T{XT@?zw8bt7eLY)lM#|p<3k2 z1lx2HO*1Iw0z+{z1(49rG}|(V;7mEwY%30fB08wX(Zm^Sib26J*+u2Eb{FNI>P9iV zrJMUnIWp<~gmPrk?aJNj_CU2!*NWnoKsE}E>E;y^8yd`9U9Pq!9WLop1HT(;HR~p# zy-n2>jcQ7G*xO(YqH`qm4MEQ+fZY(ihb+FR@Wi;0I59@C7(=DV5zu?eW@;25R9Njp zJ!I4^jh;NuDI+y3kXRP#>dHqYz19$&>^!VrPMZ~wuhfRjg7mC0E6rY3q&$Cy&Nj@y@8E2nk~gGqHQC5K?5H%0xiN0<= zEuR=-2nMgL7Kg~3e#Mb2G@cfSpM4KR9nCYY&uG!(tazUmU2uI?(kl&Lp+y&5pV6Y< z#?Y&@=uvVVDe1izex^l_lIsX9dOj3ir$x_);_D?H#d}MOo)5*>Y0;|_*Kf4w)rsqa z`RF}b^y$>rSo#?OH#yvb_I>MwVb9{v0rM~kY|Li*m5EK(XnTkF-@I*jM8z< zQqiM0?4#Ry`AJDXH;5}gvTf3arN`RbAQ9S1kS)zVAp`nj;Z!R7W@k?hJtv1h4W%Vn zEjMsa`C&N-C&&)u(eeR=NDO%3+06rhSmt3TW%ur2rhupG7Kd!XkmE?G0d_FA#H;Y zScKpEMy5aXk^LVTvJX}I7h!|UJ5_~sTL1t624YJ`L;wH)0002_L%V+f000SaNLh0L z04^f{04^f|c%?sf00007bV*G`2jc?^2rVWsk+Amw00PEIL_t(|+U=UlZqq;%hQGwA zDzQVN7s{=o66gp-D<~V@VxDx~p`wDq5`@kMmIx%EnV|56t5 zSTpl~Gd^=p9B9?5RjXFz${5pKmbrFHHogk%0c$`Ce6rSlj~PJOEA;}n1)KvnfS1OY z?dt^K=G^yl;AzYd$_9`vxE3{pvH^VbT)%+uFg5^5nVqR>Dk2kL({szZh@7eFaU%gZ z2m=vG9fU=v%vwwkk}5h?)uD(Cf!nb|NUG{sRYwINoQ8&wRM~j}225sO0V~#-vP#$C%|J*a|V2A><+lZ zd7f#(#m)0?tUSRW!GQ9V7nXetdB}ZNAR(@LNoO(5ye}(^dz98mnONEUw zdpYJuF5uN}z7_z^yzl>kL$~r{0;v<&{9#D*l>%4>^OXTG#ykhMbIiXktDcVzfLr-{ zp601DKPD3ON;WUR9pKM`<_tKB$$S-gzyr_q%oR2%k*SV6AX@WP0QkI2=1VV!RrQyM ooB*r9SKvcz&wQ&^ty<0MFCu`1o^i+R`v3p{07*qoM6N<$f*QIMG5`Po literal 0 HcmV?d00001 diff --git a/assets/images/pharmacy/arrow_left.svg b/assets/images/pharmacy/arrow_left.svg new file mode 100644 index 00000000..00fa7556 --- /dev/null +++ b/assets/images/pharmacy/arrow_left.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/images/pharmacy/arrow_right.svg b/assets/images/pharmacy/arrow_right.svg new file mode 100644 index 00000000..b4243287 --- /dev/null +++ b/assets/images/pharmacy/arrow_right.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/images/pharmacy/check_icon.svg b/assets/images/pharmacy/check_icon.svg new file mode 100644 index 00000000..cfa4f441 --- /dev/null +++ b/assets/images/pharmacy/check_icon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/images/pharmacy/compare.png b/assets/images/pharmacy/compare.png new file mode 100644 index 0000000000000000000000000000000000000000..11a49dfbf18881a724bae6e3ba9698ac4bd98eba GIT binary patch literal 704 zcmeAS@N?(olHy`uVBq!ia0vp^N!KqY3LE{-7{yi2FNExm2P z80zAbU2&bP`mqLqi*5E)hY|PEhLnm&f-@L zcK*|rAJBed&eA0r?5~VHrBq~-=7);^*j~V{y<^EFU*5z8Z6R##w%aldw%R|kuxOlg zL_EV`)q*LF(-KlkGMwM2SNvdPl~H`v@Gz0}{DTFmyhW_>lQWv%KIB`M$UiCPXkBA_ zNcJ4}6_XYmzt@oGbN#}+R$YxU{`5?NlY9UD`)@eId_z04i9+TB)rb>IWu~)!{~`C~ zoW+fUR%_NeK01Bsp7h*~jum(MKQ0U{wVJqMOL~v)qs}?Z2UkRX<#@!Yk#nH&UDg_% zPPQ%o8o6vt!~-`Nxr_2Yv&~$e`2KQ)UB|2!7oP;x ztoc>7z(_cFT^cK$OSR%gArva4o-DepSASuYGt#fwUmV*9^)?0L8PG`ptf6@%#^ z8*kp8u$L)nep<$}i0ap$97`sCKXv(lPp%OA&UsND`~LlyH`&Vel4WgN^b2mwhQ8vy iGLe<{8d`VW`oo;=**tObr%78uDaq5-&t;ucLK6Ti>MnNx literal 0 HcmV?d00001 diff --git a/assets/images/pharmacy/contact_us_icon.svg b/assets/images/pharmacy/contact_us_icon.svg new file mode 100644 index 00000000..fa591d47 --- /dev/null +++ b/assets/images/pharmacy/contact_us_icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/images/pharmacy/credit_card_icon.svg b/assets/images/pharmacy/credit_card_icon.svg new file mode 100644 index 00000000..9ba6c2bf --- /dev/null +++ b/assets/images/pharmacy/credit_card_icon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/images/pharmacy/delete_red_icon.svg b/assets/images/pharmacy/delete_red_icon.svg new file mode 100644 index 00000000..8897a683 --- /dev/null +++ b/assets/images/pharmacy/delete_red_icon.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/assets/images/pharmacy/edit_icon.svg b/assets/images/pharmacy/edit_icon.svg new file mode 100644 index 00000000..df7cca2f --- /dev/null +++ b/assets/images/pharmacy/edit_icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/pharmacy/empty_box.svg b/assets/images/pharmacy/empty_box.svg new file mode 100644 index 00000000..05816608 --- /dev/null +++ b/assets/images/pharmacy/empty_box.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/assets/images/pharmacy/hmg_shipping_greenlogo.svg b/assets/images/pharmacy/hmg_shipping_greenlogo.svg new file mode 100644 index 00000000..449712a5 --- /dev/null +++ b/assets/images/pharmacy/hmg_shipping_greenlogo.svg @@ -0,0 +1,25 @@ + + + diff --git a/assets/images/pharmacy/hmg_shipping_logo.svg b/assets/images/pharmacy/hmg_shipping_logo.svg new file mode 100644 index 00000000..8e9db3d6 --- /dev/null +++ b/assets/images/pharmacy/hmg_shipping_logo.svg @@ -0,0 +1,17 @@ + + + diff --git a/assets/images/pharmacy/lakum_icon.svg b/assets/images/pharmacy/lakum_icon.svg new file mode 100644 index 00000000..e2b223de --- /dev/null +++ b/assets/images/pharmacy/lakum_icon.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/assets/images/pharmacy/medication_refill_icon.svg b/assets/images/pharmacy/medication_refill_icon.svg new file mode 100644 index 00000000..d5951130 --- /dev/null +++ b/assets/images/pharmacy/medication_refill_icon.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/pharmacy/mobile_number_icon.svg b/assets/images/pharmacy/mobile_number_icon.svg new file mode 100644 index 00000000..d98aaf29 --- /dev/null +++ b/assets/images/pharmacy/mobile_number_icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/pharmacy/my_family_icon.svg b/assets/images/pharmacy/my_family_icon.svg new file mode 100644 index 00000000..838b357e --- /dev/null +++ b/assets/images/pharmacy/my_family_icon.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/pharmacy/my_prescription_icon.svg b/assets/images/pharmacy/my_prescription_icon.svg new file mode 100644 index 00000000..bda0e22e --- /dev/null +++ b/assets/images/pharmacy/my_prescription_icon.svg @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/pharmacy/orders_icon.svg b/assets/images/pharmacy/orders_icon.svg new file mode 100644 index 00000000..f09ae19d --- /dev/null +++ b/assets/images/pharmacy/orders_icon.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/assets/images/pharmacy/our_locations_icon.svg b/assets/images/pharmacy/our_locations_icon.svg new file mode 100644 index 00000000..2be16631 --- /dev/null +++ b/assets/images/pharmacy/our_locations_icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/images/pharmacy/pill_reminder_icon.svg b/assets/images/pharmacy/pill_reminder_icon.svg new file mode 100644 index 00000000..f4fb4ddc --- /dev/null +++ b/assets/images/pharmacy/pill_reminder_icon.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/pharmacy/quote_end.svg b/assets/images/pharmacy/quote_end.svg new file mode 100644 index 00000000..083ff39a --- /dev/null +++ b/assets/images/pharmacy/quote_end.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/assets/images/pharmacy/quote_start.svg b/assets/images/pharmacy/quote_start.svg new file mode 100644 index 00000000..74216f14 --- /dev/null +++ b/assets/images/pharmacy/quote_start.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/assets/images/pharmacy/review_icon.svg b/assets/images/pharmacy/review_icon.svg new file mode 100644 index 00000000..bb826f21 --- /dev/null +++ b/assets/images/pharmacy/review_icon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/images/pharmacy/shipping_addresses_icon.svg b/assets/images/pharmacy/shipping_addresses_icon.svg new file mode 100644 index 00000000..ebb8692f --- /dev/null +++ b/assets/images/pharmacy/shipping_addresses_icon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/images/pharmacy/shipping_mark_icon.svg b/assets/images/pharmacy/shipping_mark_icon.svg new file mode 100644 index 00000000..5cf9606b --- /dev/null +++ b/assets/images/pharmacy/shipping_mark_icon.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/assets/images/pharmacy/shipping_truck_icon.svg b/assets/images/pharmacy/shipping_truck_icon.svg new file mode 100644 index 00000000..8ffda974 --- /dev/null +++ b/assets/images/pharmacy/shipping_truck_icon.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/pharmacy/success_check_icon.svg b/assets/images/pharmacy/success_check_icon.svg new file mode 100644 index 00000000..ed1379b8 --- /dev/null +++ b/assets/images/pharmacy/success_check_icon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/images/pharmacy/success_review_icon.svg b/assets/images/pharmacy/success_review_icon.svg new file mode 100644 index 00000000..f6951456 --- /dev/null +++ b/assets/images/pharmacy/success_review_icon.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/pharmacy/terms.png b/assets/images/pharmacy/terms.png new file mode 100644 index 0000000000000000000000000000000000000000..76cfacab5761812815688012dadd0001543f321c GIT binary patch literal 1782 zcmb`I=Rezv0>*!d#4(zxRm6%BajYte5Sq63MeH=y5arrLuXS82aw@9jq(=Lx)jHJ* zTH3@ZYE)2^+M`BAj}fz48m=I&>yNlEp6C1S`{H@?WV^ZA!^GfX006)o9c(;K>2?}- z5#iIebx{*J1t`|T{wh#6q_hqI!fzaHu6X?h+A4GLSTdLCbqwZD$48H>K$>2XI7QNN zD-h)bcI7x~Ee32PZk^!bYPbM-tnBSJxd17cL$obbh#j6JI))J{gRWXE~hX zGbC?wye+(~p*5^j!asTYQpY?RgTW-blwANf)z?cu{KO?!HPPBa^GppS>;hMJc5a_6 zFF!Z?-WLc8l51;kzl=rh-PSFJCffvy6I0Sl4Zg$95#Q1toSZ$Up>fvrCYwflj@Jy` z)}>yS6ddw%{FQVY>2$i~@brtUr_eRY_|(D=1|wJG98z=!zX)G*lfC8!ON&Xrz>jTa zv3~Bo3sn+z>#($kGApF05h}{cWfp%7=7f{Uug`{*OcN0;6#kUB&`jc0=BD1jji@pQq?y*^Gnue<3nP-?Yx0H_dQi1AFx zuwM=-PDf4Rllq*_pwTh~^VIqd(+V~0{Lqz_aCl%eUNv6aENay~_)8xyKOIIiOKpOP^7nbED%Pt?p*WFVV(?8N#nc+@vW1m6+wKpo8hG=q-~G8Y>tYV5U~3dQ zVPbO(JuvUeC3yzQ4VlwMoacw2Kk|vMXNVR*z^I_muZ@ho#K)6mxIiVSNaJhE`Ajh(QjW)!o6HORv zbQ)uMK^i-nqOZq(mXR+I1&~Hh4uKKr!l3hjQxIkkRF2Z_(*p`W{a-qGCA;cfioG}1->^njKIm2QtfA8fD3~5jWn)- zO(t9eLb1lSypUd}uUw0~4<^)7g4r!)-`z+WZ06xRift{#X#uOSV~k5GpyHyoe*ZOs z^OtA$^Jkk#W7c@$!XMV3Ytpz?*7bnA~Rtd6c2)4-=tRp1v10EG}*B`@RToQ)!8|o$6TYdVF&-$ryY< zq%>QXd!#Xcrbw#(kZFyLk?+)yE^!w|kl}{>n!ndIeV!gq9Ar8$**lhScu6i&@u;VG zy>nJRk$ZL-XE7{;LS5$z_FEG}G=3UwQ`iSErZXg*B=9>=;jCdib8@{CLN0MHN(|-> zG%#~R-Go&L4qwm3+99&Hoe()mo-;A$78#fKl@E)&s;iE`t0f6SA`(`wb@nil2yr-6 z61q?7#AP&uS>7)RSIw%?0wY;pwv{lmbV!xBO=u&6C-$xZR49lH4oONnxZ3PdC(Rp? zobBrBvS(NSnf6__gPuO}3Es*4b5p$Dw{i3)=_bHWCH0o z^McV6S*b!+F9X-h2xJPzH&+(s1K7`_|556WoZXd<3SS7$a9utb7V805&4fPqIK`yr zIHbB}j9aHH**Err8DDtnl*6FP6u+L5d+<7vEIy_SDnNTU6-T4t$F*({vVFOgcR>z|q##rtT_<`achOH?sf$ literal 0 HcmV?d00001 diff --git a/assets/images/pharmacy/user.svg b/assets/images/pharmacy/user.svg new file mode 100644 index 00000000..8e978105 --- /dev/null +++ b/assets/images/pharmacy/user.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/pharmacy/user_icon.svg b/assets/images/pharmacy/user_icon.svg new file mode 100644 index 00000000..8e978105 --- /dev/null +++ b/assets/images/pharmacy/user_icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/pharmacy/wishklist_icon.svg b/assets/images/pharmacy/wishklist_icon.svg new file mode 100644 index 00000000..cd0ce16d --- /dev/null +++ b/assets/images/pharmacy/wishklist_icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/pharmacy/wishlist_icon.svg b/assets/images/pharmacy/wishlist_icon.svg new file mode 100644 index 00000000..910a3ab8 --- /dev/null +++ b/assets/images/pharmacy/wishlist_icon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/images/pharmacy_module/ic_payment_option.png b/assets/images/pharmacy_module/ic_payment_option.png new file mode 100644 index 0000000000000000000000000000000000000000..5f3fca8fbdc06239e8d934dd377526a1a3696c69 GIT binary patch literal 447 zcmV;w0YLtVP)m z*bDjvv`uAcqoh$#!8A5$%v%vt2muXwMbt!%(c;WrmLQkh-8?WXXJ_|6bI#0}O#A9W z9|kdieq6*i+{ZJ>S^zq5K7K9$gE)f**6{)JVHa>W{HtYf4{nw+>BC9vVzC673;S{? zkp?y}iK#qZUdHRlViwbQ6tETiX?ZwF2NAFz3h)Hp;>HmGtu!a?wh8XQPn@j)JHRUT z1AMD+T*W5-*09ggaSp}$bcSWT$AgI4u5vs?H?Cj@*K?f16P&65Ei{W^e8ndWWRd!D z=m$FS0vko~?%-7o=%}=7QUR|O;9jYKRaNe$1&mX#8_M<_CnEEe0$lfE+?M+JR|FWz zTYuk{en)_J*gj71KAsngM#*srYuE~VS|>^#k#a0yOqv_;u>z;53^Vb3>}cchf6#kU pyAGEfy?BE?)!J+qFQr-0)IWY5fn|^+0>=OV002ovPDHLkV1l0Fzw!V8 literal 0 HcmV?d00001 diff --git a/assets/images/pharmacy_module/ic_shipping_address.png b/assets/images/pharmacy_module/ic_shipping_address.png new file mode 100644 index 0000000000000000000000000000000000000000..9566fb30a09d27cad92a94448a0b91c4c902dba6 GIT binary patch literal 383 zcmV-_0f7FAP)*_E}|3y1x?W( z5Q9n!>d?^-sB1K12L~yXR7#gdzrf^@K)f6J9sn~=we<9~oXP_LFPupZO=?rkB|w+>)KPlz4AIran8 zbgdgTYExtv+&bc=L?~ zcxUJp0DKae0x+qg3IGJI+!+BQe)=u|0LW=O2N&9M001y+Xw9l;1pokmsz{^?002PX d(xm_Z{sYbET)o?e#uWen002ovPDHLkV1mBxiTwZo literal 0 HcmV?d00001 diff --git a/assets/images/pharmacy_module/ic_shipping_mark.png b/assets/images/pharmacy_module/ic_shipping_mark.png new file mode 100644 index 0000000000000000000000000000000000000000..cc4b272d5a875da77ddc5ad003e40fd05a6b5ebb GIT binary patch literal 782 zcmV+p1M&QcP)eo}K~y-6jg(7B)KL`1zjObu(Xr67qB43(ML0@}#1JJZMI?JcMG~~A zHdeb_7}BE0E-IHrP!VE6nfCNi5Jj106zcSX(zJ|$NzKPN|C#^2r-jZCqhe=u&UerE zJKyROW~h?7{2~ya04TG6;77b6j3L7`E=Afgw{oIMeaZkE*N=lMtcxnuUICu$P9ch*Ewipv1x(1sWM?Ij7>#BjflVoUPtLSY%uKC4q3uc!zA)KJl9EpW$Oka5#aA`b=Br8m z>F>ju`MIiS`FTMEWeDoFOdJVmvR4b~hYHraE5w_g;5mY-G(%>Bl>87tK#|z;eTB>Y zvbS+5h%dU#xc9!_-o&su$8wwIb`r41f@m)z%%j z#Gn!|?lDoPV0=@8M~4D31I$UxNK*=FVTDvvqmCj^!iMI~!0s`}xlOIz<23-1S%~9V z%dHQuzSj)|gAqI4T4`6YvFfIPh(~o1t;~{l}gcv5Tm(3A( zu!0yz3Dg5tEdad+tIrDBkmT^6aU01bD8-R#F)?L1K(Ga&O6N;k$QF}kf zOWV!?I14})11ktf1d!N26mk)f5+FwqhBb}4h^X1p<(0g(bNvAD7s#tA1!~LnG5`Po M07*qoM6N<$g1IDZ9{>OV literal 0 HcmV?d00001 diff --git a/assets/images/pharmacy_module/ic_shipping_truck.png b/assets/images/pharmacy_module/ic_shipping_truck.png new file mode 100644 index 0000000000000000000000000000000000000000..274ae1da9977edf7a306c9d2ff9ef27afd639361 GIT binary patch literal 503 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 literal 0 HcmV?d00001 diff --git a/assets/images/pharmacy_module/lakum/expired_icon.png b/assets/images/pharmacy_module/lakum/expired_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..9a9809847738aabdf56096c04e49cf5222b6efa2 GIT binary patch literal 737 zcmV<70v`Q|P)X1^@s6CN-WK00006VoOIv0RI60 z0RN!9r;`8x0+vZcK~zYIrPkkz&si7;@E4{r(~Q(+8H}uQwNh4*3#6KsM9Jv~Cpzdc(+cgN68r;}u9@s-b(FN3$rx%z2Mk z=}xiow>epNW^`5*#mvtjhATPedvGWH9~CLjWLq+4|Km^<(lW$thOWBk>qYZ;aU3S# zL$JJJxVHGZlOb+0QIG)oog*r?Zon{H{;bDmYs^Jn| z<8QI3H==k)C}sJ-TE*ccan7$RZY~+VGjv}U7Ac*=3v9%kD#S!Z_KRjS8u>&~J0}ux z;c4kqevdPJpKN;YMFqVhVxK1z3ENXtD{CO8+{$m`x6vF-Nl_iHkvLDjuR!*VSkU%L z4$g?mYaIi5o8sH5OBCYVO2!LBxp$3$xCl!{CJvNQJ}B2mKLa!H51xwqy(${SIsTyd z+AD+E_yg~;ycWY2gLh}A+Fl@QMKA8drdmidG>O+>)?>Hht0Wu#=4!wO(U%8AikFOq zG>_E=-(UT>kDt@{mN=i;<^CUbsi6stcgp%d z)K03Y9aU95uA*{WP3<_40Y)bv3{*k5EQkSA4Aicrb=KPYtc}gp*w||c3D*)6Z{_9P zE-buVQgXYr^iFB%{g#&Jixxd!vgFm8HLupLeYI}g`-2BRo;vmI-o5Yl@Be!J`tP@I z|Ns9N2s?BH=rZw=AirP+77HtD8(X`{Q>QOkx@`H1m5-l1{qgf(z;xjUKqZVx-tI1j zH*d=p0XY?(E{-7_*G-Q{iZwDYI9wE$bej0Y^I4_OxBZs#e&63Sl^l<>^R;4NVgA2} zL1ITpX(Eg5UzsgCVog&P&Hfc)vuf(Glvms8_Ij6ktrI){KC;wp+0nK)W)qrkb@O1TaS?83{1OR#z BrN#gN literal 0 HcmV?d00001 diff --git a/assets/images/pharmacy_module/lakum/lakum_card_front_bg.png b/assets/images/pharmacy_module/lakum/lakum_card_front_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..73323a0ebe7b67d06cd87139d848593505e7356f GIT binary patch literal 89083 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

Wzy7IB)>vlWq%Mm{P5ll(n{4qyl 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 Y3%I(5+Q=CKP))P5hE zXvIMhbb|J5|bFmIWm7iv6^v>D>NmAV#kS4i5wS1 zd3v#k6;Z}B%$EaF*b_~z4M)DFdMui17Q3b39M(gddFAhM1Y4LX26Je{T^T5@d$fei zg}0gxZiBz%9|-$z#oz}ze}Q6k3UBpapH&7O7)x+|G`MEqMfLxj$24wh==A0j%hG5* TPksPQ00000NkvXXu0mjfv*MR` literal 0 HcmV?d00001 diff --git a/assets/images/pharmacy_module/lakum/will_be_expired_icon.png b/assets/images/pharmacy_module/lakum/will_be_expired_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..7f31f622b941fb02f271be7be13ef908fd98c231 GIT binary patch literal 648 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 literal 0 HcmV?d00001 diff --git a/assets/images/pharmacy_module/payment/hmg_shipping_logo.png b/assets/images/pharmacy_module/payment/hmg_shipping_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..725b2e5ee5d2da3829d1631aeaad88502d720708 GIT binary patch literal 1821 zcmX}rcT`h%8wc=2aG@MHzLnAnE~pe#1W_@l2$mJ8lucP83Pq)sQG83VD4;TefDlF) zVGr35Mi^nLgpn`<0TPlx*pP%s2HEemJ?H(N&wakn`Q3l+x##>6?Cq?TmA+R3fk4Vo z8w*FEeSqitLkhrLJs7MG0_~I9|Lknp)6+9BFfcwoKKf6_#>RjK=Ku5WIe|a`7BZPk zp-}L6{DT1hz>uJz=V8wyU@xLy{T&k(9rrdSF7_=v{w+KqHW42GE-@iF37(Ran3A0M zKIL8N`{cCLWJFp@I^ul>A~hpDH8UeED-)5GnU2g#&qikEWM}2(AoFsOsN8H+UQRwL zw;&%?RG42}R8Ue}SXxq4R$5$MR#H)3T2WE@p`xtvLwQwYMOEd8>Z%Vl)s?k1RkbzM zb+tA1^|cN4b&U;m=*D_9x}gc(*xc0E(u{6tX=-h0#&7|Y9ymF4BH zR#sM5SJqZn*Vfk70qg4<8|#}J8=IS(TY#;t?d@$Qlc{l@sd<5UTAz9P67#GfaKK~% zSS+o}tRIY6=dQ5MLs*w?ve<04fhpVYHrvRYef19ex)mE@#Wt~K->_lt?ChA`+p%^6 zdWXZ|KwUU@T{*UHoS%Q?ICyg$?*nI?FaKos%a`5V-N5I-*yVD$uxKtU252si$BT;R zy?F;TkI&;LW$;sxd>{gWAU#)*QzSr@0;^!}YlQX9LNrF$)Fy1{5CRd2M4i2&?tW4K z0I-V0V(~CRJU#`qgh-N1&q^c`DSb)GSe7zYq^s*vsZ_SjlCjt_E>Ff6$OL;bnM^Je z%Ee;2Tn>)?=0CuFI2Pt;=XB_BY8oOPm0wV}x(0k9pD#P@PN4vA!4GY%Eo76RekTw} zp#f@P?rekWnt?f|yQt$hMYoUIwNSTdzy#85S606AwKic=xLFnW1(%$NTQ$fhlQ2!ex1h>jlMZMZw<5@+E$dNX80&)< zKGE$bVb?i#efpN%Ny5k{w!319a04Ux61wXY{qiZw8_~``W<2$@y&3ac9jN-;CJ&O} z&~5aG+u1aAx5E8mVxWd$RIi3D%P&wC`s}qytv>P9OKoU`a#WBu)MVBg1>;!K;m{OT z=j`G38-4H}^+wHMuFc2MMs0-q_& z@xf@KWi@l{*@28&e5ZTcnIEdS{lfC#kLi|>M&$}+izBh;)dHVYn6;T#7Z~)YL_=&V zPMljKzzr&=(C1oC?f6I(_8cP)(-X~TPeP^`8(U?9zAoa-ZcSNb+{u7?l-=*w`13cO z;7AEL-^TF9#W1cf%|GPfpB`Rvk`VUD&!;l*#ABxpe5WUtcQHBI3R7#x(M?inB{`(u zw|y0PG1Ih$3;G=czQ7S*?$w!GrOBz6$PV|N9Vrgs0i<%5zrxg$gc;r=8mq^zx!&&8 z+Ugw9Ge%;9u%vlTILQi^!;}7|HxrDY(aw&bCC%C`!)VFoPItzDjw>msBLFq@Sbxsj z#cR%6IveSa*)IIs{GP*vi4)AS%Q18d9fzN`O&n1}W;uUD^{-Qxa2H;SD!5beVp_9r z!!Lg+&^7h~%X>N$)=zmzK6-+sa-j+YD;M}seBwT<@TD)k3}`w!r%IF{q0Zw}w~}Og a=0QTA`%htE1O#xAK~PIOi@G}xV*Up+BSb#{ literal 0 HcmV?d00001 diff --git a/assets/images/pharmacy_module/payment/installment.png b/assets/images/pharmacy_module/payment/installment.png new file mode 100644 index 0000000000000000000000000000000000000000..034497efabd3db47c841d9464472527fb0095539 GIT binary patch literal 41513 zcmeFY_gjEMMK$Ie)(xfO&q<85eO`0_6y%Ty50Rkw3B29YlNRcYNhNg4~JyHWw zLJOgW63QE|?|t3x^TT~S$MXl=`2qIab9Q%jc4l|xvvWphzEvWIn2JA6lD+vJL zhXdakcpIpziCeq5@L2w(;qh~E$F&9kBxU^EEv=nwy_u|R?SZaR&(N(M&zOKVQqS~- z)%n!je)a2isQ{X^pIB=zh+Oc|(aGRe7l+A<0Ah;Uo;3kfrcit+G^2nvabaWM(-@xSEdd&$c$ z$jvVzF2pA;Ai(rrzh}77JZt9?Lpqw%i0s@?hSNvW%}ErrInkHx70Hnr~jFPi@Un| ze|PNa^(pXH@}^Y z0Jo5^fF-w;sErV}ps=u=u)xcg!hBY?|Mv4gwHFlO6A%*+6&2tU5#r}p5R(-UmRFP& z5qv2q|58|1K;YlD%C27Cmaf*e|BemBjs0J3MgFgC#pOJ0Exp}5-?_Ot|EmR>4sPCV zUJh>VOmcF6S6z(hxw@q_(DiR6$KQqe&%EVrJ%PTqHj18ZE=>POS{(R4aPj{pf&a9( z`9CE1A5F#8;AZ0fFGJ#XVpi6|qJqNQRsuFJxh<`QM7YI-t@*h5Y{hIvZ3Kjbt;G1A z@#0wI{i{6xhcf+Jh11Z##s4-9+{1qxm#r(#qC9b?^I;J$9RSD{Q@6q<<=UkGfhj7NCJG??;Umpel|O|Y1Iwmt=PUm)&uq9!gsBbwEo(aQ;Wn86{Bmb3EdFiqs-mm&-=0E@Lf;eoOH@yYfA8P2BPrqI zf6G&}|2x2c$>M)S^uJp4k1G7Hq5bbx@sA?>zwM^#kuO4&&v~!QZZ-KEj7h4*x~D5(y67~UGl-vTxZh3z1-c|o$*}nQXfEw>h#^CnIhi#owoWN z7bjTlST=G6A@bTd$2cI!#uhOLcEL8Hc8=;!)7n9k7n#$thPA61_l(#Xl+65Mf3ru> z_hr+=8|Vvyg880*V!pmgD&%iU4?b&jnKd6Nl+`dXZpl)Ep68I+t|LwSy{3o&oh+Ab zH%A=>5A4(uZzV>MlL*j}Y%UjB;}bLP3f&D2tArpLySiklN!H(S06M>|Qj*Vw!wdtU zHi*V@DLBSI@%?mN6?SHc(MSS~y2)-2)|>F~@2GX?6Q_z{#pozVJtQrc3*eQ4LY`XD z!T`L2Xt;+=8xT%20iuxc{L!~@z59%_y~9iVc-KD* zHS>*5blop)AX?TiZq?8~i}du{lkxsTR#r!YbI<4z*>k?Tb0zEFk8+ENRBy13{1)wb)kP#^stnfhb*|p`*EAy;gkdh02uW>L0Dx46 zxu7zRSG5IyKCY;McT7eQ3s(g_Nt97dANw75z?@0z8zowf z7+<}dyU3pxaIVf$Df3wg(K142| zg+*7GPvsLO<5KX+bna!4W{}i#4Z`*8C$P_006W{!h>c$nlo!}*Oj?c%Jsc)fz9;gE z0!yz=3$PHUT?sE7i0GhAbSsB+aP&}8i~I=v=jl4ZrL->M3ZEFRGOU_P z@SuXP?KFd|Wt`snjRraUyV8;tX?2O`9TuGUG#8R8RbGBn3E)jJ%OLuD5^XcT#T!-a zx!pe68*GVBNWXmfR{P=1!sqwHK*19T9rZ%Zsov@!i1+wSg-h4ZTY!@I;W=~R?|a4> z*JZNj6;J3CA_e>hEP}cN9t9WoPQjE^wW2YYgWfu!+22!r(w~GI7R?PgoKYXK^DyM$)wx4iuUcnZlU3@T_iHC z(dAA0EPCE)h>#d6XNe$unTqq!rnm5g!@UJoV(PaXA1u~3bVQlr&tsP8FiVaP+w0KN zFXv9X3b$t@A+7w9TEGnGz^<&ggB81b`0?hLu z85f}@DoxHU+B$uLfM#n(IE!6!)(PW+lGEj+mE&?IH01Gj8|Zfe2l`TG`TesTWEyR9 zYT11<-VDTg>64m{;m3hGTn8hA9aNlT7gJdD!w!juPv* zHeI!gv?X&51aX)eP1L{dmZcu^Mq!zGhykyFHbvxhS>`npaf!v%YL{2XS3ccVvt}pQ z+WeBbScgxmCdu1sB2@`u5+bo=u2Wmzh08^!7V$s5*nXap6+k*0xbSsDOL}RR?7AG> z-}6`SCwTbxMtdN1T$|d_M3^f_g;2r{4Igknm8T?gm6m~{9Z&$2^{o%*aX+ULb)M5p z7w|udj(h;R%BcM#0gnkqDo5QkyujzIg*k;=5A$GOlmfpI>K5>NR%Z?jb+`>?bT|fS z4~)3-c+H>NGV*E5mEE*;^5l3OkH7ZQY`2% z5&;mrjguykXr-j#-a;awRyvhJqZ_=RbFup}4dVMq3ukrkEVJhjF)7Arh5mavNwMc* z;Fpzuek7~QJkh_*RNV>?dWzj!++8hGG-MANdypAOjf}dt9+6OdRDU2^Ls5r3)M%>x^6CiLV-%89xwRx(B_37e zt{TtL?sm($>*s9v6WH@xor&4o7*`&NQ@WaKTb;*<6B$JtJix2cO?gE66SR8};#j9I zsJNw+v!I|f@DD69CL-`pl`R6T-40m)@OMq=j+mXs0#f$RQyL*+udXz`l%rn=SGp?C zv3jd3(ivPOd>Ud@Fd4emQ-BAEEtSjG?zPpS$=7$k`U9GnqGicjPf9of%4Yi(3Hhr4 z0F|DRVzJ4$vE`D9tIC}*g{<$3X$;hrDGZc~vX)c^DK1rF3Tpf}*+M)!J3k!d;{V21 zZuYqF1k>Fbqv`Zf{1q48+6p}RdHc7ivgJNKrJ<|%iH2VcZTzAAI$P5Ws(t#&B+UTs z7XmwF;V=!}{)-Lw-Tdk0Le>L1v=Alb@fPg9fPXFCnnh=1* zW1|;sP~7oKxL*1sL;W5m0O8OzQg(TpV&mz)t3|1DyX}X)ya@3}HVE=T4Nqs+ABFdG z?-FV(kN;WjqHhx+zkPHUkh^ez{=P*wtzm8ic1TxYznSy&U-M_EGZ^wtW_L#<+k6BH zT{aeFEZqhF0H}aN@YodS5b9zvyJO+tU$hs%<%n;fusipgmP!nagx(hxP2;#Z4Lxjr z0(;S$sb_fK9%>l{J2X_PI6Y702@%LI3+VF@WcL++TI16ZtybPi796 z;+A}21Bdo@e%Se1n^#l)v<5ga7 zZtuUm_~N3117O{(*8L8z^0wH7e@Hjx2;bvIHwoS`TtVw*aL=7OnnfPB@< zk`AxCD;H(RZTxqdA^YV|n_8eI%yMKOZ9lqSY33D%PkbnRVvvqiiRMCxA@d1!1dk~% zt{ojp!B@l5DS5)L2pqaG9hY#ISt#NwVWc-6V6a!TL(8RL=+1Oo3-|ilVea{W9fNfu zWy<$7tB*q>-~TlLxCh!m?q-a3Gvg7tgYcm0NEs4y-ol*jsuTI10InN2k_MP`2bl_# zD9!|iL4Ktttuu84a#?7l7QuWe=xZP2nc(TO)YI?d1!e%iiwVu|Swf^e-xC>iv(u!H zo@2mRlU^wMMzQQZ%?ZK$IW@Ya?+X4cVx-a~9TePvz* z#KOJqqB>}*`^W`bo*YPPMGm0y%coQ7iOqv8f*GggqZ~zM;r_WIpUl&oJe_OhPQkR=b?f%SKlO*l)e8} z6pxwi~urIXew`sYO9Hoa3Oov#L%MK9oktglvcEBG6QS@4g;EXa*f%t#rOF98pp zVG?eCQu9S-=$_>>0PENSZ2bfwwB8!L7(dFkNCW6htka1ysj4}cK1GMYY^Yv`+{100 zRKQCgn!Jso!`q*;W0mNfq9-Oyr2-oTG$f@QALmnvQ*b+)0Y4^fH2bslZQxb}2;~;8 zZzv54G0*OSl4Pjr2I)hS#_N3pK;-+9Iqb?_*fI|vZ0QmQKKB(-e(})z- z<>`fPzEV|BCjY)VwNr~3!ZT;{@=Y`3^c z40Fkpi8k}#5pKKnnIEJVGkaSyu!LOq8^}Xv7g^TR{-_6{^KQ&iSc9r-So`7(FKCor z7ZT%oZ8;O~U;l+@T)Wa&2U0@*dNF+2;rVxSS%l&p;a?QBfQ3mJ1`7D9!N}(7sl>Us zhv0R>pBn(gMwo>I|AIt$IAXLqv?e(}#-aWU_UO%)^Ul5w5v$-$KS z4GB>S zn$et#@2j7~1N8VRasG=+ZAZFtL5Aw;^PaZ9#HqMwG?kD6=Z8KLtH8ZCiYN8&lDW=E z_NEd9))e#LNIK<(O8%0DaD1-Z%XMhurz8LSs76BZ5B&TnKTdx!ra$Mpwc!c3O&{Ao zP_o+Xzb|XUdR>3Ed4Qi!p6x=v){Xn>~^yhYGg+OSCkI^^lhPVT^o z=lBV^hEgw$-lvBT;FD;^f5y#imePDOrhBm4UNG_w--b@Xz#KVImD_a-hgSxrjEG~* zLUoPM^Q`?Rd!&PyT<1Bs591Tz-Ln*w$p&khf&Z@K+3vg;YPkQLi)`>q*5rq*ShF?! zRyJcjG6z9C$KpH_*t=+@QELmlL;%ho=-eHzeqRAQ6SeVI)uR=70t5iqb1C$RIMd35 zr@vy}N^f};ZSEii&kL1E9%iR2eq|pPpXV$>q<}wL*{&?87kJ0 z$D^ajH`_E_g?$ialMG|bRVIs<$I$3{d;8wtuEG$W$vXeOkhhwvOJo z^GNi~%x)SSt3}Ev956G&gacxFf`Vr4BFKM>&zLm_8>q9(mNOr1uS)KL&bd0LRl;O*MyVY9X4<&&f{W#vW3`Ulfr~JaTHX`b zuhd5u2MONtx;ds(%Gwk4G}HPg8e@tnx@dtvPp(oQmk+CVy*q4h@0vSFo`!)>xgYz|(hqUywWfNS$RBR_bT_kHBG-m1 z7d|Ws%=L1R1|Ey;wJ_}d^Qlt!f#q|o-r&Q0l*QZnyMJ;i3EvN4K$G_^T_`QfL@b7S zqymzuT{HKy+ueir)Gc34kf0I}f+(gz$v#ca%W{gn;xo}%0(8~y8Na=p?7)^xN7|EH zwlaL@2cw~j=W0f+=Y}AaK9U!r{;uN%pJhyI#Na|ku; zQiLi2nru*t(+N|X;mdO`{#mvE4B>9-z!A?w(Jc{_WNV7MbfkbY%hHQf1J`~9d?yK$ z92W`Rb`jp)>6FK#Ybg5Rw(~LcW9*;bF){OI{xUm|{c&QKRm(9!pDBR~P0?RZfI+TA z@rQ;ORj9qGJx+$ zm4?DMvm0VUj#Kp6L>@2|x4S3eRC}do<$d;0$b0eVUhhWtVEWA5)&c&{?+M&jdU4T~ z)NAH+xnklx#j{p3>ZbGE9odMifG3w#AG>a}WQFKcUwV$4C^DxR(l6G)FteM~>b3X9 z5t!RquXu&_7hm@^I3cT_0>gtQgQT6cd z{OF!?hkbrE`Xk0M@qVP0A5UPgS!f+&RO=NJhFq?-)(N)VLPL?^%`eDSjqw7XgSf#M zUSk2!#bH*OeGGwBwCqWB=&bu(wH{IZx zN3x-P0g#CU1tG-(if!1H>)1k2j*GRGr3IeJM^;MkDeFkxXqY00%r{G}z4A3x=9vmh z9?nvydGX^)N+; z*avmLI*U#spBZn<%Ioc*knfbDWXxvl9qIpNarscaTv>b@TDVCldWpG5{~f`|K)=5v z?bNe<^9%{@8HJI44`U(>eC#|M1Txol&3sW%ZM6p1DGQa*(|0|zp=?XZkolw+TNPSb zZ#o`gC7gPTlYp6XG!b+cfkiKF9-`T^+GA9?$$9`55+t{MZC{d)MY@}U?mG&0FORyC zRK6>an2{U*A%fb$fuL#98s!z7ita*kbnE!31@0Q{HK#^(rF1-`ux8Uj_up zATFNcbShgsVXHk&Qf97p?gs)}EAWl;{6~eKBYXqo>#}Dg@du*j(OpWl zy_n*;9kLU!vkG~&SbLP26jAv5)X%ITwZMfn)zCwLLvcMP%&EG4CYl@BPuf`pO)%LVj}wX10=lkp!d;z3)BY$Vb;39pzQg{OF=$ z(Zb9n{0QupGhKb{OiS@P$gOe~;wShdw2?o0OtIpv`!yAfQ!D0XBF2L^>Rzv~?>7rS zFvHKr_^6}kyD=T~d-kF$dn!hF)era1OMV$sHaJ0OV(L7(AF_WDwR!m(#IboSg-5~_ zB6!>MV28kIN?OnZq%<+CXfpXkqWg@Yg3oV}JZsrFAg56vb4oa8*`Sth(_HZB_w_h> zWc-!1_)Tkq3hB>8MaXUe5J*L)n+CSs}jHE)U}N%y>jl^ZV(RF zN{zmsA>Db+#K9PYKofaFGer-;r@ppJl_T_JRrP$ojpA3no;7h5>F`y2i6f}+YRGa; zW+WVEB*F`FYmcvc=R2?`$hds=iczjC=8q$93i4(wkt!H*d3M5a`dWgdXlm`8lWtA2 zA)rocbI3+sW{#X~OsduVPXp@W2(H8TV-DjCWIR>is|s>LHgFXjL8EBfPP#ki=ffo> zdC_Z=#1(Bn8%B?;ma4BWR0XT9d*@_w4EopBOhlSVkS$_$r#qjZT^=qvq7_s}HQaLt z0k>Nli_HS}x7m_AMu|e*7T!BYbtA}7`8zc5PfmHHAnw(;X&$mUgPnE>(j(@a3bEBn`Q7UbvIXbv(lV1;MV;*i*Ze zzR3K>d>)PIIoV3`%kh7=Y$}0lm8Cmh%ho6qMfpqqz}g4hMg93guMew)Wz(xhsXc+` zI)4)JoLqwG$JeoN*Gjv^lyEt;oLgvPAy=J)MqT9?)_7=*t+vkC{7^x+)P`ND%qiUp zLja|BONN0`SU{ACAuh2)E-STa2a^^5uKL<2#@^J;*#1Fu>1EVtF~!F$-kfnl73TXv zWcbG?#9?OaskdTx&!BaLXLfwmZC#N=eoMv$yNZLY78q|0u^ejRIxddgnSxJy1gnD* zvrXz3;1o9Qf&Ih6im|iS{y=t)-KB(^7?oRrX;v+!eAId$mRsn4DtpYp6^`;vBxy^n z(Y3TB9HQs>2m4RGbANqo_W$p~(074^tT>Nx3gy zy}0Eo(0IU5)m3_-tq#_bubO7>0BiYb8TMW2sq?h^vMPINEBR8tO)zW1=nVULRgFdR zw$ypri8A81*G=T zDPor}x^~h4Ldjd)yv-Fy$_YevomYC=EVJ#zb1inVUNXck>2#;wSyZtuw*Fu58Cy z7G}Thl=oN+L#pj{eD=t@UP*E0mp}3@GB22y)$hGio{{HfdbjrvxH8(w5#1X2=a&v% zTO;gJlMlJ1`X%@Lel{YKR=*-wUAoqOYUf&UOcBgiZS}S_<{jgEpUGZEFW*ISlys_) z?i;yq=IX%A2P1_kdVQ_P5_8d8ZejKdeJ>b*TeN|?;VGm`ci2!0Tc5B_WfpcW;r597 zF}tqaIbv&?96!4na{PPCDQ|~~^kZ2^8iMRdHHw**Mg^+dLL<&IMAUvS)+io0bmLV- z@<~CfDgte9tu~OLU;pWig)N{|=ST+b!Ei%)Wwya5#t~_ASDGEScQ$Hiis|fh z(qC6>i-__VK(;SEd+k3-S)#pK-J~;_iXh+&B{K*xw1ao|eEZFpJD>5jMU5Zx@M)%g z1h>X+?D{v|IihJ*PQI_=w*lHUj8Nr)He&Zt95ACFWRR_IFiDx3D!1GCjvOTAR=55* zbc5sP8%Wq)tE|3mYNbbZNrLbf=V!=ekFm8Ewe``wyEMH&zbA#-s@@4;&bb?Vx6S(W z3cdmk=F0;MJ2FA~E`FT9mf6(`Uc5WE%ZfFT`h-JV5k}@af+x{l(u|SuhrNC`=%Vv` z%ES|`tTG8pL|22Oeax$SW||Vb>57N%|5%MNe)5&3oHXrck|`9#Ikq}O1LP`wta;qoL4=bzs)vmR8c3vQC-6rSvOiKgD+&&k59 zSCu0!y1d5~s-hdEvgelJn6@AqlKq)G_+>c%eDt9Z>I-B~U0JN>OZe1FnC(=^5}T{) zmztx4K|y6sl|y3mDtml>h!poQ%0jIw(_JG8c)O)p#vVSvEORvrvL0f;_6?=k-O|oh z9TcQ4xWR!)l~qDFtZ{XBXJG0fH=}ChN;92V4V4m%mKI_jRA2C&UP;7zT9pr-HCqI# zw~74h5Z1bi7VcM#_jG#{JCtJXJh1Po>=mE^DB9^SRqmpj-TPB5a|q%0A7J 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 z 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

`p-I zyUlXCtXD>H!<`}ErLk@ZwHqk}+6e2-IBHwLQ;i-?dQiT;EmmR0TJn_#CBX-tW1B=t zP5R!j)D7+04E<(={pP#VuUk2k&5B~AnPd|BERM$GWP#q;j{2@n0D#05lMlQ3!m!o! z&T;Kk-A1OmVNzkMxmo)kGgCpz6UVqQ5%x;5y#QD0=MU@JdtE;=)q!3weQd3?y31ps zLNmRoJZ%K08k~&g6?*k~d!~-SFv}DMD9P(mMYmM3ce&j3T37z&=`rE0GG`w1TD5Xo zLk=p32T;L*`;*Wo`fW+<pB5zkCqsD|e+JITItECE20}y==;M%57MY|Xl zjl=)}62rs<7wxv+pyq%V+(ZLW=sqC~0JKIUhM`(J%7PE=y-RO}vs%;<0?ErJ8^YNX8wDyj3p-SfaX7;q2(TSTRb zgN)U@uQ{F;Hu_xrwOsPPwv*{*#-}qOjA9m>y>Fit@KL;kbM#G~N=AAB!d#(PspF6y||%x`|+jqft~ToW_@#`L2|5{r&5(3!-KQ`39Ao>qx($ zJFIJG_@ngh<~+U!o96L8FWs=c$At5yC%iGdfjKga7+lhfed@e(+&8dmGu8I`5^{WW z&vx!phH94nShdR6rkUB+io#G!rjvUOQj+x}0@XP+$ybHByNkj3pcX<`6C-8kcDG82wT zDDUOS2MWxHh^$x&MpL{@Q=q{;h!z-a(0RET-QcHV#q=HM5IFe*jx56(08gKDeL&3> zt~)6QjBQF+)qr5Vd~Lqz$V-0nrXsB1$BjnT@5^z%wtJu;P`>#<$@Xwv?2M~{_o|-f4yW=Nm{!yvs@7mz8)x(vFFLoKbBYK%*yW@U4ablQvUI6`< zv7Ag#*+#e-tTor0qXnxbZ&3=5&R3=y1y)T$l;#YuLCEMx2K|ulw@sc+xNKOCDR-T5 zHhQUeZOxJ*tJ&j;7y~HKddQdX&A;N z82;Fdc`D*@w2N78UIk&_EdTQIia?2*`EY)CUq;-F^fy~?Uqk5J)3B5;Gre&iobv7{W0}?xK6vv@7jP~y50CZ6WNMsF^0=kPx}_a3wC$Z&UK?HwgGWQ zpBX{IY+vbay1McqKJg;1=HVf+Hi&U|7`bY!Ym(LHLhEWt|rWZComSE_-KG4df^Evh7F$wVdT?-4d)7PvQ zT)u=vSV|UMygFWa10cwF?>h*-1Q;NI$!HKVmXUXQE&}_mb=R`*k2Y8*YvsK%xvClM z>N32cX_{|X3G3Z8mfx4NDhHz2*(qX&!w>N_r*SCT8lOEA+pd#K2UO<$4u(9kY;h%D zxxW1HJ;GJO#*@rlXdo%AYKc!thi1w)8}p-^F+#xzAI{ zCorOyN}u}qaAK%wk=L3|d43fVwTQ5+UA%Pm*IS(V@x6&lg@;_D0^E2L3ruluZ$z@5 zbvDjCnqfONQKsAlRu`^SyUy-YR0{Gv8MkLgkzp#pNS0gktWi&@1CSrQ$iC?vu6Da1^jja0Vq9~yK zVDjC)Q!E*SP6vBV)X(4IuS@!ha0s-&M4keKpt`tXZ-_k@Q=kh;tQr9!6NJlTj@yg@ zOYY&7Ix5-mUS;kZ?9Uy^k{WiRr#M*{gM#tty=J~Dou|2VlmuO%1jNoOovU@4d3w#U ztw;J6b6kpbi|8p=q_J7w>q^80)Oi6Jv>9)fM>eFbEAV=qnc9OpY+vH@1x9e>`D;WV zKc@*m1~=W84LrN5&)=a?_~ptfbIa@ZPEUR|Eh^~dY0{Yo&tLE$I5-)xHHh+gKX-4|fIF$A$dT~k&S0+TTk1mavxHt60USz$fcYj@8abD=Oxmlz^w*ds@mKYFePAs%lz zK!-_clt+TwO8f7Euf%1j)AP72fJUFyhWGjHikt}4#a(@pn2SxD+O2pfT%ee^X?Kr`U^j}zdU6Uv)EYi zKqNw32}E@S@6&+SNK+lr;VU8sIE!M%fs(j|U+E(RWFv{4xN6R&w|FHUWrWn+2<2LJ zEQ}!nM09B860zQ%W^Gic)drD+fezdkqT$AH5Ic(s02S%&F}8u$F2Eua}WhHS5Oc~9>GCs?oqZOD;DWfhvC0={hn zk06#4V}uC&optw{x|RWP>xAKhArk#gD}cn*NSv)>Bv3RKS=5(b@d-py8(g!QMF<{n zEo#>--N*j!FmbrJ*blC3H0UUz@+{vw4ZK&KWk|oD~;|RAT5vV_aqF7B zeQ%V6)G#QrB*K$N6mPD2Z6d?l#Q5MP(-Bm+?vkHPcVKNDM74pMmMOibXr*e;Awh%~ z5E>uMlF!Pa!La~Md?L)5(Pl$K)JWQOV15Ewbvelg#ho#9(=DWZ{Ue%VpGui|Y+6J{ zZX{V_Nnj-3Tn9Kp4kk*;=3LDgG)zXzk&jXdy!NRkT6|Cn@B|LzIY1>0<$VAfO6nPL z+`Fylscf$W;i&_u>_UK5%8t&A`YVaE88)C@X?7`O-LFy$ z#RID85++7k8OBA!N+v(qJaHrkxm3de0&bv7w>kM32Be#vc=;GcbeEpY3eyQeQxWq007-FMERY$i&t3K+aiVZo4;;l#@wHF;RViByQz z08u`>cVLqsT>#KdO%lcQob5Q$ykQ!mWd6EB?vX&luQfI=#<3rOsGki0Z1m`26AvRv zMwLBgv(#Jy@b~t9Ox?f`>4F5rWYtlGqy?B9 zHq@vCFwz(PG;`eRQe`v|gaH!06ajKcJOxB1N;2x6-1VV5(oSMYn`-$y{hc#a2(&Q}gP#QcDx}K&e*I0nj6LrcQWL<6EQLnWy3)YbwIVh1(j7 zvVKu`3yLBz*MS2v8Y>}|I#SIi#DUkVtPQG$V%n^Q6dI{ji2gxR6 z8P3G>Na87+&4Zy77C0$ZNsOD4*q$@QTV>@?KI&O*SmD-FVYH0o6o-q0Z5crv$7PNS!cqBIGI-PB zrx>;{OS%bWocjd#r&D6Nf`=CSd6VIJ@JYL|wcKggS-BVl$;0BAiLugB_OM{sGrEv8KsNhX`odAAQac@G{=2Kv zTz-$BXlu!L1BZ4kv^fbQEOIRXa)jUMxj87JjUa#m(4Q7(%#|+J+gUZ)&(DgPT31b} za`RmnJ_IM7K=F=0FE@HLu5N43_I=EJwER|~y>*;}b6k#igFww!vEzZ``ezL_b|(#O zdi&QJ4V;q`^neRhO@6pZV{GT6R~o)76V7ptxLmF+o5M$#>~^K>kjc+qa7|rTni@E5 zZ%_cVfis@VrvUG=aJEiiP3#pd4wQf~0DLmc6U<8m{*V$8mzU26lN~6hE?!W?hgpWa zpmGkChaGoLx{wtfnC2IjNAykvH zq@66-#O3P+8Z%wnnbNmni>MQm@1Mi+c&k%OolAOZv4L|5f%Soyc{7n2Ri;9PQrEuB zd6CRh-|aCs^jr)Ul1?hyUERNWSHvw(VF51?%o;bDr73+@1THzy%=2S<%3Y z%$`axGqw19VW^jp<4ktUKP2CxVhvI`7aa@Y)gme2-A#=I3k0Co8wnr2_t;TD>tWC7 z`=!4Q&appuK6kto!e+HnWzMk+kxPXDQ^mVIP4(pf&UMLn$}&4A)3E|3W4r3+HLQr^ zG>6R1sfYaFZR4;FFq9Jl#8iespt5M7*albu1!JiJox%?ax#ue{cqqj?Qa_oz2s}Am z-2|&k0^&gz@6`*jN?@DGbO!<{&F-P_y>o)wGaG7^w+B3RA3RrnVEp1N0ac@X$POTi zZsB+*)qO|S3f~kQ=Ky}7>`>3J(KoW=wSsYNh1R{rX z0yt+#h7?j!H3^Oao9DVzkeFR=d2{z(IP88_6ipD;V|r%@667SfjiB@GPTDUgs;71{ z*ED(0j5|U5##+3iWN1Jxb5kSRqX5SCgGAm1Afyf`h9oPiOp6(kMNvdf2C<|PqN zH)yRO+&4eZw<*i_2$c|mBt*a=8<10Bq0E={{U_E1OFyw!%_3cpWPt+0(K8T!%12l9 zbyw%4hczEf#By= zO=kkeZuwhgCoz6vi3C`3226^AC;8Ta$Rr?^q#p@JwrP}hugaVH&$HXy-xhojg^c$C;kKrbg!{pQ~EmN zDkgeYf^|4QuRK;-*0{J5^jRGp^fvypb!yO$tj`v8BIJuZs_IAOp}_+%#PA*TN8=refc@(rm|c$SkJOee2F%&$RqAo>LbB~6PhSuzg| zp+FU~>HtE0<`C040&6)Qc_kPY5zHb>@Vb<2_#?4@Oyp6paW@E$x-#&lQ#N#+J@6+F z&LRYgaq)23w6_V7OW8EmfK%dav+g)EKLoL;X&eb#{V%Oof? zbyF%KL?eZ9Ukia!LU5_y6rC8sC&}dk1p!1!0dolYNIyVkv%n>78^du32Qs|^!&_`= zqPHR=6C*L9-*KcZ0L;iD)OtG9_GRd_B&Qe8Tuy+b|lD+2m z`jUi1_98sgb;a}slh^@K{MXt=(UswsRPcC!(<%OjmKSFNo}DqBtaQB?uI)uh4x{W( zOw<@ol$lf+P!lD}&vQEJ^(cf7tc61)e5{YL`WWm;Hr~4-;XhcoT~Kj))Q{`+!1Rrw zz#GsL_!Y%q4zrMp16)QCgmL{ae)$md*W{d9;FIl*HMZ!B;xSGOCW<5UmmbwE$%2E= z=RPt=X0|>i_IsVsi?sPgOKu$l7S_MKzap`>xOp>NIskPweI@fsRQGV$aUD(44sHDO zkMSX~WtaZf-*>g&vlWU(7h0Ew8cN9$xyi8U`(TmTq&kVSKk5pW2xa8xPuhv~wgq{S?)wt(Bb1l->LpuUQYKeCd~AJ<(QRcFaUKYS|gWxlk? zsN(5^*s4MH65Xcz=DQmMY{YepZJ1;df(cJ@RYp| zZohP5rK7EsM^cJBYNKmz{#xpf-@Q_)rXc@hu*#^n@^hf$l+$T`5FE+~h6q^v)dm%e z0R-M2avhSVDw6i9`!Yg`dw=Dt8wN2@ff@40<8hyXXj4`yq z=I>w#jbfC-t?aiY_pHh)|5%`(+8aacA?0I9MOP(_QsHcV_pLY;4eMQdHL4UgluU14 z;3#vDoBHU2b$S>c*QP4%o^xVn^V7$j|Dp}Rbf*&5d{pxQ-%Ix-VSyG`BKN}wqv=Q2 zd&Z$pJWW4hKK0Q`9~tHTTsdaeRDL$%dEw53q27*&Z~v(c$|BYL>$oSPGi_pCooQ~c zoUUeX-RtYPX(0PWwCJ8gSzEBsUv2PV`tHRq@kcLw;U7M6Zgs&gbYj5RX(i#fN4Tru z)6!UaT>hz(Zx**j6WRW111<4nQ(m~E>1;3GgtLe3c3wQo_kIt@#>}?D0Avs^pV?P& zxiV6ugO+5b`rMyjNP&IC&pYqVhw!|bFpm2c#pvM}W<3xv#ahD3u3ZY=vdcL3Ir87y zfTdqBTYwKv7ZkN?w?M_$Nin~_HvGd!1P5!8zhI1ZD7=;*_2I8JSg|ljSI79^+Hn;r z)(V=--em`=oN8B%RA1Vc*+NbgFh%VO5^?S_D`Lirg+i2nYlHgw%Dkulp$+Ed>stRq z8_?eh{#zU9I9Ip)OB>AdL{0wH1~JNI^MAAfcWr*#Uu`gktM2%#4MZPMI{#{eIkmFK zf3(4eO`*Tqpam@XM;pY}cXRyF29wA;y??a9oA)pNXoF4c`n5mWpk&!n@qdsuXxi$( zG#}SG&hna}4UTclGqgd(y24EoLmTuYwPt9&$pkk>zRI%J|M4*U$O-NDg_r%c+lyj; zwcjr}$F8$hEvvNGP}A_Z<96MZF-9=t?uY2NE%WgY%kR}@>3(?>bMvRjV^)LxT+hQ!h!`Av?{RKA`0?=y-EQ&cPr3mBEJp=$Hxrye-YihhxPN=jD0?o;8y-I>p&9)%A#M zHmB(Ci*qK*Jr(D^lWL|X!F|2%sr0csX(wX;(FXqnL;hz8hJ5|sFBp=jyzX)6;Y^>t zM$7f4^$V&GXUF0-?o}#(^0g~Y{g(py6B7Y2J{KUI(EsIQB6bb#qaA-^B4xG@AAFi` zyY&ApCi0I0`A32Lqd>lt)9F zLS(;1-?5^v8919t!RdiMjgGIG_>4;76^nkIxvyD~BbA~%1O57YU#}1lRVbL{!0+v7 zsWw#-{DT8#I-6IsGpeLyEeEY!Hm?%b8maoi5tUsk5n8a2gzP z?AXk0&Zt)Mu^e`p+stblsXiPrIPAW+nNLM9_FGwwcnW?i7_g~1mOnV+t@EvrmQkZt zYdPxY@~voQq(-B4a5O0TTQOs5= zBmXFne-z07Q-Rq0*XBeAE#8~N{<}GGq==cMuT~)|;%fyf0{(7JD6uh`6BJlH87fNY zS~EOUG?_qEQ>aPvGq7f45!uyPg>C&sno-YcgYMtBboPVI#f}$st3dUAJwLr1ov9qh z?_!j+0Ibj4vqH08F-kMZMKzkqYeQARrs-plx$E4mpzZS3xDU9VqIqiM_AQ16!{Upd zjYw(U4hsyjnifJ#xrd7N9efU|+?#KE&|38|&NsB-;j>SlH9N0Zez=$@w2&vN*2Q)9 zqCMfpT$Vc!i8_4o;^m(lAGX8l?G8RTUw55{(dm~sY;0FUE8XT&PVDxxp0&xgez>@n zr`7vHwn5ObMtnsMyHNm%ra()iC&bl`KTX|?B-`e6;Q z=mNPTZO`n+g34naJ==aCJ=3ZmRQEGx-QlE0O~T@*@}Fl4F48q;BjUnKCPip5^oR4` zf-c=RKL7d2(!+&Ii(ew>!UaT`?;Xrfb}fI#tw&>Z-7S_*Uc66Qh zDy<#u??wsd1chj~&2`_sDcdoQaHqwlJeYgszI&^DalH28kIymVdk#CNHxshr+I$Sw z=3D2s#a8ZrgMC@g|GD(6%V%f9X*}f3mzKS0jyC#hU3zeff$rN^jt389AIC;pKiV19 zjCxx7%df+{_*yuW`GYn6=LT!hw@Mh^a>u7)DvUT4I;I)SUK>+Y>-W+-0tF)mz!I({ z`RvKY?mI;c)CAZ&MRM$fGRcJ#b_l6?K_^=YzS9Kuh>$uN;uI`lc-w-}r4acVud8|S zQ(jboX2RNZ!dM^Rux8AJOk^2Oupoyg?|RcpN=GKYm$!6Se%3>3kH+HaGZl&5Fj z({i0i>20aPMA((x)T?#=73A2%Gs)p?{)KYH%;|uMowUFHgKQDw;hY{glX_F`;_~}M zPR+DPPJbb1Qi4xB=Z@cm#>M!yv=X_9K=XuTGX$ei;Xnf$Q&};bAR5X~-p5bH>0(nq zxdxfsqM2DT6{NJ9+*adPp+y?63;UEGr6qTXeJ0X0()X-p(wUu%L^48#6GUoejL8G8 zQ6QQqz*9!SHzG?9mT_``YrHNFy-QMx@O{W1#x56KuaRYy5)-Qx+xdXh1Wg4;5n_B| z2569kWr*4`Gh-VOnoa?AQlLE>P`#DJb?>XH16-yB{;L-8VrP;d{nuQP@p8UbnsHGk zTG5AaxZ^5WZ{T1}6;?wEYbF)QOMx)R$neJXruRw4mN|!ga}3e~7+dSFYXrpCAVS*_ zjMMMXn~1rB{Mf?$r_}t--JC=4=-BrBIC=H~&ak^$S+2{>KAd2UY>>zw_VHzzMI4jY z3(xT%u;{AGJG~ZEJ9YJjS-_$S`vSR0vLE2Ao#yYN8TrM5)5+|S z(N$AyP4dO%8n|sN#~UmMiCp|fg`I{1j1I!oP%u3J>u>ha3{3y4KAJB*%+E5?_7S1q zNXx6qWbl)}@&iJFerhk=KfBBa4Fl02GAaqhu;_$l#IZC`6B>ZR zmv37Fz7Cdswgh|{q-?ISH2swyXyAQ@{J^u=XM^SjOP4HDUHL8fR=FzWqf3#vmlOmQ z4Nt;?WHz7-z41%FQY#&z)lsQ8SE=Vxd2s_8No8(OL7X7K7S}FcPx)g$&>)8Su%)q2 zs#NOxfxfA5T%=YS3Rc-}R8L~6&6mMU6tLw6i&-|pE1X4yK_F->A=yG-mOoM| zZq-zrS@lU^2KOw3TPdtY%djMuI`RkDS~CYf1Afq{b(iPrvODUs=IX9>)OAo;f1+3q z;UTGZJk4JT^2~2@U+qKJ1!-4Ef=-%rx%TzkGZ zZ!PaN2`@8|sqjRG@xw5!0vh46k%52p%?uXAz~-SevP!1{6F2bsOD(?Rz>yen9o{z(*Sp0LJ_1$ChW57P+7Iq#yd! zV&D}U?5y}ZC2M|yy0yYWI8oLXiHE74Ka>6?KLA&u@Oz6Jur^LOqm^M#L!5VQ4biwS z&k!+$`(ds3xl#zR9f&7*gd_o=>ff4r`7i!}9^HUt;qq2w0DtfYU_QI8X#NI+jCkSi zFKS=PTxliv;0W_~Z5e8WF^r9GEB0?4qym3ZSx=x~b#m?Yg8*Aj5DLJgy$rlv+{PIE z_i8S^;h#Ki(ecpIcY6*1Q2|v_YP$Se0~k}*ROVPp?BO4wj1Bhv0B9kdlWEewwTHE$ z&o%8xWJJ6DwLI_aFd_m;2lE?D)if|0p+tVy=co$9twAc6q2F{Ly!+WMp;PNH zTlior9^OV|@&z%}$cEw*@B&$MgE6WF+H3Gv;bhiohKXgj^DdBUv2avJtA0ZYsP1vw zQ|e9G%y~0}Ee+5h^hmNZ)eHk-C=jRiAhQDBHcsZaY_L0pO>;j1YrF@Weh1^M+(oAmOMi{e5C#A54y6J19)fdWr9TviqQ5wk7xH_wcsk&@Gr+mu8M@B+63)OPc>$@Q`avcPP>?!Q9?-2y zV6G5utm=Fm)ln!m-B};o+qOPr)y$ON87s8guS6Ye)4LW=5q|4#!(aBtH#?tx?+n{PjC@*2TvUP{D2xGhHopi8?Cw>B1=}WFVv7wc zwZ@hNe30ph`ZSpoFcqZ)OIaBp*n;v2G`FT<2w>XHIV&M`^ugB5*9gCBwr$aw!@Bq> zh7nnKA7*R;3Pty!L`G`?K-AE18r$XS+D^8N#6mJ+65Zol;E^LfIEjgcq*@Cy7=8H?_+hSRMHN(8{1Nw?rJnIG?JS~*xzg~t~viS7! zz3{UADvjE_^rC70Q8P@H#`2_|To`fbm{Tn)B0iq)Ive(tY9`bYMSFzvbs1e!Wdn%+ zVwYlXd@p-BobB>ad1wLkHK{yl%MQHRJnZ){9mMkLeonYp!Api#G7aic9c8+m!8#leq+h#4TAtMwea#>s zTMO?2g{dbWJ!*yzR??R{HumS-VpqoVRuW_upD!+bVSr-M+%b`G`?8S51;DLkc-S(+ zqUl{Jrr1u?cim>jc8RrmW5w@h`nIigT*1q)GzJ`HMyoJelydMAz@>!Q+AJI_^9_9; zz^nqWSZ2Pxl)xeS@vhp(1T#bu_9GSrwA7vaB?4&!tS7qTU~wP`!gGfIU?>T;=JlEW zc0^v9m{z?av|fn2?iKPh4o$F+kn9ibkcwL6?;mQu%a9+1%S;UU zAyte}V8{>rZ~0OGgzW{YyJ#MPWrnJ8!jCs2NJn-D2#`rm5W`wB@JFQB=w})Tt^)9) z0m2Daa*-6_TI&;H;YH53X(*U04f5N6(BSSgIFi1>vOs4MAu!#>!rxwmb7FsGq9N^+ zcEAP;JAlo!ndKgVT^#+d>cu@Q8)NI@JxqzXD$1}}mznpl*TBYHsho1BTKC4gq29}O z8j-IC?l?Bd=PER!{(n~>-&m6w3S_&w?oO?ld}rjhfffnHE4+$PpDj_(XdAC|mk7>C zm=Rm1gr?LxIMRlF9lfCaN}YW@KFR8o%Y^Uq3X>lmqtWL&fJ$28uM=T2bTO#! zXjZa3U&LpFv&kH??hF4_fqdLz+gF-h?4)BQ$tj1#xIu97G@tJMd%iMDjj~g}1RfaN zGs=*g?7q9AU8uxK0)E=I!shsPr+H>KqpoXzHvR)ZutmshoRM&F5gK&d=(VAzF}v#1 z^SKs|%!8cOXt`{ugvA)X=RiJ15eQ7)!O4U(>3VMv zCMv<#pn^%KjLSS_2D}b2arpz`;!pu9P^BN)lYBG`zYIdL47Z5;r2YmV!n($ps$}61 zKHbZ11cKyMDUXtE#}@XsrRYOynuP)O^w3jgLSb8f6^LNiLX(Ne4aR^XQsWbG@&wav zsNKn!L^zszI>}C?!(Is#|C_Gdp1*)t6$>X{0d5nhr z=_~j9TCFD)6wUMH?r*yU+ zm-b8CCI)+Tb*C%;HYb)8X4V|{Jtu>&2-RGUk%Q*ynZSSTCxsg>^Syc3T-506@8kP< z{q4(7|7uQD(&PQ^;IFv7o?`=EaX`4d^_dciOF_O1rcgK@>nyDVsP#;3J;qk zV<}Ir%t(_JhKUvG9CJEtftLAYXh*W3Abhm6HBneD<2n!`pkJt7fZbnT3cDRIX(Cl~ zD%0QVywK%M*q-`V%}ZPEBGqz)(cCZTIbbwYDj1?4Ag)AVea&B3 z!mT*TJ~v#VlaKPP2R|u0=Yk{ zl7h|f2(>H1tDfh;dkyns!GpU7akhccb|n&~rESGG(w$VAq?F~p;t8ajdesZ# z3xc9`UB(4@r)vs^d>xviUo_Ml%RQ|=!B7lf9+V-^HOczh1s-tI-DPgs!6kX?_r_jU zxrJwX{LX%go{oBaF;wLKg#*B<5KxNXOL*Nml!ZL$xU8856C7+pfX}Mc>)eA_0kpeYkK} zTZ#hVN87USFnSs5H+UQ|CIX%l*y1}9>|hlje5@I&kNz5TcPw zPVAO_IF9&+=2vpwMAl_OvZ@LYqi5hUmD;7u zj%6*5E8sfZOyou^gWWfbn60RWO^Jj=5CQ-%5id}s0U$C+Fa)yk)L#g{4o$rQBw;n~ zUKtI@G3x16=mLw{%b5%C?-``HhqgXC2o&eD-n0ONB#OF8&}e7SHTL^#B-P43CFw zq=`WeV2?RFj(onsTGe9&5*g?omHCgB<&o!4!u;dv5Jm1rzX7U97} z8KCl-pg@_iuUL_|q_>)=C`9LLUgR=CxwH5KU%?H)K{Mp24FyvGh!mKNB&#!$CLlQi z>xIiuL6vOi!W(_QhgVENv2^-Rs}U=Zfpgbi`eFEG=&i~5|>vS(5#(QO2OkGQnnC$`mLGE9L}AP!E-xk)6#^0tj6n>(gP>yrh0_wx;g}8;Xe5woO|6X0V@>cejki3-JyT&k7_hq* z@ZeBatQ=6d8LU0ivj=47{v$uwmNj2I1Be#@kEQ}mA&1S9Ok5g!g|BOC@F*W5@T*V= zj7b^YffN=b2ni?l3mP?3lPy*gqYFR|dP*G5BxX)HZon|DMXK?RY2bp{l3$(6&~4lx zn-`k&mwk8x%>E@evQ5}@B=crKzu5;;j!O*$!2_hw5bf-yl#0rLpAto{%@Xx28aK_n z1WkiYNKgRKN{cX_XsEFY65ddyN1E_NxiKT_%z1Z9bsz*I3*a#-#06lHDwxAnSQTkx zksmu)^o;FBVWXHUS%z`eflt!OhK6~WMo@^pD`fW)y@+L1%@&)II;a5Xeq zKMas=gg~2kL~iMk8Bbw8dW~UHW-TUFg%xV|AbsA9tD^;S!h_m)D%IcKc-Uw&99pUU z`bdDCr56q)E&z;!kF;1p%9U)Y#DP2(BRV!ieF0YfUJ6LCh-#Zk1e`31NxbgW1K`d#8#%E*a&oQ9^uuH?w18=Y z=OoFcA63UVPI+vgWnBsB!|jr=3|SL7{9#|FXW}I5Bii#qu}3yFzcQL+nv+!Fv@!(g zgcgmRmq%Zvm#N8kX93n4Ys;roH2V}I*feo<0+YFp(F`DPvYiZD2fbE1m1}g0*Vg)l z--H030V*cu1zCmSPRl(y1(>D%aIJ5eoe<^4gh*h($>w|V)$iO+ApVP>StrE%8Y z>^`4n;Iq6`JHYo-I>(9Ps}OBYfMuhIev|69y|Q8436P4tOY}WIUweDo7pAjU1z0OA z7JI)`*{ACfQF44hf*k9!s}2^U(JIe+>Y<1Y@G64XU0m$%T0^pTxNvrgZ+2|C` z3vnbFd_kUX&Ou8Hcuu*2;WXkv-w-^eVb&F4&k;1h{P9FC|CwQx^XK zfu5H;ja`5$a5~zcrmpDlm>M||MV#MaoF->asRL}4*=lrpiHA$uyWUJXP^Wcx?CBn7 z0SWiT7I=6_pPa8Oviy3^rOCr>4ksjkm(oae@;eUU?aZ;JI3w2`JxY@~(a?`|jD_uu zR~FBdWu`MSnwkg(90FcU0eB2(QDi-dXeeY;)SOXtg%$0`SlwWI-}axOZ@UHsma z7>}}_WU|LBP7AC$`Daw#yy4mxxKK)^!Wdj zJ~+?~<=N>+5**ET=TWXrP1V(}!8%x={fLu7Dj@=wEPWu)T`0YLuvEso#INXnLwfFQ z=?z=JX?>N^rvj`u43l}30T`4b(hI7&!7A_?8>j7U3i+QJoXOJEyq3 zYN3T8D#BBA^q3Tym&*p1@fm6COCH__%ZMVkZ%k&t6^I-ZND$-m24I&V+#5gxDj=lb z6^l&bncce?SB*r+UfYXcukw04l77__O|U`&w9!C&fC@5Ek?!xzB;}lhu;|}w@~G>5 zm7^-I{P>OOJ5S2@*I;rNhaylEPGlyzf+Sh>2xMhWFkd!-v+?jZk$gtm;l0mb>;zW#O8TU%nK+c z(blmk77Nj$LbL(o!6aEM4hF7P4@L5V~Fo z0OYj5da0(&Hrk%(WD94o)N{i7Sej#>sd2q`*8(Dtx-W`IFlm5djS?xNII?V&K3C$CbvkX#1Zcw`Ad$%o0>S}b%ZB=1 zm02^QlGs-ncLZMr3W*)JmbavbDDYJ%@GTC47-JzYD$tNYK#;2-BPc^D8eoZVS_+4S z?^SodYrhD&j%zvYYq@=({CMAbvTtLMFQNd1kb}V@Q-r8sVNssaYTVri!}aa6>j1&@ zV3LOxi5X7-;)$khO#Br8hmZXqxrv2}(5d7K9s-}XQHHK0A5a1<4&B0zYi|LN#1_Yn_}7DIu+eb`!7 zt+oB<9}L}lP;|fVj3+07uArsCLn~Qk50X3tHbfKOxF^0b`vXBDTVz$q?`4Q9HJ?4& zk`(GdI>yAr%Me{G0R2so%&;IcATQRW3o*xDO$m<%YrJ&_pXW^4B?s-@`m&dGclr`( z2IM@~N16ZiCBH;*afyv$$U1q61jRF{}I0XG8KT z-ibmyfkhTCx-o*|>0GJW?ReI61g3!vmV~b?FE{wcH&|B=om3$k;MNT%t=;Ma0rcRY z=P2A}-#P&*Ic+cb1voGzG5|d$nXoDALtrS7m}Z#d?T{GCrd(A>p0q2Fni*nUgQ!

Y+9*_`>}PEz8p7FKCXiMz44u*7#0TdBxh*P?#i8kdpg4II((rXvmaXHsTU}XT^A@bnlFmw`JJ1i9piM<*Pfy@lV7o z+Y6f2^j|NQ0fG^$z{m``F7e6{Hl^UKFJJwgUelfHWqQr_8h7zel;)xI5&xYDIdn}SGi%l$tXVR>&J7sf* z?H;nyYzxab#`k_GMDytEv5>?vP8Fuq?;4ZdSxQ;_7Gyy%JkMMBdqpXuSvcr-yPYB37?aj__}qsJf`YQ z`j{4@IpI@%=pgn)FZ)=z6q$ejp1~L^%Ypw1srWhB=+S~f#J1;?@ydZ~OHY2837%fo zEEN-spO=q+xTyQK_T*=JWKa3&+1U7yt3wxMi>h$E>sRRNuYb+77ae+OB}8tBF%*dTHJ+#ysi7Q&FFF6O z6v&4y-_w~a#Nf_dOug9^Apx0;RNnJu$&UOodKQ>~u6qe}WykCCK2B!}PkVn?;5t8^ z8|`59-zpGBb3!!W&S$6FRGD+a55qpaO{5CeB;$6Jogc!P$Z^7R{&QJev*A)~I=6a8 z3oMJ({hhY^J7Xd=|5Jek?Q3oJUGSK0>d*`KzFBJhL`HdT`#ZUMG3er>QtkETmjZhW zfn^sqxBe)QKg|gNSLl)Hs5tWVVBL~mKiVC4Ov6k4yiC=~;!daKml_$A_Rq(1Suqp{ z@1N#`U@n%xcT;A`#LGcL!ua`%eoFZCjmR@;WgaP>7d+mraAG(iC`iH{fWR`mb7Il+Co{?5Oe6Aj`m zF53a68?p`9GvN5h2q2 zlE^ytEiq9jK5}?M;<45n8$rZ_~pNTe?I8r`mL9bb-$#%AB+0Z#cJ^W%RLT;0y)lC&QKt4+Bz8u zL`;0^w*ncs`&)tZz5A^|cD5fe6v#Q}j|>H(-&y=yfmkPtG89PvdILj&+@=>lU?>o} zEeqpz&W({FDE^~BMm)Ih7WC=K9J_vV+`Ty(7;?9G zXaoUyyG@@0FX^WL3xse1=l~^#2l)qt?0i}7 zx%>|Z`3Hpj148}*A$5$k+cc8k76oowXT(25BkOG4;LNNuk+qsgciE~yj@FrJ4ozf5 zZ&jk$Zd#aIJ-b%4RV8P8)5>Y+SzgChwMynq8y~C5qPeXatrdwoJ+IOEeiM^fZ(nQmqTc0uz4K_jW9!h1ThZSeuxt&^{Z>;gMc*57 zwhb=RLsJhrzBl1B8{Af`raR`o--;YbKV z_5T4N^SxTb4?6qLSk;m{&%EP?1V$Wh zsuq7~%vFE$Z7jY_f%4Vuh2i**dcu@n1@D3PvCHklNn;^Obo82)YsWJLmRhY`x@H@* zH(Byot(kLx-w z8s4ibM5EcP#sxX#e(M>l@^xGynYagQhf*0Q~vAxde1_-J>{P zSARj|EBzfY0x%;uv8eEanP%PWC*ONj;_Ae1_^uQqE&!QJUer@$RoL%?K7n~8NpKR@xUj#>t>n<;NM?QkNuX)zT zE^UoP^s$QK3s-)=DW2LHVh!>Quhp3}KG%Nl>f>+j-~*0k4eh~)$G5@_4xaT?b-XZr zyjfzdx9TL@(RW$&Vv1AgvI9N3uJ%Mg5$pA3l)=Nno)Z_NuN*uZe0*==&e<>=W$v>k z$95O&h+iD|+p~M@>I;>&I~`ZfeyV+}{kHeS_nPvex9!lMF9J&g$c&k?gc;-Os zeD|fx{NXc|$9GO9#BRDA(Hu!({~5Kj_wHxSgVnIb;ipb}TdgM_ef0h1Z+r6BccWIl zX~o+=PDT7$9CB)Z5b@Ibf~)@PHz$5J-+mOb*t4)!tgl0Vl6X7d`Zu@lregP-u6+L3 z=~J9v_HzG2@wl&_>Z8rOjK%t0w<0F|_1^I2$2j(fE}LDF_ldj9kKcgBZBB>J`y>>~ z#{F>e{n;Akl^^IdjpuKRuxgD5n8!ZtkA3EJsog8S9Tpl6i;D3f9hQw%=m%`PC(Y(X zxaAZ2BK$d>BfptP9XJKH^Tg>{_{z%#a%#n<`@}`A#0xmZ9JG?MQX-gTiECy70WiW` zjWrq>lc$m7C;F( zW8wQ(dIUPhhSpkN!iBG!r%Ja5K1oTTK8Q=VNL*aOSCfgh@Ko0R6uW`Ylji@0c?8U) zTBnBgz7MS2NsL}i>3knHpqbfDPUTPa4X91)af}e%y;Q&#ue%cpY4h7z3H@95aHYY( zC}t~0-2;uFc}JD^XE^U>Za@7$O1E$loBGOvh!VrZ2 z%zE$xAPQ7gKNZA9&LFkcROy+7$9);+YSUlAveu!I6bsazZ+2a7Nn03IMv-j1X;4%&D6z$o9tRDq5T1bjY3WD)RVPxS;vnb?r)V(RT%glwh^L+p6jsow(zq+I0zpFbo z5^mL6d#(CDUWI5@$^s7!xjtrFzrjT@Ezv7 zDo101&;g)l0;LdYNq=Dpgix|FTXKuW!iEJgsla(KtP^-xEt*N5P~0(C>^Kn97V4kS znjRhL``@^Z*+B|-I)vNh24D0IzCFtS-E};)Oh2~^8z3N3&>*R0$RZ8$NrjCq{f3MR z$F~hAU&jrhIf#x9n@Tj~cgrIiavKX7Y`#!S16H7+O(>Y8ReUdu(kewM@FC`I=Q460 z`u`Vu_u&*p`!0Nb5=H}uIjt*>vMgPgvU9L{!IP7Os`1deI&4A74bwq z>uG$Jv0K*Dnk?fy!WuM5DGyi%g;$)L#MI@@;)eGR>p*9jFJ(QcAu)*0c?hr$00f=7 zj`b(IxhJlpKZ8ZUL)BbiG}dkc&q4YVh!+F7n2MtV{Kx0Pp+bW-kU09Oc_nT*_knGo&)hM|10akb&~byHTUB9WO0)9IKv$?Pl#*LgGe;acqxR? z^b~i{7kgk`&E+4Yrn#Bzj}>FhO~t9obSsGT>0vT61V1{wX>=|B1|D~G%bhR1Jq8{I zZ>?h9mbZB&SDgY6Qj2m^-G6{bc2!I>E9eY(RJbia$zBJui^KV96Bcf{=;u5Cim_|y zheaddS5iq#YAekW5Y%Xrx*3=qD%?)tRV>i>06~r$AE0XY@k;N61mAq$ANPyBKG|el zDkK6LCp-jF95rU$aB-mVfx*R$L?+{%01r}}vV@9^?i3|?e*&$lMSk=7of@F;@m9F* zUhQ$;L$n{1#g2M?>8$U8rLVuQP=gvzQFilUGA%A&@FsMA2I!9WRP~>!%6{vPPgIs? zx})+ZRT-c=_N&XO@?X-#L@`&r^VUWpBCCinRi#vzI~FizQdkn|RVcq*ZXn@{eq6yB zoH6l6abe7Ze7GnIfeFOSX4lznV?w*D!1N7F9zYWWU)}(>t*Q|p02?R>7l=SdwK?#9 z9Y8xcJl;-zYij&fvrbrlSH$!;?Pzm}dbZHqstRJ}X;Jei_fmkHL^eg`V5%~riCry} zsT&@7m}rQ=c+kxfre;i_7P6UEtAeL2if_NUzk|9wN9MS^xm0Kbs#Q&FHwR<~HWg+& z5oo8?eoQ-19d3#kfOdG+$R-wo#^Qh_UM6`+W@qq zP_M7At{oN`Ls03f*kfT)(A&q=lSK{T4vIpcy9&eG4_7L0l2#F0Rwdl(=icoEK!6IO zCzz{80NG_c+TY#tzF4v5$5@7p$$++Vx9eW#XVs1$b-fx`#rNp~=DT(8H^Ng&EHPn0 z1I{s3VZtB!4vv9GYmal@t-hYR4@Vw&@6lz`RRQ_%p_zq{&pbo$!!AAgs6Ze|Cl?w_gm@o0MpOU6l0K?f^kucQU!>mf z2IACrR3{B=#VW{Kn)y?AwIsn99=<2WX8XrjwI?WbX3vng)3?P5c~m+D*3$&OhQCPW znb_!oPb3X(A*K`}ATJODtdoT9KmjCj%Ba$7C)DA7uODgWK)z^~X(SBa^FwO%ho1Ug z(9HCA(wX=%PYdUn*LW|CQ22z(otsKM23F>g6GOeL)AAfMuNPj{59gLgxsmFP2wM#a z^mmwPBR8cXWvgAiMBrRxr<_F)WOa}z7gZ~0LSQIp{0xq;72%T^=zYuhEiPa0 zRK&f=Pk`tUJ`)`yNv=R%K&UFN^Dog+xYkqs8+1h0mywT9hMj_rjl^TnvHS_vfm;0F z6i|sk1a>5h9^&SsAo8S$FG=mS7(5&hQ5ijm7HeZhwTdqU0y`bHsu;j=K#=HuSnpow z5MqS0Fp?5bD&mkUk@za;-X2n1PI35e(ecjZm)3KH&L7c1|NbA*A)fid#375^T^jqE zTmh~aiLY-!I6{iknR`vgMpw& zVB~%v2wXdjcQ=yIoe)$!a~$*lh7N(0N7)SQI*M3XoN$;PREC0>h{K_gAgjmx|5b3`9 z(5OcGP@|u#@q-ty+e2TAY%`HoYYcpr3a9w)0yQ$E#^d7+ouGekL-iaVy#bFPTJlSG z_=o^{{~SlFl9Zrh==rbh+3!6U;piFvU=msbZ*rcU4?|`enrhfoyPBv)v6C#w*vDlp zv|;NrX5HbH2W4g-i=K=Ruj*FWe(lTD9a(!==lW~y>-fm`M;M=ab*q{oGtFET5{*`A z1PSYHCK&0R^Y2@}ntf2Ln^o-jdDGI{G=N+!3rBJ2(!6o0I3Bz#L)nMj;&TQ$_B>(S zw+!hdMTHRj4@UH6jLLc!nBwqTB?l*V?L_h!3yn~rxrVK(ndk4DYp*-6&$d2ieKd98 zy1DqV*kpR@aKCt>M5VV#;5v_H#}S595{2=7pvPcv3G`k7dQS0th7a6u=s4bSqy{Y@pBN?`**2Akip~Hs8*Rb%V6Kf9zJ$)mUN#EGs{+1o zA#&5taZhv}I_kWSEE$%`SNwQO696Gwy2xfSXFa=iD#t;&64=v+IV&27Sd(A|iC7Z{ zar(=Te}3G4cB(i^E{VyGJlST?M<=O_b96iI7zSU7b}81MZ32jS{(m6UWJMtsWJx9hn%;$hz> zR!(K}{G7t54QD`EUXYP$r=)+gZn5cQn6;tavxsvE4&Srwiq3EE32h%b&-h*T+NrmW z9$OoDFM9Mio0vN=S|kfu@5nDbU%w?mSAM3H{Ns=VI7Q;XJ zIQi2f{cbo6eP?fx2$z2AitK39yVV(P;i<{Q-&u{SdL-1GFyvCd3r)g%=);{m(3mr z249ZeA89NE(?eehK#QpjBJ<-$S6Klf0fXqM-y_fk!9^ih{)YZdO|Z0N*+~&8KN#26DfztKW4ar*QPC{-lD}68GxX4 zF?geH8p8Y#`&1)gd@d_WUrq>SR1&Y&P0t%1(xdql1D51zqkzB#;F;+*Pr+Rnwg<7!t4^hhnqT4F`RfrwIk&mV)KlU2a>NUh zh8(mdsTdKDU!6x?kR^pNB(`OGb-{6!LAVmU29`pEahjVHx#>o>Iggnw9+W@OMC-^s zuhr!+44#GE?(o5RuKG#yaE{1RF%`_e1HE2FfLZf@otm|m`+&$@yG8waG%Jj*M!JH- zShX8_vr83zBiayRyzT>6B^T$S#gxivUZETxZ8MeYMm**9d(w$P(aIv>Kn>&G@E!OQ zcHswIx0ow4FXVhZzppz3=l3+{N^`0UqRVFr1P{#+^Tj6Ib%FR%cB9}#;sEJffBa;Q z9zurj!2xOnhONmC0I!zl{qmXbFamk7nG`AwqvB@Mrab7L75Q@6Q61CRQn;|| zIRmWQ=%XJ52qflGUb#JCk1EPb+n1aLnWY(98*V1jOnHx78hjBG@LCE=L@p~iOGro9 z(#{ADGx1>l#^gf>sDN{N{Z?N>T z+_>A**h}Tvv9NCC7bq}~HQ8|J)q4nR+ZA{L7~d;$sjH%daE^7Fh{WIs8jU@`oom9g z&+#KnWk4v4NQ$B7j#$NpUDtyi9XRcJ&;{5-b+qY0)@Tc<2{mFF`bK;P?bsnzhCrk6 zS+dn)S;o;u*l)toP;(xNDELk#hNCAA=OUcS%gCaKYYO-i1B!#~#n$69#Zh&oUn1bQ z;xL*O`=dA@dIV03ncQzm;RO;@n&Re7j8_>0j}gaA0f0D;YJVe+s6rh^Slub&VEBVL zKzxQv-0&)it1C_G<9YI*8ePPJb?gBb*xqe*2c5@&f#?U8>3}v1Xj!lUSP*3VmXnCo z7kKc=F-;5ucdjAsN@xmse`v(x1wQ~o2?T-|>ij%%Pz)$w8k7U?F1cQ?|LvS0_NwOG zlX!;?X#%7yON}yBLPSclrPS1%Ng#uQ2@giP0L3>5ls5Jw!1!>Z;XEtE)H<=;;$Q(( zz~fTRE8-wramd|BXhVD!=k@Z>@=~VZZ8JKpF!zj1KnnuhkW_!Df$-5|zpEG@=J8fW z3Gr+c*g(^#iQ>+2xPu<52q=tw;p;fp@LO8v_Xv)h;z;cYs?9eTS6W5(POgxq*vpZAQnnlTrmMxzv{s7I^~20cs`k zC4QAq@fJPQxg2QQT~;JD6kPBrUdc?Nga=y=Y>fkaBdAwXI)NQAa4w&! zP@R)GhWgjLm6?HWn*DTVe1m5qA?f@L{3H&RkBV3bN?jx`QNCJTFiFE&4NVE5X^j=W zuBvqHunow3+&KqI2xa1Y5KvPP6knEajsb~{_K-%_B$m+2Lga-CH5KYFe&EeH_e)KT z#@8^lk4=WOc zDjJTtR;j+yt^P8inDuI!2Uhn@97%M3B}4B)E4b7oA?noP1Kxf$RFJ@Xq{Gt2gVGOC z#$RbnUp_YhvLM_fb7kjgS4d>=Ko&GtZjF9a5%u2-i&6lMFiZq$nGQVwA|9A$?DZc6 z9%}h3jW(E$aLhJ})1%Hsj_7FmSY|e0J!t6lX0(njjI3SM_6^Wjc%v2oWI-|sE1F(b z6Z$`%@wsi)u+S1fYtVsx*$J1`Fgnzdd0hjQS5XHCzC3)8N|tNuMwvRR2AKhe9IAyL z4wZzcb4qA1m**Ra4jZptVzF^@%4zUbqe)-*Do` zH*PS>LLdwBH55S>r?od0oTNoR=1>1*?1LsEhh{h+eyrl_?KfX@s+A_HaFm)tLrqM5 zgCex*SLsRc)E@_blJyBC{R;36A0fmk-yo#Xu}>suReD(PMDMHXL{RUz^aKq467fIfv zk?OlfM81xb-_P&}EUn+8ai{L#qgr)bF$0tlz&uK&|B)O0kJgy|9vGDR#FPA>F(9oN zOf(alS1nutMRdb|Y14>g)8g!$;q)r@0dv(iaV#D|%k7F+FcZ zv&8}M4e;vXgM~YYGrj@Z`Z9@-zE2CUTHTqYKQcPUlFO(Mn$MJ#6p*%Xxrk+Ty77*N~e)z5~OF;1=1||Rs z(Ax0@+8qwk^T4f=<5d{f0*aUo=8^^BSOB?YnUpnyJhLF4YxB}PFli)+n$(|L75=1+ z+&I!tb_aSX805JFa#1!3(VxeXM9#Yenz%-raOIe|Pc66~nYy*1*nxfr66IV47TK9j zN*lDYUc{^9(W}dgi8*(tnIIh^hsJXOIcf#+KD7)Um_AT&!7cm>MtQ4 zm|uS{3svIZ>`qPF2<}aH~5L(n}i%6gfEXZd{D5kVQk`rlqfNW&qH`ol_=`;Uxx6`1lD*?kjve za0$$6_mtJtH!CdN7h%?g{Pj;38k-hhE_FpPYR6qls{SK4(C7H7&hh0~FZNll23kXc ztyhcIsAjFfjn>C<0~zfjs%!a_AzmU-)#1h3w>2DX)b}at{i(I}tnc5~)~J5K9`8W& zwyvcs>c6{f4aMzjjG_z8BQZ5a-mqGytun_{n`@dP2^)}b0e?xL-(iX*t_&i=Vu;#D zV#z?6!F)1<42?#i)&f!2eAWq{+fr<=lguN}2L)1oU(bK`i5l|KB~L8XFa}Du;i0IH z8vpzR917eI_>f8(dOe6H@Woetxc{bmO z2sCBN?UYS%M6;=5>3CzmrJM?Ch$0K)heOibT8%98aV<-)_sm}cE<*}*yUgc1udKV&W?{CiECrC%JzB`y;ZRXOnQ|B2f>c9 zw-??~ubWOf7~*mnZ5KYqZuKcReYKk43UyR7;WB$3;qrORmKCY_e(TrMEkhY98(e31 zlNvDXA|;!{En>oy2#MYbv*}liavLhoy_qhKU_Muw_diT#K z-wg(TJa~cKy~inLcWu;HhvUio4n*{4#o#julARu$ndOC@DX?2!Ln*`7_S5-R%n^0W zyxR{mmjJ71Fm2J0;v%<5R6t z+$u>9W|~yX_&=1g#&X4PIYqd3>M@qHIt;S6mVb5&+?Drir)qqE(1^`yQenuA&1p%Q zZaB>H4Emtbwig-a(LNX*-mpnK;4v!01^Imc8AWDNSDHbJW>tGXHb-z`602An5g&&` z`L&!_J;Za4pR1f ztOxm#II^|4NA4bP_MrP^yK&)a4uNXhHQjgCWEt0|z0-g!2;zv8%M{3h_~u+9xER|{ zj}9imzoi$PXVC0->6~@qj>)V9oc_8#_2Q4Y<`*m%jx7EsS&*eo_Msg0Z1qC(*Yo00 ztlYPHgswC4JSS6n$~!u+(&cX^rO&imQaD@%yVoS;^6TnUo!ftALDp5O?X|Ga?&Ve# zHH*Et!s)N@AZ@tJQRDWSsqIba&@1)HcP;mLmxl7R-deBj@vV%OnzYqhq6>^Vz1LHl z3eRocePKxU{!v_x=FKg*OG>lf4OL;w?BGEtd!@wiP)^Wi3 z;&r_6r>SzA_azQocNl^hLIoH@nB!d-L)r7H7{j=0b{NC2cm0zEsk-u9bZ_TMqy&K= z(+ep|SEiS89Mw#(l!SJfqSWLCnP1=2aXrg|oPiLQxF_+hEb(S})hr2CHM=Z{wq1g( zNseQ#tjT9t5Y{sg;>PwSgrkNnJwj-YEkk7Lx>?3+9XIwYXQdkU%s96__MEh}7WUjX z@opS>u`g@P^9pPBIMVW?2{;SO$2hVJ3Z`l}i|Yg9mJ8ky2y>OFLb}b4LC8vE`&1)W z*?_!4`dc6iQkaqShJdSL(v35{AUANIyZUREKvC6LJOD!I?8dLw{pb=Nt^GOXe(jyc z$AoJQhkL>oYfeB2FOD8h6Fy;GZWEF4!3hYt-b$u>0z&Gpx6_<}kT8)OohKlKJ-_ZZ z2)WU7z54`&c--t0{C@<5>>mPI5W?F6vjIRB!j|ApkDBKqO`dSwNA#oP( z1m~07j|3Oe!T=DGncyX~l$-xfXt}T!03jvaw}n^B$GwEts+R!}QonyBybgd6ksqy8 z00`;iYyd!rFji!9KtW9O*GFA%(XCGw00^0M#{wWEOzigV*97m|dyDyW*Grdcy^V^# zchh|?`8i&k^7j2y16Is)_a|1&X(Rh8=sfZkWatt20(k%Q8#B{WlBpF9@mUdU`YeQ?Fgc+vGzoQ%TOTftM9!S)$zL8u?=%ODoEY zJh?3&bB=!+tf;7{=eD-bAD`T)sC;+Gjr8N3m_1+l{}m7-@qY<~?8=_1ii`iMiqW?g z(|z@||Eh|7bQ_lAUsdt1s`yt`{HrR)r}nlgF+@ekAccv~l-pGuN=0@t-4ox0wyXOi zih$wj$t9ibn$g}Or^@chHMi~B8KPpBc7>^p`0cs{rDC^{?y0Ss?fUhIVvl)+>AkV- zcRRhsUfbQ%M|;~1AYwEMS8)bHwS&P^M*CjwnSl%MG?G3;`?D&}66o$Uk@ukk`Fm!G z-FKSliA#cI6hEI&*lA%?E(z7@`FyE%r?8iWP6_d=AiUDhp^DPgnx}>!2Hj+}rhrV`bp`Nbuu~u4&BuB#R!55$5)-B#5 zd!k;`1j>&&{~sTMo^hX6;X; z>ThS&*00%^B#dv;R#tS=tSd|>jDKgTKu;cim#=i6+R1XbF>q*QJ?%C|w9VUaLHUQ> z^!RXR#a8X}UJHA_x)EIL_njK3qw7x8L`rXhTWz@oGo%{@_P1JGB(y*qCI#;oaLV zD&wNdEF@b4CeOBWaH*E$W%dVOOs>VcdydnYfOxJQuC(6N|M~Pg?^gxo9Ul_+Iq65D znS$T#(9P77+}XFTkv&=*%s!;na+WKFKaQ;2RBb#UKZcC4BT!(M2 z*^IoU`ZD^>X_4Ra*S7VFmit+d%XT-*zIxu~`?lAd zmURuUS4yC{CacYhN}E0z=gDkTag6n~c9+pCXEtrr;w`TYR_pKl&NEpG?Bq@{Pkp1D z{l1#G9ch`dEci{1`1mVFCrK>Y~R zb<~jn4^iWf>mcjogvGNgX>+Fy_J2rjKEod<7aMYS0qHM`=r1%g5k`6YJeKvw;^WT$-)aUtG!PWl0^p)ZJY>~#X zNc>$t4HF9-*NA?XmvJVpEyGZ&(KAbd{R>l2SDQ1$dh_IZ->F2Tv>i(d#cG7|Vw7So zqMrPsUSNjW{ao`gzy)~V=;i(kdoNYC*jnj%A!+=_fkpsQt|fSHYnUg zG(qzW%tbsQeIek#ND4URsiYv0PrEnw2<*9kRe_$Yf^v^2bv`K zCNt2>{e&tYkp3++h?D3bub9!j80AC|Ku_=;4O-NRNo*^s|5g+YFW!(Z4!r;N7Pj`u zStR56j!D7ahJrt#%=u~Qv7tbhTD2FoMccKYPYnf5ewp51hQgjaO5=~A=r6ZEGZY*O z3G>o6J;4f0uI8HKr-njzzvAH^LxBu;=&U3jIWrXERW?+W_M8b$wE=x>qRWV2LVnH^v#`Ws&@ zG*mG~%d(o^(R-)iVIl(O%B}kx!$EKv;eRo z1VkXO+Gfq>Vx|WoO9i{HwCxB(W3i;|FXLZ2$GOgQhq2Jtxp{Ov8g2*j7*7j)i#l*y zF%S#O&aa^j-_gx4#v&?WDl3h1Id@J98K`nRR8#bcp^z7`xW?uS7zz~xK_FKbGND67 zIOgJl$Mb^c!&_ZOpsLqgJr#+a*Xp{*WX;|wb~JMJ{D|wIw(L<0>Y-ZUgzqH4J(q8_a&$|+g5aKp(i$qY~P<~lR0Qls54(Z z=sQ>6yW8E-?DT#HyMy-9?Ynjo$*AUX&UNa=91Ly%h64HWxv77i^oK_>W>+3Iz31xE z!@NpF5ANe4n%6r6xQ2EVjtzwrx1UU}zs*Sa9IMrLX#_vfz*xZtIWAo9Y%{aVet@AE zE%>OU0J`hxPp#$q^Xc>9xDZn-eC_?A=sKuyFTNeUrLCtWlQ=G4;y|8tmE3+X2gs5RWt*G5#1lH{HGBJj8Z@4Z$<%{GVuugoMbPr6hiz7v{={+ zFp5F0(DdQK#=>5Z`1E(=^b5+c=+Wu+`AC3K^jmcX6``*yPUGQ3_eOG>hOy znjU`g_v{dgfT9uuuRKF;M33cjPmo3ugs!}Ot{o^|XNwl@yyS&B*Nfv7PMA<F8He+GYabbsbfYlv+(4d*$BWW)(1}+MdV_7#bO=HY;VLFqexwV zCHK`L%pq3I*UlIPTzOvCB!<~KW7EmMmW)xr)*UlJ4&uY~Q zhlN{+txV28VT|;vXN;o1u8(c)PZ#6dNf%=dU=-^MPptwFKo?`iVS=#sw2Oh9H~iDZ z5dRT8 zCn5b0O!1+ARxU>8g?vBpDW*u3{*5V)ErmZE zuoT$8FvSZ1Q>ahuAWtzx&Z9=z*BfL@THhU4K9$?d17q!fRK;%oP};SKs{%ZKVTvNW zo+j^a2u4N7-7Y9z2ojm6sOF_bXW+`p~ zmZJB!rRa(}vlK-uhTZIsNqH5nV#@++whjoeE5!>QdKuynS_>suP;`F}DSmE#TrQfaWKdKnWJ z{hSb0BSwwX!>%UD?pwPisW)2(CMa#gD?T@xZ)qM| z3V>3`MpNVLE%0s6K`w`FWYW@3TtGx|}heqi~T*sDzr{3YzQb=gZ^x7s*?oqNod*-}W zyM5%oZuLG_3j=Cy)#3M}X_z>6iu#}+*)Ne_VO7(*j2P=H^>%B9X?t8G3%bkl^ssUei{Z=xX zFE;c)vrm5ca#&icG53s8^d}Y@61z)%i7yjijv`}G3sEpOx-dRW`-@afjnH8n0@Y|1 zn;;Eh`jEzi*DleTW@CSpFx#EzBFzhAHdu$~+(A1+nmhTyMYR)nXOx0|@{&xJRGVm1`7+vF}GPFKm)_e?i6-pcFn#V20(6^ctUt z7fU}cGC$mv*KRv+C`mPnF_JFPjSe$#`S6(NHop8L@Cl_*EgQKK{sf>D^lwzP@tGe; zYs7!Z$a<;VDG0*eDT$K{qv!R&?@>La6gM73*%qqvh^msP&5dHd!HU^F0-23fR}~vI zHJwkEL$@AjOB$>bCH^2dp%nJ|H3uyE2%tm}>I2Bo_*tJti5j-Yt z_=i&5Y$oHENj}dL5S1fB^I9$On`X9vRnnmG=$*?Dgi+WjrSNFWaQZ_jEN*nis?Wvc zq};L1*8OU(mHA1dKuGS{TPlu6XOx2UlltmElp-gzVafP)N^(uE*5RHO=En8cbS<=1 zw{CG5^K{?%M^a#aQws4jO7T?igi;v)Ln$=-?!X^Y)M~d~Vy;N~ko^VXt~>GVmWRgk59{(iuu$i)P+-`>&M3A^KN= ziIR!%zWB%qrN9_IqDbpMr4-M&_Tb^CltS;8{@fo*F+N6nr_yhI)%q_=fijOvylr$Z z?vA-jyYAF0`L7JR9qgx+;x9>oB|!j`g8GC~H23jW`eB1B2g zk231bMOU5<3AjY02m%98CCsdsx15q>bsO+06Ofh*BgZWG&?NHslc5-)TBJUB zS!kbY9$;uhhtP2OQK*&y3R*#0n4oJA2-$2t-@@Z_{q>!RCyHMvhI5*D2vR{;!?`F; zG2)a5Yunne+n4a^J!UyeSnv-FaBfyfFl`Vyklt!vc$Mw(wOn#qkunfQMBW5ingKiW zUZLnUmF87^|KP*T=C`S$txU2`p)dprnUB107x(!Z<#huh*>yj48Ei$wL)fDoYZvh! zbmAU!V)U1#VX3M9CG@iC&9$6NAzBQXmP3Z7`{`!Hn_Ti0}ZjY=HCg(*rcl;$7+7K2OX@bGl_ z5MLL&p9+Eo`;el8_?xITO;KL4D7A&xdp}V!Y#>s=9<4W|(Z}e-GqT(izwFTnHfCXa z!)Rpcdrtt`)rB(6X%I%^$g29@j>}^pz$oCsXj4HXGmXY5kmydpeIBslhs-e}5P88J z&Y^d?<`*f$PjeX4HyciK7^F?h3f69!4ro;SVvBv5do6NmYatn?lwddC6!AUvZGn?MTp5 zp1Y?pjE<%yRGQBx$Z-r~hq>~`SquZ6|HSRQ$}+c_qV$s3_#*hXYlTDiFESA4&up=9f-}#sv z49jWBbd!=&?8NQL;T5H}$P3O~dHKJW{bL*L{E<#vreffmRi&YyDC4sq}LsSAD8SUuIPUkogVJ)`971Gf%bAoo>{gn~Pos^i#c zbo(XtwZW8nfAnS0mn55$s{R8I!}z8-IK8U@#4sdiK4^{N-k=BFrDzcr+EoH9D4j*e1fk;7ZB zMh+VT+zK14%KNaMt0TNpMVDx_pRHBBAl=T*TeCvu|TY|2y-t!P0 z%G{^>F?Z2mT|2S&LBv>AdSe_V(8JKyrnb^noTOxSe91$jUb%74fNXg024hl$POd11 zJt;XncVOV+*xooygxLp5Gn{TJpGouK(d!57b~1@^I^_>_^CDFv1epu&X*;#1DfJJ$ z!BJ|I)zPP6%i!-s5>nDC z(-+Sr=srp{`LHdMTyG#^tci@aMM}GxuSJPX^|rP`nhrtN6G>IJ+`Y#q6^w<6?gHli z*7pNIX2Z5VcC040UFdD<6QHm-L2Ea;^d-iY0$xe2`|2cv(FK6@GOB4D{k41d(4yrv zH^5&$>iqoqJA;AR{K4LUCv%d)z@KAk+u1!wQMAR{a>uxx5o@Ove(@bD+ zWqL5(Iut=4v|FfuBNm5oJp0$E{!#A?YXrL=*`rh;wb7)>ogJy zR4dN7K^3j>SrdBglB6^Wsu&41z;um40-Z=fTB8u6w_3fPxDWxD7vDXUTBuOb9Kq`$ zd$Q@LQm8$`L@>(tCdN;=>^7A?MpoMocL>!{pe(S}%ur^m-S?itk!j&i27{;JEQ0}- zb2{(!OXoO)Aud=M@4Li=B50E{;Z4_0emb4_q=Sz@q9Vtn6{)TnuKG^}`Qk>H1U+;IkD8J_}GdVBeLWF+423D_R|^D5opW+ zH3ey@LbZ@Mm(~0(t3l`WtrwHm=2$>qldb2yUMvkiUvR>qT!1~E)j~%+J#R!|+<*5% z$=Z@W3I}7og?sD$|m^4)LCKJUV=bMEMsqfBSi6+1p#MIlmo2(y+WvCHj3n)iW#ax;pqN-`Dw?xCC71ylVzodA)S761mnGF zhbEn^A=&J_uUkjNj%KXijpiNE)mxU{+i#lfC9-Mk#hiU9eyQ-^sBC4C8d1J8e{ss+ z*@v~}6WC?NuyXq`0aR=}0>UHg_VP(h2bL#~T!m?Kxlsf`>k?s8>MNFV$WAv>LT>jU zOHGEEv#)o`m!{hFJTr?il0t2HmRFF~iSS!u!lX+g9pCq5C-2qlG|H{eZ55ttoQpH| zo-q>#p2T6rNr^UYY`She{=g8!a<|}a-UzMVWpa8tu92a0={5wh`02^pY_+y-Z|7Zd zp7$#sNRBlbKk=qQAM8@yPek*-!FjVKCFWi~eGNvmf9;o>R|w-%ey!J!dKf78Z_iV! zQ0M2dk{2X8SABBtd|&wPdAea{dcb*)t=4giH`~0ebMEb#x;6LAUbx8Ggm$VNVm_ys zXT~bU=aLUPN-OQ#ykGuN;j+}J6x|w!opmHuR`Z50{<+$VYCYWSY> z0oKDq^I(5(qwRV7Ov8~Ib<6Am$9_&w`xU!}0+NJ;kXQ-USX*ad_Kaur zO~)uubz;<(RGfY|?@!_4X?nwnjZyOS5`Nyq=Pei38Crr6ml?x%zB9IkQ}Wxb zEd01~lG)%g+c?f_XqEo=nGMxf2*&dPE~I3B8IoZT3mwhH0e?9f=}e&)3m<(SkUiyI zy2sd5MCA99+hU7rtjv6*)M|N)d!ov2eo$%mqj{^CYW_FoD#u05dWFOLhzYb!OHnX0 zmQs|mVo4Hn0oT3IV)w?ko_K!ywUynQ3;l0Ir}$P>7biQs*Xj8@U2O0AVbm39R$SPO zI}}>mvJQln7G|1)E?hg#Y|M29c{@H#aB5C-aZ9yU)V<}SxyF7P#o8Z1ix`)iRB{HOfF9gSJvZH-s*a1~x8n-To_Pta`55Jky2yC?SqdlO< z`&U)`t1ABgqAGa)w^W7mMN$yME)3^iM6vuYqR3myE2vmn`WI1bV^_DQ|3wu4B8qCy`Nd9-y6o@L8BAeAk^|x+A6-U3aJc(8`i}yxy7QlRLq81`U@uMly ze0%{`i<;?1L&I4P6`WS9n)bq@L(*Fn*NIkbrrjpe)_8g9XqLo4Q1Y3n&6{78tQ>6I z#uwJM%FC6$BmHW|U#~frOIdx_z;&P8C$7qx=3ZCe{7JGmyj4V~Z{;*kHFI!vJ6kQy zHY}g=!`!#>VnHu!C*2y{3atLlySIhbE*2BBZJS%QBT0+?S{~Eftb)bv^*`Om>pt_( z-|AGlx~ULT`%R4Bvi?KFwBTI6{`c2mp1!bksTk`?6DtTC3RdM| zQK?{V;uX{8Ol0D-735uO;S!B&_R+?RvaRSMBIRtr$XDcXnxQVlQj^cW$n|KQd1iX+55YYBtYjeIr?$_P! z@fuE4Iq#^f?N9?FV!?IFmbP-?vCw9-eh>G-;rAbJ4}f2`QVVt$r4I@=aXQXX^aon) z1U9i)RJQx*x&)+Qor0*e%^}&gIa?OLa}*{yDA}sOz#Myld8ew&LGPq3FPJ*3nb>7! z`P{9t$QyCbUvQwV{7*Px5E#Jb&lhAi4tJ}HLgp_7*vi-!SA_$eQVAJXd)AP{TlPmL zUN0B^kM{2T8w$UF`1ovQ%os}&Lu8aKQYw|ThU{C2>>4UNO|oyzAnTAVTb2>BFUcMm zCHq#g?^=*0v{{?)P^!;$UFUr7`?vet=lUPs=e(EmdcGgG6|I6qf}MN+J)D@dk7;&) zL3_6vyWxydn(Al!;)+a%qX?;S=+THE=&|;W>OAqAEBt&cy?t=qjNT6C0 z^u;oCq2Jd(LG66A-Kurym)YBIp@Fwxgc(KK?qK2}b{xpVLk1gYNeezFN+(OA3nv2) zkRWIbUAt(M7{$P*#yJX%a@tpgOsm)lC*-S_Mc>Ma_Fa$1!|4UxXzg17 zZbzMhTOHU0i6X%^RE5HuJ>j=P0d!0FsZgZ+M};Et&Z|di?z1-Ke=8KE2USB4im(sJ z?8(n1lAn7ZEA|u$V=mxp=i(h92AB|COL(17(^Z8r{%?fG<)bZ zdKh|p(r9f#pG6sOVo7v0B#p?2z02uJlVBPWSY;WZ7>P7?MR1`J*Lx67qUm12?p*?D zJ+w~e*I<|6;1`qNN)nyiBusrcQ}ZKiu7r^d2W-G(T{g-xkj%Pblw~BDRYRiNMAPlZ zL4ui*I#klXxuyT{CrDX_!&$mDjF&vK)v5l(U;MX zHgd0u?uHZCBn!)ohgvyHA)fXs#L9R6IFEn$6U!XMtBB$qe_}VH*r?g*DBLEI*^|IJ z0Nsv1fyrc|jZ9bkXE@PRye>rlRkE0a?oT)|)fNY=jJfSz6c<-CKU@^pUwZs^H-V3U zQ|9xLJ@j|*bOanE3q#YnTq@^fb?5=;G!>0_;L2}o*H2|?_S%Ubl4VzZw-ciAt1Vt2 z44?`}2QQ)5_o^^+MQ}$_hi*#?*PZTEmN{4AA1Wd>uy89;(1upIwO4s78MsNN(?rAS ztKz~ra2iY?G=N5866h0FVcTAjzh1$Y6Y6B_@CaJ)6Q2;Js6yk!6~!9xy#VaZBIkq$m!r$~ zMk=A>v{$X}#!SQ+T3;7CkOjF~#=B|9pCCc5dI$20H|_8f*k)_adMZC*mz?8Z z9~DHIk4bw}?acYy&l~1W^(O#LUe=*I{)ARj)M(+#CW9C;r%&Abovj*wbsUEhvKI~2 z2?InPYYEW;iHkOtRrtLTw&le)l9*ajk}Cp;WwwR{QbpNHb4zJ;n}>08-LY0#lh$&3 zV#qqIdaJp%wu4z3%);3*mF?|x&^G2Sqo7&PzFkhphni13FzKvIZh}O{U2P7K zun(aM6Vh94uAJ?$oFKt-MTxbomZM#EQea16=Y6v_pOb^);$F6mwm&9R{ryZMBygIn_1 zyN+9~#G}2cV?8PMy>iE3o-qIQU4P<@eV?Kl07D-rKX4oQy^o*P(bW#Fqt+i)3qD6} zCz$L_tQ_n$V8=VUQmE|&IW@4h&$z|6(k{F)aHpNve)=Yg2rW(So$0t0uCmik06JgS zO%4W0`&@=UxM4N$=^HY^r<<)4dU|dMW#i#G)2t`b^{btT9QGKDz(~51C13lBwAe>N zm`uCiYynMYn}ip8f0V#3dFOCD1RQD|HZ-uIq0GTcMY`H$+PgH~jCAx1E;j?~2J1>- zr+W~CK7=3NbIw@3F*k|)Rxsp8gsPNu3)0&P)s3_x0gKxV%i%e>Yr)^@?$R8ECXgmv zrN>jZ?R-aj!Qb+j&nTv>-4a{EbksQ4tC%Rzbn{1e;^92+3mXK)@EDE)^oPKf`XC~ZkQc&eLQ0Y z8c5zNDA;xjii^a=52J*gf&#x&P_XS46z9CFoTThd5BgyLDkw>ePaQ8c#jqooHR^0nv&A zuJ-_3@vim@?hZL>s7tPq@iy^-FykJGG>LAbht{lz7PX9cL_u)jX^OG5MK@`g0Gr_$ zNHx9!u#8{;&?}T6%J2+47&=WR@a!a{3`-4A=>&1m>!JX74^+SXn|2Q<>mG0*DL1hu zH-9*G3OVe?a-6E(OmW@B93z6$0~MnVvY&wpJ%mD#)RVY0@7yv6%=Lm? z7B;u#y_)vJt&ZgC6Jr3@WTuq{@B$+kdMAM4Kxo@6x9&v(bbH{<+~xn9h~iDA9D(7C zXRP2v=3wyDRAW#8Ku&o&5i9MG6ml*qM8h|5k+G2JNL!iUkjGTAIxB4h{=;oS(Hk1c zEEg?!dO5pOVr-6{G&iCkc{LhC?ED%}rn@T#Fv23N^fL93S~O#um9wvEFMJ=*G8^0Y zmx$uh8PD69U6c))K*SI?%7T{3K(ze;!SHK$vTQ)>1$vGE?Te`v{4LjG1|{u)v^-FD zGLW_z_2Mqv1vd#oGpjE1SOt@?AQmCXi{Ym~Jh;iaf8H36-&{Uop4=LXP?gM#{wOR{ zhnLHeKIHXf!qay-x{2?upCSNgfiDdb%woZ-3T7`5VtkW(GMF9CdMhWvjL3%x z$k#+L@GKaW#mr!^?=#QM!B-8O91EmU*s*lt)Ft63?|PGF-;A`Mc$Pdu*{7m-(B;cs zL~*9H^7(A(^E6-CqhArlONPtx`y7~2xGsU!lHMpE>#<j|rlW*@v6cuGn zw{8@?G7JI6cw7d`VSu5uWwh&aT?q}C17Hpe1<0ZC(qX8K@7j2*CBcW)%f56sqG$jm zz4!I^L}BZQ3<-kPo*3Xg4spEa%^-j>Hj+o#fTl#ga{SHwO>PD$ho*yWThxdm+j+4< zV5xngI==Q+?x9dwKE{1(tfuLvOjUe13G@=3c2$UzVQYV1jJNBs-A+U?WwAb6esU(x zEi`EQ3Cd_S!NU2~7)l|CU3oII=irHA_HT1Hh=bLmPX>IwmY$}Kt)?yeC(w9lUv1pjM0Y`+p%kxqr3fs%w9)9kEkRp15Z`2gGwZV(XF)e07 z`{YzxQ1y00)@a6G_3xc1-SS~#XzFc6bm*4%yMlb%0;vn$M ziAEfV`yJU&$s3t_do}Ppe-HlP76GMQnC4uN)UEN#Ip6EO-PIUtRfa3Y#whTCQ_*MG zZwP|f+eLw=)-Yf}B$~p?NIS%vw=dkm9{eQn2K02&zS8Sh3?r|&KR~@F_Xf|A#~}*# z7I&wOI>&C`^38H^aG0+n{)m(xg8-4@h4@HXtXx4zIoR|pI z8w3baa4^s;fCqV>EJvpaEWTbgxnEV>Ux0MW$fDqEU5IJF?bUqZ1p7Iq_PJb}FP_F* zAN1=Z+6xtdFN}jZXgGMtFZq5=3x@p_K_l8DdAJ~%s3 zB%VvEWx0rmo)y7kfqqOE6`6eeOShs zruUlgI<|Ev3<5D*zK@B4_?GywkD{5sEqTE1pLT9hGFu%8DdvM+^n)VJ0WQmUsiY{P zrPvXUjP8Zm#K%KjsTRyUQVJj_Q+SUm<>v)!B&69DG-J$7i89Yt^Z?liu2#0H`uAMBGx6;3Pl<0svU0 zi+53>Cj<3~S9wCPu>B|uSX0crNPW8AG(XJ;fW!dbgbwQPrter35IEJM=!snUZBbw| z+J0FSG^SC1EQ)P#C@zXmP_-0jBFhRPU$=cI_|u{Y-mxgwe_9kh`*T2tDNlb{6r8^; zikvdzXc4Hj?9t@s^Zr5#A$u0ZVBN}|MZuk!O8P}n;LVJMDZeZVoE#@XPN?>xG^EDE zzX2>pxV&poaQ?O^@Iv4PwqF*7^~KDe7DZLkwlTl@^EBxN`Ahbvt}*kTR{vvB$nIGb z!m$yopq~~6jhWGJi^9KJj-P)>Y-~gRnzZ5wLVIRQo`jnTUhK`6tm5Ds1^nOr9>&em~=}3=dMM8Qr{&Z)fS}+!ArN{sTPGn8>dN2ws(uVJm2ArtbziyrzVFDbu$gO*mf)mK$|vN4KLJ) zc7N#{&Axw>4J)Wzp}S{Mv^0*Ld?a6^*3r?y99^j*iK*YUC>j>{?RG7S7reaZhS|#P zJ685A3g>`^+LkiGH|k@fol8R(q0=l>ih^QD+xcpN?+VqTP;P8`5EU!mBD-f%B$RcC z=c$Z$XfBp<4NSGlZfJB{*`^3Gt(y|;m20@^g`xa z^)3VNlvVSNZ?P9O0jFP#qPftzZxY9u5+J^@jEdXKl8lWI{2?pPFgv3v;}P=C%> zE4vm&3#94(tFZR!JXTX3{?0hItn)LGucjb99D5dpaKOQYnv)O(A)dSHAko)nbvPAl zbi_1zt=CUb4&)`*D@&aOXb2TjEeep#KK%VtnS6$K%L{_;o9tQ?!5vH($#_GOT&c<# zQ(eUyEM247$SiG1szssIb>uzQd8$RRc3JeNMIoq*mVeD?t9w~Sj|YybijrO7B#=#B z@?tdA=+oM$76tZ_CfANdA^S2wZt=prIhQWi6$>s#y_D1+y5Ps7Ju;=*oXc9CrzKgb z76rLamgTjqDgJ7BiiPAoi|s48K86VsX7<<}i^B5d;j_VgsxkpzPsgg2^m9@z3e>Je zVI9Hi(0iI*|IW644N9LcYS*H`4Cv_+tn}*LUUHj6>aV}(pKH|jInzs-*3rgy8iZ?v zmDom??OGHPT=j3M76p^?hFmLjO~Bc1YrYj7v}wNSV&B#K#XL2J**->~0G-*#D0Z68wEOiMIhUEyT39|rmb8)R`@VRe zhb{%|IWop&;i0fPluq8Tzs3N^aKOO>!(Cf+8J&7~)#1nY&!>dvlx>eZDetH~wPR8E z$>>+zM>AGwUlTXHcr=u5*P=L6dqpT1?`C}$+G*%0k05WGWFHuvI6CU*Ga@?*0lo*9 zZ5_=F9u5TZ1aUe?XS$X zzM3|J9}V;l$(++Vv^+pxGPbm3w92iRl9=%R3eYVJ2~C`Xk+Mi((~a4E9Zrz3AL* z&eXvo3uIRgmlsXuMgQ;`$nr8;5 zPwZI~d9iyIMOBGM-RO=*(K4XD7@rY&O(m{JiErSO-W5pXh5DZs1?k1y19J$~qQGM4 zaq4sSZ)G6QRUB_@2E0M)&HGzF8gg!80o@tv>Z>{&;UxZ|vuBWu*sCT`cFK*f148d))< z$I1q(aYoI>?N}5aBOJd)EX`l}^fA?ub=RWEN)D@S~!oRyr*}htV2^6X9Au zWc{(m##R@FgWlY;C{Q?fWe{yKnbvI}<^VoTv|QFR{V5{UadN-V$z|w;TP)ejhb)J{HQ&Pg7%k1!NW+kD1ej7s{$8R z1-VxRt&m04gO=m5W%*8g`m4tnZ}Y%z3*SRhPBpLc+_@K*cWY}-Q=#vcME6AkA77O= zI<55WdXmalaSPPPaiWFdnHm9~GxYh-Qzb5ak*a-ujq6nZEiJ2cO)u|664@V6|GbX# zVakG);Ns|fod(+Ch649jR!$CXwn31Yq6NtDsYS}gnlC&Vd4WS;s#n-Ph&wC7ZfXm- zm@#55XY&{5bts+C+Q{V9zZ&{Y+$Cmdrn=+PwQy&XVqw#?LbKv;t(z{BTqXjNF6xZO zuAig79X)J6aP!igZ_BLTOg?egR=T>f)kso453;*CF`~3)zVH~2*h+qxM}ARn?R2Gl zC;6xN7NUKg8R^8kF4)vnemlDHFj-0>pAtQ1WNoNSV3QHRJwj>+{#0r!jWo2&&O7!kKD90 z-n|&idw0$1LD4%8j`PVy+=n5duJYVoPn(NDi=M~(HoR{=yv{ukqoj`B*r;I3(17IU zFec;$eD|&PYOXJ=bvuF$KN7II`GsavuTq1t&0Jl8&FEpDmB*T*erWRvpJ7B&SO`kp z?!0g& zy6}C_NTAYcWIWBc&@+8B+hwMCUrCLDm&s<^*3rX8^?Bbpl5U|ej40gIrvgNVqIBQy z%|c!jF2g(8$L|S!(%&2v@Qrgq4Z?yifM5^h_(~?p0U*lB-H0NXSwN@2dgXtQD2B9o zx{}4|9$HMs5V{EDKF^!BI>w;!5bT$97TFn5nGq+h6{SI;f0T1g$GM4n*WL@ z=vHmz9)a$i>KqnJ@2%~qHUo?Ir@~$OX;Bt}uuZZFi zEt{xj7VZG0p?Ck6u~$SwxF#aW>QbTB`=znG{VpbhDQ=&a7B|l=??eE@UdH+Lcmhy1rRLL1p`4W3uo9wDSE=L33{ zmoE^L1g?3zWDjtYkxg9Mr6QS!{OKjv&;k2Y|6hqHa;LcnKO_Xx?{W<5kwOrjyEH|P zVyG&D8c`V8=42+CQ6q|!w#2#2RBA+#i}lO1$<58H`52QO*hY;g+CFCFhjvjTis~kV zd9Ip`4dIf*s~psb0#uWeRmAc1*b}s$=iHM{RjI|hujImxl@HmDkV;29sS$;Z%Wgy= z-1{@4IBfWnrg*hWQ`Ck`Ki#1zHcycM8&Uj&rl1Tb$$USMIxMrs*w1l(eRgHoZhbDy z?b*g6qucok>Ju&d)@=73isje0^^|(ch0m1w8(T0kP}R~KB8|QNEQm}aXX%CXMnjGW tHo$fM8&U9!WgP9a(Rq^8U(0{?Np7dZe + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + compileSdkVersion 29 + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + lintOptions { + disable 'InvalidPackage' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.example.help" + minSdkVersion 16 + targetSdkVersion 29 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" +} diff --git a/help/android/app/src/debug/AndroidManifest.xml b/help/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 00000000..fa2c5cd4 --- /dev/null +++ b/help/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/help/android/app/src/main/AndroidManifest.xml b/help/android/app/src/main/AndroidManifest.xml new file mode 100644 index 00000000..125d6242 --- /dev/null +++ b/help/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + diff --git a/help/android/app/src/main/kotlin/com/example/help/MainActivity.kt b/help/android/app/src/main/kotlin/com/example/help/MainActivity.kt new file mode 100644 index 00000000..75298a08 --- /dev/null +++ b/help/android/app/src/main/kotlin/com/example/help/MainActivity.kt @@ -0,0 +1,6 @@ +package com.example.help + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { +} diff --git a/help/android/app/src/main/res/drawable/launch_background.xml b/help/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 00000000..304732f8 --- /dev/null +++ b/help/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/help/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/help/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..db77bb4b7b0906d62b1847e87f15cdcacf6a4f29 GIT binary patch literal 544 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAj~WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!h8bpbvhu0Wd6uZuB!w&u2PAxD2eNXD>P5D~Wn-+_Wa#27Xc zC?Zj|6r#X(-D3u$NCt}(Ms06KgJ4FxJVv{GM)!I~&n8Bnc94O7-Hd)cjDZswgC;Qs zO=b+9!WcT8F?0rF7!Uys2bs@gozCP?z~o%U|N3vA*22NaGQG zlg@K`O_XuxvZ&Ks^m&R!`&1=spLvfx7oGDKDwpwW`#iqdw@AL`7MR}m`rwr|mZgU`8P7SBkL78fFf!WnuYWm$5Z0 zNXhDbCv&49sM544K|?c)WrFfiZvCi9h0O)B3Pgg&ebxsLQ05GG~ AQ2+n{ literal 0 HcmV?d00001 diff --git a/help/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/help/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..17987b79bb8a35cc66c3c1fd44f5a5526c1b78be GIT binary patch literal 442 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5Xx&nMcT!A!W`0S9QKQy;}1Cl^CgaH=;G9cpY;r$Q>i*pfB zP2drbID<_#qf;rPZx^FqH)F_D#*k@@q03KywUtLX8Ua?`H+NMzkczFPK3lFz@i_kW%1NOn0|D2I9n9wzH8m|-tHjsw|9>@K=iMBhxvkv6m8Y-l zytQ?X=U+MF$@3 zt`~i=@j|6y)RWMK--}M|=T`o&^Ni>IoWKHEbBXz7?A@mgWoL>!*SXo`SZH-*HSdS+ yn*9;$7;m`l>wYBC5bq;=U}IMqLzqbYCidGC!)_gkIk_C@Uy!y&wkt5C($~2D>~)O*cj@FGjOCM)M>_ixfudOh)?xMu#Fs z#}Y=@YDTwOM)x{K_j*Q;dPdJ?Mz0n|pLRx{4n|)f>SXlmV)XB04CrSJn#dS5nK2lM zrZ9#~WelCp7&e13Y$jvaEXHskn$2V!!DN-nWS__6T*l;H&Fopn?A6HZ-6WRLFP=R` zqG+CE#d4|IbyAI+rJJ`&x9*T`+a=p|0O(+s{UBcyZdkhj=yS1>AirP+0R;mf2uMgM zC}@~JfByORAh4SyRgi&!(cja>F(l*O+nd+@4m$|6K6KDn_&uvCpV23&>G9HJp{xgg zoq1^2_p9@|WEo z*X_Uko@K)qYYv~>43eQGMdbiGbo>E~Q& zrYBH{QP^@Sti!`2)uG{irBBq@y*$B zi#&(U-*=fp74j)RyIw49+0MRPMRU)+a2r*PJ$L5roHt2$UjExCTZSbq%V!HeS7J$N zdG@vOZB4v_lF7Plrx+hxo7(fCV&}fHq)$ literal 0 HcmV?d00001 diff --git a/help/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/help/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..d5f1c8d34e7a88e3f88bea192c3a370d44689c3c GIT binary patch literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q8Ax83A=Cw=BuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFa`(sgt!6~Yi|1%a`XoT0ojZ}lNrNjb9xjc(B0U1_% zz5^97Xt*%oq$rQy4?0GKNfJ44uvxI)gC`h-NZ|&0-7(qS@?b!5r36oQ}zyZrNO3 zMO=Or+<~>+A&uN&E!^Sl+>xE!QC-|oJv`ApDhqC^EWD|@=#J`=d#Xzxs4ah}w&Jnc z$|q_opQ^2TrnVZ0o~wh<3t%W&flvYGe#$xqda2bR_R zvPYgMcHgjZ5nSA^lJr%;<&0do;O^tDDh~=pIxA#coaCY>&N%M2^tq^U%3DB@ynvKo}b?yu-bFc-u0JHzced$sg7S3zqI(2 z#Km{dPr7I=pQ5>FuK#)QwK?Y`E`B?nP+}U)I#c1+FM*1kNvWG|a(TpksZQ3B@sD~b zpQ2)*V*TdwjFOtHvV|;OsiDqHi=6%)o4b!)x$)%9pGTsE z-JL={-Ffv+T87W(Xpooq<`r*VzWQcgBN$$`u}f>-ZQI1BB8ykN*=e4rIsJx9>z}*o zo~|9I;xof literal 0 HcmV?d00001 diff --git a/help/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/help/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..4d6372eebdb28e45604e46eeda8dd24651419bc0 GIT binary patch literal 1443 zcmb`G{WsKk6vsdJTdFg%tJav9_E4vzrOaqkWF|A724Nly!y+?N9`YV6wZ}5(X(D_N(?!*n3`|_r0Hc?=PQw&*vnU?QTFY zB_MsH|!j$PP;I}?dppoE_gA(4uc!jV&0!l7_;&p2^pxNo>PEcNJv za5_RT$o2Mf!<+r?&EbHH6nMoTsDOa;mN(wv8RNsHpG)`^ymG-S5By8=l9iVXzN_eG%Xg2@Xeq76tTZ*dGh~Lo9vl;Zfs+W#BydUw zCkZ$o1LqWQO$FC9aKlLl*7x9^0q%0}$OMlp@Kk_jHXOjofdePND+j!A{q!8~Jn+s3 z?~~w@4?egS02}8NuulUA=L~QQfm;MzCGd)XhiftT;+zFO&JVyp2mBww?;QByS_1w! zrQlx%{^cMj0|Bo1FjwY@Q8?Hx0cIPF*@-ZRFpPc#bBw{5@tD(5%sClzIfl8WU~V#u zm5Q;_F!wa$BSpqhN>W@2De?TKWR*!ujY;Yylk_X5#~V!L*Gw~;$%4Q8~Mad z@`-kG?yb$a9cHIApZDVZ^U6Xkp<*4rU82O7%}0jjHlK{id@?-wpN*fCHXyXh(bLt* zPc}H-x0e4E&nQ>y%B-(EL=9}RyC%MyX=upHuFhAk&MLbsF0LP-q`XnH78@fT+pKPW zu72MW`|?8ht^tz$iC}ZwLp4tB;Q49K!QCF3@!iB1qOI=?w z7In!}F~ij(18UYUjnbmC!qKhPo%24?8U1x{7o(+?^Zu0Hx81|FuS?bJ0jgBhEMzf< zCgUq7r2OCB(`XkKcN-TL>u5y#dD6D!)5W?`O5)V^>jb)P)GBdy%t$uUMpf$SNV31$ zb||OojAbvMP?T@$h_ZiFLFVHDmbyMhJF|-_)HX3%m=CDI+ID$0^C>kzxprBW)hw(v zr!Gmda);ICoQyhV_oP5+C%?jcG8v+D@9f?Dk*!BxY}dazmrT@64UrP3hlslANK)bq z$67n83eh}OeW&SV@HG95P|bjfqJ7gw$e+`Hxo!4cx`jdK1bJ>YDSpGKLPZ^1cv$ek zIB?0S<#tX?SJCLWdMd{-ME?$hc7A$zBOdIJ)4!KcAwb=VMov)nK;9z>x~rfT1>dS+ zZ6#`2v@`jgbqq)P22H)Tx2CpmM^o1$B+xT6`(v%5xJ(?j#>Q$+rx_R|7TzDZe{J6q zG1*EcU%tE?!kO%^M;3aM6JN*LAKUVb^xz8-Pxo#jR5(-KBeLJvA@-gxNHx0M-ZJLl z;#JwQoh~9V?`UVo#}{6ka@II>++D@%KqGpMdlQ}?9E*wFcf5(#XQnP$Dk5~%iX^>f z%$y;?M0BLp{O3a(-4A?ewryHrrD%cx#Q^%KY1H zNre$ve+vceSLZcNY4U(RBX&)oZn*Py()h)XkE?PL$!bNb{N5FVI2Y%LKEm%yvpyTP z(1P?z~7YxD~Rf<(a@_y` literal 0 HcmV?d00001 diff --git a/help/android/app/src/main/res/values/styles.xml b/help/android/app/src/main/res/values/styles.xml new file mode 100644 index 00000000..1f83a33f --- /dev/null +++ b/help/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/help/android/app/src/profile/AndroidManifest.xml b/help/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 00000000..fa2c5cd4 --- /dev/null +++ b/help/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/help/android/build.gradle b/help/android/build.gradle new file mode 100644 index 00000000..3100ad2d --- /dev/null +++ b/help/android/build.gradle @@ -0,0 +1,31 @@ +buildscript { + ext.kotlin_version = '1.3.50' + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.5.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +allprojects { + repositories { + google() + jcenter() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/help/android/gradle.properties b/help/android/gradle.properties new file mode 100644 index 00000000..94adc3a3 --- /dev/null +++ b/help/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true diff --git a/help/android/gradle/wrapper/gradle-wrapper.properties b/help/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..296b146b --- /dev/null +++ b/help/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Jun 23 08:50:38 CEST 2017 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip diff --git a/help/android/settings.gradle b/help/android/settings.gradle new file mode 100644 index 00000000..44e62bcf --- /dev/null +++ b/help/android/settings.gradle @@ -0,0 +1,11 @@ +include ':app' + +def localPropertiesFile = new File(rootProject.projectDir, "local.properties") +def properties = new Properties() + +assert localPropertiesFile.exists() +localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } + +def flutterSdkPath = properties.getProperty("flutter.sdk") +assert flutterSdkPath != null, "flutter.sdk not set in local.properties" +apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" diff --git a/help/ios/.gitignore b/help/ios/.gitignore new file mode 100644 index 00000000..e96ef602 --- /dev/null +++ b/help/ios/.gitignore @@ -0,0 +1,32 @@ +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/help/ios/Flutter/AppFrameworkInfo.plist b/help/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 00000000..f2872cf4 --- /dev/null +++ b/help/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 9.0 + + diff --git a/help/ios/Flutter/Debug.xcconfig b/help/ios/Flutter/Debug.xcconfig new file mode 100644 index 00000000..592ceee8 --- /dev/null +++ b/help/ios/Flutter/Debug.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/help/ios/Flutter/Release.xcconfig b/help/ios/Flutter/Release.xcconfig new file mode 100644 index 00000000..592ceee8 --- /dev/null +++ b/help/ios/Flutter/Release.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/help/ios/Runner.xcodeproj/project.pbxproj b/help/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 00000000..4f158fea --- /dev/null +++ b/help/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,495 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1020; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.help; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.help; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.help; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/help/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/help/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..1d526a16 --- /dev/null +++ b/help/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/help/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/help/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/help/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/help/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/help/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..f9b0d7c5 --- /dev/null +++ b/help/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/help/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/help/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 00000000..a28140cf --- /dev/null +++ b/help/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/help/ios/Runner.xcworkspace/contents.xcworkspacedata b/help/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..1d526a16 --- /dev/null +++ b/help/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/help/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/help/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/help/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/help/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/help/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..f9b0d7c5 --- /dev/null +++ b/help/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/help/ios/Runner/AppDelegate.swift b/help/ios/Runner/AppDelegate.swift new file mode 100644 index 00000000..70693e4a --- /dev/null +++ b/help/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..d36b1fab --- /dev/null +++ b/help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..dc9ada4725e9b0ddb1deab583e5b5102493aa332 GIT binary patch literal 10932 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 literal 0 HcmV?d00001 diff --git a/help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..f091b6b0bca859a3f474b03065bef75ba58a9e4c GIT binary patch literal 1588 zcmV-42Fv-0P)C1SqPt}wig>|5Crh^=oyX$BK<}M8eLU3e2hGT;=G|!_SP)7zNI6fqUMB=)y zRAZ>eDe#*r`yDAVgB_R*LB*MAc)8(b{g{9McCXW!lq7r(btRoB9!8B-#AI6JMb~YFBEvdsV)`mEQO^&#eRKx@b&x- z5lZm*!WfD8oCLzfHGz#u7sT0^VLMI1MqGxF^v+`4YYnVYgk*=kU?HsSz{v({E3lb9 z>+xILjBN)t6`=g~IBOelGQ(O990@BfXf(DRI5I$qN$0Gkz-FSc$3a+2fX$AedL4u{ z4V+5Ong(9LiGcIKW?_352sR;LtDPmPJXI{YtT=O8=76o9;*n%_m|xo!i>7$IrZ-{l z-x3`7M}qzHsPV@$v#>H-TpjDh2UE$9g6sysUREDy_R(a)>=eHw-WAyfIN z*qb!_hW>G)Tu8nSw9yn#3wFMiLcfc4pY0ek1}8(NqkBR@t4{~oC>ryc-h_ByH(Cg5 z>ao-}771+xE3um9lWAY1FeQFxowa1(!J(;Jg*wrg!=6FdRX+t_<%z&d&?|Bn){>zm zZQj(aA_HeBY&OC^jj*)N`8fa^ePOU72VpInJoI1?`ty#lvlNzs(&MZX+R%2xS~5Kh zX*|AU4QE#~SgPzOXe9>tRj>hjU@c1k5Y_mW*Jp3fI;)1&g3j|zDgC+}2Q_v%YfDax z!?umcN^n}KYQ|a$Lr+51Nf9dkkYFSjZZjkma$0KOj+;aQ&721~t7QUKx61J3(P4P1 zstI~7-wOACnWP4=8oGOwz%vNDqD8w&Q`qcNGGrbbf&0s9L0De{4{mRS?o0MU+nR_! zrvshUau0G^DeMhM_v{5BuLjb#Hh@r23lDAk8oF(C+P0rsBpv85EP>4CVMx#04MOfG z;P%vktHcXwTj~+IE(~px)3*MY77e}p#|c>TD?sMatC0Tu4iKKJ0(X8jxQY*gYtxsC z(zYC$g|@+I+kY;dg_dE>scBf&bP1Nc@Hz<3R)V`=AGkc;8CXqdi=B4l2k|g;2%#m& z*jfX^%b!A8#bI!j9-0Fi0bOXl(-c^AB9|nQaE`*)Hw+o&jS9@7&Gov#HbD~#d{twV zXd^Tr^mWLfFh$@Dr$e;PBEz4(-2q1FF0}c;~B5sA}+Q>TOoP+t>wf)V9Iy=5ruQa;z)y zI9C9*oUga6=hxw6QasLPnee@3^Rr*M{CdaL5=R41nLs(AHk_=Y+A9$2&H(B7!_pURs&8aNw7?`&Z&xY_Ye z)~D5Bog^td-^QbUtkTirdyK^mTHAOuptDflut!#^lnKqU md>ggs(5nOWAqO?umG&QVYK#ibz}*4>0000U6E9hRK9^#O7(mu>ETqrXGsduA8$)?`v2seloOCza43C{NQ$$gAOH**MCn0Q?+L7dl7qnbRdqZ8LSVp1ItDxhxD?t@5_yHg6A8yI zC*%Wgg22K|8E#!~cTNYR~@Y9KepMPrrB8cABapAFa=`H+UGhkXUZV1GnwR1*lPyZ;*K(i~2gp|@bzp8}og7e*#% zEnr|^CWdVV!-4*Y_7rFvlww2Ze+>j*!Z!pQ?2l->4q#nqRu9`ELo6RMS5=br47g_X zRw}P9a7RRYQ%2Vsd0Me{_(EggTnuN6j=-?uFS6j^u69elMypu?t>op*wBx<=Wx8?( ztpe^(fwM6jJX7M-l*k3kEpWOl_Vk3@(_w4oc}4YF4|Rt=2V^XU?#Yz`8(e?aZ@#li0n*=g^qOcVpd-Wbok=@b#Yw zqn8u9a)z>l(1kEaPYZ6hwubN6i<8QHgsu0oE) ziJ(p;Wxm>sf!K+cw>R-(^Y2_bahB+&KI9y^);#0qt}t-$C|Bo71lHi{_+lg#f%RFy z0um=e3$K3i6K{U_4K!EX?F&rExl^W|G8Z8;`5z-k}OGNZ0#WVb$WCpQu-_YsiqKP?BB# vzVHS-CTUF4Ozn5G+mq_~Qqto~ahA+K`|lyv3(-e}00000NkvXXu0mjfd`9t{ literal 0 HcmV?d00001 diff --git a/help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d0ef06e7edb86cdfe0d15b4b0d98334a86163658 GIT binary patch literal 1716 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 literal 0 HcmV?d00001 diff --git a/help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c8f9ed8f5cee1c98386d13b17e89f719e83555b2 GIT binary patch literal 1895 zcmV-t2blPYP)FQtfgmafE#=YDCq`qUBt#QpG%*H6QHY765~R=q zZ6iudfM}q!Pz#~9JgOi8QJ|DSu?1-*(kSi1K4#~5?#|rh?sS)(-JQqX*}ciXJ56_H zdw=^s_srbAdqxlvGyrgGet#6T7_|j;95sL%MtM;q86vOxKM$f#puR)Bjv9Zvz9-di zXOTSsZkM83)E9PYBXC<$6(|>lNLVBb&&6y{NByFCp%6+^ALR@NCTse_wqvNmSWI-m z!$%KlHFH2omF!>#%1l3LTZg(s7eof$7*xB)ZQ0h?ejh?Ta9fDv59+u#MokW+1t8Zb zgHv%K(u9G^Lv`lh#f3<6!JVTL3(dCpxHbnbA;kKqQyd1~^Xe0VIaYBSWm6nsr;dFj z4;G-RyL?cYgsN1{L4ZFFNa;8)Rv0fM0C(~Tkit94 zz#~A)59?QjD&pAPSEQ)p8gP|DS{ng)j=2ux)_EzzJ773GmQ_Cic%3JJhC0t2cx>|v zJcVusIB!%F90{+}8hG3QU4KNeKmK%T>mN57NnCZ^56=0?&3@!j>a>B43pi{!u z7JyDj7`6d)qVp^R=%j>UIY6f+3`+qzIc!Y_=+uN^3BYV|o+$vGo-j-Wm<10%A=(Yk^beI{t%ld@yhKjq0iNjqN4XMGgQtbKubPM$JWBz}YA65k%dm*awtC^+f;a-x4+ddbH^7iDWGg&N0n#MW{kA|=8iMUiFYvMoDY@sPC#t$55gn6ykUTPAr`a@!(;np824>2xJthS z*ZdmT`g5-`BuJs`0LVhz+D9NNa3<=6m;cQLaF?tCv8)zcRSh66*Z|vXhG@$I%U~2l z?`Q zykI#*+rQ=z6Jm=Bui-SfpDYLA=|vzGE(dYm=OC8XM&MDo7ux4UF1~0J1+i%aCUpRe zt3L_uNyQ*cE(38Uy03H%I*)*Bh=Lb^Xj3?I^Hnbeq72(EOK^Y93CNp*uAA{5Lc=ky zx=~RKa4{iTm{_>_vSCm?$Ej=i6@=m%@VvAITnigVg{&@!7CDgs908761meDK5azA} z4?=NOH|PdvabgJ&fW2{Mo$Q0CcD8Qc84%{JPYt5EiG{MdLIAeX%T=D7NIP4%Hw}p9 zg)==!2Lbp#j{u_}hMiao9=!VSyx0gHbeCS`;q&vzeq|fs`y&^X-lso(Ls@-706qmA z7u*T5PMo_w3{se1t2`zWeO^hOvTsohG_;>J0wVqVe+n)AbQCx)yh9;w+J6?NF5Lmo zecS@ieAKL8%bVd@+-KT{yI|S}O>pYckUFs;ry9Ow$CD@ztz5K-*D$^{i(_1llhSh^ zEkL$}tsQt5>QA^;QgjgIfBDmcOgi5YDyu?t6vSnbp=1+@6D& z5MJ}B8q;bRlVoxasyhcUF1+)o`&3r0colr}QJ3hcSdLu;9;td>kf@Tcn<@9sIx&=m z;AD;SCh95=&p;$r{Xz3iWCO^MX83AGJ(yH&eTXgv|0=34#-&WAmw{)U7OU9!Wz^!7 zZ%jZFi@JR;>Mhi7S>V7wQ176|FdW2m?&`qa(ScO^CFPR80HucLHOTy%5s*HR0^8)i h0WYBP*#0Ks^FNSabJA*5${_#%002ovPDHLkV1oKhTl@e3 literal 0 HcmV?d00001 diff --git a/help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..a6d6b8609df07bf62e5100a53a01510388bd2b22 GIT binary patch literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ literal 0 HcmV?d00001 diff --git a/help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a6d6b8609df07bf62e5100a53a01510388bd2b22 GIT binary patch literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ literal 0 HcmV?d00001 diff --git a/help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..75b2d164a5a98e212cca15ea7bf2ab5de5108680 GIT binary patch literal 3831 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 literal 0 HcmV?d00001 diff --git a/help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/help/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..c4df70d39da7941ef3f6dcb7f06a192d8dcb308d GIT binary patch literal 1888 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 iW8Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/help/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/help/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/help/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/help/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/help/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/help/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 00000000..89c2725b --- /dev/null +++ b/help/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/help/ios/Runner/Base.lproj/LaunchScreen.storyboard b/help/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 00000000..f2e259c7 --- /dev/null +++ b/help/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/help/ios/Runner/Base.lproj/Main.storyboard b/help/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 00000000..f3c28516 --- /dev/null +++ b/help/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/help/ios/Runner/Info.plist b/help/ios/Runner/Info.plist new file mode 100644 index 00000000..71ce57cb --- /dev/null +++ b/help/ios/Runner/Info.plist @@ -0,0 +1,48 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + help + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + < key >NSCameraUsageDescription< /key > + < string >Camera permission is required for barcode scanning.< /string > + + diff --git a/help/ios/Runner/Runner-Bridging-Header.h b/help/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 00000000..308a2a56 --- /dev/null +++ b/help/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/help/lib/main.dart b/help/lib/main.dart new file mode 100644 index 00000000..11655b66 --- /dev/null +++ b/help/lib/main.dart @@ -0,0 +1,117 @@ +import 'package:flutter/material.dart'; + +void main() { + runApp(MyApp()); +} + +class MyApp extends StatelessWidget { + // This widget is the root of your application. + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Flutter Demo', + theme: ThemeData( + // This is the theme of your application. + // + // Try running your application with "flutter run". You'll see the + // application has a blue toolbar. Then, without quitting the app, try + // changing the primarySwatch below to Colors.green and then invoke + // "hot reload" (press "r" in the console where you ran "flutter run", + // or simply save your changes to "hot reload" in a Flutter IDE). + // Notice that the counter didn't reset back to zero; the application + // is not restarted. + primarySwatch: Colors.blue, + // This makes the visual density adapt to the platform that you run + // the app on. For desktop platforms, the controls will be smaller and + // closer together (more dense) than on mobile platforms. + visualDensity: VisualDensity.adaptivePlatformDensity, + ), + home: MyHomePage(title: 'Flutter Demo Home Page'), + ); + } +} + +class MyHomePage extends StatefulWidget { + MyHomePage({Key key, this.title}) : super(key: key); + + // This widget is the home page of your application. It is stateful, meaning + // that it has a State object (defined below) that contains fields that affect + // how it looks. + + // This class is the configuration for the state. It holds the values (in this + // case the title) provided by the parent (in this case the App widget) and + // used by the build method of the State. Fields in a Widget subclass are + // always marked "final". + + final String title; + + @override + _MyHomePageState createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State { + int _counter = 0; + + void _incrementCounter() { + setState(() { + // This call to setState tells the Flutter framework that something has + // changed in this State, which causes it to rerun the build method below + // so that the display can reflect the updated values. If we changed + // _counter without calling setState(), then the build method would not be + // called again, and so nothing would appear to happen. + _counter++; + }); + } + + @override + Widget build(BuildContext context) { + // This method is rerun every time setState is called, for instance as done + // by the _incrementCounter method above. + // + // The Flutter framework has been optimized to make rerunning build methods + // fast, so that you can just rebuild anything that needs updating rather + // than having to individually change instances of widgets. + return Scaffold( + appBar: AppBar( + // Here we take the value from the MyHomePage object that was created by + // the App.build method, and use it to set our appbar title. + title: Text(widget.title), + ), + body: Center( + // Center is a layout widget. It takes a single child and positions it + // in the middle of the parent. + child: Column( + // Column is also a layout widget. It takes a list of children and + // arranges them vertically. By default, it sizes itself to fit its + // children horizontally, and tries to be as tall as its parent. + // + // Invoke "debug painting" (press "p" in the console, choose the + // "Toggle Debug Paint" action from the Flutter Inspector in Android + // Studio, or the "Toggle Debug Paint" command in Visual Studio Code) + // to see the wireframe for each widget. + // + // Column has various properties to control how it sizes itself and + // how it positions its children. Here we use mainAxisAlignment to + // center the children vertically; the main axis here is the vertical + // axis because Columns are vertical (the cross axis would be + // horizontal). + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'You have pushed the button this many times:', + ), + Text( + '$_counter', + style: Theme.of(context).textTheme.headline4, + ), + ], + ), + ), + floatingActionButton: FloatingActionButton( + onPressed: _incrementCounter, + tooltip: 'Increment', + child: Icon(Icons.add), + ), // This trailing comma makes auto-formatting nicer for build methods. + ); + } +} diff --git a/help/pubspec.yaml b/help/pubspec.yaml new file mode 100644 index 00000000..66af3d9e --- /dev/null +++ b/help/pubspec.yaml @@ -0,0 +1,76 @@ +name: help +description: A new Flutter project. + +# The following line prevents the package from being accidentally published to +# pub.dev using `pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +version: 1.0.0+1 + +environment: + sdk: ">=2.7.0 <3.0.0" + +dependencies: + flutter: + sdk: flutter + + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.0 + +dev_dependencies: + flutter_test: + sdk: flutter + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware. + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/assets-and-images/#from-packages + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/custom-fonts/#from-packages diff --git a/help/test/widget_test.dart b/help/test/widget_test.dart new file mode 100644 index 00000000..9ca1523f --- /dev/null +++ b/help/test/widget_test.dart @@ -0,0 +1,32 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility that Flutter provides. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../lib/main.dart'; + + + +void main() { + testWidgets('Counter increments smoke test', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(MyApp()); + + // Verify that our counter starts at 0. + expect(find.text('0'), findsOneWidget); + expect(find.text('1'), findsNothing); + + // Tap the '+' icon and trigger a frame. + await tester.tap(find.byIcon(Icons.add)); + await tester.pump(); + + // Verify that our counter has incremented. + expect(find.text('0'), findsNothing); + expect(find.text('1'), findsOneWidget); + }); +} diff --git a/ios/.gitignore b/ios/.gitignore index e67828a4..04b5cf29 100644 --- a/ios/.gitignore +++ b/ios/.gitignore @@ -30,6 +30,4 @@ Runner/GeneratedPluginRegistrant.* !default.mode2v3 !default.pbxuser !default.perspectivev3 -/Runner.xcworkspace/contents.xcworkspacedata -/Runner.xcodeproj/project.pbxproj /Flutter/.last_build_id diff --git a/ios/Flutter/.last_build_id b/ios/Flutter/.last_build_id index 6bca0336..b8024672 100644 --- a/ios/Flutter/.last_build_id +++ b/ios/Flutter/.last_build_id @@ -1 +1 @@ -f4a819c27119d0f472892c1088ad1ca3 \ No newline at end of file +59a6c452ee075b50114918f17f1ad8f5 \ No newline at end of file diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist index f2872cf4..6b4c0f78 100644 --- a/ios/Flutter/AppFrameworkInfo.plist +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 9.0 + 8.0 diff --git a/ios/GoogleService-Info.plist b/ios/GoogleService-Info.plist new file mode 100644 index 00000000..0c093a2a --- /dev/null +++ b/ios/GoogleService-Info.plist @@ -0,0 +1,36 @@ + + + + + CLIENT_ID + 864393916058-ekeb4s8tgfo58dutv0l54399t7ivr06r.apps.googleusercontent.com + REVERSED_CLIENT_ID + com.googleusercontent.apps.864393916058-ekeb4s8tgfo58dutv0l54399t7ivr06r + API_KEY + AIzaSyA_6ayGCk4fly7o7eTVBrj9kuHBYHMAOfs + GCM_SENDER_ID + 864393916058 + PLIST_VERSION + 1 + BUNDLE_ID + com.cloud.diplomaticquarterapp + PROJECT_ID + diplomaticquarter-d2385 + STORAGE_BUCKET + diplomaticquarter-d2385.appspot.com + IS_ADS_ENABLED + + IS_ANALYTICS_ENABLED + + IS_APPINVITE_ENABLED + + IS_GCM_ENABLED + + IS_SIGNIN_ENABLED + + GOOGLE_APP_ID + 1:864393916058:ios:13f787bbfe6051f8b97923 + DATABASE_URL + https://diplomaticquarter-d2385.firebaseio.com + + \ No newline at end of file diff --git a/ios/Podfile b/ios/Podfile index 1d1a003e..5579d926 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -platform :ios, '11.0' + platform :ios, '11.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' @@ -10,32 +10,85 @@ project 'Runner', { 'Release' => :release, } -def flutter_root - generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) - unless File.exist?(generated_xcode_build_settings_path) - raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" - end +# pod 'FBSDKCoreKit' +# pod 'FBSDKLoginKit' - File.foreach(generated_xcode_build_settings_path) do |line| - matches = line.match(/FLUTTER_ROOT\=(.*)/) - return matches[1].strip if matches +def parse_KV_file(file, separator='=') + file_abs_path = File.expand_path(file) + if !File.exists? file_abs_path + return []; + end + generated_key_values = {} + skip_line_start_symbols = ["#", "/"] + File.foreach(file_abs_path) do |line| + next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } + plugin = line.split(pattern=separator) + if plugin.length == 2 + podname = plugin[0].strip() + path = plugin[1].strip() + podpath = File.expand_path("#{path}", file_abs_path) + generated_key_values[podname] = podpath + else + puts "Invalid plugin specification: #{line}" + end end - raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" + generated_key_values end -require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) - -flutter_ios_podfile_setup - target 'Runner' do use_frameworks! use_modular_headers! - flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) + # Native Pods + pod 'NVActivityIndicatorView' + + + # Flutter Pod + copied_flutter_dir = File.join(__dir__, 'Flutter') + copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework') + copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec') + unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path) + # Copy Flutter.framework and Flutter.podspec to Flutter/ to have something to link against if the xcode backend script has not run yet. + # That script will copy the correct debug/profile/release version of the framework based on the currently selected Xcode configuration. + # CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist. + + generated_xcode_build_settings_path = File.join(copied_flutter_dir, 'Generated.xcconfig') + unless File.exist?(generated_xcode_build_settings_path) + raise "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path) + cached_framework_dir = generated_xcode_build_settings['FLUTTER_FRAMEWORK_DIR']; + + unless File.exist?(copied_framework_path) + FileUtils.cp_r(File.join(cached_framework_dir, 'Flutter.framework'), copied_flutter_dir) + end + unless File.exist?(copied_podspec_path) + FileUtils.cp(File.join(cached_framework_dir, 'Flutter.podspec'), copied_flutter_dir) + end + end + + # Keep pod path relative so it can be checked into Podfile.lock. + pod 'Flutter', :path => 'Flutter' + + # Plugin Pods + + # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock + # referring to absolute paths on developers' machines. + system('rm -rf .symlinks') + system('mkdir -p .symlinks/plugins') + plugin_pods = parse_KV_file('../.flutter-plugins') + plugin_pods.each do |name, path| + symlink = File.join('.symlinks', 'plugins', name) + File.symlink(path, symlink) + pod name, :path => File.join(symlink, 'ios') + end end post_install do |installer| installer.pods_project.targets.each do |target| - flutter_additional_ios_build_settings(target) + target.build_configurations.each do |config| + config.build_settings['ENABLE_BITCODE'] = 'NO' + end end -end \ No newline at end of file +end + diff --git a/ios/Podfile.lock b/ios/Podfile.lock new file mode 100644 index 00000000..77dfa5e1 --- /dev/null +++ b/ios/Podfile.lock @@ -0,0 +1,455 @@ +PODS: + - android_intent (0.0.1): + - Flutter + - barcode_scan_fix (0.0.1): + - Flutter + - MTBBarcodeScanner + - connectivity (0.0.1): + - Flutter + - Reachability + - connectivity_for_web (0.1.0): + - Flutter + - connectivity_macos (0.0.1): + - Flutter + - device_calendar (0.0.1): + - Flutter + - device_info (0.0.1): + - Flutter + - Firebase/CoreOnly (6.33.0): + - FirebaseCore (= 6.10.3) + - Firebase/Messaging (6.33.0): + - Firebase/CoreOnly + - FirebaseMessaging (~> 4.7.0) + - firebase_core (0.5.3): + - Firebase/CoreOnly (~> 6.33.0) + - Flutter + - firebase_core_web (0.1.0): + - Flutter + - firebase_messaging (7.0.3): + - Firebase/CoreOnly (~> 6.33.0) + - Firebase/Messaging (~> 6.33.0) + - firebase_core + - Flutter + - FirebaseCore (6.10.3): + - FirebaseCoreDiagnostics (~> 1.6) + - GoogleUtilities/Environment (~> 6.7) + - GoogleUtilities/Logger (~> 6.7) + - FirebaseCoreDiagnostics (1.7.0): + - GoogleDataTransport (~> 7.4) + - GoogleUtilities/Environment (~> 6.7) + - GoogleUtilities/Logger (~> 6.7) + - nanopb (~> 1.30906.0) + - FirebaseInstallations (1.7.0): + - FirebaseCore (~> 6.10) + - GoogleUtilities/Environment (~> 6.7) + - GoogleUtilities/UserDefaults (~> 6.7) + - PromisesObjC (~> 1.2) + - FirebaseInstanceID (4.8.0): + - FirebaseCore (~> 6.10) + - FirebaseInstallations (~> 1.6) + - GoogleUtilities/Environment (~> 6.7) + - GoogleUtilities/UserDefaults (~> 6.7) + - FirebaseMessaging (4.7.1): + - FirebaseCore (~> 6.10) + - FirebaseInstanceID (~> 4.7) + - GoogleUtilities/AppDelegateSwizzler (~> 6.7) + - GoogleUtilities/Environment (~> 6.7) + - GoogleUtilities/Reachability (~> 6.7) + - GoogleUtilities/UserDefaults (~> 6.7) + - Protobuf (>= 3.9.2, ~> 3.9) + - Flutter (1.0.0) + - flutter_email_sender (0.0.1): + - Flutter + - flutter_flexible_toast (0.0.1): + - Flutter + - flutter_inappwebview (0.0.1): + - Flutter + - flutter_local_notifications (0.0.1): + - Flutter + - flutter_plugin_android_lifecycle (0.0.1): + - Flutter + - flutter_tts (0.0.1): + - Flutter + - geolocator (6.1.9): + - Flutter + - google_maps_flutter (0.0.1): + - Flutter + - GoogleMaps (< 3.10) + - GoogleDataTransport (7.5.1): + - nanopb (~> 1.30906.0) + - GoogleMaps (3.9.0): + - GoogleMaps/Maps (= 3.9.0) + - GoogleMaps/Base (3.9.0) + - GoogleMaps/Maps (3.9.0): + - GoogleMaps/Base + - GoogleUtilities/AppDelegateSwizzler (6.7.2): + - GoogleUtilities/Environment + - GoogleUtilities/Logger + - GoogleUtilities/Network + - GoogleUtilities/Environment (6.7.2): + - PromisesObjC (~> 1.2) + - GoogleUtilities/Logger (6.7.2): + - GoogleUtilities/Environment + - GoogleUtilities/Network (6.7.2): + - GoogleUtilities/Logger + - "GoogleUtilities/NSData+zlib" + - GoogleUtilities/Reachability + - "GoogleUtilities/NSData+zlib (6.7.2)" + - GoogleUtilities/Reachability (6.7.2): + - GoogleUtilities/Logger + - GoogleUtilities/UserDefaults (6.7.2): + - GoogleUtilities/Logger + - hexcolor (0.0.1): + - Flutter + - image_cropper (0.0.3): + - Flutter + - TOCropViewController (~> 2.5.4) + - image_picker (0.0.1): + - Flutter + - just_audio (0.0.1): + - Flutter + - local_auth (0.0.1): + - Flutter + - manage_calendar_events (0.0.1): + - Flutter + - map_launcher (0.0.1): + - Flutter + - maps_launcher (0.0.1): + - Flutter + - MTBBarcodeScanner (5.0.11) + - nanopb (1.30906.0): + - nanopb/decode (= 1.30906.0) + - nanopb/encode (= 1.30906.0) + - nanopb/decode (1.30906.0) + - nanopb/encode (1.30906.0) + - native_device_orientation (0.0.1): + - Flutter + - native_progress_hud (0.0.1): + - Flutter + - NVActivityIndicatorView (5.1.1): + - NVActivityIndicatorView/Base (= 5.1.1) + - NVActivityIndicatorView/Base (5.1.1) + - path_provider (0.0.1): + - Flutter + - path_provider_linux (0.0.1): + - Flutter + - path_provider_macos (0.0.1): + - Flutter + - path_provider_windows (0.0.1): + - Flutter + - "permission_handler (5.0.1+1)": + - Flutter + - PromisesObjC (1.2.11) + - Protobuf (3.13.0) + - Reachability (3.2) + - screen (0.0.1): + - Flutter + - shared_preferences (0.0.1): + - Flutter + - shared_preferences_linux (0.0.1): + - Flutter + - shared_preferences_macos (0.0.1): + - Flutter + - shared_preferences_web (0.0.1): + - Flutter + - shared_preferences_windows (0.0.1): + - Flutter + - speech_to_text (0.0.1): + - Flutter + - Try + - TOCropViewController (2.5.5) + - Try (2.1.1) + - "twilio_programmable_video (0.5.0+4)": + - Flutter + - TwilioVideo (~> 3.4) + - TwilioVideo (3.8.0) + - url_launcher (0.0.1): + - Flutter + - url_launcher_linux (0.0.1): + - Flutter + - url_launcher_macos (0.0.1): + - Flutter + - url_launcher_web (0.0.1): + - Flutter + - url_launcher_windows (0.0.1): + - Flutter + - vibration (1.7.3): + - Flutter + - vibration_web (1.6.2): + - Flutter + - video_player (0.0.1): + - Flutter + - video_player_web (0.0.1): + - Flutter + - wakelock (0.0.1): + - Flutter + - webview_flutter (0.0.1): + - Flutter + - wifi (0.0.1): + - Flutter + +DEPENDENCIES: + - android_intent (from `.symlinks/plugins/android_intent/ios`) + - barcode_scan_fix (from `.symlinks/plugins/barcode_scan_fix/ios`) + - connectivity (from `.symlinks/plugins/connectivity/ios`) + - connectivity_for_web (from `.symlinks/plugins/connectivity_for_web/ios`) + - connectivity_macos (from `.symlinks/plugins/connectivity_macos/ios`) + - device_calendar (from `.symlinks/plugins/device_calendar/ios`) + - device_info (from `.symlinks/plugins/device_info/ios`) + - firebase_core (from `.symlinks/plugins/firebase_core/ios`) + - firebase_core_web (from `.symlinks/plugins/firebase_core_web/ios`) + - firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`) + - Flutter (from `Flutter`) + - flutter_email_sender (from `.symlinks/plugins/flutter_email_sender/ios`) + - flutter_flexible_toast (from `.symlinks/plugins/flutter_flexible_toast/ios`) + - flutter_inappwebview (from `.symlinks/plugins/flutter_inappwebview/ios`) + - flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`) + - flutter_plugin_android_lifecycle (from `.symlinks/plugins/flutter_plugin_android_lifecycle/ios`) + - flutter_tts (from `.symlinks/plugins/flutter_tts/ios`) + - geolocator (from `.symlinks/plugins/geolocator/ios`) + - google_maps_flutter (from `.symlinks/plugins/google_maps_flutter/ios`) + - hexcolor (from `.symlinks/plugins/hexcolor/ios`) + - image_cropper (from `.symlinks/plugins/image_cropper/ios`) + - image_picker (from `.symlinks/plugins/image_picker/ios`) + - just_audio (from `.symlinks/plugins/just_audio/ios`) + - local_auth (from `.symlinks/plugins/local_auth/ios`) + - manage_calendar_events (from `.symlinks/plugins/manage_calendar_events/ios`) + - map_launcher (from `.symlinks/plugins/map_launcher/ios`) + - maps_launcher (from `.symlinks/plugins/maps_launcher/ios`) + - native_device_orientation (from `.symlinks/plugins/native_device_orientation/ios`) + - native_progress_hud (from `.symlinks/plugins/native_progress_hud/ios`) + - NVActivityIndicatorView + - path_provider (from `.symlinks/plugins/path_provider/ios`) + - path_provider_linux (from `.symlinks/plugins/path_provider_linux/ios`) + - path_provider_macos (from `.symlinks/plugins/path_provider_macos/ios`) + - path_provider_windows (from `.symlinks/plugins/path_provider_windows/ios`) + - permission_handler (from `.symlinks/plugins/permission_handler/ios`) + - screen (from `.symlinks/plugins/screen/ios`) + - shared_preferences (from `.symlinks/plugins/shared_preferences/ios`) + - shared_preferences_linux (from `.symlinks/plugins/shared_preferences_linux/ios`) + - shared_preferences_macos (from `.symlinks/plugins/shared_preferences_macos/ios`) + - shared_preferences_web (from `.symlinks/plugins/shared_preferences_web/ios`) + - shared_preferences_windows (from `.symlinks/plugins/shared_preferences_windows/ios`) + - speech_to_text (from `.symlinks/plugins/speech_to_text/ios`) + - twilio_programmable_video (from `.symlinks/plugins/twilio_programmable_video/ios`) + - url_launcher (from `.symlinks/plugins/url_launcher/ios`) + - url_launcher_linux (from `.symlinks/plugins/url_launcher_linux/ios`) + - url_launcher_macos (from `.symlinks/plugins/url_launcher_macos/ios`) + - url_launcher_web (from `.symlinks/plugins/url_launcher_web/ios`) + - url_launcher_windows (from `.symlinks/plugins/url_launcher_windows/ios`) + - vibration (from `.symlinks/plugins/vibration/ios`) + - vibration_web (from `.symlinks/plugins/vibration_web/ios`) + - video_player (from `.symlinks/plugins/video_player/ios`) + - video_player_web (from `.symlinks/plugins/video_player_web/ios`) + - wakelock (from `.symlinks/plugins/wakelock/ios`) + - webview_flutter (from `.symlinks/plugins/webview_flutter/ios`) + - wifi (from `.symlinks/plugins/wifi/ios`) + +SPEC REPOS: + trunk: + - Firebase + - FirebaseCore + - FirebaseCoreDiagnostics + - FirebaseInstallations + - FirebaseInstanceID + - FirebaseMessaging + - GoogleDataTransport + - GoogleMaps + - GoogleUtilities + - MTBBarcodeScanner + - nanopb + - NVActivityIndicatorView + - PromisesObjC + - Protobuf + - Reachability + - TOCropViewController + - Try + - TwilioVideo + +EXTERNAL SOURCES: + android_intent: + :path: ".symlinks/plugins/android_intent/ios" + barcode_scan_fix: + :path: ".symlinks/plugins/barcode_scan_fix/ios" + connectivity: + :path: ".symlinks/plugins/connectivity/ios" + connectivity_for_web: + :path: ".symlinks/plugins/connectivity_for_web/ios" + connectivity_macos: + :path: ".symlinks/plugins/connectivity_macos/ios" + device_calendar: + :path: ".symlinks/plugins/device_calendar/ios" + device_info: + :path: ".symlinks/plugins/device_info/ios" + firebase_core: + :path: ".symlinks/plugins/firebase_core/ios" + firebase_core_web: + :path: ".symlinks/plugins/firebase_core_web/ios" + firebase_messaging: + :path: ".symlinks/plugins/firebase_messaging/ios" + Flutter: + :path: Flutter + flutter_email_sender: + :path: ".symlinks/plugins/flutter_email_sender/ios" + flutter_flexible_toast: + :path: ".symlinks/plugins/flutter_flexible_toast/ios" + flutter_inappwebview: + :path: ".symlinks/plugins/flutter_inappwebview/ios" + flutter_local_notifications: + :path: ".symlinks/plugins/flutter_local_notifications/ios" + flutter_plugin_android_lifecycle: + :path: ".symlinks/plugins/flutter_plugin_android_lifecycle/ios" + flutter_tts: + :path: ".symlinks/plugins/flutter_tts/ios" + geolocator: + :path: ".symlinks/plugins/geolocator/ios" + google_maps_flutter: + :path: ".symlinks/plugins/google_maps_flutter/ios" + hexcolor: + :path: ".symlinks/plugins/hexcolor/ios" + image_cropper: + :path: ".symlinks/plugins/image_cropper/ios" + image_picker: + :path: ".symlinks/plugins/image_picker/ios" + just_audio: + :path: ".symlinks/plugins/just_audio/ios" + local_auth: + :path: ".symlinks/plugins/local_auth/ios" + manage_calendar_events: + :path: ".symlinks/plugins/manage_calendar_events/ios" + map_launcher: + :path: ".symlinks/plugins/map_launcher/ios" + maps_launcher: + :path: ".symlinks/plugins/maps_launcher/ios" + native_device_orientation: + :path: ".symlinks/plugins/native_device_orientation/ios" + native_progress_hud: + :path: ".symlinks/plugins/native_progress_hud/ios" + path_provider: + :path: ".symlinks/plugins/path_provider/ios" + path_provider_linux: + :path: ".symlinks/plugins/path_provider_linux/ios" + path_provider_macos: + :path: ".symlinks/plugins/path_provider_macos/ios" + path_provider_windows: + :path: ".symlinks/plugins/path_provider_windows/ios" + permission_handler: + :path: ".symlinks/plugins/permission_handler/ios" + screen: + :path: ".symlinks/plugins/screen/ios" + shared_preferences: + :path: ".symlinks/plugins/shared_preferences/ios" + shared_preferences_linux: + :path: ".symlinks/plugins/shared_preferences_linux/ios" + shared_preferences_macos: + :path: ".symlinks/plugins/shared_preferences_macos/ios" + shared_preferences_web: + :path: ".symlinks/plugins/shared_preferences_web/ios" + shared_preferences_windows: + :path: ".symlinks/plugins/shared_preferences_windows/ios" + speech_to_text: + :path: ".symlinks/plugins/speech_to_text/ios" + twilio_programmable_video: + :path: ".symlinks/plugins/twilio_programmable_video/ios" + url_launcher: + :path: ".symlinks/plugins/url_launcher/ios" + url_launcher_linux: + :path: ".symlinks/plugins/url_launcher_linux/ios" + url_launcher_macos: + :path: ".symlinks/plugins/url_launcher_macos/ios" + url_launcher_web: + :path: ".symlinks/plugins/url_launcher_web/ios" + url_launcher_windows: + :path: ".symlinks/plugins/url_launcher_windows/ios" + vibration: + :path: ".symlinks/plugins/vibration/ios" + vibration_web: + :path: ".symlinks/plugins/vibration_web/ios" + video_player: + :path: ".symlinks/plugins/video_player/ios" + video_player_web: + :path: ".symlinks/plugins/video_player_web/ios" + wakelock: + :path: ".symlinks/plugins/wakelock/ios" + webview_flutter: + :path: ".symlinks/plugins/webview_flutter/ios" + wifi: + :path: ".symlinks/plugins/wifi/ios" + +SPEC CHECKSUMS: + android_intent: 367df2f1277a74e4a90e14a8ab3df3112d087052 + barcode_scan_fix: 80dd65de55f27eec6591dd077c8b85f2b79e31f1 + connectivity: c4130b2985d4ef6fd26f9702e886bd5260681467 + connectivity_for_web: 2b8584556930d4bd490d82b836bcf45067ce345b + connectivity_macos: e2e9731b6b22dda39eb1b128f6969d574460e191 + device_calendar: 23b28a5f1ab3bf77e34542fb1167e1b8b29a98f5 + device_info: d7d233b645a32c40dfdc212de5cf646ca482f175 + Firebase: 8db6f2d1b2c5e2984efba4949a145875a8f65fe5 + firebase_core: 5d6a02f3d85acd5f8321c2d6d62877626a670659 + firebase_core_web: d501d8b946b60c8af265428ce483b0fff5ad52d1 + firebase_messaging: 0aea2cd5885b65e19ede58ee3507f485c992cc75 + FirebaseCore: d889d9e12535b7f36ac8bfbf1713a0836a3012cd + FirebaseCoreDiagnostics: 770ac5958e1372ce67959ae4b4f31d8e127c3ac1 + FirebaseInstallations: 466c7b4d1f58fe16707693091da253726a731ed2 + FirebaseInstanceID: bd3ffc24367f901a43c063b36c640b345a4a5dd1 + FirebaseMessaging: 5eca4ef173de76253352511aafef774caa1cba2a + Flutter: 0e3d915762c693b495b44d77113d4970485de6ec + flutter_email_sender: f787522d0e82f50e5766c1213dbffff22fdcf009 + flutter_flexible_toast: 0547e740cae0c33bb7c51bcd931233f4584e1143 + flutter_inappwebview: 69dfbac46157b336ffbec19ca6dfd4638c7bf189 + flutter_local_notifications: 9e4738ce2471c5af910d961a6b7eadcf57c50186 + flutter_plugin_android_lifecycle: dc0b544e129eebb77a6bfb1239d4d1c673a60a35 + flutter_tts: 0f492aab6accf87059b72354fcb4ba934304771d + geolocator: 057a0c63a43e9c5296d8ad845a3ac8e6df23d899 + google_maps_flutter: c7f9c73576de1fbe152a227bfd6e6c4ae8088619 + GoogleDataTransport: f56af7caa4ed338dc8e138a5d7c5973e66440833 + GoogleMaps: 4b5346bddfe6911bb89155d43c903020170523ac + GoogleUtilities: 7f2f5a07f888cdb145101d6042bc4422f57e70b3 + hexcolor: fdfb9c4258ad96e949c2dbcdf790a62194b8aa89 + image_cropper: c8f9b4157933c7bb965a66d1c5e6c8fd408c6eb4 + image_picker: 9c3312491f862b28d21ecd8fdf0ee14e601b3f09 + just_audio: baa7252489dbcf47a4c7cc9ca663e9661c99aafa + local_auth: 25938960984c3a7f6e3253e3f8d962fdd16852bd + manage_calendar_events: 0338d505ea26cdfd20cd883279bc28afa11eca34 + map_launcher: e325db1261d029ff33e08e03baccffe09593ffea + maps_launcher: eae38ee13a9c3f210fa04e04bb4c073fa4c6ed92 + MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb + nanopb: 59317e09cf1f1a0af72f12af412d54edf52603fc + native_device_orientation: e24d00be281de72996640885d80e706142707660 + native_progress_hud: f95f5529742b36a3c7fdecfa88dc018319e39bf9 + NVActivityIndicatorView: 1f6c5687f1171810aa27a3296814dc2d7dec3667 + path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c + path_provider_linux: 4d630dc393e1f20364f3e3b4a2ff41d9674a84e4 + path_provider_macos: f760a3c5b04357c380e2fddb6f9db6f3015897e0 + path_provider_windows: a2b81600c677ac1959367280991971cb9a1edb3b + permission_handler: eac8e15b4a1a3fba55b761d19f3f4e6b005d15b6 + PromisesObjC: 8c196f5a328c2cba3e74624585467a557dcb482f + Protobuf: 3dac39b34a08151c6d949560efe3f86134a3f748 + Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96 + screen: abd91ca7bf3426e1cc3646d27e9b2358d6bf07b0 + shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d + shared_preferences_linux: afefbfe8d921e207f01ede8b60373d9e3b566b78 + shared_preferences_macos: f3f29b71ccbb56bf40c9dd6396c9acf15e214087 + shared_preferences_web: 141cce0c3ed1a1c5bf2a0e44f52d31eeb66e5ea9 + shared_preferences_windows: 36b76d6f54e76ead957e60b49e2f124b4cd3e6ae + speech_to_text: b43a7d99aef037bd758ed8e45d79bbac035d2dfe + TOCropViewController: da59f531f8ac8a94ef6d6c0fc34009350f9e8bfe + Try: 5ef669ae832617b3cee58cb2c6f99fb767a4ff96 + twilio_programmable_video: 6a41593640f3d86af60b22541fd457b22deaae7f + TwilioVideo: c13a51ceca375e91620eb7578d2573c90cf53b46 + url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef + url_launcher_linux: ac237cb7a8058736e4aae38bdbcc748a4b394cc0 + url_launcher_macos: fd7894421cd39320dce5f292fc99ea9270b2a313 + url_launcher_web: e5527357f037c87560776e36436bf2b0288b965c + url_launcher_windows: 683d7c283894db8d1914d3ab2223b20cc1ad95d5 + vibration: b5a33e764c3f609a975b9dca73dce20fdde627dc + vibration_web: 0ba303d92469ba34d71c612a228b315908d7fcd9 + video_player: 9cc823b1d9da7e8427ee591e8438bfbcde500e6e + video_player_web: da8cadb8274ed4f8dbee8d7171b420dedd437ce7 + wakelock: 0d4a70faf8950410735e3f61fb15d517c8a6efc4 + webview_flutter: d2b4d6c66968ad042ad94cbb791f5b72b4678a96 + wifi: d7d77c94109e36c4175d845f0a5964eadba71060 + +PODFILE CHECKSUM: 5a17be3f8af73a757fa4439c77cf6ab2db29a6e7 + +COCOAPODS: 1.10.0 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 00000000..0f0f942c --- /dev/null +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,697 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 51; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 813F9CBA7DD5ED63B28B8BB6 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 767C165F7ABF3BF1F829B9BF /* Pods_Runner.framework */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + E91B5396256AAA6500E96549 /* GlobalHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = E91B538D256AAA6500E96549 /* GlobalHelper.swift */; }; + E91B5397256AAA6500E96549 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E91B538E256AAA6500E96549 /* Extensions.swift */; }; + E91B5398256AAA6500E96549 /* API.swift in Sources */ = {isa = PBXBuildFile; fileRef = E91B538F256AAA6500E96549 /* API.swift */; }; + E91B539A256AAA6500E96549 /* MainFlutterVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = E91B5392256AAA6500E96549 /* MainFlutterVC.swift */; }; + E91B539B256AAA6500E96549 /* HMG_Internet.swift in Sources */ = {isa = PBXBuildFile; fileRef = E91B5394256AAA6500E96549 /* HMG_Internet.swift */; }; + E91B539C256AAA6500E96549 /* HMG_GUEST_bkp.swift in Sources */ = {isa = PBXBuildFile; fileRef = E91B5395256AAA6500E96549 /* HMG_GUEST_bkp.swift */; }; + E91B539F256AAC1400E96549 /* GuestPOC_Certificate.p12 in Resources */ = {isa = PBXBuildFile; fileRef = E91B539D256AAC1400E96549 /* GuestPOC_Certificate.p12 */; }; + E91B53A0256AAC1400E96549 /* GuestPOC_Certificate.cer in Resources */ = {isa = PBXBuildFile; fileRef = E91B539E256AAC1400E96549 /* GuestPOC_Certificate.cer */; }; + E91B53A3256AAD8200E96549 /* Main_Custom.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E91B53A1256AAD8200E96549 /* Main_Custom.storyboard */; }; + E923EFD225863FDF00E3E751 /* GeoZoneModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E923EFD125863FDF00E3E751 /* GeoZoneModel.swift */; }; + E923EFD4258645C100E3E751 /* HMG_Geofence.swift in Sources */ = {isa = PBXBuildFile; fileRef = E923EFD3258645C100E3E751 /* HMG_Geofence.swift */; }; + E923EFD62587443800E3E751 /* HMGPlatformBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = E923EFD52587443800E3E751 /* HMGPlatformBridge.swift */; }; + E923EFD82588D17700E3E751 /* gpx.gpx in Resources */ = {isa = PBXBuildFile; fileRef = E923EFD72588D17700E3E751 /* gpx.gpx */; }; + E9620805255C2ED100D3A35D /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E9620804255C2ED100D3A35D /* NetworkExtension.framework */; }; + E9C8C136256BACDA00EFFB62 /* HMG_Guest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9C8C135256BACDA00EFFB62 /* HMG_Guest.swift */; }; + E9E27168256E3A4000F49B69 /* LocalizedFromFlutter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9E27167256E3A4000F49B69 /* LocalizedFromFlutter.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 308FEC658188F7D588BE7580 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 767C165F7ABF3BF1F829B9BF /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 969F0CEC868FD7C196987A3E /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DCFFD369041FFFFA94CF7B26 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + E91B538D256AAA6500E96549 /* GlobalHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GlobalHelper.swift; sourceTree = ""; }; + E91B538E256AAA6500E96549 /* Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = ""; }; + E91B538F256AAA6500E96549 /* API.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = API.swift; sourceTree = ""; }; + E91B5392256AAA6500E96549 /* MainFlutterVC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainFlutterVC.swift; sourceTree = ""; }; + E91B5394256AAA6500E96549 /* HMG_Internet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HMG_Internet.swift; sourceTree = ""; }; + E91B5395256AAA6500E96549 /* HMG_GUEST_bkp.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HMG_GUEST_bkp.swift; sourceTree = ""; }; + E91B539D256AAC1400E96549 /* GuestPOC_Certificate.p12 */ = {isa = PBXFileReference; lastKnownFileType = file; path = GuestPOC_Certificate.p12; sourceTree = ""; }; + E91B539E256AAC1400E96549 /* GuestPOC_Certificate.cer */ = {isa = PBXFileReference; lastKnownFileType = file; path = GuestPOC_Certificate.cer; sourceTree = ""; }; + E91B53A2256AAD8200E96549 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main_Custom.storyboard; sourceTree = ""; }; + E923EFD125863FDF00E3E751 /* GeoZoneModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeoZoneModel.swift; sourceTree = ""; }; + E923EFD3258645C100E3E751 /* HMG_Geofence.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HMG_Geofence.swift; sourceTree = ""; }; + E923EFD52587443800E3E751 /* HMGPlatformBridge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HMGPlatformBridge.swift; sourceTree = ""; }; + E923EFD72588D17700E3E751 /* gpx.gpx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = gpx.gpx; sourceTree = ""; }; + E9620803255C2ED100D3A35D /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; + E9620804255C2ED100D3A35D /* NetworkExtension.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NetworkExtension.framework; path = System/Library/Frameworks/NetworkExtension.framework; sourceTree = SDKROOT; }; + E9C8C135256BACDA00EFFB62 /* HMG_Guest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HMG_Guest.swift; sourceTree = ""; }; + E9E27167256E3A4000F49B69 /* LocalizedFromFlutter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalizedFromFlutter.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 813F9CBA7DD5ED63B28B8BB6 /* Pods_Runner.framework in Frameworks */, + E9620805255C2ED100D3A35D /* NetworkExtension.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 555EAAA626EFB641859EF0BE /* Frameworks */ = { + isa = PBXGroup; + children = ( + E9620804255C2ED100D3A35D /* NetworkExtension.framework */, + 767C165F7ABF3BF1F829B9BF /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 605039E5DDF72C245F9765FE /* Pods */ = { + isa = PBXGroup; + children = ( + DCFFD369041FFFFA94CF7B26 /* Pods-Runner.debug.xcconfig */, + 969F0CEC868FD7C196987A3E /* Pods-Runner.release.xcconfig */, + 308FEC658188F7D588BE7580 /* Pods-Runner.profile.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + E923EFD72588D17700E3E751 /* gpx.gpx */, + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 605039E5DDF72C245F9765FE /* Pods */, + 555EAAA626EFB641859EF0BE /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + E91B539E256AAC1400E96549 /* GuestPOC_Certificate.cer */, + E91B539D256AAC1400E96549 /* GuestPOC_Certificate.p12 */, + E91B5390256AAA6500E96549 /* Controllers */, + E91B538C256AAA6500E96549 /* Helper */, + E91B5393256AAA6500E96549 /* WifiConnect */, + E9620803255C2ED100D3A35D /* Runner.entitlements */, + E91B53A1256AAD8200E96549 /* Main_Custom.storyboard */, + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; + E91B538C256AAA6500E96549 /* Helper */ = { + isa = PBXGroup; + children = ( + E91B538D256AAA6500E96549 /* GlobalHelper.swift */, + E91B538E256AAA6500E96549 /* Extensions.swift */, + E91B538F256AAA6500E96549 /* API.swift */, + E9E27167256E3A4000F49B69 /* LocalizedFromFlutter.swift */, + E923EFD125863FDF00E3E751 /* GeoZoneModel.swift */, + E923EFD3258645C100E3E751 /* HMG_Geofence.swift */, + E923EFD52587443800E3E751 /* HMGPlatformBridge.swift */, + ); + path = Helper; + sourceTree = ""; + }; + E91B5390256AAA6500E96549 /* Controllers */ = { + isa = PBXGroup; + children = ( + E91B5392256AAA6500E96549 /* MainFlutterVC.swift */, + ); + path = Controllers; + sourceTree = ""; + }; + E91B5393256AAA6500E96549 /* WifiConnect */ = { + isa = PBXGroup; + children = ( + E9C8C135256BACDA00EFFB62 /* HMG_Guest.swift */, + E91B5394256AAA6500E96549 /* HMG_Internet.swift */, + E91B5395256AAA6500E96549 /* HMG_GUEST_bkp.swift */, + ); + path = WifiConnect; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 299B8FE131E5BAE7FA7E2FC9 /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 125A739F71A29FBAE7B4D5AC /* [CP] Embed Pods Frameworks */, + CBB18A5CEEEB971DCFC36E00 /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1020; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E91B53A0256AAC1400E96549 /* GuestPOC_Certificate.cer in Resources */, + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + E923EFD82588D17700E3E751 /* gpx.gpx in Resources */, + E91B539F256AAC1400E96549 /* GuestPOC_Certificate.p12 in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + E91B53A3256AAD8200E96549 /* Main_Custom.storyboard in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 125A739F71A29FBAE7B4D5AC /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 299B8FE131E5BAE7FA7E2FC9 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; + CBB18A5CEEEB971DCFC36E00 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E923EFD225863FDF00E3E751 /* GeoZoneModel.swift in Sources */, + E91B539A256AAA6500E96549 /* MainFlutterVC.swift in Sources */, + E91B539C256AAA6500E96549 /* HMG_GUEST_bkp.swift in Sources */, + E91B5396256AAA6500E96549 /* GlobalHelper.swift in Sources */, + E923EFD4258645C100E3E751 /* HMG_Geofence.swift in Sources */, + E923EFD62587443800E3E751 /* HMGPlatformBridge.swift in Sources */, + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + E9E27168256E3A4000F49B69 /* LocalizedFromFlutter.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + E9C8C136256BACDA00EFFB62 /* HMG_Guest.swift in Sources */, + E91B539B256AAA6500E96549 /* HMG_Internet.swift in Sources */, + E91B5397256AAA6500E96549 /* Extensions.swift in Sources */, + E91B5398256AAA6500E96549 /* API.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; + E91B53A1256AAD8200E96549 /* Main_Custom.storyboard */ = { + isa = PBXVariantGroup; + children = ( + E91B53A2256AAD8200E96549 /* Base */, + ); + name = Main_Custom.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = ""; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.HMG.HMG-Smartphone"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = ""; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.HMG.HMG-Smartphone"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = ""; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.HMG.HMG-Smartphone"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 31d8d1f5..fb2dffc4 100644 --- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ + + + + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings index 58d01805..f9b0d7c5 100644 --- a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -2,8 +2,6 @@ - DisableBuildSystemDeprecationWarning - PreviewsEnabled diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift index 70693e4a..e686619c 100644 --- a/ios/Runner/AppDelegate.swift +++ b/ios/Runner/AppDelegate.swift @@ -1,13 +1,47 @@ import UIKit import Flutter +import GoogleMaps + @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { - override func application( - _ application: UIApplication, - didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? - ) -> Bool { - GeneratedPluginRegistrant.register(with: self) - return super.application(application, didFinishLaunchingWithOptions: launchOptions) + let locationManager = CLLocationManager() + + override func application( _ application: UIApplication,didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { +// initLocationManager() + + GMSServices.provideAPIKey("AIzaSyCiiJiHkocPbcziHt9O8rGWavDrxHRQys8") + GeneratedPluginRegistrant.register(with: self) + + if let mainViewController = window.rootViewController as? MainFlutterVC{ + HMGPlatformBridge.initialize(flutterViewController: mainViewController) + } + + if let _ = launchOptions?[.location] { + HMG_Geofence.initGeofencing() + } + + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} + +extension AppDelegate: CLLocationManagerDelegate { + + func initLocationManager(){ + locationManager.allowsBackgroundLocationUpdates = true + locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters + locationManager.activityType = .other + locationManager.delegate = self + locationManager.requestAlwaysAuthorization() + } + + func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) { + if region is CLCircularRegion { + } + } + + func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) { + if region is CLCircularRegion { + } } } diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json index 65b74d7e..d36b1fab 100644 --- a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1 +1,122 @@ -{"images":[{"size":"60x60","expected-size":"180","filename":"180.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"40x40","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"60x60","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"57x57","expected-size":"57","filename":"57.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"87","filename":"87.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"57x57","expected-size":"114","filename":"114.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"60","filename":"60.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"1024x1024","filename":"1024.png","expected-size":"1024","idiom":"ios-marketing","folder":"Assets.xcassets/AppIcon.appiconset/","scale":"1x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"72x72","expected-size":"72","filename":"72.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"76x76","expected-size":"152","filename":"152.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"50x50","expected-size":"100","filename":"100.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"76x76","expected-size":"76","filename":"76.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"50x50","expected-size":"50","filename":"50.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"72x72","expected-size":"144","filename":"144.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"40x40","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"83.5x83.5","expected-size":"167","filename":"167.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"20x20","expected-size":"20","filename":"20.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"}]} \ No newline at end of file +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..dc9ada4725e9b0ddb1deab583e5b5102493aa332 GIT binary patch literal 10932 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 literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..f091b6b0bca859a3f474b03065bef75ba58a9e4c GIT binary patch literal 1588 zcmV-42Fv-0P)C1SqPt}wig>|5Crh^=oyX$BK<}M8eLU3e2hGT;=G|!_SP)7zNI6fqUMB=)y zRAZ>eDe#*r`yDAVgB_R*LB*MAc)8(b{g{9McCXW!lq7r(btRoB9!8B-#AI6JMb~YFBEvdsV)`mEQO^&#eRKx@b&x- z5lZm*!WfD8oCLzfHGz#u7sT0^VLMI1MqGxF^v+`4YYnVYgk*=kU?HsSz{v({E3lb9 z>+xILjBN)t6`=g~IBOelGQ(O990@BfXf(DRI5I$qN$0Gkz-FSc$3a+2fX$AedL4u{ z4V+5Ong(9LiGcIKW?_352sR;LtDPmPJXI{YtT=O8=76o9;*n%_m|xo!i>7$IrZ-{l z-x3`7M}qzHsPV@$v#>H-TpjDh2UE$9g6sysUREDy_R(a)>=eHw-WAyfIN z*qb!_hW>G)Tu8nSw9yn#3wFMiLcfc4pY0ek1}8(NqkBR@t4{~oC>ryc-h_ByH(Cg5 z>ao-}771+xE3um9lWAY1FeQFxowa1(!J(;Jg*wrg!=6FdRX+t_<%z&d&?|Bn){>zm zZQj(aA_HeBY&OC^jj*)N`8fa^ePOU72VpInJoI1?`ty#lvlNzs(&MZX+R%2xS~5Kh zX*|AU4QE#~SgPzOXe9>tRj>hjU@c1k5Y_mW*Jp3fI;)1&g3j|zDgC+}2Q_v%YfDax z!?umcN^n}KYQ|a$Lr+51Nf9dkkYFSjZZjkma$0KOj+;aQ&721~t7QUKx61J3(P4P1 zstI~7-wOACnWP4=8oGOwz%vNDqD8w&Q`qcNGGrbbf&0s9L0De{4{mRS?o0MU+nR_! zrvshUau0G^DeMhM_v{5BuLjb#Hh@r23lDAk8oF(C+P0rsBpv85EP>4CVMx#04MOfG z;P%vktHcXwTj~+IE(~px)3*MY77e}p#|c>TD?sMatC0Tu4iKKJ0(X8jxQY*gYtxsC z(zYC$g|@+I+kY;dg_dE>scBf&bP1Nc@Hz<3R)V`=AGkc;8CXqdi=B4l2k|g;2%#m& z*jfX^%b!A8#bI!j9-0Fi0bOXl(-c^AB9|nQaE`*)Hw+o&jS9@7&Gov#HbD~#d{twV zXd^Tr^mWLfFh$@Dr$e;PBEz4(-2q1FF0}c;~B5sA}+Q>TOoP+t>wf)V9Iy=5ruQa;z)y zI9C9*oUga6=hxw6QasLPnee@3^Rr*M{CdaL5=R41nLs(AHk_=Y+A9$2&H(B7!_pURs&8aNw7?`&Z&xY_Ye z)~D5Bog^td-^QbUtkTirdyK^mTHAOuptDflut!#^lnKqU md>ggs(5nOWAqO?umG&QVYK#ibz}*4>0000U6E9hRK9^#O7(mu>ETqrXGsduA8$)?`v2seloOCza43C{NQ$$gAOH**MCn0Q?+L7dl7qnbRdqZ8LSVp1ItDxhxD?t@5_yHg6A8yI zC*%Wgg22K|8E#!~cTNYR~@Y9KepMPrrB8cABapAFa=`H+UGhkXUZV1GnwR1*lPyZ;*K(i~2gp|@bzp8}og7e*#% zEnr|^CWdVV!-4*Y_7rFvlww2Ze+>j*!Z!pQ?2l->4q#nqRu9`ELo6RMS5=br47g_X zRw}P9a7RRYQ%2Vsd0Me{_(EggTnuN6j=-?uFS6j^u69elMypu?t>op*wBx<=Wx8?( ztpe^(fwM6jJX7M-l*k3kEpWOl_Vk3@(_w4oc}4YF4|Rt=2V^XU?#Yz`8(e?aZ@#li0n*=g^qOcVpd-Wbok=@b#Yw zqn8u9a)z>l(1kEaPYZ6hwubN6i<8QHgsu0oE) ziJ(p;Wxm>sf!K+cw>R-(^Y2_bahB+&KI9y^);#0qt}t-$C|Bo71lHi{_+lg#f%RFy z0um=e3$K3i6K{U_4K!EX?F&rExl^W|G8Z8;`5z-k}OGNZ0#WVb$WCpQu-_YsiqKP?BB# vzVHS-CTUF4Ozn5G+mq_~Qqto~ahA+K`|lyv3(-e}00000NkvXXu0mjfd`9t{ literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d0ef06e7edb86cdfe0d15b4b0d98334a86163658 GIT binary patch literal 1716 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 literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c8f9ed8f5cee1c98386d13b17e89f719e83555b2 GIT binary patch literal 1895 zcmV-t2blPYP)FQtfgmafE#=YDCq`qUBt#QpG%*H6QHY765~R=q zZ6iudfM}q!Pz#~9JgOi8QJ|DSu?1-*(kSi1K4#~5?#|rh?sS)(-JQqX*}ciXJ56_H zdw=^s_srbAdqxlvGyrgGet#6T7_|j;95sL%MtM;q86vOxKM$f#puR)Bjv9Zvz9-di zXOTSsZkM83)E9PYBXC<$6(|>lNLVBb&&6y{NByFCp%6+^ALR@NCTse_wqvNmSWI-m z!$%KlHFH2omF!>#%1l3LTZg(s7eof$7*xB)ZQ0h?ejh?Ta9fDv59+u#MokW+1t8Zb zgHv%K(u9G^Lv`lh#f3<6!JVTL3(dCpxHbnbA;kKqQyd1~^Xe0VIaYBSWm6nsr;dFj z4;G-RyL?cYgsN1{L4ZFFNa;8)Rv0fM0C(~Tkit94 zz#~A)59?QjD&pAPSEQ)p8gP|DS{ng)j=2ux)_EzzJ773GmQ_Cic%3JJhC0t2cx>|v zJcVusIB!%F90{+}8hG3QU4KNeKmK%T>mN57NnCZ^56=0?&3@!j>a>B43pi{!u z7JyDj7`6d)qVp^R=%j>UIY6f+3`+qzIc!Y_=+uN^3BYV|o+$vGo-j-Wm<10%A=(Yk^beI{t%ld@yhKjq0iNjqN4XMGgQtbKubPM$JWBz}YA65k%dm*awtC^+f;a-x4+ddbH^7iDWGg&N0n#MW{kA|=8iMUiFYvMoDY@sPC#t$55gn6ykUTPAr`a@!(;np824>2xJthS z*ZdmT`g5-`BuJs`0LVhz+D9NNa3<=6m;cQLaF?tCv8)zcRSh66*Z|vXhG@$I%U~2l z?`Q zykI#*+rQ=z6Jm=Bui-SfpDYLA=|vzGE(dYm=OC8XM&MDo7ux4UF1~0J1+i%aCUpRe zt3L_uNyQ*cE(38Uy03H%I*)*Bh=Lb^Xj3?I^Hnbeq72(EOK^Y93CNp*uAA{5Lc=ky zx=~RKa4{iTm{_>_vSCm?$Ej=i6@=m%@VvAITnigVg{&@!7CDgs908761meDK5azA} z4?=NOH|PdvabgJ&fW2{Mo$Q0CcD8Qc84%{JPYt5EiG{MdLIAeX%T=D7NIP4%Hw}p9 zg)==!2Lbp#j{u_}hMiao9=!VSyx0gHbeCS`;q&vzeq|fs`y&^X-lso(Ls@-706qmA z7u*T5PMo_w3{se1t2`zWeO^hOvTsohG_;>J0wVqVe+n)AbQCx)yh9;w+J6?NF5Lmo zecS@ieAKL8%bVd@+-KT{yI|S}O>pYckUFs;ry9Ow$CD@ztz5K-*D$^{i(_1llhSh^ zEkL$}tsQt5>QA^;QgjgIfBDmcOgi5YDyu?t6vSnbp=1+@6D& z5MJ}B8q;bRlVoxasyhcUF1+)o`&3r0colr}QJ3hcSdLu;9;td>kf@Tcn<@9sIx&=m z;AD;SCh95=&p;$r{Xz3iWCO^MX83AGJ(yH&eTXgv|0=34#-&WAmw{)U7OU9!Wz^!7 zZ%jZFi@JR;>Mhi7S>V7wQ176|FdW2m?&`qa(ScO^CFPR80HucLHOTy%5s*HR0^8)i h0WYBP*#0Ks^FNSabJA*5${_#%002ovPDHLkV1oKhTl@e3 literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..a6d6b8609df07bf62e5100a53a01510388bd2b22 GIT binary patch literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a6d6b8609df07bf62e5100a53a01510388bd2b22 GIT binary patch literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..75b2d164a5a98e212cca15ea7bf2ab5de5108680 GIT binary patch literal 3831 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 literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..c4df70d39da7941ef3f6dcb7f06a192d8dcb308d GIT binary patch literal 1888 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 iW8Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 00000000..89c2725b --- /dev/null +++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/ios/Runner/Base.lproj/Main.storyboard b/ios/Runner/Base.lproj/Main.storyboard index f3c28516..8ae1ba59 100644 --- a/ios/Runner/Base.lproj/Main.storyboard +++ b/ios/Runner/Base.lproj/Main.storyboard @@ -1,26 +1,29 @@ - - + + + - + + - + - + - + - + + diff --git a/ios/Runner/Base.lproj/Main_Custom.storyboard b/ios/Runner/Base.lproj/Main_Custom.storyboard new file mode 100644 index 00000000..de2d580c --- /dev/null +++ b/ios/Runner/Base.lproj/Main_Custom.storyboard @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Controllers/MainFlutterVC.swift b/ios/Runner/Controllers/MainFlutterVC.swift new file mode 100644 index 00000000..4f91d052 --- /dev/null +++ b/ios/Runner/Controllers/MainFlutterVC.swift @@ -0,0 +1,118 @@ +// +// MainFlutterVC.swift +// Runner +// +// Created by ZiKambrani on 25/03/1442 AH. +// + +import UIKit +import Flutter +import NetworkExtension +import SystemConfiguration.CaptiveNetwork + +class MainFlutterVC: FlutterViewController { + + override func viewDidLoad() { + super.viewDidLoad() + +// flutterMethodChannel?.setMethodCallHandler { (methodCall, result) in +// +// if methodCall.method == "connectHMGInternetWifi"{ +// self.connectHMGInternetWifi(methodCall:methodCall, result: result) +// +// }else if methodCall.method == "connectHMGGuestWifi"{ +// self.connectHMGGuestWifi(methodCall:methodCall, result: result) +// +// }else if methodCall.method == "isHMGNetworkAvailable"{ +// self.isHMGNetworkAvailable(methodCall:methodCall, result: result) +// +// }else if methodCall.method == "registerHmgGeofences"{ +// self.registerHmgGeofences(result: result) +// } +// +// print("") +// } +// +// FlutterText.with(key: "errorConnectingHmgNetwork") { (localized) in +// print(localized) +// } + + } + + + // Connect HMG Wifi and Internet + func connectHMGInternetWifi(methodCall:FlutterMethodCall ,result: @escaping FlutterResult){ + + guard let pateintId = (methodCall.arguments as? [Any])?.first as? String + else { return assert(true, "Missing or invalid arguments (Must have one argument 'String at 0'") } + + + HMG_Internet.shared.connect(patientId: pateintId) { (status, message) in + result(status ? 1 : 0) + if status{ + self.showMessage(title:"Congratulations", message:message) + }else{ + self.showMessage(title:"Ooops,", message:message) + } + } + } + + // Connect HMG-Guest for App Access + func connectHMGGuestWifi(methodCall:FlutterMethodCall ,result: @escaping FlutterResult){ + HMG_GUEST.shared.connect() { (status, message) in + result(status ? 1 : 0) + if status{ + self.showMessage(title:"Congratulations", message:message) + }else{ + self.showMessage(title:"Ooops,", message:message) + } + } + } + + func isHMGNetworkAvailable(methodCall:FlutterMethodCall ,result: @escaping FlutterResult) -> Bool{ + guard let ssid = methodCall.arguments as? String else { + assert(true, "Missing or invalid arguments (Must have one argument 'String at 0'") + return false + } + + let queue = DispatchQueue.init(label: "com.hmg.wifilist") + NEHotspotHelper.register(options: nil, queue: queue) { (command) in + print(command) + + if(command.commandType == NEHotspotHelperCommandType.filterScanList) { + if let networkList = command.networkList{ + for network in networkList{ + print(network.ssid) + } + } + } + } + return false + + } + + + // Message Dailog + func showMessage(title:String, message:String){ + DispatchQueue.main.async { + let alert = UIAlertController(title: title, message: message, preferredStyle: .alert ) + alert.addAction(UIAlertAction(title: "OK", style: .destructive, handler: nil)) + self.present(alert, animated: true) { + + } + } + } + + // Register Geofence + func registerHmgGeofences(result: @escaping FlutterResult){ + flutterMethodChannel?.invokeMethod("getGeofencePreferenceKey", arguments: nil){ geoFencesJsonString in + if let jsonString = geoFencesJsonString as? String{ + let allZones = GeoZoneModel.list(from: jsonString) + HMG_Geofence().register(geoZones: allZones) + + }else{ + } + } + } + +} diff --git a/ios/Runner/GoogleService-Info.plist b/ios/Runner/GoogleService-Info.plist new file mode 100644 index 00000000..0c093a2a --- /dev/null +++ b/ios/Runner/GoogleService-Info.plist @@ -0,0 +1,36 @@ + + + + + CLIENT_ID + 864393916058-ekeb4s8tgfo58dutv0l54399t7ivr06r.apps.googleusercontent.com + REVERSED_CLIENT_ID + com.googleusercontent.apps.864393916058-ekeb4s8tgfo58dutv0l54399t7ivr06r + API_KEY + AIzaSyA_6ayGCk4fly7o7eTVBrj9kuHBYHMAOfs + GCM_SENDER_ID + 864393916058 + PLIST_VERSION + 1 + BUNDLE_ID + com.cloud.diplomaticquarterapp + PROJECT_ID + diplomaticquarter-d2385 + STORAGE_BUCKET + diplomaticquarter-d2385.appspot.com + IS_ADS_ENABLED + + IS_ANALYTICS_ENABLED + + IS_APPINVITE_ENABLED + + IS_GCM_ENABLED + + IS_SIGNIN_ENABLED + + GOOGLE_APP_ID + 1:864393916058:ios:13f787bbfe6051f8b97923 + DATABASE_URL + https://diplomaticquarter-d2385.firebaseio.com + + \ No newline at end of file diff --git a/ios/Runner/GuestPOC_Certificate.cer b/ios/Runner/GuestPOC_Certificate.cer new file mode 100644 index 0000000000000000000000000000000000000000..f3804f6e57a63cf93cf7e336c7aa48b403d4e955 GIT binary patch literal 1596 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 NEi~`CJkGx>`CqoWTH^o! literal 0 HcmV?d00001 diff --git a/ios/Runner/Helper/API.swift b/ios/Runner/Helper/API.swift new file mode 100644 index 00000000..763147c8 --- /dev/null +++ b/ios/Runner/Helper/API.swift @@ -0,0 +1,17 @@ +// +// API.swift +// Runner +// +// Created by ZiKambrani on 04/04/1442 AH. +// + +import UIKit + +fileprivate let DOMAIN = "https://uat.hmgwebservices.com" +fileprivate let SERVICE = "Services/Patients.svc/REST" +fileprivate let BASE_URL = "\(DOMAIN)/\(SERVICE)" + +struct API { + static let WIFI_CREDENTIALS = "\(BASE_URL)/Hmg_SMS_Get_By_ProjectID_And_PatientID" + +} diff --git a/ios/Runner/Helper/Extensions.swift b/ios/Runner/Helper/Extensions.swift new file mode 100644 index 00000000..a8793617 --- /dev/null +++ b/ios/Runner/Helper/Extensions.swift @@ -0,0 +1,132 @@ +// +// Extensions.swift +// Runner +// +// Created by ZiKambrani on 04/04/1442 AH. +// + +import UIKit + + +extension String{ + func toUrl() -> URL?{ + return URL(string: self) + } + + func removeSpace() -> String?{ + return self.replacingOccurrences(of: " ", with: "") + } +} + +extension Bundle { + + func certificate(named name: String) -> SecCertificate { + let cerURL = self.url(forResource: name, withExtension: "cer")! + let cerData = try! Data(contentsOf: cerURL) + let cer = SecCertificateCreateWithData(nil, cerData as CFData)! + return cer + } + + func identity(named name: String, password: String) -> SecIdentity { + let p12URL = self.url(forResource: name, withExtension: "p12")! + let p12Data = try! Data(contentsOf: p12URL) + + var importedCF: CFArray? = nil + let options = [kSecImportExportPassphrase as String: password] + let err = SecPKCS12Import(p12Data as CFData, options as CFDictionary, &importedCF) + precondition(err == errSecSuccess) + let imported = importedCF! as NSArray as! [[String:AnyObject]] + precondition(imported.count == 1) + + return (imported[0][kSecImportItemIdentity as String]!) as! SecIdentity + } + + +} + +extension SecCertificate{ + func trust() -> Bool?{ + var optionalTrust: SecTrust? + let policy = SecPolicyCreateBasicX509() + + let status = SecTrustCreateWithCertificates([self] as AnyObject, + policy, + &optionalTrust) + guard status == errSecSuccess else { return false} + let trust = optionalTrust! + + let stat = optionalTrust?.evaluateAllowing(rootCertificates: [self]) + return stat + } + + func secTrustObject() -> SecTrust?{ + var optionalTrust: SecTrust? + let policy = SecPolicyCreateBasicX509() + + let status = SecTrustCreateWithCertificates([self] as AnyObject, + policy, + &optionalTrust) + return optionalTrust + } +} + + +extension SecTrust { + + func evaluate() -> Bool { + var trustResult: SecTrustResultType = .invalid + let err = SecTrustEvaluate(self, &trustResult) + guard err == errSecSuccess else { return false } + return [.proceed, .unspecified].contains(trustResult) + } + + func evaluateAllowing(rootCertificates: [SecCertificate]) -> Bool { + + // Apply our custom root to the trust object. + + var err = SecTrustSetAnchorCertificates(self, rootCertificates as CFArray) + guard err == errSecSuccess else { return false } + + // Re-enable the system's built-in root certificates. + + err = SecTrustSetAnchorCertificatesOnly(self, false) + guard err == errSecSuccess else { return false } + + // Run a trust evaluation and only allow the connection if it succeeds. + + return self.evaluate() + } +} + + +extension UIView{ + func show(){ + self.alpha = 0.0 + self.isHidden = false + UIView.animate(withDuration: 0.25, animations: { + self.alpha = 1 + }) { (complete) in + + } + } + + func hide(){ + UIView.animate(withDuration: 0.25, animations: { + self.alpha = 0.0 + }) { (complete) in + self.isHidden = true + } + } +} + + +extension UIViewController{ + func showAlert(withTitle: String, message: String){ + let alert = UIAlertController(title: withTitle, message: message, preferredStyle: .alert) + alert.addAction(UIAlertAction(title: "OK", style: .destructive, handler: nil)) + present(alert, animated: true) { + + } + } +} + diff --git a/ios/Runner/Helper/GeoZoneModel.swift b/ios/Runner/Helper/GeoZoneModel.swift new file mode 100644 index 00000000..e703b64c --- /dev/null +++ b/ios/Runner/Helper/GeoZoneModel.swift @@ -0,0 +1,67 @@ +// +// GeoZoneModel.swift +// Runner +// +// Created by ZiKambrani on 13/12/2020. +// + +import UIKit +import CoreLocation + +class GeoZoneModel{ + var geofenceId:Int = -1 + var description:String = "" + var descriptionN:String? + var latitude:String? + var longitude:String? + var radius:Int? + var type:Int? + var projectID:Int? + var imageURL:String? + var isCity:String? + + func identifier() -> String{ + return "\(geofenceId)_hmg" + } + + func message() -> String{ + return description + } + + func toRegion(locationManager:CLLocationManager) -> CLCircularRegion?{ + if let rad = radius, let lat = latitude?.removeSpace(), let long = longitude?.removeSpace(), + let radius_d = Double("\(rad)"), let lat_d = Double(lat), let long_d = Double(long){ + + let coordinate = CLLocationCoordinate2D(latitude: lat_d, longitude: long_d) + let validatedRadius = min(radius_d, locationManager.maximumRegionMonitoringDistance) + + let region = CLCircularRegion(center: coordinate, radius: validatedRadius, identifier: identifier()) + region.notifyOnExit = true + region.notifyOnEntry = true + return region + } + return nil + } + + class func from(json:[String:Any]) -> GeoZoneModel{ + let model = GeoZoneModel() + model.geofenceId = json["GEOF_ID"] as? Int ?? 0 + model.radius = json["Radius"] as? Int + model.projectID = json["ProjectID"] as? Int + model.type = json["Type"] as? Int + model.description = json["Description"] as? String ?? "" + model.descriptionN = json["DescriptionN"] as? String + model.latitude = json["Latitude"] as? String + model.longitude = json["Longitude"] as? String + model.imageURL = json["ImageURL"] as? String + model.isCity = json["IsCity"] as? String + + return model + } + + class func list(from jsonString:String) -> [GeoZoneModel]{ + let value = dictionaryArray(from: jsonString) + let geoZones = value.map { GeoZoneModel.from(json: $0) } + return geoZones + } +} diff --git a/ios/Runner/Helper/GlobalHelper.swift b/ios/Runner/Helper/GlobalHelper.swift new file mode 100644 index 00000000..c5eb7295 --- /dev/null +++ b/ios/Runner/Helper/GlobalHelper.swift @@ -0,0 +1,85 @@ +// +// GlobalHelper.swift +// Runner +// +// Created by ZiKambrani on 29/03/1442 AH. +// + +import UIKit + +func dictionaryArray(from:String) -> [[String:Any]]{ + if let data = from.data(using: .utf8) { + do { + return try JSONSerialization.jsonObject(with: data, options: []) as? [[String: Any]] ?? [] + } catch { + print(error.localizedDescription) + } + } + return [] + +} + +func dictionary(from:String) -> [String:Any]?{ + if let data = from.data(using: .utf8) { + do { + return try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] + } catch { + print(error.localizedDescription) + } + } + return nil + +} + +func showNotification(identifier:String? = nil, title:String?, subtitle:String?, message:String?, sound:UNNotificationSound = UNNotificationSound.default){ + let notificationContent = UNMutableNotificationContent() + + if identifier != nil { notificationContent.categoryIdentifier = identifier! } + if title != nil { notificationContent.title = title! } + if subtitle != nil { notificationContent.body = message! } + if message != nil { notificationContent.subtitle = subtitle! } + + notificationContent.sound = UNNotificationSound.default + let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false) + let request = UNNotificationRequest(identifier: "\(Date().timeIntervalSinceNow)", content: notificationContent, trigger: trigger) + UNUserNotificationCenter.current().add(request) { error in + if let error = error { + print("Error: \(error)") + } + } +} + + +func httpPostRequest(urlString:String, jsonBody:[String:Any], completion:((Bool,[String:Any]?)->Void)?){ + let json: [String: Any] = jsonBody + let jsonData = try? JSONSerialization.data(withJSONObject: json) + + // create post request + let url = URL(string: urlString)! + var request = URLRequest(url: url) + request.addValue("application/json", forHTTPHeaderField: "Content-Type") + request.addValue("*/*", forHTTPHeaderField: "Accept") + request.httpMethod = "POST" + request.httpBody = jsonData + + let task = URLSession.shared.dataTask(with: request) { data, response, error in + guard let data = data, error == nil else { + print(error?.localizedDescription ?? "No data") + return + } + + let responseJSON = try? JSONSerialization.jsonObject(with: data, options: []) + if let responseJSON = responseJSON as? [String: Any], let status = responseJSON["MessageStatus"] as? Int{ + print(responseJSON) + if status == 1{ + completion?(true,responseJSON) + }else{ + completion?(false,responseJSON) + } + + } + } + + task.resume() + +} diff --git a/ios/Runner/Helper/HMGPlatformBridge.swift b/ios/Runner/Helper/HMGPlatformBridge.swift new file mode 100644 index 00000000..f897188c --- /dev/null +++ b/ios/Runner/Helper/HMGPlatformBridge.swift @@ -0,0 +1,137 @@ +// +// HMGPlatformBridge.swift +// Runner +// +// Created by ZiKambrani on 14/12/2020. +// + +import UIKit +import NetworkExtension +import SystemConfiguration.CaptiveNetwork + +var flutterMethodChannel:FlutterMethodChannel? = nil +var mainViewController:MainFlutterVC! + +class HMGPlatformBridge{ + private let channelName = "HMG-Platform-Bridge" + private static var shared_:HMGPlatformBridge? + + class func initialize(flutterViewController:MainFlutterVC){ + shared_ = HMGPlatformBridge() + mainViewController = flutterViewController + shared_?.openChannel() + } + + func shared() -> HMGPlatformBridge{ + assert((HMGPlatformBridge.shared_ != nil), "HMGPlatformBridge is not initialized, call initialize(mainViewController:MainFlutterVC) function first.") + return HMGPlatformBridge.shared_! + } + + private func openChannel(){ + flutterMethodChannel = FlutterMethodChannel(name: channelName, binaryMessenger: mainViewController.binaryMessenger) + flutterMethodChannel?.setMethodCallHandler { (methodCall, result) in + print("Called function \(methodCall.method)") + if methodCall.method == "connectHMGInternetWifi"{ + self.connectHMGInternetWifi(methodCall:methodCall, result: result) + + }else if methodCall.method == "connectHMGGuestWifi"{ + self.connectHMGGuestWifi(methodCall:methodCall, result: result) + + }else if methodCall.method == "isHMGNetworkAvailable"{ + self.isHMGNetworkAvailable(methodCall:methodCall, result: result) + + }else if methodCall.method == "registerHmgGeofences"{ + self.registerHmgGeofences(result: result) + + }else if methodCall.method == "unRegisterHmgGeofences"{ + self.unRegisterHmgGeofences(result: result) + } + + print("") + } + } + + + + // Connect HMG Wifi and Internet + func connectHMGInternetWifi(methodCall:FlutterMethodCall ,result: @escaping FlutterResult){ + + guard let pateintId = (methodCall.arguments as? [Any])?.first as? String + else { return assert(true, "Missing or invalid arguments (Must have one argument 'String at 0'") } + + + HMG_Internet.shared.connect(patientId: pateintId) { (status, message) in + result(status ? 1 : 0) + if status{ + self.showMessage(title:"Congratulations", message:message) + }else{ + self.showMessage(title:"Ooops,", message:message) + } + } + } + + // Connect HMG-Guest for App Access + func connectHMGGuestWifi(methodCall:FlutterMethodCall ,result: @escaping FlutterResult){ + HMG_GUEST.shared.connect() { (status, message) in + result(status ? 1 : 0) + if status{ + self.showMessage(title:"Congratulations", message:message) + }else{ + self.showMessage(title:"Ooops,", message:message) + } + } + } + + func isHMGNetworkAvailable(methodCall:FlutterMethodCall ,result: @escaping FlutterResult) -> Bool{ + guard let ssid = methodCall.arguments as? String else { + assert(true, "Missing or invalid arguments (Must have one argument 'String at 0'") + return false + } + + let queue = DispatchQueue.init(label: "com.hmg.wifilist") + NEHotspotHelper.register(options: nil, queue: queue) { (command) in + print(command) + + if(command.commandType == NEHotspotHelperCommandType.filterScanList) { + if let networkList = command.networkList{ + for network in networkList{ + print(network.ssid) + } + } + } + } + return false + + } + + + // Message Dailog + func showMessage(title:String, message:String){ + DispatchQueue.main.async { + let alert = UIAlertController(title: title, message: message, preferredStyle: .alert ) + alert.addAction(UIAlertAction(title: "OK", style: .destructive, handler: nil)) + mainViewController.present(alert, animated: true) { + + } + } + } + + // Register Geofence + func registerHmgGeofences(result: @escaping FlutterResult){ + flutterMethodChannel?.invokeMethod("getGeoZones", arguments: nil){ geoFencesJsonString in + if let jsonString = geoFencesJsonString as? String{ + let allZones = GeoZoneModel.list(from: jsonString) + HMG_Geofence.shared().register(geoZones: allZones) + result(true) + }else{ + } + } + } + + // Register Geofence + func unRegisterHmgGeofences(result: @escaping FlutterResult){ + HMG_Geofence.shared().unRegisterAll() + result(true) + } + +} diff --git a/ios/Runner/Helper/HMG_Geofence.swift b/ios/Runner/Helper/HMG_Geofence.swift new file mode 100644 index 00000000..fb469165 --- /dev/null +++ b/ios/Runner/Helper/HMG_Geofence.swift @@ -0,0 +1,189 @@ +// +// HMG_Geofence.swift +// Runner +// +// Created by ZiKambrani on 13/12/2020. +// + +import UIKit +import CoreLocation + +fileprivate var df = DateFormatter() +fileprivate var transition = "" + +enum Transition:Int { + case entry = 1 + case exit = 2 + func name() -> String{ + return self.rawValue == 1 ? "Enter" : "Exit" + } +} + +class HMG_Geofence:NSObject{ + + var geoZones:[GeoZoneModel]? + var locationManager:CLLocationManager!{ + didSet{ + // https://developer.apple.com/documentation/corelocation/cllocationmanager/1423531-startmonitoringsignificantlocati + + locationManager.allowsBackgroundLocationUpdates = true + locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters + locationManager.activityType = .other + locationManager.delegate = self + locationManager.requestAlwaysAuthorization() + // locationManager.distanceFilter = 500 + // locationManager.startMonitoringSignificantLocationChanges() + } + } + + private static var shared_:HMG_Geofence? + class func shared() -> HMG_Geofence{ + if HMG_Geofence.shared_ == nil{ + HMG_Geofence.initGeofencing() + } + return shared_! + } + + class func initGeofencing(){ + shared_ = HMG_Geofence() + shared_?.locationManager = CLLocationManager() + } + + func register(geoZones:[GeoZoneModel]){ + + self.geoZones = geoZones + + let monitoredRegions_ = monitoredRegions() + self.geoZones?.forEach({ (zone) in + if let region = zone.toRegion(locationManager: locationManager){ + if let already = monitoredRegions_.first(where: {$0.identifier == zone.identifier()}){ + debugPrint("Already monitering region: \(already)") + }else{ + startMonitoring(region: region) + } + }else{ + debugPrint("Invalid region: \(zone.latitude ?? "invalid_latitude"),\(zone.longitude ?? "invalid_longitude"),r\(zone.radius ?? 0) | \(zone.identifier())") + } + }) + } + + func monitoredRegions() -> Set{ + return locationManager.monitoredRegions + } + + func unRegisterAll(){ + for region in locationManager.monitoredRegions { + locationManager.stopMonitoring(for: region) + } + } + +} + +// CLLocationManager Delegates +extension HMG_Geofence : CLLocationManagerDelegate{ + + func startMonitoring(region: CLCircularRegion) { + if !CLLocationManager.isMonitoringAvailable(for: CLCircularRegion.self) { + return + } + + if CLLocationManager.authorizationStatus() != .authorizedAlways { + let message = """ + Your geotification is saved but will only be activated once you grant + HMG permission to access the device location. + """ + debugPrint(message) + } + + locationManager.startMonitoring(for: region) + locationManager.requestState(for: region) + debugPrint("Starts monitering region: \(region)") + } + + func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) { + debugPrint("didEnterRegion: \(region)") + if region is CLCircularRegion { + handleEvent(for: region,transition: .entry, location: manager.location) + } + } + + func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) { + debugPrint("didExitRegion: \(region)") + if region is CLCircularRegion { + handleEvent(for: region,transition: .exit, location: manager.location) + } + } + + func locationManager(_ manager: CLLocationManager, didDetermineState state: CLRegionState, for region: CLRegion) { + debugPrint("didDetermineState: \(state)") + } + + func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { + debugPrint("didUpdateLocations: \(locations)") + } + + +} + +// Helpers +extension HMG_Geofence{ + + func handleEvent(for region: CLRegion!, transition:Transition, location:CLLocation?) { + notifyUser(forRegion: region, transition: transition, location: locationManager.location) + notifyServer(forRegion: region, transition: transition, location: locationManager.location) + } + + func geoZone(by id: String) -> GeoZoneModel? { + var zone:GeoZoneModel? = nil + if let zones_ = geoZones{ + zone = zones_.first(where: { $0.identifier() == id}) + }else{ + // let jsonArray = UserDefaults.standard.string(forKey: "hmg-geo-fences") + } + return zone + } + + + func notifyUser(forRegion:CLRegion, transition:Transition, location:CLLocation?){ + if let zone = geoZone(by: forRegion.identifier){ + if UIApplication.shared.applicationState == .active { + mainViewController.showAlert(withTitle: transition.name(), message: zone.message()) + }else{ + + } + } + } + + func notifyServer(forRegion:CLRegion, transition:Transition, location:CLLocation?){ + df.dateFormat = "MMM/dd/yyyy hh:mm:ss" + if let userProfileJson = UserDefaults.standard.string(forKey: "flutter.user-profile"), + let userProfile = dictionary(from: userProfileJson), let patientId = userProfile["PatientID"] as? Int{ + + if let idString = forRegion.identifier.split(separator: "_").first, let idInt = Int(idString){ + let body:[String:Any] = [ + "PointsID":idInt, + "GeoType":transition.rawValue, + "PatientID":patientId + ] + + let url = "https://hmgwebservices.com/Services/Patients.svc/REST/GeoF_InsertPatientFileInfo" + httpPostRequest(urlString: url, jsonBody: body){ (status,json) in + let status_ = status ? "Notified" : "Not notified" + showNotification(title: transition.name(), subtitle: forRegion.identifier, message: status_) + + + var logs = UserDefaults.init(suiteName: "GeoFenceLog")?.dictionary(forKey: "LOGS") ?? [:] + if var geo = logs[forRegion.identifier] as? [String]{ + geo.append("\(status_) at \(df.string(from: Date()))") + }else{ + logs.updateValue(["\(status_) at \(df.string(from: Date()))"], forKey: forRegion.identifier) + } + + UserDefaults.init(suiteName: "GeoFenceLog")?.set(logs, forKey: "LOGS") + + } + } + } + } +} + diff --git a/ios/Runner/Helper/LocalizedFromFlutter.swift b/ios/Runner/Helper/LocalizedFromFlutter.swift new file mode 100644 index 00000000..88530649 --- /dev/null +++ b/ios/Runner/Helper/LocalizedFromFlutter.swift @@ -0,0 +1,22 @@ +// +// LocalizedFromFlutter.swift +// Runner +// +// Created by ZiKambrani on 10/04/1442 AH. +// + +import UIKit + +class FlutterText{ + + class func with(key:String,completion: @escaping (String)->Void){ + flutterMethodChannel?.invokeMethod("localizedValue", arguments: key, result: { (result) in + if let localized = result as? String{ + completion(localized) + }else{ + completion(key) + } + }) + } + +} diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 6a2a87ce..ae084167 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -4,8 +4,6 @@ CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - Dr. Alhabib MC CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier @@ -13,7 +11,7 @@ CFBundleInfoDictionaryVersion 6.0 CFBundleName - DiplomaticQuarter + diplomaticquarterapp CFBundlePackageType APPL CFBundleShortVersionString @@ -24,47 +22,43 @@ $(FLUTTER_BUILD_NUMBER) LSRequiresIPhoneOS - NSBluetoothAlwaysUsageDescription - This App requires access to Bluetooth to connect blood pressure & blood sugar devices with the app to analyze the data. - NSBluetoothPeripheralUsageDescription - This App requires access to Bluetooth to connect blood pressure & blood sugar devices with the app to analyze the data. NSCalendarsUsageDescription - This app requires calendar access to set reminders for Virtual & Normal Appointments. + We need access to record you event in to calender. NSCameraUsageDescription - This app requires camera access to enable virtual consultation between patient & doctor - NSContactsUsageDescription - This app requires contacts access to show incoming virtual consultation request. - NSFaceIDUsageDescription - This app requires Face ID to allow biometric authentication for app login. + Need camera access for uploading images NSLocationAlwaysAndWhenInUseUsageDescription - This App requires access to your location to show the nearest hospitals & ER Locations from your location. + This app will use your location to show cool stuffs near you. NSLocationAlwaysUsageDescription - This App requires access to your location to show the nearest hospitals from your location. + This app will use your location to show cool stuffs near you. + NSLocationUsageDescription + Need location access for updating nearby friends NSLocationWhenInUseUsageDescription - This App requires access to your location to show the nearest hospitals from your location. + This app will use your location to show cool stuffs near you. NSMicrophoneUsageDescription - This app requires microphone access to enable virtual consultation between patient & doctor - NSMotionUsageDescription - This app requires motion detection access to function properly. + Need microphone access for uploading videos NSPhotoLibraryUsageDescription - This app requires photo library access to select image as document & upload it. - NSRemindersUsageDescription - This app requires calendar access to set reminders for Virtual & Normal Appointments. - NSSpeechRecognitionUsageDescription - This app requires access to speech recognition to identify which words are spoken into the microphone. - NSAppleMusicUsageDescription - Required usage description for a Flutter dependency + Need photo library access for uploading images UIBackgroundModes - remote-notification + fetch + location + processing UILaunchStoryboardName LaunchScreen UIMainStoryboardFile Main + UIRequiredDeviceCapabilities + + location-services + gps + armv7 + UISupportedInterfaceOrientations UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad diff --git a/ios/Runner/Runner.entitlements b/ios/Runner/Runner.entitlements index 903def2a..be2e0283 100644 --- a/ios/Runner/Runner.entitlements +++ b/ios/Runner/Runner.entitlements @@ -2,7 +2,13 @@ + + aps-environment development + com.apple.developer.networking.HotspotConfiguration + + com.apple.developer.networking.wifi-info + diff --git a/ios/Runner/WifiConnect/HMG_GUEST.swift b/ios/Runner/WifiConnect/HMG_GUEST.swift new file mode 100644 index 00000000..ad6d3922 --- /dev/null +++ b/ios/Runner/WifiConnect/HMG_GUEST.swift @@ -0,0 +1,77 @@ +// +// HMG_GUEST.swift +// HMG-iOS-Wifi +// +// Created by ZiKambrani on 23/03/1442 AH. +// Copyright © 1442 ZiKambrani. All rights reserved. +// + +import UIKit +import NetworkExtension +import SystemConfiguration.CaptiveNetwork + +fileprivate let SSID = "HMG-MobileApp" + +class HMG_GUEST{ + static let shared = HMG_GUEST() + + private var complete:((_ status:Bool, _ message:String) -> Void)! + func connect(completion:@escaping ((_ status:Bool, _ message:String) -> Void)){ + complete = completion + + if isAlreadyConnected() { + FlutterText.with(key: "alreadyConnectedHmgNetwork") { (localized) in + self.complete(true, localized ) + } + }else{ + connect() + } + } + + private func connect() { + + let hotspotConfig = NEHotspotConfiguration(ssid: "\(SSID)") + hotspotConfig.joinOnce = false + NEHotspotConfigurationManager.shared.apply(hotspotConfig) {[weak self] (error) in + guard let self = self else { return; } + + if let error = error { + FlutterText.with(key: "errorConnectingHmgNetwork") { (localized) in + self.complete(false, localized ) + } + }else{ + _ = Timer.scheduledTimer(withTimeInterval: 10, repeats: false) { (timer) in + let connected = self.isAlreadyConnected() + let message = connected ? "successConnectingHmgNetwork" : "failedConnectingHmgNetwork" + FlutterText.with(key: message) { (localized) in + self.complete(false, localized ) + } + } + } + } + + +// NSMutableURLRequest(url: URL(string: "www.google.com")!).bind(to: command) +// NEHotspotHelper.register(options: [:], queue: DispatchQueue.global()) { (command) in +// command +// print(command) +// } + + } + + private func isAlreadyConnected() -> Bool{ + var currentSSID: String? + if let interfaces = CNCopySupportedInterfaces() as NSArray? { + for interface in interfaces { + if let interfaceInfo = CNCopyCurrentNetworkInfo(interface as! CFString) as NSDictionary? { + currentSSID = interfaceInfo[kCNNetworkInfoKeySSID as String] as? String + break + } + } + } + + print("CurrentConnectedSSID: \(currentSSID)") + return currentSSID == SSID + } + +} diff --git a/ios/Runner/WifiConnect/HMG_GUEST_bkp.swift b/ios/Runner/WifiConnect/HMG_GUEST_bkp.swift new file mode 100644 index 00000000..e3dfd468 --- /dev/null +++ b/ios/Runner/WifiConnect/HMG_GUEST_bkp.swift @@ -0,0 +1,129 @@ +//// +//// HMG_GUEST.swift +//// HMG-iOS-Wifi +//// +//// Created by ZiKambrani on 23/03/1442 AH. +//// Copyright © 1442 ZiKambrani. All rights reserved. +//// +// +//import UIKit +//import NetworkExtension +//import SystemConfiguration.CaptiveNetwork +// +// +//class HMG_GUEST{ +// static let shared = HMG_GUEST() +// private let SSID = "GUEST-POC" +// private let USER = "1301" +// private let PASS = "8928" +// +// var complete:((_ status:Bool, _ message:String) -> Void)! +// func connect(completion:@escaping ((_ status:Bool, _ message:String) -> Void)){ +// complete = completion +// +// if isAlreadyConnected() { +// hasInternet { (has) in +// if has == true{ +// self.complete(true, "You already connected to internet") +// return +// }else{ +// self.authenticate() +// } +// } +// }else{ +// connect() +// } +// } +// +// private func connect() { +// let hotspotConfig = NEHotspotConfiguration(ssid: SSID) +// hotspotConfig.joinOnce = true +// +// NEHotspotConfigurationManager.shared.apply(hotspotConfig) {[weak self] (error) in +// guard let self = self else { return; } +// +// if let error = error { +// self.complete(false, error.localizedDescription ?? "Error connecting to HMG wifi network" ) +// }else{ +// _ = Timer.scheduledTimer(withTimeInterval: 2, repeats: false) { (timer) in +// self.authenticate() +// } +// } +// } +// } +// +// func authenticate(){ +// +// func callLogin(){ +// +// let parameters = "Login=Log%20In&cmd=authenticate&password=1820&user=2300" +// let postData = parameters.data(using: .utf8) +// +// var request = URLRequest(url: URL(string: "https://captiveportal-login.hmg.com/cgi-bin/login")!,timeoutInterval: 5) +// request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") +// +// request.httpMethod = "POST" +// request.httpBody = postData +// +// let task = URLSession.shared.dataTask(with: request) { data, response, error in +// // guard let data = data else { +// // self.complete(false, "Error at authentication") +// // return +// // } +// +// self.hasInternet { (has) in +// self.complete(has, has ? "Successfully connected to the internet" : "Authentication failed or you are already using your credentials on another device") +// } +// } +// task.resume() +// +// } +// +// self.hasInternet { (has) in +// if has == true{ +// self.complete(true, "Your internet account is already authenticated") +// }else{ +// callLogin() +// } +// } +// +// } +// +// private func isAlreadyConnected() -> Bool{ +// var currentSSID: String? +// if let interfaces = CNCopySupportedInterfaces() as NSArray? { +// for interface in interfaces { +// if let interfaceInfo = CNCopyCurrentNetworkInfo(interface as! CFString) as NSDictionary? { +// currentSSID = interfaceInfo[kCNNetworkInfoKeySSID as String] as? String +// break +// } +// } +// } +// +// print("CurrentConnectedSSID: \(currentSSID)") +// return currentSSID == SSID +// } +// +// +// func hasInternet( completion:@escaping ((Bool)->Void)){ +// +// let testUrl = "https://captive.apple.com" +// var request = URLRequest(url: URL(string: testUrl)!,timeoutInterval: 5) +// request.httpMethod = "GET" +// let task = URLSession.shared.dataTask(with: request) { data, response, error in +// guard let data = data else { +// completion(false) +// return +// } +// let resp = String(data: data, encoding: .utf8)! +// if resp.contains("Success"){ +// completion(true) +// }else{ +// completion(false) +// } +// +// } +// task.resume() +// } +// +//} diff --git a/ios/Runner/WifiConnect/HMG_Internet.swift b/ios/Runner/WifiConnect/HMG_Internet.swift new file mode 100644 index 00000000..00ac172f --- /dev/null +++ b/ios/Runner/WifiConnect/HMG_Internet.swift @@ -0,0 +1,193 @@ +// +// HMG_GUEST.swift +// HMG-iOS-Wifi +// +// Created by ZiKambrani on 23/03/1442 AH. +// Copyright © 1442 ZiKambrani. All rights reserved. +// + +import UIKit +import NetworkExtension +import SystemConfiguration.SCNetworkConnection + +fileprivate var TEST = false +fileprivate let SSID = "GUEST-POC" +fileprivate var USER = "" +fileprivate var PASS = "" + +fileprivate func supportedEAPTypes() -> [NSNumber]{ + let peap = NEHotspotEAPSettings.EAPType.EAPPEAP.rawValue + let fast = NEHotspotEAPSettings.EAPType.EAPFAST.rawValue + let tls = NEHotspotEAPSettings.EAPType.EAPTLS.rawValue + let ttls = NEHotspotEAPSettings.EAPType.EAPTTLS.rawValue + return [NSNumber(value: peap), NSNumber(value: fast), NSNumber(value: tls), NSNumber(value: ttls)] +} + +class HMG_Internet{ + static let shared = HMG_Internet() + + private var complete:((_ status:Bool, _ message:String) -> Void)! + func connect(patientId:String, completion:@escaping ((_ status:Bool, _ message:String) -> Void)){ + complete = completion + + if isAlreadyConnected() { + hasInternet { (has) in + if has == true{ + FlutterText.with(key: "alreadyConnectedHmgNetwork"){ localized in + self.complete(true, localized) + } + return + }else{ + FlutterText.with(key: "connectedToHmgNetworkWithNoInternet"){ localized in + self.complete(false, localized) + } + } + } + }else{ + connect(patientId: patientId) + } + } + + private func connect(patientId:String) { + + getWifiCredentials(patientId: patientId) { + let trust_cert = Bundle.main.certificate(named: "GuestPOC_Certificate") + guard trust_cert.trust() == true else{ + FlutterText.with(key: "notConnectedToHmgNetworkSecurityIssue"){ localized in + self.complete(false,localized) + } + return + } + + let eapSettings = NEHotspotEAPSettings() + eapSettings.username = USER + eapSettings.password = PASS + eapSettings.trustedServerNames = ["*.hmg.com","onboard.hmg.com","hmg.com"] + eapSettings.supportedEAPTypes = [supportedEAPTypes().first!] +// eapSettings.isTLSClientCertificateRequired = true +// eapSettings.ttlsInnerAuthenticationType = .eapttlsInnerAuthenticationMSCHAPv2 // MSCHAPv2 +// eapSettings.setIdentity(Bundle.main.identity(named: "GuestPOC_Certificate", password: "1")) +// eapSettings.setTrustedServerCertificates([trust_cert]) + + let hotspotConfig = NEHotspotConfiguration(ssid: SSID, eapSettings: eapSettings) + NEHotspotConfigurationManager.shared.apply(hotspotConfig) {[weak self] (error) in + guard let self = self else { return; } + + if let error = error { + + FlutterText.with(key: "errorConnectingHmgNetwork"){ localized in + self.complete(false,localized) + } + + }else{ + _ = Timer.scheduledTimer(withTimeInterval: 5, repeats: false) { (timer) in + self.hasInternet { (has) in + if has == true{ + FlutterText.with(key: "connectedHmgNetworkWithInternet"){ localized in + self.complete(true,localized) + } + return + }else{ + FlutterText.with(key: "connectedToHmgNetworkWithNoInternet"){ localized in + self.complete(false,localized) + } + } + } + } + } + } + + } + } + + private func isAlreadyConnected() -> Bool{ + var currentSSID: String? + if let interfaces = CNCopySupportedInterfaces() as NSArray? { + for interface in interfaces { + if let interfaceInfo = CNCopyCurrentNetworkInfo(interface as! CFString) as NSDictionary? { + currentSSID = interfaceInfo[kCNNetworkInfoKeySSID as String] as? String + break + } + } + } + print("CurrentConnectedSSID: \(currentSSID)") + return currentSSID == SSID + } + + + private func getWifiCredentials(patientId:String, success: @escaping (() -> Void)){ + if TEST { + success() + return + } + + guard let url = API.WIFI_CREDENTIALS.toUrl() else { return assert(true, "Invalid URL: \(API.WIFI_CREDENTIALS)") } + + // JSON Body for HTTP Request + let json: [String: Any] = ["PatientID": patientId] + let jsonData = try? JSONSerialization.data(withJSONObject: json) + + var request = URLRequest(url: url, timeoutInterval: 20) + request.httpMethod = "POST" + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + request.httpBody = jsonData + + let task = URLSession.shared.dataTask(with: request) { data, response, error in + guard let data = data else { + self.somethingWentWrong() + return + } + + if let responseJSON = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]{ + if let requiredData = (responseJSON["Hmg_SMS_Get_By_ProjectID_And_PatientIDList"] as? [[String:Any]])?.first, + let userName = requiredData["UserName"] as? String, let password = requiredData["Password"] as? String{ + + USER = userName + PASS = password + success() + + }else if let errorMessage = responseJSON["ErrorMessage"] as? String{ + self.complete(false, errorMessage) + }else{ + self.somethingWentWrong() + } + }else{ + self.somethingWentWrong() + } + + } + task.resume() + + } + + private func somethingWentWrong(){ + FlutterText.with(key: "somethingWentWrong") { (localized) in + self.complete(false, localized) + } + } + + + func hasInternet( completion:@escaping ((Bool)->Void)){ + + let testUrl = "https://captive.apple.com" + var request = URLRequest(url: URL(string: testUrl)!,timeoutInterval: 5) + request.httpMethod = "GET" + let task = URLSession.shared.dataTask(with: request) { data, response, error in + guard let data = data else { + completion(false) + return + } + + completion( + String(data: data, encoding: .utf8)! + .replacingOccurrences(of: " ", with: "") + .replacingOccurrences(of: "\n", with: "") + .lowercased() + .contains("success") + ) + + } + task.resume() + } + +} diff --git a/ios/Runner/WifiConnect/HMG_Wifi.swift b/ios/Runner/WifiConnect/HMG_Wifi.swift new file mode 100644 index 00000000..1335f766 --- /dev/null +++ b/ios/Runner/WifiConnect/HMG_Wifi.swift @@ -0,0 +1,172 @@ +// +// HMG_GUEST.swift +// HMG-iOS-Wifi +// +// Created by ZiKambrani on 23/03/1442 AH. +// Copyright © 1442 ZiKambrani. All rights reserved. +// + +import UIKit +import NetworkExtension +import SystemConfiguration.CaptiveNetwork + +fileprivate var TEST = true +fileprivate let SSID = "GUEST-POC" +fileprivate var USER = "0696" +fileprivate var PASS = "0000" + +fileprivate func supportedEAPTypes() -> [NSNumber]{ + let peap = NEHotspotEAPSettings.EAPType.EAPPEAP.rawValue + let fast = NEHotspotEAPSettings.EAPType.EAPFAST.rawValue + let tls = NEHotspotEAPSettings.EAPType.EAPTLS.rawValue + let ttls = NEHotspotEAPSettings.EAPType.EAPTTLS.rawValue + return [NSNumber(value: peap), NSNumber(value: fast), NSNumber(value: tls), NSNumber(value: ttls)] +} + +class HMG_Internet{ + static let shared = HMG_Wifi() + + private var complete:((_ status:Bool, _ message:String) -> Void)! + func connect(patientId:String, completion:@escaping ((_ status:Bool, _ message:String) -> Void)){ + complete = completion + + if isAlreadyConnected() { + hasInternet { (has) in + if has == true{ + self.complete(true, "You already connected to HMG network to access internet") + return + }else{ + self.complete(false, "You are connected to HMG network but it have no internet access") + } + } + }else{ + connect(patientId: patientId) + } + } + + private func connect(patientId:String) { + + getWifiCredentials(patientId: patientId) { + let trust_cert = Bundle.main.certificate(named: "GuestPOC_Certificate") + guard trust_cert.trust() == true else{ + self.complete(false,"We are not able to connect you to HMG network due to security certificate") + return + } + + let eapSettings = NEHotspotEAPSettings() + eapSettings.username = USER + eapSettings.password = PASS + eapSettings.trustedServerNames = ["*.hmg.com","onboard.hmg.com","hmg.com"] + eapSettings.supportedEAPTypes = [supportedEAPTypes().first!] +// eapSettings.isTLSClientCertificateRequired = true +// eapSettings.ttlsInnerAuthenticationType = .eapttlsInnerAuthenticationMSCHAPv2 // MSCHAPv2 +// eapSettings.setIdentity(Bundle.main.identity(named: "GuestPOC_Certificate", password: "1")) +// eapSettings.setTrustedServerCertificates([trust_cert]) + + let hotspotConfig = NEHotspotConfiguration(ssid: SSID, eapSettings: eapSettings) + NEHotspotConfigurationManager.shared.apply(hotspotConfig) {[weak self] (error) in + guard let self = self else { return; } + + if let error = error { + self.complete(false, "Error connecting to HMG network" /*error.localizedDescription*/ ) + }else{ + _ = Timer.scheduledTimer(withTimeInterval: 3, repeats: false) { (timer) in + self.hasInternet { (has) in + if has == true{ + self.complete(true, "Successfully connected to the HMG network to access internet") + return + }else{ + self.complete(false, "Successfully connected to the HMG network but it have no internet access") + } + } + } + } + } + + } + } + + private func isAlreadyConnected() -> Bool{ + var currentSSID: String? + if let interfaces = CNCopySupportedInterfaces() as NSArray? { + for interface in interfaces { + if let interfaceInfo = CNCopyCurrentNetworkInfo(interface as! CFString) as NSDictionary? { + currentSSID = interfaceInfo[kCNNetworkInfoKeySSID as String] as? String + break + } + } + } + + print("CurrentConnectedSSID: \(currentSSID)") + return currentSSID == SSID + } + + + private func getWifiCredentials(patientId:String, completion: @escaping (() -> Void)){ + if TEST { + completion() + return + } + + guard let url = API.WIFI_CREDENTIALS.toUrl() else { return assert(true, "Invalid URL: \(API.WIFI_CREDENTIALS)") } + + // JSON Body for HTTP Request + let json: [String: Any] = ["PatientID": patientId] + let jsonData = try? JSONSerialization.data(withJSONObject: json) + + var request = URLRequest(url: url, timeoutInterval: 20) + request.httpMethod = "POST" + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + request.httpBody = jsonData + + let task = URLSession.shared.dataTask(with: request) { data, response, error in + guard let data = data else { + self.complete(false, "Failed to get your internet credentials") + return + } + + if let responseJSON = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]{ + if let requiredData = responseJSON["Hmg_SMS_Get_By_ProjectID_And_PatientIDList"] as? [String:Any], + let userName = requiredData["UserName"] as? String, let password = requiredData["Password"] as? String{ + + USER = userName + PASS = password + completion() + + }else if let errorMessage = responseJSON["ErrorMessage"] as? String{ + self.complete(false, errorMessage) + } + }else{ + self.complete(false, "Failed to get your internet credentials") + } + + } + task.resume() + + } + + + func hasInternet( completion:@escaping ((Bool)->Void)){ + + let testUrl = "https://captive.apple.com" + var request = URLRequest(url: URL(string: testUrl)!,timeoutInterval: 5) + request.httpMethod = "GET" + let task = URLSession.shared.dataTask(with: request) { data, response, error in + guard let data = data else { + completion(false) + return + } + + completion( + String(data: data, encoding: .utf8)! + .replacingOccurrences(of: " ", with: "") + .replacingOccurrences(of: "\n", with: "") + .lowercased() + .contains("success") + ) + + } + task.resume() + } + +} diff --git a/ios/gpx.gpx b/ios/gpx.gpx new file mode 100644 index 00000000..9cc26956 --- /dev/null +++ b/ios/gpx.gpx @@ -0,0 +1 @@ + Sverrir Sigmundarson Office Office Mahmoud Home Mahmoud Home Panorama Mall Panorama Mall Saudi Architects Crossing Saudi Architects Crossing Office Office \ No newline at end of file diff --git a/lib/Constants.dart b/lib/Constants.dart new file mode 100644 index 00000000..5b8fd9da --- /dev/null +++ b/lib/Constants.dart @@ -0,0 +1,3 @@ +import 'package:flutter/material.dart'; + +final Color secondaryColor = Colors.red[800]; \ No newline at end of file diff --git a/lib/config/config.dart b/lib/config/config.dart index 786c323b..3f5f8755 100644 --- a/lib/config/config.dart +++ b/lib/config/config.dart @@ -1,22 +1,35 @@ import 'dart:io'; +import 'package:diplomaticquarterapp/core/service/geofencing/GeofencingServices.dart'; import 'package:diplomaticquarterapp/models/Request.dart'; import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; import 'package:diplomaticquarterapp/widgets/mobile-no/mobile_no.dart'; const MAX_SMALL_SCREEN = 660; -//const BASE_URL = 'https://uat.hmgwebservices.com/'; -const BASE_URL = 'https://hmgwebservices.com/'; -const PHARMACY_BASE_URL = 'https://uat.hmgwebservices.com/epharmacy/api/'; +// PACKAGES and OFFERS +const EXA_CART_API_BASE_URL = 'https://mdlaboratories.com/exacartapi'; +const PACKAGES_CATEGORIES = '/api/categories'; +const PACKAGES_PRODUCTS = '/api/products'; -//const BASE_URL = 'https://uat.hmgwebservices.com/'; +const BASE_URL = 'https://uat.hmgwebservices.com/'; // const BASE_URL = 'https://hmgwebservices.com/'; + +//const BASE_PHARMACY_URL = 'http://swd-pharapp-01:7200/api/'; +const BASE_PHARMACY_URL = 'https://uat.hmgwebservices.com/epharmacy/api/'; +const PHARMACY_BASE_URL = 'https://uat.hmgwebservices.com/epharmacy/api/'; +const PING_SERVICE = 'Services/Weather.svc/REST/CheckConnectivity'; + const GET_PROJECT = 'Services/Lists.svc/REST/GetProject'; +///Geofencing +const GET_GEO_ZONES = 'Services/Patients.svc/REST/GeoF_GetAllPoints'; +const LOG_GEO_ZONES = 'Services/Patients.svc/REST/GeoF_InsertPatientFileInfo'; //weather const WEATHER_INDICATOR = 'Services/Weather.svc/REST/GetCityInfo'; +const GET_PRIVILEGE = 'Services/Patients.svc/REST/Service_Privilege'; + ///Doctor const GET_MY_DOCTOR = 'Services/Doctors.svc/REST/GetPatientDoctorAppointmentResult'; @@ -42,11 +55,18 @@ const GET_PRESCRIPTION_REPORT_ENH = const GET_Patient_LAB_ORDERS = 'Services/Patients.svc/REST/GetPatientLabOrders'; const GET_Patient_LAB_SPECIAL_RESULT = 'Services/Patients.svc/REST/GetPatientLabSpecialResults'; +const SEND_LAB_RESULT_EMAIL = + 'Services/Notifications.svc/REST/SendLabReportEmail'; const GET_Patient_LAB_RESULT = 'Services/Patients.svc/REST/GetPatientLabResults'; +const GET_Patient_LAB_ORDERS_RESULT = + 'Services/Patients.svc/REST/GetPatientLabOrdersResults'; /// const GET_PATIENT_ORDERS = 'Services/Patients.svc/REST/GetPatientRadOrders'; +const GET_PATIENT_LAB_ORDERS_BY_APPOINTMENT = + 'Services/Patients.svc/REST/GetPatientLabResultsByAppointmentNo'; + const GET_PATIENT_ORDERS_DETAILS = 'Services/Patients.svc/REST/Rad_UpdatePatientRadOrdersToRead'; const GET_RAD_IMAGE_URL = 'Services/Patients.svc/Rest/GetRadImageURL'; @@ -107,7 +127,7 @@ const GET_NEWCHILD_REQUEST = 'Services/Community.svc/REST/CreateNewBaby'; const GET_NEW_USER_REQUEST = 'Services/Community.svc/REST/CreateNewUser_New'; ///delete Child -const DELETE_CHILD_REQUEST = '/Services/Community.svc/REST/DeleteBaby'; +const DELETE_CHILD_REQUEST = 'Services/Community.svc/REST/DeleteBaby'; ///addNewTABLE const GET_TABLE_REQUEST = 'Services/Community.svc/REST/CreateVaccinationTable'; @@ -131,6 +151,8 @@ const SAVE_BLOOD_AGREEMENT = const REPORTS = 'Services/Doctors.svc/REST/GetPatientMedicalReportStatusInfo'; const INSERT_REQUEST_FOR_MEDICAL_REPORT = 'Services/Doctors.svc/REST/InsertRequestForMedicalReport'; +const SEND_MEDICAL_REPORT_EMAIL = + 'Services/Notifications.svc/REST/SendMedicalReportEmail'; ///Rate const IS_LAST_APPOITMENT_RATED = @@ -252,18 +274,15 @@ const CANCEL_LIVECARE_REQUEST = const SEND_LIVECARE_INVOICE_EMAIL = 'Services/Notifications.svc/REST/SendInvoiceForLiveCare'; -const GET_USER_TERMS = '/Services/Patients.svc/REST/GetUserTermsAndConditions'; +const GET_USER_TERMS = 'Services/Patients.svc/REST/GetUserTermsAndConditions'; const UPDATE_HEALTH_TERMS = - '/services/Patients.svc/REST/UpdatePateintHealthSummaryReport'; - -/// -const GET_PRIVILEGE = 'Services/Patients.svc/REST/Service_Privilege'; + 'services/Patients.svc/REST/UpdatePateintHealthSummaryReport'; //URL to get medicine and pharmacies list const CHANNEL = 3; const GENERAL_ID = 'Cs2020@2016\$2958'; const IP_ADDRESS = '10.20.10.20'; -const VERSION_ID = 5.6; +const VERSION_ID = 5.8; const SETUP_ID = '91877'; const LANGUAGE = 2; const PATIENT_OUT_SA = 0; @@ -282,6 +301,10 @@ const GET_PAtIENTS_INSURANCE_UPDATED = "Services/Patients.svc/REST/PatientER_GetPatientInsuranceCardUpdateHistory"; const INSURANCE_DETAILS = "Services/Patients.svc/REST/Get_InsuranceCheckList"; +const GET_PATIENT_INSURANCE_DETAILS = + "Services/Patients.svc/REST/PatientER_GetPatientInsuranceDetails"; +const UPLOAD_INSURANCE_CARD = + 'Services/Patients.svc/REST/PatientER_PatientInfoForInsuranceCardUpdate'; const GET_VACCINES = "Services/Patients.svc/REST/GetDoneVaccinesByPatientID"; const GET_VACCINES_EMAIL = "Services/Notifications.svc/REST/SendVaccinesEmail"; @@ -372,12 +395,46 @@ const GET_ALL_CITIES = 'services/Lists.svc/rest/GetAllCities'; const CREATE_E_REFERRAL = "Services/Patients.svc/REST/CreateEReferral"; const GET_E_REFERRALS = "Services/Patients.svc/REST/GetEReferrals"; +//Pharmacy wishlist +// const GET_WISHLIST = "http://swd-pharapp-01:7200/api/shopping_cart_items/"; + // pharmacy +const PHARMACY_VERIFY_CUSTOMER = "epharmacy/api/VerifyCustomer"; +const PHARMACY_GET_COUNTRY = "epharmacy/api/countries"; +const PHARMACY_CREATE_CUSTOMER = "epharmacy/api/CreateCustomer"; const GET_PHARMACY_BANNER = "epharmacy/api/promotionbanners"; const GET_PHARMACY_TOP_MANUFACTURER = "epharmacy/api/topmanufacturer"; const GET_PHARMACY_BEST_SELLER_PRODUCT = "epharmacy/api/bestsellerproducts"; const GET_PHARMACY_PRODUCTs_BY_IDS = "epharmacy/api/productsbyids/"; const GET_CUSTOMERS_ADDRESSES = "epharmacy/api/Customers/"; +const GET_ORDER = "orders?"; +const GET_ORDER_DETAILS = "epharmacy/api/orders/"; +const ADD_CUSTOMER_ADDRESS = "epharmacy/api/addcustomeraddress"; +const EDIT_CUSTOMER_ADDRESS = "epharmacy/api/editcustomeraddress"; +const DELETE_CUSTOMER_ADDRESS = "epharmacy/api/deletecustomeraddress"; +const GET_ADDRESS = "Customers/"; +const GET_Cancel_ORDER = "cancelorder/"; +const WRITE_REVIEW = "Content-Type" + "text/plain; charset=utf-8"; +const GET_SHOPPING_CART = "epharmacy/api/shopping_cart_items/"; +const GET_SHIPPING_OPTIONS = "epharmacy/api/get_shipping_option/"; +const DELETE_SHOPPING_CART = "epharmacy/api/delete_shopping_cart_items/"; +const DELETE_SHOPPING_CART_ALL = + "epharmacy/api/delete_shopping_cart_item_by_customer/"; +const ORDER_SHOPPING_CART = "epharmacy/api/orders"; +const GET_LACUM_ACCOUNT_INFORMATION = + "Services/Patients.svc/REST/GetLakumAccountInformation"; +const GET_LACUM_GROUP_INFORMATION = + "Services/Patients.svc/REST/GetlakumInQueryInfoGrouping"; +const LACUM_ACCOUNT_ACTIVATE = + "Services/Patients.svc/REST/LakumAccountActivation"; +const LACUM_ACCOUNT_DEACTIVATE = + "Services/Patients.svc/REST/LakumAccountDeactivation"; +const CREATE_LAKUM_ACCOUNT = + "Services/Patients.svc/REST/PHR_CreateLakumAccount"; +const TRANSFER_YAHALA_LOYALITY_POINTS = + "Services/Patients.svc/REST/TransferYaHalaLoyaltyPoints"; +const LAKUM_GET_USER_TERMS_AND_CONDITIONS = + "Services/ERP.svc/REST/GetUserTermsAndConditionsForEPharmcy"; // Home Health Care const HHC_GET_ALL_SERVICES = @@ -399,6 +456,18 @@ const GET_PATIENT_ALL_PRES_ORD = 'Services/Patients.svc/REST/PatientER_GetPatientAllPresOrders'; const PATIENT_ER_INSERT_PRES_ORDER = 'Services/Patients.svc/REST/PatientER_InsertPresOrder'; +const PHARMACY_MAKE_REVIEW = 'epharmacy/api/insertreviews'; + +//Pharmacy wishlist +const GET_WISHLIST = "shopping_cart_items/"; +const DELETE_WISHLIST = "delete_shopping_cart_item_by_product?customer_id="; +const GET_REVIEW = "customerreviews/"; +const GET_BRANDS = "manufacturer"; +const GET_TOP_BRANDS = "topmanufacturer?page=1&limit=8"; +const GET_PRODUCT_DETAIL = "products/"; +const GET_LOCATION = "Services/Patients.svc/REST/GetPharmcyListBySKU"; +const GET_SPECIFICATION = "productspecification/"; +const GET_BRAND_ITEMS = "products?ManufacturerId="; // External API const ADD_ADDRESS_INFO = @@ -408,10 +477,32 @@ const GET_CUSTOMER_ADDRESSES = const GET_CUSTOMER_INFO = "https://mdlaboratories.com/exacartapi/api/VerifyCustomer"; +//Pharmacy + +const GET_PHARMACY_CATEGORISE = + 'epharmacy/api/categories?fields=id,name,namen,description,image,localized_names,display_order,parent_category_id,is_leaf&parent_id=0'; +const GET_OFFERS_CATEGORISE = 'epharmacy/api/discountcategories'; +const GET_OFFERS_PRODUCTS = 'epharmacy/api/offerproducts/'; +const GET_CATEGORISE_PARENT = + 'epharmacy/api/categories?fields=id,name,namen,description,image,localized_names,display_order,parent_category_id,is_leaf&parent_id='; +const GET_PARENT_PRODUCTS = 'epharmacy/api/products?categoryid='; +const GET_SUB_CATEGORISE = + 'epharmacy/api/categories?fields=id,name,namen,description,image,localized_names,display_order,parent_category_id,is_leaf&parent_id='; +const GET_SUB_PRODUCTS = 'epharmacy/api/products?categoryid='; +const GET_FINAL_PRODUCTS = + 'epharmacy/api/products?fields=id,reviews,discount_ids,name,namen,localized_names,display_order,short_description,full_description,full_descriptionn,sku,order_minimum_quantity,order_maximum_quantity,price,old_price,images,is_rx,rx_message,rx_messagen,discount_name,discount_namen,approved_rating_sum,approved_total_reviews,allow_back_in_stock_subscriptions,stock_quantity,stock_availability,stock_availabilityn,discount_percentage&CategoryId='; + const TIMER_MIN = 10; const GOOGLE_API_KEY = "AIzaSyCmevVlr2Bh-c8W1VUzo8gt8JRY7n5PANw"; +const GET_BRANDS_LIST = 'epharmacy/api/categoryManufacturer?categoryids='; + +const GET_SEARCH_PRODUCTS = + 'epharmacy/api/searchproducts?fields=id,discount_ids,reviews,name,namen,localized_names,display_order,short_description,full_description,full_descriptionn,sku,order_minimum_quantity,order_maximum_quantity,price,old_price,images,is_rx,rx_message,rx_messagen,discount_name,discount_namen,approved_rating_sum,approved_total_reviews,allow_back_in_stock_subscriptions,stock_quantity,stock_availability,stock_availabilityn,discount_percentage&search_key='; + +const SCAN_QR_CODE = 'epharmacy/api/productbysku/'; + class AppGlobal { static var context; diff --git a/lib/config/localized_values.dart b/lib/config/localized_values.dart index 1f933203..8eea6cbb 100644 --- a/lib/config/localized_values.dart +++ b/lib/config/localized_values.dart @@ -1,3 +1,49 @@ +// --------- - -- - - - - - - - - ---------------- +// Used for Native through Platform Method Channel +// --------- - -- - - - - - - - - ---------------- +const Map platformLocalizedValues = { + "errorConnectingHmgNetwork": { + "en": "Sorry you are not connecting to HMG network", + "ar": "نعتذر لست متصل في شكبة مستشفى د.سليمان الحبيب" + }, + "successConnectingHmgNetwork": { + "en": "You connected to HMG network successfully, you can access the app", + "ar": + "تم التصال بشبكة د.سليمان الحبيب بنجاح, تستطيع الان استخدام تطبيق الحبيب" + }, + "failedConnectingHmgNetwork": { + "en": + "Sorry the connection to HMG network had been failed, make sure you are in range of HMG network", + "ar": + "نعتذر لقد فشل الاتصال بشبكة د.سليمان الحبيب, تاكد من وجودك داخل نطاق الشبكة" + }, + "alreadyConnectedHmgNetwork": { + "en": " You already connected to HMG network to access Alhabib app", + "ar": "انت متصل مسبقاً بالشبكة تستطيع استخدام تطبيق الحبيب" + }, + "somethingWentWrong": { + "en": "Sorry something went wrong please try again later", + "ar": "نعتذر لخدمتكم يرجى المحاولة لاحقا" + }, + "enablingWifi": {"en": "Enabling wifi...", "ar": "Enabling wifi..."}, + "connectedHmgNetworkWithInternet": { + "en": "Successfully connected to the HMG network to access internet", + "ar": "Successfully connected to the HMG network to access internet" + }, + "connectedToHmgNetworkWithNoInternet": { + "en": + "Successfully connected to the HMG network but it have no internet access", + "ar": + "Successfully connected to the HMG network but it have no internet access" + }, + "notConnectedToHmgNetworkSecurityIssue": { + "en": + "We are not able to connect you to HMG network due to security reasons", + "ar": + "We are not able to connect you to HMG network due to security reasons" + } +}; + const Map localizedValues = { 'dashboardScreenToolbarTitle': {'ar': 'الرئيسة', 'en': 'Home'}, 'settings': {'en': 'Settings', 'ar': 'الاعدادات'}, @@ -74,6 +120,11 @@ const Map localizedValues = { 'en': 'Please confirm the appointment to avoid cancellation', 'ar': 'يرجى تأكيد الموعد لتفادي الإلغاء' }, + "book-success-confirm-more-24-1-2": { + "en": + "The online payment process will be available 24 hours before the appointment.", + "ar": "- عملية الدفع الالكتروني ستكون متاحة قبل الموعد ب 24 ساعة." + }, 'upcoming-payment-pending': { 'en': 'Online Payment will be Activated before 24 Hours of Appointment Time', @@ -291,7 +342,7 @@ const Map localizedValues = { }, "ksa": {"en": "KSA", "ar": "السعودية"}, "dubai": {"en": "Dubai", "ar": "دبي"}, - "enter-email": {"en": "Enter Email", "ar": "ادخل البريد الالكتروني"}, + "enter-email": {"en": "Please Enter Email", "ar": "ادخل البريد الالكتروني"}, "family": {"en": "My Family", "ar": "عائلتي"}, "family-title": {"en": "My Family Files", "ar": "ملفات العائلة"}, "myFamily": {"en": "My Family", "ar": "ملفات العائلة"}, @@ -300,7 +351,7 @@ const Map localizedValues = { "recieved-requests": {"en": "Recieved Requests", "ar": "الطلبات المستلمة"}, "manage-files": {"en": "Manage Family Files", "ar": "إدارة ملفات العائلة"}, 'oxygenation': {'en': 'Oxygenation', 'ar': 'الأوكسجين'}, - 'bodyMeasurements': {'en': 'body Mass', 'ar': 'قياسات الجسم'}, + 'bodyMeasurements': {'en': 'body Mass Index', 'ar': 'مؤشر الكتلة'}, 'temperature': {'en': 'Temperature', 'ar': 'درجة الحرارة'}, 'pulse': {'en': 'Pulse', 'ar': 'النبض'}, 'respiration': {'en': 'Respiration', 'ar': 'التنفس'}, @@ -318,7 +369,7 @@ const Map localizedValues = { "reject-view": {"en": "Reject", "ar": "رفض"}, "delete-view": {"en": "Delete", "ar": "حذف"}, // "my-family": {"en": "MY FAMILY", "ar": "عائلتي"}, - "approvals": {"en": "Approvals", "ar": "موفقات التأمين"}, + "approvals": {"en": "Approvals", "ar": "موافقات التأمين"}, "approvalNo": {"en": "Approval No.: ", "ar": "رقم الموافقة: "}, "companyName": {"en": "Company Name ", "ar": "اسم الشركة: "}, "receiptOn": {"en": "Receipt on: ", "ar": "تاريخ الفاتورة: "}, @@ -351,6 +402,7 @@ const Map localizedValues = { "en": "All your medical records", 'ar': 'جميع سجلاتك الطبية' }, + "viewMore": {"en": "View More", 'ar': 'عرض المزيد'}, "homeHealthCareService": { "en": "Home Health Care Service", @@ -376,6 +428,7 @@ const Map localizedValues = { 'ar': 'عرض خدمات الحبيب الطبية' }, "viewAll": {"en": "View All", 'ar': 'عرض الكل'}, + "view": {"en": "View", 'ar': 'عرض'}, "ContactUs": {"en": "Contact Us", 'ar': 'الوصول إلينا'}, "ViewAllWaysReachUs": { "en": "View All Ways Reach Us", @@ -483,7 +536,7 @@ const Map localizedValues = { "LabOrders": {"en": "Lab Orders", "ar": "تحاليل المختبر"}, "BillNo": {"en": "Bill No :", "ar": "رقم الفاتورة"}, "Prescriptions": {"en": "Prescriptions", "ar": "الوصفات الطبية"}, - "History": {"en": "History", "ar": "السجل"}, + "History": {"en": "History", "ar": "السجلات"}, "OrderNo": {"en": "Order No", "ar": "رقم الطلب"}, "OrderDetails": {"en": "Order Details", "ar": "تفاصيل الطلب"}, "VitalSign": {"en": "Vital Sign", "ar": "العلامة حيوية"}, @@ -629,6 +682,82 @@ const Map localizedValues = { "ar": "خدمة الاشعة: هذه الخدمة تمكنك من الاطلاع على تقارير وصور الاشعة التي تمت في مجموعة الحبيب الطبية وكذلك ارسال التقرير عن طريق الايميل." }, + "orders": {"en": "Orders", "ar": "الطلبات"}, + "lakum": {"en": "Lakum", "ar": "لكم"}, + "wishlist": {"en": "Wishlist", "ar": "الرغبات"}, + "reviews": {"en": "Reviews", "ar": "التقيمات"}, + // "myPrescriptions": {"en": "My Prescriptions", "ar": "وصفاتي"}, + // "medicationRefill": {"en": "Medication Refill", "ar": "تعبئة الأدوية"}, + "pillReminder": {"en": "Pill Reminder", "ar": "تذكير الأدويه"}, + "shippingAddresses": {"en": "Shipping Addresses", "ar": "عناوين الشحن"}, + "reachUs": {"en": "Reach Us", "ar": "الوصول لنا"}, + "ourLocations": {"en": "Our Locations", "ar": "مواقعنا"}, + "edit": {"en": "Edit", "ar": "تعديل"}, + "delete": {"en": "Delete", "ar": " حذف"}, + "addAddress": {"en": "ADD A NEW ADDRESS", "ar": " اضافة عنوان جديد"}, + "addNewAddress": {"en": "Add New Address", "ar": " اضافة عنوان جديد"}, + "order": {"en": "My Order", "ar": " طلباتي"}, + "delivered": {"en": "Delivered", "ar": " تم التوصيل"}, + "pending": {"en": "Pending", "ar": " معلقة "}, + "processing": {"en": "Processing", "ar": " تحت المعالجة"}, + "cancelled": {"en": "Cancelled", "ar": " ملغي"}, + "writeReview": {"en": "Write Review", "ar": " اكتب تقييمك"}, + "shareReview": {"en": "SHARE REVIEW", "ar": " اكتب تقييمك"}, + "review": {"en": " reviews", "ar": " تقييمات"}, + "pendingOrder": {"en": " PENDING", "ar": " معلقة"}, + "deliveredOrder": {"en": " DELIVERED", "ar": " تم التوصيل"}, + "processingOrder": {"en": " PROCESSING", "ar": "قيد التنفيذ"}, + "cancelledOrder": {"en": " CANCELLED", "ar": "ملغي"}, + "compare": {"en": " Compare", "ar": "مقارنه"}, + "medicationsRefill": {"en": " Medication Refill", "ar": "طلب أعادة صرف"}, + "myPrescription": {"en": " My Prescriptions", "ar": "وصفاتي"}, + "quantity": {"en": " QTY ", "ar": "الكمية"}, + "backMyAccount": { + "en": "BACK TO MY ACCOUNT ", + "ar": " الرجوع لحسابي الشخصي" + }, + "reviewSuccessful": {"en": "Review Successful", "ar": " تقييم ناجح"}, + "reviewShared": { + "en": "Your review has been shared on product review section", + "ar": " تمت مشاركة تقييمك في قسم تقييم المنتج" + }, + "reviewComment": { + "en": "Your reviews help other to choose better product", + "ar": " تقييمك سوف يساعد الأخرين في اختيار المنتج الأفضل" + }, + "shippedMethod": {"en": "SHIP BY:", "ar": " الشحن بواسطة:"}, + "orderDetail": {"en": "Order Details", "ar": " تفاصيل الطلب"}, + "orderSummary": {"en": "Order Summary", "ar": " تفاصيل المنتج"}, + "subtotal": {"en": "Subtotal", "ar": " المجموع الفرعي"}, + "shipping": {"en": "Shipping", "ar": " الشحن"}, + "shipBy": {"en": "SHIP BY:", "ar": "الشحن عن طريق:"}, + "lakumPoints": {"en": "Lakum Points", "ar": "نقاط لكم"}, + "use": {"en": "USE", "ar": "استخدم"}, + "proceedPay": {"en": "PROCEED TO PAY", "ar": "المتابعة للدفع"}, + "vat": {"en": "VAT (15%)", "ar": "(15%) القيمة المضافة"}, + "inclusiveVat": {"en": "(inclusive VAT)", "ar": "(شامل الضريبة)"}, + "items": {"en": "item(s)", "ar": "عنصر"}, + "checkOut": {"en": "CHECK OUT", "ar": "الدفع"}, + "sar": {"en": "SAR", "ar": " ر.س "}, + "payOnline": {"en": "PAY ONLINE", "ar": "اتمام عملية الدفع "}, + "cancelOrder": {"en": "CANCEL ORDER", "ar": "الغاء الطلب "}, + "confirmAddress": {"en": "CONFIRM ADDRESS ", "ar": " تأكيد العنوان "}, + "confirmLocation": {"en": "CONFIRM LOCATION ", "ar": " تأكيد الموقع "}, + "conditionsHMG": {"en": "Terms & Conditions ", "ar": "الشروط و الأحكام "}, + "conditions": {"en": "Terms & Conditions of Lakum", "ar": "شروط و احكام لكم"}, + "confirmDeleteMsg": { + "en": "Are you sure! want to delete ", + "ar": "هل انت متأكد تريد الحذف " + }, + "confirmDelete": {"en": "DELETE", "ar": "حذف"}, + "confirmCancellation": { + "en": "Are you sure! want to cancel this order ", + "ar": "هل انت متأكد تريد حذف هذا المنتج " + }, + "orderNumber": {"en": "Order#: ", "ar": "الطلب: "}, + "orderDate": {"en": "Date", "ar": "التاريخ:"}, + "itemsNo": {"en": "items(s)", "ar": "عناصر"}, + "noOrder": {"en": "You Don't have any orders.", "ar": "ليس لديك طلبات"}, "TermsService": {"en": "Terms of Service", "ar": "شروط الخدمه"}, "Beforeusing": { @@ -687,6 +816,26 @@ const Map localizedValues = { "recentlyViewed": {"en": "Recently Viewed", "ar": "شوهدت مؤخرا"}, "bestSellers": {"en": "Best Sellers", "ar": "أفضل البائعين"}, "deleteAllItems": {"en": "Delete All Items", "ar": "حذف كافة العناصر"}, + "total": {"en": "Total", "ar": "المجموع"}, + "selectAddress": {"en": "Select Address", "ar": "حدد العنوان"}, + "shippingAddress": {"en": "SHIPPING ADDRESS", "ar": "عنوان الشحن"}, + "changeAddress": {"en": "Change Address", "ar": "تغيير العنوان"}, + "selectPaymentOption": { + "en": "Select Payment Option", + "ar": "حدد خيار الدفع" + }, + "changeMethod": {"en": "Change Method", "ar": "تغيير خيار الدفع"}, + "reviewOrder": {"en": "Review Order", "ar": "مراجعة الطلب"}, + "active": {"en": "ACTIVE", "ar": "فعال"}, + "inactive": {"en": "INACTIVE", "ar": "غير فعال"}, + "balance": {"en": "BALANCE", "ar": "الحالي"}, + "gained": {"en": "GAINED", "ar": "المكتسب"}, + "consumed": {"en": "CONSUMED", "ar": "المستهلك"}, + "transferred": {"en": "TRANSFERRED", "ar": "المحول"}, + "checkBeneficiary": {"en": "CHECK BENEFICIARY", "ar": "تحقق من المستفيد"}, + "beneficiaryName": {"en": "Beneficiary Name", "ar": "اسم المستفيد"}, + "accountActivation": {"en": "Account Activation", "ar": "تفعيل الحساب"}, + "acceptLbl": {"en": "Accept", "ar": "موافقة"}, "select-gender": {"en": "Select Gender", "ar": "اختر الجنس"}, "i-am-a": {"en": "I am a ...", "ar": "أنا ..."}, "select-age": {"en": "Select Your Age", "ar": "حدد العمر"}, @@ -696,6 +845,15 @@ const Map localizedValues = { "en": "Drag point to change your age", "ar": "اسحب لتغيير عمرك" }, + + "categorise": {"en": "Categories", "ar": "التطبيقات"}, + "wishList": {"en": "WishList", "ar": "الرغبات"}, + "myAccount": {"en": "My Account", "ar": "حسابي"}, + "cart": {"en": "Cart", "ar": "التسوق"}, + "searchProductHere": { + "en": "Search Product here", + "ar": "ابحث في الطلب الخاص بك" + }, "HHCNotAuthMsg": { "en": "This service provides a set of home health care services, continuous and comprehensive follow-up in their places of residence for those who cannot access health facilities, such as (laboratory analyzes - radiology - vaccinations - physical therapy), etc.", @@ -929,7 +1087,7 @@ const Map localizedValues = { "en": "Please enter the subject", "ar": "يرجى ادخال الموضوع" }, - "empty-message": {"en": "Please enter message", "ar": "يرجى ادخال الموضوع"}, + "empty-message": {"en": "Please enter message", "ar": "يرجى ادخال الرسالة"}, "select-attachment": {"en": "Select Attachment", "ar": "إختر المرفق"}, "complain-appo": {"en": "Complaint for appointment", "ar": "شكوى على موعد"}, "complain-without-appo": { @@ -940,7 +1098,10 @@ const Map localizedValues = { "message-type": {"en": "Message Type", "ar": "نوع الرسالة"}, "compliment": {"en": "compliment", "ar": "ثناء"}, "suggestion": {"en": "Suggestion", "ar": "إقتراح"}, - "your-feedback": {"en": "Your feedback was sent", "ar": "إقتراح"}, + "your-feedback": { + "en": "Your feedback was sent", + "ar": "لقد تم ارسال اقراحك شكرا لك" + }, "select-part": { "en": "Please select the part that complain about", "ar": "يرجى تحديد الجزء الذي تشكو منه" @@ -948,7 +1109,6 @@ const Map localizedValues = { "number": {"en": "Number", "ar": "الرقم"}, "not-classified": {"en": "Not classified", "ar": "غير محدد"}, "selectClinic": {"en": "Select Clinic", "ar": " بحث بالعيادة"}, - "reviews": {"en": "Reviews", "ar": "تقييمات"}, "searchItemError": { "en": "Item name should be more than 3 character ", "ar": "يجب أن يكون اسم العنصر أكثر من 3 أحرف" @@ -965,6 +1125,17 @@ const Map localizedValues = { "en": "To view the terms and conditions", "ar": "عرض الشروط والأحكام" }, + "wantConnectHmgNetwork": { + "en": + "Dear customer there is no internet access, Do you want to connect with HMG network to use our app, make sure you are in range of HMG network", + "ar": + "عزيز العميل لا يوجد اتصال بالإنترنت, هل تريد الاتصال بشبكة مستشفى د. سليمان الحبيب لاستخدام التطبيق. يجب عليك ان تكون في نطاق شبكة المستشفى" + }, + "failedToAccessHmgServices": { + "en": "Connected with HMG Network,\n\nBut failed to access HMG services", + "ar": "Connected with HMG Network,\n\nBut failed to access HMG services" + }, + "offerAndPackages": {"en": "Offers And Packages", "ar": "العروض والباقات"}, "InvoiceNo": {"en": " Invoice No", "ar": "رقم الفاتورة"}, "SpecialResult": {"en": " Special Result", "ar": "نتيجة خاصة"}, "GeneralResult": {"en": "General Result", "ar": "نتيجة عامة"}, @@ -1020,7 +1191,6 @@ const Map localizedValues = { "en": "Select Transportation Method", "ar": "حدد طريقة النقل" }, - "sar": {"en": "SR", "ar": "ر.س"}, "RRT-direction-heading": {"en": "Select Direction", "ar": "حدد الاتجاه"}, "to-hospital": {"en": "To Hospital", "ar": "الى المستشفى"}, "from-hospital": {"en": "From Hospital", "ar": "من المستشفى"}, @@ -1029,7 +1199,7 @@ const Map localizedValues = { "pickup-location": {"en": "Pickup Location", "ar": "نقطة الانطلاق"}, "pickup-spot": {"en": "Pickup Spot", "ar": "نقطة اللقاء"}, "inside-home": {"en": "Inside Home", "ar": "داخل المنزل"}, - "have-appo": {"en": "Do you have an appointment?", "ar": "هل لديك موعد؟"}, + "have-appo": {"en": "Do you have an appointment ?", "ar": "هل لديك موعد ؟"}, "dropoff-location": {"en": "Dropoff Location", "ar": "نقطة الوصول"}, "select-all": { "en": "Please select all fields", @@ -1073,6 +1243,10 @@ const Map localizedValues = { "ar": "هذه الخدمة تم تصميمها لتتمكن من ربط الملفات الطبية للعائلة بملفك الطبي حتى تتمكن من إدارة سجلاتهم عن طريق تسجيل الدخول إلى ملفك الطبي." }, + "update-succ": { + "en": "Successfully updated profile", + "ar": "تم تحديث البيانات بنجاح" + }, "dental-complains": {"en": "Symptoms", "ar": "الأعراض"}, "empty-result": { "en": "There is no search results found", @@ -1123,36 +1297,178 @@ const Map localizedValues = { "requested": {"en": "Requested", "ar": "مطلوب"}, "ready": {"en": "Ready", "ar": "جاهز"}, "completed": {"en": "Completed", "ar": "مكتمل"}, - "cancelled": {"en": "Cancelled", "ar": "ملغى"}, "request-medical-report": { "en": "Request medical report", "ar": "طلب تقرير طبي" }, - - "vaccination": {"en": "Vaccination", "ar": "جدول التطعيمات"}, - "welcomeBack": {"en": "Welcome back", "ar": "مرحبا مرة أخرى"}, + "insur-cards": {"en": "Insurance Cards", "ar": "بطاقات التأمين"}, + 'labResult': {"en": "Lab results", "ar": "نتائج التحاليل المخبرية"}, + 'details': {'en': 'Details', 'ar': 'التفاصيل'}, + "age": {"en": "Age", "ar": "العمر"}, + "active-insurence": {"en": "Active", "ar": "نشطة"}, + "not-active": {"en": "Not Active", "ar": "غير نشط"}, + "card-detail": {"en": "Insurance Details", "ar": "منافعك التامينية"}, + "Dr": {"en": "Dr. ", "ar": "الدكتور."}, + "empty": {"en": "You do not have any records.", "ar": "ليس لديك أي سجلات"}, + "last-visit": { + "en": "How was your last visit with doctor?", + "ar": "كيف تقيم زيارتك الأخيرة للطبيب؟" + }, + "tap-title": {"en": "Please rate the doctor", "ar": "يرجى تقييم الطبيب"}, + "later": {"en": "Later", "ar": "لاحقاً"}, + "sendSuc": { + "en": "A copy has been sent to the email", + "ar": "تم إرسال نسخة إلى البريد الإلكتروني" + }, "instructions": { "en": - "Please ensure that the email address is up-to-date and process to view the schedule", - "ar": "يرجى التأكد من صحة عنوان البريد الالكتروني و المتابعة لعرض الجدول " + "You can now talk directly to the appointments department by chat or request a call back", + "ar": + "يمكنك الان التحدث مباشرة مع قسم المواعيد عن طريق خدمة المحادثة النصية أو طلب معاودة الاتصال" + }, + "instructions-pharmacies": { + "en": + "You can now talk directly to the pharmacist by chat or request a call back", + "ar": + "يمكنك الآن التحدث مباشرة إلى الصيدلي عن طريق الدردشة أو طلب معاودة الاتصال" + }, + "select-hospital": {"en": "Choose Hospital", "ar": "اختر المستشفى"}, + "start": {"en": "Start", "ar": "ابدأ"}, + "info-chat": { + "en": + "This service allows you to chat with customer service directly without the need to call.", + "ar": + "المحادثة المباشرة: هذه الخدمة تمكنك التحدث كتابياً مع خدمة العملاء مباشرة دون الحاجة الى الاتصال هاتفياً." + }, + "last-appointment": { + "en": "How was your appointment?", + "ar": "كيف كان موعدك الطبي ؟" + }, + "rate-clinic": {"en": "Please rate the clinic", "ar": "يرجى تقييم العيادة"}, + "fetch-data": {"en": "Fetch Data", "ar": "تحديث الان"}, + "rate": {"en": "Rate", "ar": "تقييم"}, + "send-email": { + "en": "Send a copy of this report to the email", + "ar": "أرسل نسخة من هذا التقرير إلى البريد الإلكتروني" }, "update-email": {"en": "Update Email", "ar": "تحديث البريد الالكتروني"}, - - "updated-email": { - "en": "Updated email successfully", - "ar": "تم تحديث البريد الالكتروني" + "booked-success": { + "en": "The appointment has been successfully booked.", + "ar": "لقد تم حجز الموعد بنجاح" + }, + "appo-reminder-select-option-30": { + "en": "Before 30 Mins", + "ar": "قبل 30 دقيقة" + }, + "appo-reminder-select-option-60": { + "en": "Before 1 Hour", + "ar": "قبل ساعة واحدة" + }, + "appo-reminder-select-option-90": { + "en": "Before 1 Hour and 30 mins", + "ar": "قبل ساعة و 30 دقيقة" + }, + "appo-reminder-select-option-120": { + "en": "Before 2 Hours", + "ar": "قبل ساعتين" + }, + "noDataAvailable": { + "en": "No data available", + "ar": " لا يوجد بيانات متاحة " + }, + "thename": {"en": "The Name", "ar": "الاسم"}, + "noSearchResult": {"en": "No Search Result", "ar": "لا توجد نتيجة بحث"}, + "selectFileSouse": {"en": "Select file souse", "ar": "حدد الملف"}, + "gallery": {"en": "Gallery", "ar": "معرض الصور"}, + "camera": {"en": "Camera", "ar": "كاميرا"}, + "med-report": {"en": "Medical Reports", "ar": "التقارير الطبية"}, + "new-med-report": {"en": "Requests", "ar": "الطلبات"}, + "requestReport": {"en": "Request a report", "ar": " طلب تقرير"}, + "confirm-msg-report": { + "en": "Request for medical report?", + "ar": "طلب تقرير طبي؟" + }, + "successSendReport": { + "en": "The request has been submitted successfully", + "ar": "تم تنفيذ طلبك بنجاح" + }, + "pulseTitle": {"en": "Heart rate", "ar": "معدل النبض بالدقيقة"}, + "systolic-lng": {"en": "Systolic", "ar": "الإنقباض"}, + "diastolic-lng": {"en": "Diastolic", "ar": "الإنبساط"}, + "policy-holder": {"en": "Policy Holder", "ar": "حامل بطاقة التأمين"}, + "policy-no": {"en": "Policy Number", "ar": "رقم سياسات"}, + "agree": { + "en": "I agree, this is the correct information", + "ar": "موافق، هذه المعلومات صحيحة" + }, + "disagree": { + "en": "No, this is not the correct information", + "ar": "غير موافق، هذه المعلومات غير الصحيحة" + }, + "expiry-date": {"en": "Expiry Date", "ar": "تاريخ انتهاء الصلاحية"}, + "class": {"en": "Class", "ar": "فئة"}, + "approval": {"en": "Approval", "ar": "موافقة"}, + "no-data": {"en": "No data found", "ar": "لاتوجد بيانات"}, + "insurance-details": {"en": "Insurance Details", "ar": "تفاصيل التأمين"}, + "nearest-hospital": {"en": "Nearest Hospital", "ar": "أقرب مستشفى"}, + "request-sent": { + "en": "Request sent successfully", + "ar": "تم إرسال الطلب بنجاح" + }, + "message-sent": { + "en": "Message sent successfully", + "ar": "تم إرسال الرسالة بنجاح" + }, + "sent-on": {"en": "Sent on", "ar": "أرسلت في"}, + "attach-insurace-image": { + "en": "Attach insurance card image", + "ar": "إرفاق صورة بطاقة التأمين" + }, + "upload-without-image": { + "en": "You can still submit, if you don't have Insurance Image", + "ar": "لا يزال بإمكانك الإرسال ، إذا لم يكن لديك صورة تأمين" + }, + "info-insur-cards": { + "en": + "This service allows you to view all the insurance cards that recorded during your visits to Al Habib Medical Group in addition to:", + "ar": + "خدمة بطاقات التامين: هذه الخدمة تمكنك من الاطلاع على جميع بطاقات التامين والتي تم تسجيلها اثناء زياراتك لمجموعة الحبيب الطبية بالاضافة الى:" + }, + "scan-now": { + "en": "If you have a card / Document Scan now", + "ar": "إذا كانت لديك بطاقة / مستند ارفقها الان" }, + "liveCare": {"en": "Live Care", "ar": "لايف كير"}, + "topBrands": {"en": "Top Brands", "ar": "اعلى العلامات التجارية"}, - "view-list-children": { - "en": "View List of Children", - "ar": "عرض قائمة الأطفال" + "notifyMe": {"en": "notify me", "ar": "اعلمني"}, + "specification": {"en": "Specification", "ar": "تخصيص"}, + + "availability": {"en": "Availability", "ar": "التوفر"}, + + "vaccination": {"en": "Vaccination", "ar": "جدول التطعيمات"}, + "welcomeBack": {"en": "Welcome back", "ar": "مرحبا مرة أخرى"}, + "quantitySize": {"en": "Quantity", "ar": "كميه"}, + "addToCart": {"en": "add to cart", "ar": "إضفة للسلة"}, + "buyNow": {"en": "buy now", "ar": "إشتري الان"}, + "quantityShortcut": {"en": "QTY", "ar": "كمية"}, + + "pharmacyServiceTermsCondition": { + "en": + "I agree with the terms of service and I adhere to them unconditionally", + "ar": " أوافق على شروط الخدمة وألتزم بها دون قيد أو شرط" }, + "Year": {"en": "YEAR", "ar": "السنة"}, + "Month": {"en": "MONTH", "ar": "الشهر"}, + "point": {"en": "POINT", "ar": "النقاط"}, + "riyal": {"en": "RIYAL", "ar": "الريال"}, + "termOfService": {"en": "Terms of service", "ar": "شروط الخدمة"}, + "shoppingCart": {"en": "Shopping Cart", "ar": "عربة التسوق"}, "add-child": {"en": "Add New Child", "ar": "اضافة طفل"}, "child-name": {"en": "Child Name", "ar": "اسم الطفل"}, "childDob": {"en": "Birth Date", "ar": "تاريخ الولادة"}, - "delete": {"en": "Delete", "ar": "حذف"}, "deleted-child-mes": { "en": "The request was successful. The children have removed from the vaccination schedule subscription service.", @@ -1160,6 +1476,33 @@ const Map localizedValues = { }, "deleted-child": {"en": "Delete child", "ar": "إالغاء الطفل"}, "visit": {"en": "Visit", "ar": "زيارة"}, + "referralStatus": {"en": "Referral Status", "ar": "حالة الإحالة"}, + "referralDate": {"en": "Referral Date", "ar": "تاريخ الإحالة"}, + "patientName": {"en": "Patient Name", "ar": "اسم المريض"}, + "referralNumber": {"en": "Referral Number", "ar": "رقم الإحالة"}, + "requestID": {"en": "Request ID", "ar": " رقم الطلب"}, + "OrderStatus": {"en": "Status", "ar": "الحاله"}, + "pickupDate": {"en": "Pickup Date", "ar": "التاريخ"}, + "serviceName": {"en": "Service Name", "ar": " اسم الخدمة"}, + "orderLocation": {"en": "Location", "ar": "الموقع"}, + "selectService": {"en": "Select Service", "ar": "حدد الخدمة"}, + "coveredService": {"en": "Covered Service : ", "ar": " الخدمات المغطاة : "}, + "selectedService": { + "en": "Selected Service : ", + "ar": " الخدمات المختارة : " + }, + "cancelOrderMsg": { + "en": "Are you sure!! want to cancel this order", + "ar": "هل أنت واثق!! تريد إلغاء هذا الطلب" + }, + "processDoneSuccessfully": { + "en": "Process Done Successfully", + "ar": "تمت العملية بنجاح" + }, + "selectHomeHealthCareServices": { + "en": "Select Home Health Care Services", + "ar": " حدد خدمات الرعاية الصحية المنزلية" + }, "description-vaccination": {"en": "Description", "ar": "وصف"}, "due-date": {"en": "Due date", "ar": "تاريخ الاستحقاق"}, "valid-email": { @@ -1192,28 +1535,6 @@ const Map localizedValues = { "ar": " تم إرسال طلب الإحالة بنجاح ، وسيتم الاتصال بك في أسرع وقت ممكن لإكمال العملية. رقم طلب الإحالة" }, - "Year": {"en": "YEAR", "ar": "السنة"}, - "Month": {"en": "MONTH", "ar": "الشهر"}, - "point": {"en": "POINT", "ar": "النقاط"}, - "riyal": {"en": "RIYAL", "ar": "الريال"}, - "termOfService": {"en": "Terms of service", "ar": "شروط الخدمة"}, - "shoppingCart": {"en": "Shopping Cart", "ar": "عربة التسوق"}, - - "referralStatus": {"en": "Referral Status", "ar": "حالة الإحالة"}, - "referralDate": {"en": "Referral Date", "ar": "تاريخ الإحالة"}, - "patientName": {"en": "Patient Name", "ar": "اسم المريض"}, - "referralNumber": {"en": "Referral Number", "ar": "رقم الإحالة"}, - "requestID": {"en": "Request ID", "ar": " رقم الطلب"}, - "OrderStatus": {"en": "Status", "ar": "الحاله"}, - "pickupDate": {"en": "Pickup Date", "ar": "التاريخ"}, - "serviceName": {"en": "Service Name", "ar": " اسم الخدمة"}, - "orderLocation": {"en": "Location", "ar": "الموقع"}, - "selectService": {"en": "Select Service", "ar": "حدد الخدمة"}, - "coveredService": {"en": "Covered Service : ", "ar": " الخدمات المغطاة : "}, - "selectedService": { - "en": "Selected Service : ", - "ar": " الخدمات المختارة : " - }, "help": {"en": "Help", "ar": "مساعدة"}, @@ -1222,19 +1543,35 @@ const Map localizedValues = { "Hi, This is HABIB, your personal assistant. I'm here to assist you by voice commands. How can I help?", "ar": "مرحباً ، معك حبيب مساعدك الشخصي. أنا هنا لمساعدتك بالأوامر الصوتية." }, + "updated-email": { + "en": "Updated email successfully", + "ar": "تم تحديث البريد الالكتروني" + }, - "selectAddress": {"en": "Select Address", "ar": "حدد العنوان"}, - "addNewAddress": {"en": "Add New Address", "ar": "أضف عنوان جديد"}, - "cancelOrderMsg": { - "en": "Are you sure!! want to cancel this order", - "ar": "هل أنت واثق!! تريد إلغاء هذا الطلب" + "view-list-children": { + "en": "View List of Children", + "ar": "عرض قائمة الأطفال" }, - "processDoneSuccessfully": { - "en": "Process Done Successfully", - "ar": "تمت العملية بنجاح" + "covidTest": {"en": "COVID-19 TEST", "ar": "فحص كورونا"}, + "driveThru": {"en": "Drive-Thru", "ar": "من السيارة"}, + "NearestErDesc": { + "en": + "\nThis service Displays nearest branch\n among all the branches of All Habib \n medical Group based on your current Location", + "ar": + "\nتعرض هذه الخدمة أقرب فرع\n من بين جميع فروع مجموعة \nالحبيب الطبية بناءً على موقعك الحالي." }, - "selectHomeHealthCareServices": { - "en": "Select Home Health Care Services", - "ar": " حدد خدمات الرعاية الصحية المنزلية" + "NearestEr": {"en": "Nearest ER", "ar": "أقرب ER"}, + "infoCMC": { + "en": + "Through this service, you can request a set of tests that help you and your doctor to understand the current health condition and then identify potential risks.", + "ar": + "من خلال هذه الخدمة يمكنك طلب مجموعة من الفحوصات التي تساعدك وتساعد طبيبك في فهم حالتك الصحية الحالية ومن ثم تحديد المخاطر المحتملة" + }, + "instructionAgree": { + "en": + "This monthly Health Summary Report reflects the health indicators and analysis results of the latest visits. Please note that this will be sent automatically from the system and it's not considered as an official report so no medical decisions should be taken based on it.", + "ar": + "هذا ملخص التقرير الصحي الشهري و الذي يسرد المؤشرات الصحية و نتائج التحاليل لأخر الزيارات. يرجى ملاحظة أن هذا التقرير هو تقرير يتم ارساله بشكل آلي من النظام و لا يعتبر رسمي و لا تؤخذ عليه أي قرارات طبية" }, + "reqId": {"en": "Request ID:", "ar": " رقم الطلب"}, }; diff --git a/lib/config/shared_pref_kay.dart b/lib/config/shared_pref_kay.dart index 39e2649d..4f7b2646 100644 --- a/lib/config/shared_pref_kay.dart +++ b/lib/config/shared_pref_kay.dart @@ -19,8 +19,12 @@ const IS_LIVECARE_APPOINTMENT = 'is_livecare_appointment'; const IS_VIBRATION = 'is_vibration'; const THEME_VALUE = 'is_vibration'; const MAIN_USER = 'main-user'; -const WEATHER = 'weather'; const PHARMACY_LAST_VISITED_PRODUCTS = 'last-visited'; const PHARMACY_CUSTOMER_ID = 'costumer-id'; const IS_ROBOT_VISIBLE = 'robot-visible'; const IS_ROBOT_INIT = 'robot-init'; +const HMG_GEOFENCES = 'hmg-geo-fences'; +const WEATHER = 'weather'; +const BLOOD_TYPE = 'blood-type'; +const NOTIFICATION_COUNT = 'notification-count'; +const PHARMACY_SELECTED_ADDRESS = 'selected-address'; diff --git a/lib/core/model/ImagesInfo.dart b/lib/core/model/ImagesInfo.dart index 5ab48fb3..54e8042b 100644 --- a/lib/core/model/ImagesInfo.dart +++ b/lib/core/model/ImagesInfo.dart @@ -1,6 +1,7 @@ class ImagesInfo { final String imageAr; final String imageEn; + final bool isAsset; - ImagesInfo({this.imageAr, this.imageEn}); + ImagesInfo({this.imageAr, this.imageEn, this.isAsset = false}); } diff --git a/lib/core/model/er/PickUpRequestPresOrder.dart b/lib/core/model/er/PickUpRequestPresOrder.dart index 376e30ae..c4f359f5 100644 --- a/lib/core/model/er/PickUpRequestPresOrder.dart +++ b/lib/core/model/er/PickUpRequestPresOrder.dart @@ -18,8 +18,8 @@ class PickUpRequestPresOrder { int pickupSpot; dynamic dropoffLocationId; int transportationMethodId; - double cost; - double vAT; + dynamic cost; + dynamic vAT; double totalPrice; int amountCollected; int selectedAmbulate; diff --git a/lib/core/model/geofencing/requests/GeoZonesRequestModel.dart b/lib/core/model/geofencing/requests/GeoZonesRequestModel.dart new file mode 100644 index 00000000..219c46ae --- /dev/null +++ b/lib/core/model/geofencing/requests/GeoZonesRequestModel.dart @@ -0,0 +1,11 @@ +class GeoZonesRequestModel { + final String PatientID; + + GeoZonesRequestModel({this.PatientID}); + + Map toFlatMap() { + if (PatientID == null) return {}; + + return {"PatientID": PatientID.toString()}; + } +} diff --git a/lib/core/model/geofencing/requests/LogGeoZoneRequestModel.dart b/lib/core/model/geofencing/requests/LogGeoZoneRequestModel.dart new file mode 100644 index 00000000..e21a7d69 --- /dev/null +++ b/lib/core/model/geofencing/requests/LogGeoZoneRequestModel.dart @@ -0,0 +1,12 @@ +import 'package:flutter/cupertino.dart'; + +class LogGeoZoneRequestModel { + final int PointsID; + final int GeoType; + + LogGeoZoneRequestModel({@required this.PointsID, @required this.GeoType}); + + Map toFlatMap() { + return {"PointsID": PointsID.toString(), "GeoType": GeoType.toString()}; + } +} diff --git a/lib/core/model/geofencing/responses/GeoZonesResponseModel.dart b/lib/core/model/geofencing/responses/GeoZonesResponseModel.dart new file mode 100644 index 00000000..58771fab --- /dev/null +++ b/lib/core/model/geofencing/responses/GeoZonesResponseModel.dart @@ -0,0 +1,62 @@ +import 'package:diplomaticquarterapp/generated/json/base/json_convert_content.dart'; +import 'package:diplomaticquarterapp/generated/json/base/json_field.dart'; + +class GeoZonesResponseModel with JsonConvert { + @JSONField(name: "GEOF_ID") + int geofId; + @JSONField(name: "Description") + String description; + @JSONField(name: "DescriptionN") + String descriptionN; + @JSONField(name: "Latitude") + String latitude; + @JSONField(name: "Longitude") + String longitude; + @JSONField(name: "Radius") + int radius; + @JSONField(name: "Type") + int type; + @JSONField(name: "ProjectID") + int projectID; + @JSONField(name: "ImageURL") + String imageURL; + @JSONField(name: "IsCity") + bool isCity; + + // Outside Server Response + bool isRegistered = false; + bool onEntry = true; + bool onExit = true; + + String geofenceId() { + return "$geofId\_${description.replaceAll(" ", "")}"; + } + + static get(String coordinates, int radius, String name) { + coordinates = coordinates.replaceAll(" ", ""); + var geo = GeoZonesResponseModel(); + geo.latitude = coordinates.split(",").first; + geo.longitude = coordinates.split(",").last; + geo.radius = radius; + geo.description = name; + return geo; + } + + static GeoZonesResponseModel zkH() { + var geo = GeoZonesResponseModel(); + geo.latitude = "24.691136"; + geo.longitude = "46.650116"; + geo.radius = 150; + geo.description = "zkH"; + return geo; + } + + static GeoZonesResponseModel csO() { + var geo = GeoZonesResponseModel(); + geo.latitude = "24.7087913"; + geo.longitude = "46.6656461"; + geo.radius = 150; + geo.description = "csO"; + return geo; + } +} diff --git a/lib/core/model/geofencing/responses/LogGeoZoneResponseModel.dart b/lib/core/model/geofencing/responses/LogGeoZoneResponseModel.dart new file mode 100644 index 00000000..2242755f --- /dev/null +++ b/lib/core/model/geofencing/responses/LogGeoZoneResponseModel.dart @@ -0,0 +1,26 @@ +import 'package:diplomaticquarterapp/generated/json/base/json_convert_content.dart'; +import 'package:diplomaticquarterapp/generated/json/base/json_field.dart'; + +class LogGeoZoneResponseModel with JsonConvert { + @JSONField(name: "LanguageID") + int languageID; + @JSONField(name: "ErrorCode") + dynamic errorCode; + @JSONField(name: "ErrorEndUserMessage") + String errorEndUserMessage; + @JSONField(name: "ErrorEndUserMessageN") + dynamic errorEndUserMessageN; + @JSONField(name: "ErrorMessage") + dynamic errorMessage; + @JSONField(name: "ErrorType") + int errorType; + @JSONField(name: "IsAuthenticated") + bool isAuthenticated; + @JSONField(name: "SuccessMsg") + dynamic successMsg; + @JSONField(name: "SuccessMsgN") + dynamic successMsgN; + int statusCode; + @JSONField(name: "MessageStatus") + int messageStatus; +} diff --git a/lib/core/model/insurance/Insurance_card_details.dart b/lib/core/model/insurance/Insurance_card_details.dart new file mode 100644 index 00000000..ddc33b2e --- /dev/null +++ b/lib/core/model/insurance/Insurance_card_details.dart @@ -0,0 +1,88 @@ +class InsuranceCardDetailsModel { + int approvalLimit; + int companyGroupID; + String companyName; + String companyRemarks; + String dOB; + int deductible; + String effectiveFrom; + String effectiveTo; + String eligabilityFailureReason; + bool isMemberEligible; + String memberID; + String memberName; + String memberStatus; + dynamic message; + String nationalId; + String policyNumber; + String responseMessage; + String room; + String subCategory; + + InsuranceCardDetailsModel( + {this.approvalLimit, + this.companyGroupID, + this.companyName, + this.companyRemarks, + this.dOB, + this.deductible, + this.effectiveFrom, + this.effectiveTo, + this.eligabilityFailureReason, + this.isMemberEligible, + this.memberID, + this.memberName, + this.memberStatus, + this.message, + this.nationalId, + this.policyNumber, + this.responseMessage, + this.room, + this.subCategory}); + + InsuranceCardDetailsModel.fromJson(Map json) { + approvalLimit = json['ApprovalLimit']; + companyGroupID = json['CompanyGroupID']; + companyName = json['CompanyName']; + companyRemarks = json['CompanyRemarks']; + dOB = json['DOB']; + deductible = json['Deductible']; + effectiveFrom = json['EffectiveFrom']; + effectiveTo = json['EffectiveTo']; + eligabilityFailureReason = json['EligabilityFailureReason']; + isMemberEligible = json['IsMemberEligible']; + memberID = json['MemberID']; + memberName = json['MemberName']; + memberStatus = json['MemberStatus']; + message = json['Message']; + nationalId = json['NationalId']; + policyNumber = json['PolicyNumber']; + responseMessage = json['ResponseMessage']; + room = json['Room']; + subCategory = json['SubCategory']; + } + + Map toJson() { + final Map data = new Map(); + data['ApprovalLimit'] = this.approvalLimit; + data['CompanyGroupID'] = this.companyGroupID; + data['CompanyName'] = this.companyName; + data['CompanyRemarks'] = this.companyRemarks; + data['DOB'] = this.dOB; + data['Deductible'] = this.deductible; + data['EffectiveFrom'] = this.effectiveFrom; + data['EffectiveTo'] = this.effectiveTo; + data['EligabilityFailureReason'] = this.eligabilityFailureReason; + data['IsMemberEligible'] = this.isMemberEligible; + data['MemberID'] = this.memberID; + data['MemberName'] = this.memberName; + data['MemberStatus'] = this.memberStatus; + data['Message'] = this.message; + data['NationalId'] = this.nationalId; + data['PolicyNumber'] = this.policyNumber; + data['ResponseMessage'] = this.responseMessage; + data['Room'] = this.room; + data['SubCategory'] = this.subCategory; + return data; + } +} diff --git a/lib/core/model/insurance/insurance_card_update.dart b/lib/core/model/insurance/insurance_card_update_model.dart similarity index 100% rename from lib/core/model/insurance/insurance_card_update.dart rename to lib/core/model/insurance/insurance_card_update_model.dart diff --git a/lib/core/model/labs/LabOrderResult.dart b/lib/core/model/labs/LabOrderResult.dart new file mode 100644 index 00000000..ecb4ae65 --- /dev/null +++ b/lib/core/model/labs/LabOrderResult.dart @@ -0,0 +1,88 @@ +class LabOrderResult { + String description; + dynamic femaleInterpretativeData; + int gender; + int lineItemNo; + dynamic maleInterpretativeData; + dynamic notes; + String packageID; + int patientID; + String projectID; + String referanceRange; + String resultValue; + String sampleCollectedOn; + String sampleReceivedOn; + String setupID; + dynamic superVerifiedOn; + String testCode; + String uOM; + String verifiedOn; + String verifiedOnDateTime; + + LabOrderResult( + {this.description, + this.femaleInterpretativeData, + this.gender, + this.lineItemNo, + this.maleInterpretativeData, + this.notes, + this.packageID, + this.patientID, + this.projectID, + this.referanceRange, + this.resultValue, + this.sampleCollectedOn, + this.sampleReceivedOn, + this.setupID, + this.superVerifiedOn, + this.testCode, + this.uOM, + this.verifiedOn, + this.verifiedOnDateTime}); + + LabOrderResult.fromJson(Map json) { + description = json['Description']; + femaleInterpretativeData = json['FemaleInterpretativeData']; + gender = json['Gender']; + lineItemNo = json['LineItemNo']; + maleInterpretativeData = json['MaleInterpretativeData']; + notes = json['Notes']; + packageID = json['PackageID']; + patientID = json['PatientID']; + projectID = json['ProjectID']; + referanceRange = json['ReferanceRange']; + resultValue = json['ResultValue']; + sampleCollectedOn = json['SampleCollectedOn']; + sampleReceivedOn = json['SampleReceivedOn']; + setupID = json['SetupID']; + superVerifiedOn = json['SuperVerifiedOn']; + testCode = json['TestCode']; + uOM = json['UOM']; + verifiedOn = json['VerifiedOn']; + verifiedOnDateTime = json['VerifiedOnDateTime']; + } + + Map toJson() { + final Map data = new Map(); + data['Description'] = this.description; + data['FemaleInterpretativeData'] = this.femaleInterpretativeData; + data['Gender'] = this.gender; + data['LineItemNo'] = this.lineItemNo; + data['MaleInterpretativeData'] = this.maleInterpretativeData; + data['Notes'] = this.notes; + data['PackageID'] = this.packageID; + data['PatientID'] = this.patientID; + data['ProjectID'] = this.projectID; + data['ReferanceRange'] = this.referanceRange; + data['ResultValue'] = this.resultValue; + data['SampleCollectedOn'] = this.sampleCollectedOn; + data['SampleReceivedOn'] = this.sampleReceivedOn; + data['SetupID'] = this.setupID; + data['SuperVerifiedOn'] = this.superVerifiedOn; + data['TestCode'] = this.testCode; + data['UOM'] = this.uOM; + data['VerifiedOn'] = this.verifiedOn; + data['VerifiedOnDateTime'] = this.verifiedOnDateTime; + return data; + } +} diff --git a/lib/core/model/labs/lab_result.dart b/lib/core/model/labs/lab_result.dart index c9acd809..2deb13f3 100644 --- a/lib/core/model/labs/lab_result.dart +++ b/lib/core/model/labs/lab_result.dart @@ -1,9 +1,9 @@ class LabResult { String description; - Null femaleInterpretativeData; + dynamic femaleInterpretativeData; int gender; int lineItemNo; - Null maleInterpretativeData; + dynamic maleInterpretativeData; String notes; String packageID; int patientID; @@ -13,11 +13,11 @@ class LabResult { String sampleCollectedOn; String sampleReceivedOn; String setupID; - Null superVerifiedOn; + dynamic superVerifiedOn; String testCode; String uOM; String verifiedOn; - Null verifiedOnDateTime; + dynamic verifiedOnDateTime; LabResult( {this.description, @@ -92,8 +92,7 @@ class LabResultList { String filterName = ""; List patientLabResultList = List(); - LabResultList( - {this.filterName, LabResult lab}) { + LabResultList({this.filterName, LabResult lab}) { patientLabResultList.add(lab); } } diff --git a/lib/core/model/labs/patient_lab_orders.dart b/lib/core/model/labs/patient_lab_orders.dart index 26daaff0..3c49b80a 100644 --- a/lib/core/model/labs/patient_lab_orders.dart +++ b/lib/core/model/labs/patient_lab_orders.dart @@ -34,7 +34,7 @@ class PatientLabOrders { String qR; String setupID; List speciality; - + bool isLiveCareAppointment; PatientLabOrders( {this.actualDoctorRate, this.clinicDescription, @@ -68,7 +68,7 @@ class PatientLabOrders { this.projectNameN, this.qR, this.setupID, - this.speciality}); + this.speciality,this.isLiveCareAppointment}); PatientLabOrders.fromJson(Map json) { actualDoctorRate = json['ActualDoctorRate']; @@ -103,6 +103,7 @@ class PatientLabOrders { projectNameN = json['ProjectNameN']; qR = json['QR']; setupID = json['SetupID']; + isLiveCareAppointment = json['IsLiveCareAppointment']; // speciality = json['Speciality'].cast(); } @@ -141,6 +142,7 @@ class PatientLabOrders { data['QR'] = this.qR; data['SetupID'] = this.setupID; data['Speciality'] = this.speciality; + data['IsLiveCareAppointment'] = this.isLiveCareAppointment; return data; } } diff --git a/lib/core/model/packages_offers/requests/OffersCategoriesRequestModel.dart b/lib/core/model/packages_offers/requests/OffersCategoriesRequestModel.dart new file mode 100644 index 00000000..f2f4af11 --- /dev/null +++ b/lib/core/model/packages_offers/requests/OffersCategoriesRequestModel.dart @@ -0,0 +1,11 @@ +class OffersCategoriesRequestModel { + final int limit; + final int page; + final int sinceId; + + OffersCategoriesRequestModel({this.limit, this.page, this.sinceId}); + + Map toFlatMap() { + return {"limit": limit.toString(), "page": page.toString(), "sinceId": sinceId.toString()}; + } +} diff --git a/lib/core/model/packages_offers/requests/OffersProductsRequestModel.dart b/lib/core/model/packages_offers/requests/OffersProductsRequestModel.dart new file mode 100644 index 00000000..84862568 --- /dev/null +++ b/lib/core/model/packages_offers/requests/OffersProductsRequestModel.dart @@ -0,0 +1,12 @@ +class OffersProductsRequestModel { + final int categoryId; + final int limit; + final int page; + final int sinceId; + + OffersProductsRequestModel({this.categoryId, this.limit, this.page, this.sinceId}); + + Map toFlatMap() { + return {"limit": limit.toString(), "page": page.toString(), "sinceId": sinceId.toString(), "categoryId": categoryId.toString()}; + } +} diff --git a/lib/core/model/packages_offers/responses/OfferCategoriesResponseModel.dart b/lib/core/model/packages_offers/responses/OfferCategoriesResponseModel.dart new file mode 100644 index 00000000..087f1961 --- /dev/null +++ b/lib/core/model/packages_offers/responses/OfferCategoriesResponseModel.dart @@ -0,0 +1,65 @@ +import 'package:diplomaticquarterapp/generated/json/base/json_convert_content.dart'; +import 'package:diplomaticquarterapp/generated/json/base/json_field.dart'; + +class OfferCategoriesResponseModel with JsonConvert { + String id; + String name; + String namen; + @JSONField(name: "localized_names") + List localizedNames; + dynamic description; + @JSONField(name: "category_template_id") + int categoryTemplateId; + @JSONField(name: "meta_keywords") + String metaKeywords; + @JSONField(name: "meta_description") + String metaDescription; + @JSONField(name: "meta_title") + String metaTitle; + @JSONField(name: "parent_category_id") + int parentCategoryId; + @JSONField(name: "page_size") + int pageSize; + @JSONField(name: "page_size_options") + String pageSizeOptions; + @JSONField(name: "price_ranges") + dynamic priceRanges; + @JSONField(name: "show_on_home_page") + bool showOnHomePage; + @JSONField(name: "include_in_top_menu") + bool includeInTopMenu; + @JSONField(name: "has_discounts_applied") + dynamic hasDiscountsApplied; + bool published; + bool deleted; + @JSONField(name: "display_order") + int displayOrder; + @JSONField(name: "created_on_utc") + String createdOnUtc; + @JSONField(name: "updated_on_utc") + String updatedOnUtc; + @JSONField(name: "role_ids") + List roleIds; + @JSONField(name: "discount_ids") + List discountIds; + @JSONField(name: "store_ids") + List storeIds; + OfferCategoriesResponseModelImage image; + @JSONField(name: "se_name") + String seName; + @JSONField(name: "is_leaf") + bool isLeaf; +} + +class OfferCategoriesResponseModelLocalizedName with JsonConvert { + @JSONField(name: "language_id") + int languageId; + @JSONField(name: "localized_name") + String localizedName; +} + +class OfferCategoriesResponseModelImage with JsonConvert { + String src; + dynamic thumb; + dynamic attachment; +} diff --git a/lib/core/model/packages_offers/responses/OfferProductsResponseModel.dart b/lib/core/model/packages_offers/responses/OfferProductsResponseModel.dart new file mode 100644 index 00000000..58481a8b --- /dev/null +++ b/lib/core/model/packages_offers/responses/OfferProductsResponseModel.dart @@ -0,0 +1,235 @@ +import 'package:diplomaticquarterapp/generated/json/base/json_convert_content.dart'; +import 'package:diplomaticquarterapp/generated/json/base/json_field.dart'; + +class OfferProductsResponseModel with JsonConvert { + String id; + @JSONField(name: "visible_individually") + bool visibleIndividually; + String name; + String namen; + @JSONField(name: "localized_names") + List localizedNames; + @JSONField(name: "short_description") + String shortDescription; + @JSONField(name: "short_descriptionn") + String shortDescriptionn; + @JSONField(name: "full_description") + String fullDescription; + @JSONField(name: "full_descriptionn") + String fullDescriptionn; + @JSONField(name: "markas_new") + bool markasNew; + @JSONField(name: "show_on_home_page") + bool showOnHomePage; + @JSONField(name: "meta_keywords") + dynamic metaKeywords; + @JSONField(name: "meta_description") + dynamic metaDescription; + @JSONField(name: "meta_title") + dynamic metaTitle; + @JSONField(name: "allow_customer_reviews") + bool allowCustomerReviews; + @JSONField(name: "approved_rating_sum") + int approvedRatingSum; + @JSONField(name: "not_approved_rating_sum") + int notApprovedRatingSum; + @JSONField(name: "approved_total_reviews") + int approvedTotalReviews; + @JSONField(name: "not_approved_total_reviews") + int notApprovedTotalReviews; + String sku; + @JSONField(name: "is_rx") + bool isRx; + @JSONField(name: "prescription_required") + bool prescriptionRequired; + @JSONField(name: "rx_message") + dynamic rxMessage; + @JSONField(name: "rx_messagen") + dynamic rxMessagen; + @JSONField(name: "manufacturer_part_number") + dynamic manufacturerPartNumber; + dynamic gtin; + @JSONField(name: "is_gift_card") + bool isGiftCard; + @JSONField(name: "require_other_products") + bool requireOtherProducts; + @JSONField(name: "automatically_add_required_products") + bool automaticallyAddRequiredProducts; + @JSONField(name: "is_download") + bool isDownload; + @JSONField(name: "unlimited_downloads") + bool unlimitedDownloads; + @JSONField(name: "max_number_of_downloads") + int maxNumberOfDownloads; + @JSONField(name: "download_expiration_days") + dynamic downloadExpirationDays; + @JSONField(name: "has_sample_download") + bool hasSampleDownload; + @JSONField(name: "has_user_agreement") + bool hasUserAgreement; + @JSONField(name: "is_recurring") + bool isRecurring; + @JSONField(name: "recurring_cycle_length") + int recurringCycleLength; + @JSONField(name: "recurring_total_cycles") + int recurringTotalCycles; + @JSONField(name: "is_rental") + bool isRental; + @JSONField(name: "rental_price_length") + int rentalPriceLength; + @JSONField(name: "is_ship_enabled") + bool isShipEnabled; + @JSONField(name: "is_free_shipping") + bool isFreeShipping; + @JSONField(name: "ship_separately") + bool shipSeparately; + @JSONField(name: "additional_shipping_charge") + double additionalShippingCharge; + @JSONField(name: "is_tax_exempt") + bool isTaxExempt; + @JSONField(name: "is_telecommunications_or_broadcasting_or_electronic_services") + bool isTelecommunicationsOrBroadcastingOrElectronicServices; + @JSONField(name: "use_multiple_warehouses") + bool useMultipleWarehouses; + @JSONField(name: "manage_inventory_method_id") + int manageInventoryMethodId; + @JSONField(name: "stock_quantity") + int stockQuantity; + @JSONField(name: "stock_availability") + String stockAvailability; + @JSONField(name: "stock_availabilityn") + String stockAvailabilityn; + @JSONField(name: "display_stock_availability") + bool displayStockAvailability; + @JSONField(name: "display_stock_quantity") + bool displayStockQuantity; + @JSONField(name: "min_stock_quantity") + int minStockQuantity; + @JSONField(name: "notify_admin_for_quantity_below") + int notifyAdminForQuantityBelow; + @JSONField(name: "allow_back_in_stock_subscriptions") + bool allowBackInStockSubscriptions; + @JSONField(name: "order_minimum_quantity") + int orderMinimumQuantity; + @JSONField(name: "order_maximum_quantity") + int orderMaximumQuantity; + @JSONField(name: "allowed_quantities") + dynamic allowedQuantities; + @JSONField(name: "allow_adding_only_existing_attribute_combinations") + bool allowAddingOnlyExistingAttributeCombinations; + @JSONField(name: "disable_buy_button") + bool disableBuyButton; + @JSONField(name: "disable_wishlist_button") + bool disableWishlistButton; + @JSONField(name: "available_for_pre_order") + bool availableForPreOrder; + @JSONField(name: "pre_order_availability_start_date_time_utc") + dynamic preOrderAvailabilityStartDateTimeUtc; + @JSONField(name: "call_for_price") + bool callForPrice; + double price; + @JSONField(name: "old_price") + double oldPrice; + @JSONField(name: "product_cost") + double productCost; + @JSONField(name: "special_price") + dynamic specialPrice; + @JSONField(name: "special_price_start_date_time_utc") + dynamic specialPriceStartDateTimeUtc; + @JSONField(name: "special_price_end_date_time_utc") + dynamic specialPriceEndDateTimeUtc; + @JSONField(name: "customer_enters_price") + bool customerEntersPrice; + @JSONField(name: "minimum_customer_entered_price") + double minimumCustomerEnteredPrice; + @JSONField(name: "maximum_customer_entered_price") + double maximumCustomerEnteredPrice; + @JSONField(name: "baseprice_enabled") + bool basepriceEnabled; + @JSONField(name: "baseprice_amount") + double basepriceAmount; + @JSONField(name: "baseprice_base_amount") + double basepriceBaseAmount; + @JSONField(name: "has_tier_prices") + bool hasTierPrices; + @JSONField(name: "has_discounts_applied") + bool hasDiscountsApplied; + @JSONField(name: "discount_name") + dynamic discountName; + @JSONField(name: "discount_namen") + dynamic discountNamen; + @JSONField(name: "discount_description") + dynamic discountDescription; + @JSONField(name: "discount_Descriptionn") + dynamic discountDescriptionn; + @JSONField(name: "discount_percentage") + dynamic discountPercentage; + String currency; + String currencyn; + double weight; + double length; + double width; + double height; + @JSONField(name: "available_start_date_time_utc") + dynamic availableStartDateTimeUtc; + @JSONField(name: "available_end_date_time_utc") + dynamic availableEndDateTimeUtc; + @JSONField(name: "display_order") + int displayOrder; + bool published; + bool deleted; + @JSONField(name: "created_on_utc") + String createdOnUtc; + @JSONField(name: "updated_on_utc") + String updatedOnUtc; + @JSONField(name: "product_type") + String productType; + @JSONField(name: "parent_grouped_product_id") + int parentGroupedProductId; + @JSONField(name: "role_ids") + List roleIds; + @JSONField(name: "discount_ids") + List discountIds; + @JSONField(name: "store_ids") + List storeIds; + @JSONField(name: "manufacturer_ids") + List manufacturerIds; + List reviews; + List images; + List attributes; + List specifications; + @JSONField(name: "associated_product_ids") + List associatedProductIds; + List tags; + @JSONField(name: "vendor_id") + int vendorId; + @JSONField(name: "se_name") + String seName; +} + +class OfferProductsResponseModelLocalizedName with JsonConvert { + @JSONField(name: "language_id") + int languageId; + @JSONField(name: "localized_name") + String localizedName; +} + +class OfferProductsResponseModelImage with JsonConvert { + int id; + int position; + String src; + String thumb; + String attachment; +} + +class OfferProductsResponseModelSpecification with JsonConvert { + int id; + @JSONField(name: "display_order") + int displayOrder; + @JSONField(name: "default_value") + String defaultValue; + @JSONField(name: "default_valuen") + String defaultValuen; + String name; + String nameN; +} diff --git a/lib/core/model/pharmacies/Addresses.dart b/lib/core/model/pharmacies/Addresses.dart index 74d5a591..b00b1a17 100644 --- a/lib/core/model/pharmacies/Addresses.dart +++ b/lib/core/model/pharmacies/Addresses.dart @@ -17,6 +17,7 @@ class Addresses { String createdOnUtc; String province; String latLong; + bool isChecked; Addresses( {this.id, @@ -36,7 +37,8 @@ class Addresses { this.customerAttributes, this.createdOnUtc, this.province, - this.latLong}); + this.latLong, + this.isChecked = false}); Addresses.fromJson(Map json) { id = json['id']; @@ -57,6 +59,7 @@ class Addresses { createdOnUtc = json['created_on_utc']; province = json['province']; latLong = json['lat_long']; + isChecked = json['isChecked']; } Map toJson() { @@ -79,6 +82,7 @@ class Addresses { data['created_on_utc'] = this.createdOnUtc; data['province'] = this.province; data['lat_long'] = this.latLong; + data['isChecked'] = this.isChecked; return data; } diff --git a/lib/core/model/pharmacies/BillingAddress.dart b/lib/core/model/pharmacies/BillingAddress.dart new file mode 100644 index 00000000..765ac54d --- /dev/null +++ b/lib/core/model/pharmacies/BillingAddress.dart @@ -0,0 +1,84 @@ +class BillingAddress { + String id; + String firstName; + String lastName; + String email; + String company; + int countryId; + String country; + String stateProvinceId; + String city; + String address1; + String address2; + String zipPostalCode; + String phoneNumber; + String faxNumber; + String customerAttributes; + String createdOnUtc; + String province; + String latLong; + + BillingAddress( + {this.id, + this.firstName, + this.lastName, + this.email, + this.company, + this.countryId, + this.country, + this.stateProvinceId, + this.city, + this.address1, + this.address2, + this.zipPostalCode, + this.phoneNumber, + this.faxNumber, + this.customerAttributes, + this.createdOnUtc, + this.province, + this.latLong}); + + BillingAddress.fromJson(Map json) { + id = json['id']; + firstName = json['first_name']; + lastName = json['last_name']; + email = json['email']; + company = json['company']; + countryId = json['country_id']; + country = json['country']; + stateProvinceId = json['state_province_id']; + city = json['city']; + address1 = json['address1']; + address2 = json['address2']; + zipPostalCode = json['zip_postal_code']; + phoneNumber = json['phone_number']; + faxNumber = json['fax_number']; + customerAttributes = json['customer_attributes']; + createdOnUtc = json['created_on_utc']; + province = json['province']; + latLong = json['lat_long']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['first_name'] = this.firstName; + data['last_name'] = this.lastName; + data['email'] = this.email; + data['company'] = this.company; + data['country_id'] = this.countryId; + data['country'] = this.country; + data['state_province_id'] = this.stateProvinceId; + data['city'] = this.city; + data['address1'] = this.address1; + data['address2'] = this.address2; + data['zip_postal_code'] = this.zipPostalCode; + data['phone_number'] = this.phoneNumber; + data['fax_number'] = this.faxNumber; + data['customer_attributes'] = this.customerAttributes; + data['created_on_utc'] = this.createdOnUtc; + data['province'] = this.province; + data['lat_long'] = this.latLong; + return data; + } +} diff --git a/lib/core/model/pharmacies/Country.dart b/lib/core/model/pharmacies/Country.dart new file mode 100644 index 00000000..77f519d3 --- /dev/null +++ b/lib/core/model/pharmacies/Country.dart @@ -0,0 +1,32 @@ +class CountryData { + int id; + String name; + String namen; + String twoLetterIsoCode; + String threeLetterIsoCode; + + CountryData( + {this.id, + this.name, + this.namen, + this.twoLetterIsoCode, + this.threeLetterIsoCode}); + + CountryData.fromJson(Map json) { + id = json['id']; + name = json['name']; + namen = json['namen']; + twoLetterIsoCode = json['two_letter_iso_code']; + threeLetterIsoCode = json['three_letter_iso_code']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['name'] = this.name; + data['namen'] = this.namen; + data['two_letter_iso_code'] = this.twoLetterIsoCode; + data['three_letter_iso_code'] = this.threeLetterIsoCode; + return data; + } +} diff --git a/lib/core/model/pharmacies/Customer.dart b/lib/core/model/pharmacies/Customer.dart index a5311489..e3defbbe 100644 --- a/lib/core/model/pharmacies/Customer.dart +++ b/lib/core/model/pharmacies/Customer.dart @@ -1,4 +1,10 @@ +import 'package:diplomaticquarterapp/core/model/pharmacies/Addresses.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/BillingAddress.dart'; + class Customer { + BillingAddress billingAddress; + BillingAddress shippingAddress; + List addresses; String fileNumber; String iqamaNumber; int isOutSa; @@ -8,8 +14,6 @@ class Customer { String phone; String countryCode; String yahalaAccountno; - String billingAddress; - String shippingAddress; String id; String username; String email; @@ -17,50 +21,63 @@ class Customer { String lastName; String languageId; String adminComment; - String isTaxExempt; - String hasShoppingCartItems; - String active; - String deleted; - String isSystemAccount; + bool isTaxExempt; + bool hasShoppingCartItems; + bool active; + bool deleted; + bool isSystemAccount; String systemName; String lastIpAddress; String createdOnUtc; String lastLoginDateUtc; String lastActivityDateUtc; - String registeredInStoreId; + int registeredInStoreId; Customer( - {this.fileNumber, - this.iqamaNumber, - this.isOutSa, - this.patientType, - this.gender, - this.birthDate, - this.phone, - this.countryCode, - this.yahalaAccountno, - this.billingAddress, - this.shippingAddress, - this.id, - this.username, - this.email, - this.firstName, - this.lastName, - this.languageId, - this.adminComment, - this.isTaxExempt, - this.hasShoppingCartItems, - this.active, - this.deleted, - this.isSystemAccount, - this.systemName, - this.lastIpAddress, - this.createdOnUtc, - this.lastLoginDateUtc, - this.lastActivityDateUtc, - this.registeredInStoreId}); + {this.billingAddress, + this.shippingAddress, + this.addresses, + this.fileNumber, + this.iqamaNumber, + this.isOutSa, + this.patientType, + this.gender, + this.birthDate, + this.phone, + this.countryCode, + this.yahalaAccountno, + this.id, + this.username, + this.email, + this.firstName, + this.lastName, + this.languageId, + this.adminComment, + this.isTaxExempt, + this.hasShoppingCartItems, + this.active, + this.deleted, + this.isSystemAccount, + this.systemName, + this.lastIpAddress, + this.createdOnUtc, + this.lastLoginDateUtc, + this.lastActivityDateUtc, + this.registeredInStoreId}); Customer.fromJson(Map json) { + billingAddress = json['billing_address'] != null + ? new BillingAddress.fromJson(json['billing_address']) + : null; + shippingAddress = json['shipping_address'] != null + ? new BillingAddress.fromJson(json['shipping_address']) + : null; + if (json['addresses'] != null) { + addresses = new List(); + json['addresses'].forEach((v) { + addresses.add(new Addresses.fromJson(v)); + }); + } fileNumber = json['file_number']; iqamaNumber = json['iqama_number']; isOutSa = json['is_out_sa']; @@ -70,8 +87,6 @@ class Customer { phone = json['phone']; countryCode = json['country_code']; yahalaAccountno = json['yahala_accountno']; - billingAddress = json['billing_address']; - shippingAddress = json['shipping_address']; id = json['id']; username = json['username']; email = json['email']; @@ -94,6 +109,15 @@ class Customer { Map toJson() { final Map data = new Map(); + if (this.billingAddress != null) { + data['billing_address'] = this.billingAddress.toJson(); + } + if (this.shippingAddress != null) { + data['shipping_address'] = this.shippingAddress.toJson(); + } + if (this.addresses != null) { + data['addresses'] = this.addresses.map((v) => v.toJson()).toList(); + } data['file_number'] = this.fileNumber; data['iqama_number'] = this.iqamaNumber; data['is_out_sa'] = this.isOutSa; @@ -103,8 +127,6 @@ class Customer { data['phone'] = this.phone; data['country_code'] = this.countryCode; data['yahala_accountno'] = this.yahalaAccountno; - data['billing_address'] = this.billingAddress; - data['shipping_address'] = this.shippingAddress; data['id'] = this.id; data['username'] = this.username; data['email'] = this.email; @@ -125,4 +147,4 @@ class Customer { data['registered_in_store_id'] = this.registeredInStoreId; return data; } -} \ No newline at end of file +} diff --git a/lib/core/model/pharmacies/LacumAccountInformation.dart b/lib/core/model/pharmacies/LacumAccountInformation.dart new file mode 100644 index 00000000..4f1d0455 --- /dev/null +++ b/lib/core/model/pharmacies/LacumAccountInformation.dart @@ -0,0 +1,1926 @@ +import 'LakumInquiryInformationObjVersion.dart'; + +class LacumAccountInformation { + + String date; + int languageID; + int serviceName; + String time; + String androidLink; + String authenticationTokenID; + String data; + bool dataw; + int dietType; + String errorCode; + String errorEndUserMessage; + String errorEndUserMessageN; + String errorMessage; + int errorType; + int foodCategory; + String iOSLink; + bool isAuthenticated; + int mealOrderStatus; + int mealType; + int messageStatus; + int numberOfResultRecords; + String patientBlodType; + String successMsg; + String successMsgN; + int accountStatus; + String activeArchiveObject; + int activeMedicationCount; + String allMedicationTakenDuringAdmissionList; + int appointmentNo; + String arePatientsOnlineList; + String balanceAmount; + String bloodGroupList; + int cVIUnreadCount; + String checkUserHasAccount; + int complaintNo; + String dischargeList; + int episodeID; + String finalRadiologyList; + String fullName; + String geoFPointsList; + String geoGetPateintInfo; + String getAllDoctorsByProjectAndClinicList; + String getAppointmentNumbersForDoctorList; + String getCheckUpItemsList; + String getCosmeticConferenceForTodayList; + String getDoctorERClinicResult; + String getInvoiceApprovalList; + String getNearestProjectList; + String getPatientAdmissionOrAppoinmentNoList; + String getPatientBloodType; + String getPatientInsuranceCardStatusStatisticsList; + String getSurveyList; + String getTotalRegisteredPatientList; + String getUserDetailsList; + String getCustomerPointInfo; + String hISApprovalList; + String hISInpAdmissionList; + String hISProgNoteAssesmentModelList; + String hMGGetAllOffersList; + bool hasApproval; + bool hasConsultation; + bool hasDental; + bool hasLab; + bool hasPharmacy; + bool hasRad; + String hmgSMSGetByProjectIDAndPatientIDList; + int hoursLeft; + String iNPMGetAllAdmissionList; + String iNPMGetPatientInfoForSickLeaveReportList; + String iNPMHISPatientMedicalStatusUnreadCount; + String iNPMLABGetPatientLabOrdersResultsList; + String iNPMLABGetPatientLabResultsList; + String iNPMLABGetPatientRADReportList; + String iNPMLABGetPatientRadResultsList; + String iNPMRadGetPatientRadOrdersCVIList; + String iNPMRadGetPatientRadOrdersList; + String iNPMRadGetRadMedicalRecordsList; + String iNPGetPrescriptionDischargesList; + String iNPGetPrescriptionReportList; + String identificationNo; + bool isHomeMedicineDeliverySupported; + int isInsertedOrUpdated; + bool isMainAcoountEqualPatienID; + bool isPatientAlreadyAgreed; + bool isPatientCallBackBlackList; + bool isPatientHaveFingerPrint; + bool isPatientOnline; + bool isPatientTokenRemoved; + bool isPaused; + bool isProjectWorkingHours; + String isStoreRateAllowed; + String isStoreRateInserted; + String isStoreRateUpdated; + int labRadUpdatedToRead; + int labReportUnreadNo; + String lakumInquiryInformationObj; + LakumInquiryInformationObjVersion lakumInquiryInformationObjVersion; + String lakumResponseList; + String laserGetBodyPartsByCategoryList; + String laserGetCategoriesList; + String list; + int listCount; + int listCountDeliverd; + int listCountUnDeliverd; + String listDeviceInfo; + String listFamilyAppointments; + String listLabResultsByAppNo; + String listLakumInquiryInformationObj; + String listOpinionGetAllPeriod; + String listOpinionGetAllServices; + String listOpinionGetIsAgreeValue; + String listOpinionGetOpinionLogin; + String listOpinionGetRequestedSerives; + String listOpinionGetShareServicesDetails; + String listOpinionUserTerms; + String listPLO; + String listPLR; + String listPLSR; + String listPRM; + String listPatientFamilyFiles; + String listPatientFileInfo; + String listRAD; + String listRADAPI; + String listActiveGetPrescriptionReportByPatientID; + String listAppointmentsForDentalClinic; + String listBabyInfoResult; + String listCheckInsuranceCoverage; + String listCompanyClass; + String listConsentMedicalReport; + String listDentalAppointments; + String listDeviceTokenIDByAppointmentNo; + String listDischargeDiagnosis; + String listDischargeMedicine; + String listDischargeSummary; + String listDoctorResponse; + String listDoneVaccines; + String listEReferralResult; + String listEReferrals; + String listGetAllPatientsLiveCareAdmin; + String listGetDataForExcel; + String listGetMainCountID; + String listGetPrescriptionReportByPatientID; + String listGetSickLeave; + String listHISInvoice; + String listHISInvoiceProcedures; + String listInpatientInvoices; + String listInsuranceCheckList; + String listInsuranceCompanies; + String listInsuranceCompaniesGroup; + String listInsuranceUpdateDetails; + String listInvoiceApprovalProcedureInfo; + String listIsLastSatisfactionSurveyReviewedModel; + String listLabOrderDetailsModel; + String listMedicalReport; + String listMedicalReportApprovals; + String listMedicalReportStatus; + String listMonthBloodPressureResult; + String listMonthBloodPressureResultAverage; + String listMonthDiabtecPatientResult; + String listMonthDiabtectResultAverage; + String listMonthWeightMeasurementResult; + String listMonthWeightMeasurementResultAverage; + String listOnlinePrescriptionResult; + String listOutPatientInvoices; + String listPHRInvoice; + String listPHRInvoiceItems; + String listPHRPaymentMethods; + String listPateintDetails; + String listPateintInformation; + String listPatientAdmissionInfo; + String listPatientAdvanceBalanceAmount; + String listPatientCallBackLogs; + String listPatientCallBackToUpdateFromICServer; + String listPatientCount; + String listPatientDashboard; + String listPatientERGetAdminClinicsModel; + String listPatientERGetAdminProjectsModel; + String listPatientERGetAllClinicsModel; + String listPatientHISInvoices; + String listPatientICProjects; + String listPatientICProjectsByID; + String listPatientICProjectsTimings; + String listPatientIDByUID; + String listPatientIDForSurveyResult; + String listPatientInfo; + String listPatientInfoForDDScreen; + String listPatientInfoForSickleaveReport; + String listPatientInsuranceCard; + String listPatientInsuranceCardHistory; + String listPatientInsuranceDetails; + String listPatientPHRInvoices; + String listPatientServicePoint; + String listPatientStatusCount; + String listPatientChatRequestMapModel; + String listPatientChatRequestModel; + String listPatientChatRequestVCModel; + String listPaymentMethods; + String listPointServices; + String listPregnancyStagesInfo; + String listProjectAvgERWaitingTime; + String listProjectAvgERWaitingTimeHourly; + String listRadMedicalRecords; + String listRadMedicalRecordsAPI; + String listRadMedicalRecordsCVI; + String listRadMedicalRecordsCVIAPI; + String listRadMedicalRecordsResults; + String listSickLeave; + String listTransaction; + String listVideoConferenceSessions; + String listWeekBloodPressureResult; + String listWeekBloodPressureResultAverage; + String listWeekDiabtecPatientResult; + String listWeekDiabtectResultAverage; + String listWeekWeightMeasurementResult; + String listWeekWeightMeasurementResultAverage; + String listYearBloodPressureResult; + String listYearBloodPressureResultAverage; + String listYearDiabtecPatientResult; + String listYearDiabtecResultAverage; + String listYearWeightMeasurementResult; + String listYearWeightMeasurementResultAverage; + String listEInvoiceForDental; + String listEInvoiceForOnlineCheckIn; + String medGetActivitiesTransactionsStsList; + String medGetAvgMonthTransactionsStsList; + String medGetAvgWeekTransactionsStsList; + String medGetCategoriesList; + String medGetMonthActivitiesTransactionsStsList; + String medGetMonthStepsTransactionsStsList; + String medGetMonthTransactionsStsList; + String medGetPatientLastRecordList; + String medGetSubCategoriesList; + String medGetTransactionsAndActTransactionsResult; + String medGetTransactionsList; + String medGetWeekActivitiesTransactionsStsList; + String medGetWeekStepsTransactionsStsList; + String medGetWeekTransactionsStsList; + String medGetYearActivitiesTransactionsStsList; + String medGetYearSleepTransactionsStsList; + String medGetYearStepsTransactionsStsList; + String medGetYearTransactionsStsList; + String medInsertTransactionsOutputsList; + String medicalRecordImages; + int medicalReportToRead; + int medicalReportUnreadNo; + bool missingIDCardAttachment; + bool missingInsuranceCardAttachment; + bool missingMedicalReportAttachment; + bool missingOtherRelationship; + bool missingPatientContactNo; + bool missingPatientId; + bool missingPatientIdentityNumber; + bool missingPatientName; + bool missingReferralContactNo; + bool missingReferralRelationship; + bool missingReferralRequesterName; + String mobileNumber; + int nationalityNumber; + String onlineCheckInAppointments; + String opinionUserAgreementContent; + bool orderInsert; + String pateintInfoForUpdateList; + String pateintUpatedList; + String patientBirthdayCertificate; + String patientERCMCRequestSummaryByProject; + String patientERCMCRequestWithTotal; + String patientERCMCGetAllServicesList; + String patientERCMCGetTransactionsForOrderList; + String patientERCoordinates; + String patientERCountOrderList; + String patientERCountsForApprovalOffice; + String patientERDeleteOldCurrentDoctorsOutputsList; + String patientERDeliveryGetAllDeliverdOrderList; + String patientERDeliveryGetAllOrderList; + bool patientERDeliveryIsOrderInserted; + bool patientERDeliveryIsOrderUpdated; + bool patientERDeliveryIsPausedChanged; + String patientERDeliveryNextOrder; + int patientERDeliveryOrderInsert; + int patientERDeliveryUpdateOrderStatus; + bool patientERDriverUpdate; + String patientERExacartCheckIsDispenseAccpetableList; + String patientERExacartGetDispenseQuantitiesByOrderIDList; + String patientERExacartGetOrderDetailsByePharmacyOrderNoList; + String patientERExacartGetOrderDetailsList; + String patientERExacartGetTotalDispenseQuantitiesByPresNoList; + bool patientERExacartIsDispenseAdded; + String patientERExacartIsDispenseAddedList; + bool patientERExacartIsOrderCompleted; + String patientERGetAdminByProjectAndRoleList; + String patientERGetAdminProjectsList; + String patientERGetAllDriversList; + String patientERGetAllNeedAproveStatusList; + String patientERGetAllPresOrdersStatusList; + String patientERGetAllProjectsList; + String patientERGetArchiveInformationList; + String patientERGetAskDoctorTotalByDateFilterList; + String patientERGetBookScheduleConfigsList; + String patientERGetClinicAndTimeAndEpisodeForAppointmentList; + String patientERGetClinicAndTimeForDischargeList; + String patientERGetDashboardDataforApporvalSectionForAdminList; + String patientERGetDashboardDataforApporvalSectionList; + String patientERGetDashboardDataforHHCSectionForAdminList; + String patientERGetDashboardDataforHHCSectionList; + String patientERGetDashboardDataforPrescriptionSectionForAdminList; + String patientERGetDashboardDataforPrescriptionSectionList; + String patientERGetDoctorDashboardDataModelList; + String patientERGetDriverLocationList; + String patientERGetInsuranceCardRequestByDateFilterList; + String patientERGetLiveCareSummaryBookedAppoinmentStatusList; + String patientERGetLiveCareSummaryCovidList; + String patientERGetLiveCareSummaryForCMCList; + String patientERGetLiveCareSummaryForHHCList; + String patientERGetLiveCareSummaryForHomeDeliveryList; + String patientERGetLiveCareSummaryForInsuranceCardRequestList; + String patientERGetLiveCareSummaryForNewFilesList; + String patientERGetLiveCareSummaryForOnlinePaymetRequestList; + String patientERGetLiveCareSummaryForOnlinePharmacyOrdersList; + String patientERGetLiveCareSummaryForTrasnportationList; + String patientERGetLiveCareSummaryLiveCareCountsList; + String patientERGetMedicalRequestTotalByDateFilterList; + String patientERGetNearestPendingOrdersList; + String patientERGetNeedAproveHistoryForOrderList; + String patientERGetNeedAprovePendingOrdersList; + String patientERGetNeedAproveStatusStatisticsList; + String patientERGetPatientAllPresOrdersList; + String patientERGetPendingPatientsCountList; + String patientERGetPresOrdersHistoryForAdminList; + String patientERGetPresOrdersHistoryForOrderList; + String patientERGetPresOrdersStatusStatisticsList; + String patientERHHCRequest; + String patientERHHCRequestSummaryByProject; + String patientERHHCRequestWithTotal; + String patientERHHCGetAllServicesList; + String patientERHHCGetTransactionsForOrderList; + String patientERHomeDeliveryCounts; + bool patientERInsertDriver; + String patientERInsertNewCurrentDoctorsOutputsList; + String patientERInsuranceStatusCountList; + bool patientERIsNearestProjectUpdated; + bool patientERIsNeedAproveReturnedToQueue; + bool patientERIsNeedAproveUpdated; + bool patientERIsOrderClientRequestUpdated; + bool patientERIsOrderReturnedToQueue; + bool patientERIsPresOrderInserted; + bool patientERIsPresOrderUpdated; + bool patientERIsProjectUpdated; + String patientERNotCompletedDetails; + String patientERPatientsCountByCallStatus; + String patientERPeakHourCounts; + String patientERPresOrderInfo; + String patientERPrescriptionCounts; + String patientERProjectsContribution; + String patientERRRTGetAllQuestionsList; + String patientERRRTGetAllTransportationMethodList; + String patientERRRTGetPickUpRequestByPresOrderIDList; + String patientERRealRRTGetAllServicesList; + String patientERRealRRTGetOrderDetailsList; + String patientERRealRRTGetTransactionsForOrderList; + bool patientERRealRRTIsTransInserted; + String patientERRequestList; + String patientERTransportationRequestWithTotal; + String patientERealRRTGetServicePriceList; + String patientInfoByAdmissionNoList; + String patientMonitorGetPatientHeartRate; + int patientNotServedCounts; + String patientPrescriptionList; + String patientAllergies; + String patientCheckAppointmentValidationList; + String patientLoginTokenList; + String patientQRLoginInfoList; + String patientSELECTDeviceIMEIbyIMEIList; + String pharmList; + String prefLang; + int radReportUnreadNo; + String radGetPatientRadOrdersForDentalList; + int referralNumber; + String reminderConfigurations; + String requestNo; + int rowCount; + String servicePrivilegeList; + String shareFamilyFileObj; + String status; + int successCode; + String surveyRate; + String symptomCheckerConditionList; + String symptomCheckerGetAllDefaultQuestionsList; + String symptomCheckerGetBodyPartSymptomsList; + String symptomCheckerGetBodyPartsByCodeList; + String symptomCheckerGetBodyPartsList; + String symptomCheckerJsonResponseInString; + int timerTime; + int totalAdvanceBalanceAmount; + int totalPatientsCount; + int totalPendingApprovalCount; + int totalUnUsedCount; + int transactionNo; + int unReadCounts; + bool updateStatus; + String userAgreementContent; + int yahalaAccountNo; + bool check24HourComplaint; + String currency; + String message; + int patientID; + int returnValue; + String returnValueStr; + int statusCode; + + LacumAccountInformation( + {this.date, + this.languageID, + this.serviceName, + this.time, + this.androidLink, + this.authenticationTokenID, + this.data, + this.dataw, + this.dietType, + this.errorCode, + this.errorEndUserMessage, + this.errorEndUserMessageN, + this.errorMessage, + this.errorType, + this.foodCategory, + this.iOSLink, + this.isAuthenticated, + this.mealOrderStatus, + this.mealType, + this.messageStatus, + this.numberOfResultRecords, + this.patientBlodType, + this.successMsg, + this.successMsgN, + this.accountStatus, + this.activeArchiveObject, + this.activeMedicationCount, + this.allMedicationTakenDuringAdmissionList, + this.appointmentNo, + this.arePatientsOnlineList, + this.balanceAmount, + this.bloodGroupList, + this.cVIUnreadCount, + this.checkUserHasAccount, + this.complaintNo, + this.dischargeList, + this.episodeID, + this.finalRadiologyList, + this.fullName, + this.geoFPointsList, + this.geoGetPateintInfo, + this.getAllDoctorsByProjectAndClinicList, + this.getAppointmentNumbersForDoctorList, + this.getCheckUpItemsList, + this.getCosmeticConferenceForTodayList, + this.getDoctorERClinicResult, + this.getInvoiceApprovalList, + this.getNearestProjectList, + this.getPatientAdmissionOrAppoinmentNoList, + this.getPatientBloodType, + this.getPatientInsuranceCardStatusStatisticsList, + this.getSurveyList, + this.getTotalRegisteredPatientList, + this.getUserDetailsList, + this.getCustomerPointInfo, + this.hISApprovalList, + this.hISInpAdmissionList, + this.hISProgNoteAssesmentModelList, + this.hMGGetAllOffersList, + this.hasApproval, + this.hasConsultation, + this.hasDental, + this.hasLab, + this.hasPharmacy, + this.hasRad, + this.hmgSMSGetByProjectIDAndPatientIDList, + this.hoursLeft, + this.iNPMGetAllAdmissionList, + this.iNPMGetPatientInfoForSickLeaveReportList, + this.iNPMHISPatientMedicalStatusUnreadCount, + this.iNPMLABGetPatientLabOrdersResultsList, + this.iNPMLABGetPatientLabResultsList, + this.iNPMLABGetPatientRADReportList, + this.iNPMLABGetPatientRadResultsList, + this.iNPMRadGetPatientRadOrdersCVIList, + this.iNPMRadGetPatientRadOrdersList, + this.iNPMRadGetRadMedicalRecordsList, + this.iNPGetPrescriptionDischargesList, + this.iNPGetPrescriptionReportList, + this.identificationNo, + this.isHomeMedicineDeliverySupported, + this.isInsertedOrUpdated, + this.isMainAcoountEqualPatienID, + this.isPatientAlreadyAgreed, + this.isPatientCallBackBlackList, + this.isPatientHaveFingerPrint, + this.isPatientOnline, + this.isPatientTokenRemoved, + this.isPaused, + this.isProjectWorkingHours, + this.isStoreRateAllowed, + this.isStoreRateInserted, + this.isStoreRateUpdated, + this.labRadUpdatedToRead, + this.labReportUnreadNo, + this.lakumInquiryInformationObj, + this.lakumInquiryInformationObjVersion, + this.lakumResponseList, + this.laserGetBodyPartsByCategoryList, + this.laserGetCategoriesList, + this.list, + this.listCount, + this.listCountDeliverd, + this.listCountUnDeliverd, + this.listDeviceInfo, + this.listFamilyAppointments, + this.listLabResultsByAppNo, + this.listLakumInquiryInformationObj, + this.listOpinionGetAllPeriod, + this.listOpinionGetAllServices, + this.listOpinionGetIsAgreeValue, + this.listOpinionGetOpinionLogin, + this.listOpinionGetRequestedSerives, + this.listOpinionGetShareServicesDetails, + this.listOpinionUserTerms, + this.listPLO, + this.listPLR, + this.listPLSR, + this.listPRM, + this.listPatientFamilyFiles, + this.listPatientFileInfo, + this.listRAD, + this.listRADAPI, + this.listActiveGetPrescriptionReportByPatientID, + this.listAppointmentsForDentalClinic, + this.listBabyInfoResult, + this.listCheckInsuranceCoverage, + this.listCompanyClass, + this.listConsentMedicalReport, + this.listDentalAppointments, + this.listDeviceTokenIDByAppointmentNo, + this.listDischargeDiagnosis, + this.listDischargeMedicine, + this.listDischargeSummary, + this.listDoctorResponse, + this.listDoneVaccines, + this.listEReferralResult, + this.listEReferrals, + this.listGetAllPatientsLiveCareAdmin, + this.listGetDataForExcel, + this.listGetMainCountID, + this.listGetPrescriptionReportByPatientID, + this.listGetSickLeave, + this.listHISInvoice, + this.listHISInvoiceProcedures, + this.listInpatientInvoices, + this.listInsuranceCheckList, + this.listInsuranceCompanies, + this.listInsuranceCompaniesGroup, + this.listInsuranceUpdateDetails, + this.listInvoiceApprovalProcedureInfo, + this.listIsLastSatisfactionSurveyReviewedModel, + this.listLabOrderDetailsModel, + this.listMedicalReport, + this.listMedicalReportApprovals, + this.listMedicalReportStatus, + this.listMonthBloodPressureResult, + this.listMonthBloodPressureResultAverage, + this.listMonthDiabtecPatientResult, + this.listMonthDiabtectResultAverage, + this.listMonthWeightMeasurementResult, + this.listMonthWeightMeasurementResultAverage, + this.listOnlinePrescriptionResult, + this.listOutPatientInvoices, + this.listPHRInvoice, + this.listPHRInvoiceItems, + this.listPHRPaymentMethods, + this.listPateintDetails, + this.listPateintInformation, + this.listPatientAdmissionInfo, + this.listPatientAdvanceBalanceAmount, + this.listPatientCallBackLogs, + this.listPatientCallBackToUpdateFromICServer, + this.listPatientCount, + this.listPatientDashboard, + this.listPatientERGetAdminClinicsModel, + this.listPatientERGetAdminProjectsModel, + this.listPatientERGetAllClinicsModel, + this.listPatientHISInvoices, + this.listPatientICProjects, + this.listPatientICProjectsByID, + this.listPatientICProjectsTimings, + this.listPatientIDByUID, + this.listPatientIDForSurveyResult, + this.listPatientInfo, + this.listPatientInfoForDDScreen, + this.listPatientInfoForSickleaveReport, + this.listPatientInsuranceCard, + this.listPatientInsuranceCardHistory, + this.listPatientInsuranceDetails, + this.listPatientPHRInvoices, + this.listPatientServicePoint, + this.listPatientStatusCount, + this.listPatientChatRequestMapModel, + this.listPatientChatRequestModel, + this.listPatientChatRequestVCModel, + this.listPaymentMethods, + this.listPointServices, + this.listPregnancyStagesInfo, + this.listProjectAvgERWaitingTime, + this.listProjectAvgERWaitingTimeHourly, + this.listRadMedicalRecords, + this.listRadMedicalRecordsAPI, + this.listRadMedicalRecordsCVI, + this.listRadMedicalRecordsCVIAPI, + this.listRadMedicalRecordsResults, + this.listSickLeave, + this.listTransaction, + this.listVideoConferenceSessions, + this.listWeekBloodPressureResult, + this.listWeekBloodPressureResultAverage, + this.listWeekDiabtecPatientResult, + this.listWeekDiabtectResultAverage, + this.listWeekWeightMeasurementResult, + this.listWeekWeightMeasurementResultAverage, + this.listYearBloodPressureResult, + this.listYearBloodPressureResultAverage, + this.listYearDiabtecPatientResult, + this.listYearDiabtecResultAverage, + this.listYearWeightMeasurementResult, + this.listYearWeightMeasurementResultAverage, + this.listEInvoiceForDental, + this.listEInvoiceForOnlineCheckIn, + this.medGetActivitiesTransactionsStsList, + this.medGetAvgMonthTransactionsStsList, + this.medGetAvgWeekTransactionsStsList, + this.medGetCategoriesList, + this.medGetMonthActivitiesTransactionsStsList, + this.medGetMonthStepsTransactionsStsList, + this.medGetMonthTransactionsStsList, + this.medGetPatientLastRecordList, + this.medGetSubCategoriesList, + this.medGetTransactionsAndActTransactionsResult, + this.medGetTransactionsList, + this.medGetWeekActivitiesTransactionsStsList, + this.medGetWeekStepsTransactionsStsList, + this.medGetWeekTransactionsStsList, + this.medGetYearActivitiesTransactionsStsList, + this.medGetYearSleepTransactionsStsList, + this.medGetYearStepsTransactionsStsList, + this.medGetYearTransactionsStsList, + this.medInsertTransactionsOutputsList, + this.medicalRecordImages, + this.medicalReportToRead, + this.medicalReportUnreadNo, + this.missingIDCardAttachment, + this.missingInsuranceCardAttachment, + this.missingMedicalReportAttachment, + this.missingOtherRelationship, + this.missingPatientContactNo, + this.missingPatientId, + this.missingPatientIdentityNumber, + this.missingPatientName, + this.missingReferralContactNo, + this.missingReferralRelationship, + this.missingReferralRequesterName, + this.mobileNumber, + this.nationalityNumber, + this.onlineCheckInAppointments, + this.opinionUserAgreementContent, + this.orderInsert, + this.pateintInfoForUpdateList, + this.pateintUpatedList, + this.patientBirthdayCertificate, + this.patientERCMCRequestSummaryByProject, + this.patientERCMCRequestWithTotal, + this.patientERCMCGetAllServicesList, + this.patientERCMCGetTransactionsForOrderList, + this.patientERCoordinates, + this.patientERCountOrderList, + this.patientERCountsForApprovalOffice, + this.patientERDeleteOldCurrentDoctorsOutputsList, + this.patientERDeliveryGetAllDeliverdOrderList, + this.patientERDeliveryGetAllOrderList, + this.patientERDeliveryIsOrderInserted, + this.patientERDeliveryIsOrderUpdated, + this.patientERDeliveryIsPausedChanged, + this.patientERDeliveryNextOrder, + this.patientERDeliveryOrderInsert, + this.patientERDeliveryUpdateOrderStatus, + this.patientERDriverUpdate, + this.patientERExacartCheckIsDispenseAccpetableList, + this.patientERExacartGetDispenseQuantitiesByOrderIDList, + this.patientERExacartGetOrderDetailsByePharmacyOrderNoList, + this.patientERExacartGetOrderDetailsList, + this.patientERExacartGetTotalDispenseQuantitiesByPresNoList, + this.patientERExacartIsDispenseAdded, + this.patientERExacartIsDispenseAddedList, + this.patientERExacartIsOrderCompleted, + this.patientERGetAdminByProjectAndRoleList, + this.patientERGetAdminProjectsList, + this.patientERGetAllDriversList, + this.patientERGetAllNeedAproveStatusList, + this.patientERGetAllPresOrdersStatusList, + this.patientERGetAllProjectsList, + this.patientERGetArchiveInformationList, + this.patientERGetAskDoctorTotalByDateFilterList, + this.patientERGetBookScheduleConfigsList, + this.patientERGetClinicAndTimeAndEpisodeForAppointmentList, + this.patientERGetClinicAndTimeForDischargeList, + this.patientERGetDashboardDataforApporvalSectionForAdminList, + this.patientERGetDashboardDataforApporvalSectionList, + this.patientERGetDashboardDataforHHCSectionForAdminList, + this.patientERGetDashboardDataforHHCSectionList, + this.patientERGetDashboardDataforPrescriptionSectionForAdminList, + this.patientERGetDashboardDataforPrescriptionSectionList, + this.patientERGetDoctorDashboardDataModelList, + this.patientERGetDriverLocationList, + this.patientERGetInsuranceCardRequestByDateFilterList, + this.patientERGetLiveCareSummaryBookedAppoinmentStatusList, + this.patientERGetLiveCareSummaryCovidList, + this.patientERGetLiveCareSummaryForCMCList, + this.patientERGetLiveCareSummaryForHHCList, + this.patientERGetLiveCareSummaryForHomeDeliveryList, + this.patientERGetLiveCareSummaryForInsuranceCardRequestList, + this.patientERGetLiveCareSummaryForNewFilesList, + this.patientERGetLiveCareSummaryForOnlinePaymetRequestList, + this.patientERGetLiveCareSummaryForOnlinePharmacyOrdersList, + this.patientERGetLiveCareSummaryForTrasnportationList, + this.patientERGetLiveCareSummaryLiveCareCountsList, + this.patientERGetMedicalRequestTotalByDateFilterList, + this.patientERGetNearestPendingOrdersList, + this.patientERGetNeedAproveHistoryForOrderList, + this.patientERGetNeedAprovePendingOrdersList, + this.patientERGetNeedAproveStatusStatisticsList, + this.patientERGetPatientAllPresOrdersList, + this.patientERGetPendingPatientsCountList, + this.patientERGetPresOrdersHistoryForAdminList, + this.patientERGetPresOrdersHistoryForOrderList, + this.patientERGetPresOrdersStatusStatisticsList, + this.patientERHHCRequest, + this.patientERHHCRequestSummaryByProject, + this.patientERHHCRequestWithTotal, + this.patientERHHCGetAllServicesList, + this.patientERHHCGetTransactionsForOrderList, + this.patientERHomeDeliveryCounts, + this.patientERInsertDriver, + this.patientERInsertNewCurrentDoctorsOutputsList, + this.patientERInsuranceStatusCountList, + this.patientERIsNearestProjectUpdated, + this.patientERIsNeedAproveReturnedToQueue, + this.patientERIsNeedAproveUpdated, + this.patientERIsOrderClientRequestUpdated, + this.patientERIsOrderReturnedToQueue, + this.patientERIsPresOrderInserted, + this.patientERIsPresOrderUpdated, + this.patientERIsProjectUpdated, + this.patientERNotCompletedDetails, + this.patientERPatientsCountByCallStatus, + this.patientERPeakHourCounts, + this.patientERPresOrderInfo, + this.patientERPrescriptionCounts, + this.patientERProjectsContribution, + this.patientERRRTGetAllQuestionsList, + this.patientERRRTGetAllTransportationMethodList, + this.patientERRRTGetPickUpRequestByPresOrderIDList, + this.patientERRealRRTGetAllServicesList, + this.patientERRealRRTGetOrderDetailsList, + this.patientERRealRRTGetTransactionsForOrderList, + this.patientERRealRRTIsTransInserted, + this.patientERRequestList, + this.patientERTransportationRequestWithTotal, + this.patientERealRRTGetServicePriceList, + this.patientInfoByAdmissionNoList, + this.patientMonitorGetPatientHeartRate, + this.patientNotServedCounts, + this.patientPrescriptionList, + this.patientAllergies, + this.patientCheckAppointmentValidationList, + this.patientLoginTokenList, + this.patientQRLoginInfoList, + this.patientSELECTDeviceIMEIbyIMEIList, + this.pharmList, + this.prefLang, + this.radReportUnreadNo, + this.radGetPatientRadOrdersForDentalList, + this.referralNumber, + this.reminderConfigurations, + this.requestNo, + this.rowCount, + this.servicePrivilegeList, + this.shareFamilyFileObj, + this.status, + this.successCode, + this.surveyRate, + this.symptomCheckerConditionList, + this.symptomCheckerGetAllDefaultQuestionsList, + this.symptomCheckerGetBodyPartSymptomsList, + this.symptomCheckerGetBodyPartsByCodeList, + this.symptomCheckerGetBodyPartsList, + this.symptomCheckerJsonResponseInString, + this.timerTime, + this.totalAdvanceBalanceAmount, + this.totalPatientsCount, + this.totalPendingApprovalCount, + this.totalUnUsedCount, + this.transactionNo, + this.unReadCounts, + this.updateStatus, + this.userAgreementContent, + this.yahalaAccountNo, + this.check24HourComplaint, + this.currency, + this.message, + this.patientID, + this.returnValue, + this.returnValueStr, + this.statusCode}); + + LacumAccountInformation.fromJson(Map json) { + date = json['Date']; + languageID = json['LanguageID']; + serviceName = json['ServiceName']; + time = json['Time']; + androidLink = json['AndroidLink']; + authenticationTokenID = json['AuthenticationTokenID']; + data = json['Data']; + dataw = json['Dataw']; + dietType = json['DietType']; + errorCode = json['ErrorCode']; + errorEndUserMessage = json['ErrorEndUserMessage']; + errorEndUserMessageN = json['ErrorEndUserMessageN']; + errorMessage = json['ErrorMessage']; + errorType = json['ErrorType']; + foodCategory = json['FoodCategory']; + iOSLink = json['IOSLink']; + isAuthenticated = json['IsAuthenticated']; + mealOrderStatus = json['MealOrderStatus']; + mealType = json['MealType']; + messageStatus = json['MessageStatus']; + numberOfResultRecords = json['NumberOfResultRecords']; + patientBlodType = json['PatientBlodType']; + successMsg = json['SuccessMsg']; + successMsgN = json['SuccessMsgN']; + accountStatus = json['AccountStatus']; + activeArchiveObject = json['ActiveArchiveObject']; + activeMedicationCount = json['ActiveMedicationCount']; + allMedicationTakenDuringAdmissionList = + json['AllMedicationTakenDuringAdmission_List']; + appointmentNo = json['AppointmentNo']; + arePatientsOnlineList = json['ArePatientsOnlineList']; + balanceAmount = json['BalanceAmount']; + bloodGroupList = json['BloodGroupList']; + cVIUnreadCount = json['CVI_UnreadCount']; + checkUserHasAccount = json['CheckUserHasAccount']; + complaintNo = json['ComplaintNo']; + dischargeList = json['DischargeList']; + episodeID = json['EpisodeID']; + finalRadiologyList = json['FinalRadiologyList']; + fullName = json['FullName']; + geoFPointsList = json['GeoF_PointsList']; + geoGetPateintInfo = json['GeoGetPateintInfo']; + getAllDoctorsByProjectAndClinicList = + json['GetAllDoctorsByProjectAndClinicList']; + getAppointmentNumbersForDoctorList = + json['GetAppointmentNumbersForDoctorList']; + getCheckUpItemsList = json['GetCheckUpItemsList']; + getCosmeticConferenceForTodayList = + json['GetCosmeticConferenceForTodayList']; + getDoctorERClinicResult = json['GetDoctorERClinicResult']; + getInvoiceApprovalList = json['GetInvoiceApprovalList']; + getNearestProjectList = json['GetNearestProjectList']; + getPatientAdmissionOrAppoinmentNoList = + json['GetPatientAdmissionOrAppoinmentNo_List']; + getPatientBloodType = json['GetPatientBloodType']; + getPatientInsuranceCardStatusStatisticsList = + json['GetPatientInsuranceCardStatusStatisticsList']; + getSurveyList = json['GetSurveyList']; + getTotalRegisteredPatientList = json['GetTotalRegisteredPatientList']; + getUserDetailsList = json['GetUserDetailsList']; + getCustomerPointInfo = json['Get_CustomerPointInfo']; + hISApprovalList = json['HIS_Approval_List']; + hISInpAdmissionList = json['HIS_InpAdmission_List']; + hISProgNoteAssesmentModelList = json['HIS_ProgNoteAssesmentModel_List']; + hMGGetAllOffersList = json['HMG_GetAllOffersList']; + hasApproval = json['Has_Approval']; + hasConsultation = json['Has_Consultation']; + hasDental = json['Has_Dental']; + hasLab = json['Has_Lab']; + hasPharmacy = json['Has_Pharmacy']; + hasRad = json['Has_Rad']; + hmgSMSGetByProjectIDAndPatientIDList = + json['Hmg_SMS_Get_By_ProjectID_And_PatientIDList']; + hoursLeft = json['HoursLeft']; + iNPMGetAllAdmissionList = json['INPM_GetAllAdmission_List']; + iNPMGetPatientInfoForSickLeaveReportList = + json['INPM_GetPatientInfoForSickLeaveReport_List']; + iNPMHISPatientMedicalStatusUnreadCount = + json['INPM_HIS_PatientMedicalStatus_UnreadCount']; + iNPMLABGetPatientLabOrdersResultsList = + json['INPM_LAB_GetPatientLabOrdersResults_List']; + iNPMLABGetPatientLabResultsList = + json['INPM_LAB_GetPatientLabResults_List']; + iNPMLABGetPatientRADReportList = json['INPM_LAB_GetPatientRADReport_List']; + iNPMLABGetPatientRadResultsList = + json['INPM_LAB_GetPatientRadResults_List']; + iNPMRadGetPatientRadOrdersCVIList = + json['INPM_Rad_GetPatientRadOrders_CVI_List']; + iNPMRadGetPatientRadOrdersList = json['INPM_Rad_GetPatientRadOrders_List']; + iNPMRadGetRadMedicalRecordsList = + json['INPM_Rad_GetRadMedicalRecords_List']; + iNPGetPrescriptionDischargesList = + json['INP_GetPrescriptionDischarges_List']; + iNPGetPrescriptionReportList = json['INP_GetPrescriptionReport_List']; + identificationNo = json['IdentificationNo']; + isHomeMedicineDeliverySupported = json['IsHomeMedicineDeliverySupported']; + isInsertedOrUpdated = json['IsInsertedOrUpdated']; + isMainAcoountEqualPatienID = json['IsMainAcoountEqualPatienID']; + isPatientAlreadyAgreed = json['IsPatientAlreadyAgreed']; + isPatientCallBackBlackList = json['IsPatientCallBackBlackList']; + isPatientHaveFingerPrint = json['IsPatientHaveFingerPrint']; + isPatientOnline = json['IsPatientOnline']; + isPatientTokenRemoved = json['IsPatientTokenRemoved']; + isPaused = json['IsPaused']; + isProjectWorkingHours = json['IsProjectWorkingHours']; + isStoreRateAllowed = json['IsStoreRateAllowed']; + isStoreRateInserted = json['IsStoreRateInserted']; + isStoreRateUpdated = json['IsStoreRateUpdated']; + labRadUpdatedToRead = json['LabRadUpdatedToRead']; + labReportUnreadNo = json['LabReportUnreadNo']; + lakumInquiryInformationObj = json['LakumInquiryInformationObj']; + lakumInquiryInformationObjVersion = + json['LakumInquiryInformationObjVersion'] != null + ? new LakumInquiryInformationObjVersion.fromJson( + json['LakumInquiryInformationObjVersion']) + : null; + lakumResponseList = json['LakumResponseList']; + laserGetBodyPartsByCategoryList = json['Laser_GetBodyPartsByCategoryList']; + laserGetCategoriesList = json['Laser_GetCategoriesList']; + list = json['List']; + listCount = json['ListCount']; + listCountDeliverd = json['ListCountDeliverd']; + listCountUnDeliverd = json['ListCountUnDeliverd']; + listDeviceInfo = json['ListDeviceInfo']; + listFamilyAppointments = json['ListFamilyAppointments']; + listLabResultsByAppNo = json['ListLabResultsByAppNo']; + listLakumInquiryInformationObj = json['ListLakumInquiryInformationObj']; + listOpinionGetAllPeriod = json['ListOpinion_GetAllPeriod']; + listOpinionGetAllServices = json['ListOpinion_GetAllServices']; + listOpinionGetIsAgreeValue = json['ListOpinion_GetIsAgreeValue']; + listOpinionGetOpinionLogin = json['ListOpinion_GetOpinionLogin']; + listOpinionGetRequestedSerives = json['ListOpinion_GetRequestedSerives']; + listOpinionGetShareServicesDetails = + json['ListOpinion_GetShareServicesDetails']; + listOpinionUserTerms = json['ListOpinion_UserTerms']; + listPLO = json['ListPLO']; + listPLR = json['ListPLR']; + listPLSR = json['ListPLSR']; + listPRM = json['ListPRM']; + listPatientFamilyFiles = json['ListPatientFamilyFiles']; + listPatientFileInfo = json['ListPatientFileInfo']; + listRAD = json['ListRAD']; + listRADAPI = json['ListRADAPI']; + listActiveGetPrescriptionReportByPatientID = + json['List_ActiveGetPrescriptionReportByPatientID']; + listAppointmentsForDentalClinic = json['List_AppointmentsForDentalClinic']; + listBabyInfoResult = json['List_BabyInfoResult']; + listCheckInsuranceCoverage = json['List_CheckInsuranceCoverage']; + listCompanyClass = json['List_CompanyClass']; + listConsentMedicalReport = json['List_ConsentMedicalReport']; + listDentalAppointments = json['List_DentalAppointments']; + listDeviceTokenIDByAppointmentNo = + json['List_DeviceTokenIDByAppointmentNo']; + listDischargeDiagnosis = json['List_DischargeDiagnosis']; + listDischargeMedicine = json['List_DischargeMedicine']; + listDischargeSummary = json['List_DischargeSummary']; + listDoctorResponse = json['List_DoctorResponse']; + listDoneVaccines = json['List_DoneVaccines']; + listEReferralResult = json['List_EReferralResult']; + listEReferrals = json['List_EReferrals']; + listGetAllPatientsLiveCareAdmin = + json['List_GetAllPatients_LiveCare_Admin']; + listGetDataForExcel = json['List_GetDataForExcel']; + listGetMainCountID = json['List_GetMainCountID']; + listGetPrescriptionReportByPatientID = + json['List_GetPrescriptionReportByPatientID']; + listGetSickLeave = json['List_GetSickLeave']; + listHISInvoice = json['List_HISInvoice']; + listHISInvoiceProcedures = json['List_HISInvoiceProcedures']; + listInpatientInvoices = json['List_InpatientInvoices']; + listInsuranceCheckList = json['List_InsuranceCheckList']; + listInsuranceCompanies = json['List_InsuranceCompanies']; + listInsuranceCompaniesGroup = json['List_InsuranceCompaniesGroup']; + listInsuranceUpdateDetails = json['List_InsuranceUpdateDetails']; + listInvoiceApprovalProcedureInfo = + json['List_InvoiceApprovalProcedureInfo']; + listIsLastSatisfactionSurveyReviewedModel = + json['List_IsLastSatisfactionSurveyReviewedModel']; + listLabOrderDetailsModel = json['List_LabOrderDetailsModel']; + listMedicalReport = json['List_MedicalReport']; + listMedicalReportApprovals = json['List_MedicalReportApprovals']; + listMedicalReportStatus = json['List_MedicalReportStatus']; + listMonthBloodPressureResult = json['List_MonthBloodPressureResult']; + listMonthBloodPressureResultAverage = + json['List_MonthBloodPressureResultAverage']; + listMonthDiabtecPatientResult = json['List_MonthDiabtecPatientResult']; + listMonthDiabtectResultAverage = json['List_MonthDiabtectResultAverage']; + listMonthWeightMeasurementResult = + json['List_MonthWeightMeasurementResult']; + listMonthWeightMeasurementResultAverage = + json['List_MonthWeightMeasurementResultAverage']; + listOnlinePrescriptionResult = json['List_OnlinePrescriptionResult']; + listOutPatientInvoices = json['List_OutPatientInvoices']; + listPHRInvoice = json['List_PHRInvoice']; + listPHRInvoiceItems = json['List_PHRInvoiceItems']; + listPHRPaymentMethods = json['List_PHRPaymentMethods']; + listPateintDetails = json['List_PateintDetails']; + listPateintInformation = json['List_PateintInformation']; + listPatientAdmissionInfo = json['List_PatientAdmissionInfo']; + listPatientAdvanceBalanceAmount = json['List_PatientAdvanceBalanceAmount']; + listPatientCallBackLogs = json['List_PatientCallBackLogs']; + listPatientCallBackToUpdateFromICServer = + json['List_PatientCallBackToUpdateFromICServer']; + listPatientCount = json['List_PatientCount']; + listPatientDashboard = json['List_PatientDashboard']; + listPatientERGetAdminClinicsModel = + json['List_PatientER_GetAdminClinicsModel']; + listPatientERGetAdminProjectsModel = + json['List_PatientER_GetAdminProjectsModel']; + listPatientERGetAllClinicsModel = json['List_PatientER_GetAllClinicsModel']; + listPatientHISInvoices = json['List_PatientHISInvoices']; + listPatientICProjects = json['List_PatientICProjects']; + listPatientICProjectsByID = json['List_PatientICProjectsByID']; + listPatientICProjectsTimings = json['List_PatientICProjectsTimings']; + listPatientIDByUID = json['List_PatientIDByUID']; + listPatientIDForSurveyResult = json['List_PatientIDForSurveyResult']; + listPatientInfo = json['List_PatientInfo']; + listPatientInfoForDDScreen = json['List_PatientInfoForDDScreen']; + listPatientInfoForSickleaveReport = + json['List_PatientInfoForSickleaveReport']; + listPatientInsuranceCard = json['List_PatientInsuranceCard']; + listPatientInsuranceCardHistory = json['List_PatientInsuranceCardHistory']; + listPatientInsuranceDetails = json['List_PatientInsuranceDetails']; + listPatientPHRInvoices = json['List_PatientPHRInvoices']; + listPatientServicePoint = json['List_PatientServicePoint']; + listPatientStatusCount = json['List_PatientStatusCount']; + listPatientChatRequestMapModel = json['List_Patient_ChatRequestMapModel']; + listPatientChatRequestModel = json['List_Patient_ChatRequestModel']; + listPatientChatRequestVCModel = json['List_Patient_ChatRequestVCModel']; + listPaymentMethods = json['List_PaymentMethods']; + listPointServices = json['List_PointServices']; + listPregnancyStagesInfo = json['List_PregnancyStagesInfo']; + listProjectAvgERWaitingTime = json['List_ProjectAvgERWaitingTime']; + listProjectAvgERWaitingTimeHourly = + json['List_ProjectAvgERWaitingTimeHourly']; + listRadMedicalRecords = json['List_RadMedicalRecords']; + listRadMedicalRecordsAPI = json['List_RadMedicalRecordsAPI']; + listRadMedicalRecordsCVI = json['List_RadMedicalRecordsCVI']; + listRadMedicalRecordsCVIAPI = json['List_RadMedicalRecordsCVIAPI']; + listRadMedicalRecordsResults = json['List_RadMedicalRecordsResults']; + listSickLeave = json['List_SickLeave']; + listTransaction = json['List_Transaction']; + listVideoConferenceSessions = json['List_VideoConferenceSessions']; + listWeekBloodPressureResult = json['List_WeekBloodPressureResult']; + listWeekBloodPressureResultAverage = + json['List_WeekBloodPressureResultAverage']; + listWeekDiabtecPatientResult = json['List_WeekDiabtecPatientResult']; + listWeekDiabtectResultAverage = json['List_WeekDiabtectResultAverage']; + listWeekWeightMeasurementResult = json['List_WeekWeightMeasurementResult']; + listWeekWeightMeasurementResultAverage = + json['List_WeekWeightMeasurementResultAverage']; + listYearBloodPressureResult = json['List_YearBloodPressureResult']; + listYearBloodPressureResultAverage = + json['List_YearBloodPressureResultAverage']; + listYearDiabtecPatientResult = json['List_YearDiabtecPatientResult']; + listYearDiabtecResultAverage = json['List_YearDiabtecResultAverage']; + listYearWeightMeasurementResult = json['List_YearWeightMeasurementResult']; + listYearWeightMeasurementResultAverage = + json['List_YearWeightMeasurementResultAverage']; + listEInvoiceForDental = json['List_eInvoiceForDental']; + listEInvoiceForOnlineCheckIn = json['List_eInvoiceForOnlineCheckIn']; + medGetActivitiesTransactionsStsList = + json['Med_GetActivitiesTransactionsStsList']; + medGetAvgMonthTransactionsStsList = + json['Med_GetAvgMonthTransactionsStsList']; + medGetAvgWeekTransactionsStsList = + json['Med_GetAvgWeekTransactionsStsList']; + medGetCategoriesList = json['Med_GetCategoriesList']; + medGetMonthActivitiesTransactionsStsList = + json['Med_GetMonthActivitiesTransactionsStsList']; + medGetMonthStepsTransactionsStsList = + json['Med_GetMonthStepsTransactionsStsList']; + medGetMonthTransactionsStsList = json['Med_GetMonthTransactionsStsList']; + medGetPatientLastRecordList = json['Med_GetPatientLastRecordList']; + medGetSubCategoriesList = json['Med_GetSubCategoriesList']; + medGetTransactionsAndActTransactionsResult = + json['Med_GetTransactionsAndActTransactionsResult']; + medGetTransactionsList = json['Med_GetTransactionsList']; + medGetWeekActivitiesTransactionsStsList = + json['Med_GetWeekActivitiesTransactionsStsList']; + medGetWeekStepsTransactionsStsList = + json['Med_GetWeekStepsTransactionsStsList']; + medGetWeekTransactionsStsList = json['Med_GetWeekTransactionsStsList']; + medGetYearActivitiesTransactionsStsList = + json['Med_GetYearActivitiesTransactionsStsList']; + medGetYearSleepTransactionsStsList = + json['Med_GetYearSleepTransactionsStsList']; + medGetYearStepsTransactionsStsList = + json['Med_GetYearStepsTransactionsStsList']; + medGetYearTransactionsStsList = json['Med_GetYearTransactionsStsList']; + medInsertTransactionsOutputsList = + json['Med_InsertTransactionsOutputsList']; + medicalRecordImages = json['MedicalRecordImages']; + medicalReportToRead = json['MedicalReportToRead']; + medicalReportUnreadNo = json['MedicalReportUnreadNo']; + missingIDCardAttachment = json['Missing_IDCardAttachment']; + missingInsuranceCardAttachment = json['Missing_InsuranceCardAttachment']; + missingMedicalReportAttachment = json['Missing_MedicalReportAttachment']; + missingOtherRelationship = json['Missing_OtherRelationship']; + missingPatientContactNo = json['Missing_PatientContactNo']; + missingPatientId = json['Missing_PatientId']; + missingPatientIdentityNumber = json['Missing_PatientIdentityNumber']; + missingPatientName = json['Missing_PatientName']; + missingReferralContactNo = json['Missing_ReferralContactNo']; + missingReferralRelationship = json['Missing_ReferralRelationship']; + missingReferralRequesterName = json['Missing_ReferralRequesterName']; + mobileNumber = json['MobileNumber']; + nationalityNumber = json['NationalityNumber']; + onlineCheckInAppointments = json['OnlineCheckInAppointments']; + opinionUserAgreementContent = json['Opinion_UserAgreementContent']; + orderInsert = json['OrderInsert']; + pateintInfoForUpdateList = json['PateintInfoForUpdateList']; + pateintUpatedList = json['PateintUpatedList']; + patientBirthdayCertificate = json['PatientBirthdayCertificate']; + patientERCMCRequestSummaryByProject = + json['PatientER_CMCRequestSummaryByProject']; + patientERCMCRequestWithTotal = json['PatientER_CMCRequestWithTotal']; + patientERCMCGetAllServicesList = json['PatientER_CMC_GetAllServicesList']; + patientERCMCGetTransactionsForOrderList = + json['PatientER_CMC_GetTransactionsForOrderList']; + patientERCoordinates = json['PatientER_Coordinates']; + patientERCountOrderList = json['PatientER_CountOrderList']; + patientERCountsForApprovalOffice = + json['PatientER_CountsForApprovalOffice']; + patientERDeleteOldCurrentDoctorsOutputsList = + json['PatientER_DeleteOldCurrentDoctorsOutputsList']; + patientERDeliveryGetAllDeliverdOrderList = + json['PatientER_Delivery_GetAllDeliverdOrderList']; + patientERDeliveryGetAllOrderList = + json['PatientER_Delivery_GetAllOrderList']; + patientERDeliveryIsOrderInserted = + json['PatientER_Delivery_IsOrderInserted']; + patientERDeliveryIsOrderUpdated = json['PatientER_Delivery_IsOrderUpdated']; + patientERDeliveryIsPausedChanged = + json['PatientER_Delivery_IsPausedChanged']; + patientERDeliveryNextOrder = json['PatientER_Delivery_NextOrder']; + patientERDeliveryOrderInsert = json['PatientER_Delivery_OrderInsert']; + patientERDeliveryUpdateOrderStatus = + json['PatientER_Delivery_UpdateOrderStatus']; + patientERDriverUpdate = json['PatientER_DriverUpdate']; + patientERExacartCheckIsDispenseAccpetableList = + json['PatientER_Exacart_CheckIsDispenseAccpetableList']; + patientERExacartGetDispenseQuantitiesByOrderIDList = + json['PatientER_Exacart_GetDispenseQuantitiesByOrderIDList']; + patientERExacartGetOrderDetailsByePharmacyOrderNoList = + json['PatientER_Exacart_GetOrderDetailsByePharmacyOrderNoList']; + patientERExacartGetOrderDetailsList = + json['PatientER_Exacart_GetOrderDetailsList']; + patientERExacartGetTotalDispenseQuantitiesByPresNoList = + json['PatientER_Exacart_GetTotalDispenseQuantitiesByPresNoList']; + patientERExacartIsDispenseAdded = json['PatientER_Exacart_IsDispenseAdded']; + patientERExacartIsDispenseAddedList = + json['PatientER_Exacart_IsDispenseAddedList']; + patientERExacartIsOrderCompleted = + json['PatientER_Exacart_IsOrderCompleted']; + patientERGetAdminByProjectAndRoleList = + json['PatientER_GetAdminByProjectAndRoleList']; + patientERGetAdminProjectsList = json['PatientER_GetAdminProjectsList']; + patientERGetAllDriversList = json['PatientER_GetAllDriversList']; + patientERGetAllNeedAproveStatusList = + json['PatientER_GetAllNeedAproveStatusList']; + patientERGetAllPresOrdersStatusList = + json['PatientER_GetAllPresOrdersStatusList']; + patientERGetAllProjectsList = json['PatientER_GetAllProjectsList']; + patientERGetArchiveInformationList = + json['PatientER_GetArchiveInformation_List']; + patientERGetAskDoctorTotalByDateFilterList = + json['PatientER_GetAskDoctorTotalByDateFilterList']; + patientERGetBookScheduleConfigsList = + json['PatientER_GetBookScheduleConfigsList']; + patientERGetClinicAndTimeAndEpisodeForAppointmentList = + json['PatientER_GetClinicAndTimeAndEpisodeForAppointmentList']; + patientERGetClinicAndTimeForDischargeList = + json['PatientER_GetClinicAndTimeForDischargeList']; + patientERGetDashboardDataforApporvalSectionForAdminList = + json['PatientER_GetDashboardDataforApporvalSectionForAdminList']; + patientERGetDashboardDataforApporvalSectionList = + json['PatientER_GetDashboardDataforApporvalSectionList']; + patientERGetDashboardDataforHHCSectionForAdminList = + json['PatientER_GetDashboardDataforHHCSectionForAdminList']; + patientERGetDashboardDataforHHCSectionList = + json['PatientER_GetDashboardDataforHHCSectionList']; + patientERGetDashboardDataforPrescriptionSectionForAdminList = + json['PatientER_GetDashboardDataforPrescriptionSectionForAdminList']; + patientERGetDashboardDataforPrescriptionSectionList = + json['PatientER_GetDashboardDataforPrescriptionSectionList']; + patientERGetDoctorDashboardDataModelList = + json['PatientER_GetDoctorDashboardDataModelList']; + patientERGetDriverLocationList = json['PatientER_GetDriverLocationList']; + patientERGetInsuranceCardRequestByDateFilterList = + json['PatientER_GetInsuranceCardRequestByDateFilterList']; + patientERGetLiveCareSummaryBookedAppoinmentStatusList = + json['PatientER_GetLiveCareSummaryBookedAppoinmentStatusList']; + patientERGetLiveCareSummaryCovidList = + json['PatientER_GetLiveCareSummaryCovidList']; + patientERGetLiveCareSummaryForCMCList = + json['PatientER_GetLiveCareSummaryForCMCList']; + patientERGetLiveCareSummaryForHHCList = + json['PatientER_GetLiveCareSummaryForHHCList']; + patientERGetLiveCareSummaryForHomeDeliveryList = + json['PatientER_GetLiveCareSummaryForHomeDeliveryList']; + patientERGetLiveCareSummaryForInsuranceCardRequestList = + json['PatientER_GetLiveCareSummaryForInsuranceCardRequestList']; + patientERGetLiveCareSummaryForNewFilesList = + json['PatientER_GetLiveCareSummaryForNewFilesList']; + patientERGetLiveCareSummaryForOnlinePaymetRequestList = + json['PatientER_GetLiveCareSummaryForOnlinePaymetRequestList']; + patientERGetLiveCareSummaryForOnlinePharmacyOrdersList = + json['PatientER_GetLiveCareSummaryForOnlinePharmacyOrdersList']; + patientERGetLiveCareSummaryForTrasnportationList = + json['PatientER_GetLiveCareSummaryForTrasnportationList']; + patientERGetLiveCareSummaryLiveCareCountsList = + json['PatientER_GetLiveCareSummaryLiveCareCountsList']; + patientERGetMedicalRequestTotalByDateFilterList = + json['PatientER_GetMedicalRequestTotalByDateFilterList']; + patientERGetNearestPendingOrdersList = + json['PatientER_GetNearestPendingOrdersList']; + patientERGetNeedAproveHistoryForOrderList = + json['PatientER_GetNeedAproveHistoryForOrderList']; + patientERGetNeedAprovePendingOrdersList = + json['PatientER_GetNeedAprovePendingOrdersList']; + patientERGetNeedAproveStatusStatisticsList = + json['PatientER_GetNeedAproveStatusStatisticsList']; + patientERGetPatientAllPresOrdersList = + json['PatientER_GetPatientAllPresOrdersList']; + patientERGetPendingPatientsCountList = + json['PatientER_GetPendingPatientsCountList']; + patientERGetPresOrdersHistoryForAdminList = + json['PatientER_GetPresOrdersHistoryForAdminList']; + patientERGetPresOrdersHistoryForOrderList = + json['PatientER_GetPresOrdersHistoryForOrderList']; + patientERGetPresOrdersStatusStatisticsList = + json['PatientER_GetPresOrdersStatusStatisticsList']; + patientERHHCRequest = json['PatientER_HHCRequest']; + patientERHHCRequestSummaryByProject = + json['PatientER_HHCRequestSummaryByProject']; + patientERHHCRequestWithTotal = json['PatientER_HHCRequestWithTotal']; + patientERHHCGetAllServicesList = json['PatientER_HHC_GetAllServicesList']; + patientERHHCGetTransactionsForOrderList = + json['PatientER_HHC_GetTransactionsForOrderList']; + patientERHomeDeliveryCounts = json['PatientER_HomeDeliveryCounts']; + patientERInsertDriver = json['PatientER_InsertDriver']; + patientERInsertNewCurrentDoctorsOutputsList = + json['PatientER_InsertNewCurrentDoctorsOutputsList']; + patientERInsuranceStatusCountList = + json['PatientER_InsuranceStatusCountList']; + patientERIsNearestProjectUpdated = + json['PatientER_IsNearestProjectUpdated']; + patientERIsNeedAproveReturnedToQueue = + json['PatientER_IsNeedAproveReturnedToQueue']; + patientERIsNeedAproveUpdated = json['PatientER_IsNeedAproveUpdated']; + patientERIsOrderClientRequestUpdated = + json['PatientER_IsOrderClientRequestUpdated']; + patientERIsOrderReturnedToQueue = json['PatientER_IsOrderReturnedToQueue']; + patientERIsPresOrderInserted = json['PatientER_IsPresOrderInserted']; + patientERIsPresOrderUpdated = json['PatientER_IsPresOrderUpdated']; + patientERIsProjectUpdated = json['PatientER_IsProjectUpdated']; + patientERNotCompletedDetails = json['PatientER_NotCompletedDetails']; + patientERPatientsCountByCallStatus = + json['PatientER_PatientsCountByCallStatus']; + patientERPeakHourCounts = json['PatientER_PeakHourCounts']; + patientERPresOrderInfo = json['PatientER_PresOrderInfo']; + patientERPrescriptionCounts = json['PatientER_PrescriptionCounts']; + patientERProjectsContribution = json['PatientER_ProjectsContribution']; + patientERRRTGetAllQuestionsList = json['PatientER_RRT_GetAllQuestionsList']; + patientERRRTGetAllTransportationMethodList = + json['PatientER_RRT_GetAllTransportationMethodList']; + patientERRRTGetPickUpRequestByPresOrderIDList = + json['PatientER_RRT_GetPickUpRequestByPresOrderIDList']; + patientERRealRRTGetAllServicesList = + json['PatientER_RealRRT_GetAllServicesList']; + patientERRealRRTGetOrderDetailsList = + json['PatientER_RealRRT_GetOrderDetailsList']; + patientERRealRRTGetTransactionsForOrderList = + json['PatientER_RealRRT_GetTransactionsForOrderList']; + patientERRealRRTIsTransInserted = json['PatientER_RealRRT_IsTransInserted']; + patientERRequestList = json['PatientER_RequestList']; + patientERTransportationRequestWithTotal = + json['PatientER_TransportationRequestWithTotal']; + patientERealRRTGetServicePriceList = + json['PatientE_RealRRT_GetServicePriceList']; + patientInfoByAdmissionNoList = json['PatientInfoByAdmissionNo_List']; + patientMonitorGetPatientHeartRate = + json['PatientMonitor_GetPatientHeartRate']; + patientNotServedCounts = json['PatientNotServedCounts']; + patientPrescriptionList = json['PatientPrescriptionList']; + patientAllergies = json['Patient_Allergies']; + patientCheckAppointmentValidationList = + json['Patient_CheckAppointmentValidationList']; + patientLoginTokenList = json['Patient_LoginTokenList']; + patientQRLoginInfoList = json['Patient_QRLoginInfoList']; + patientSELECTDeviceIMEIbyIMEIList = + json['Patient_SELECTDeviceIMEIbyIMEIList']; + pharmList = json['PharmList']; + prefLang = json['PrefLang']; + radReportUnreadNo = json['RadReportUnreadNo']; + radGetPatientRadOrdersForDentalList = + json['Rad_GetPatientRadOrdersForDental_List']; + referralNumber = json['ReferralNumber']; + reminderConfigurations = json['ReminderConfigurations']; + requestNo = json['RequestNo']; + rowCount = json['RowCount']; + servicePrivilegeList = json['ServicePrivilegeList']; + shareFamilyFileObj = json['ShareFamilyFileObj']; + status = json['Status']; + successCode = json['SuccessCode']; + surveyRate = json['SurveyRate']; + symptomCheckerConditionList = json['SymptomChecker_ConditionList']; + symptomCheckerGetAllDefaultQuestionsList = + json['SymptomChecker_GetAllDefaultQuestionsList']; + symptomCheckerGetBodyPartSymptomsList = + json['SymptomChecker_GetBodyPartSymptomsList']; + symptomCheckerGetBodyPartsByCodeList = + json['SymptomChecker_GetBodyPartsByCodeList']; + symptomCheckerGetBodyPartsList = json['SymptomChecker_GetBodyPartsList']; + symptomCheckerJsonResponseInString = + json['SymptomChecker_JsonResponseInString']; + timerTime = json['TimerTime']; + totalAdvanceBalanceAmount = json['TotalAdvanceBalanceAmount']; + totalPatientsCount = json['TotalPatientsCount']; + totalPendingApprovalCount = json['TotalPendingApprovalCount']; + totalUnUsedCount = json['TotalUnUsedCount']; + transactionNo = json['TransactionNo']; + unReadCounts = json['UnReadCounts']; + updateStatus = json['UpdateStatus']; + userAgreementContent = json['UserAgreementContent']; + yahalaAccountNo = json['YahalaAccountNo']; + check24HourComplaint = json['check24HourComplaint']; + currency = json['currency']; + message = json['message']; + patientID = json['patientID']; + returnValue = json['returnValue']; + returnValueStr = json['returnValueStr']; + statusCode = json['statusCode']; + } + + Map toJson() { + final Map data = new Map(); + data['Date'] = this.date; + data['LanguageID'] = this.languageID; + data['ServiceName'] = this.serviceName; + data['Time'] = this.time; + data['AndroidLink'] = this.androidLink; + data['AuthenticationTokenID'] = this.authenticationTokenID; + data['Data'] = this.data; + data['Dataw'] = this.dataw; + data['DietType'] = this.dietType; + data['ErrorCode'] = this.errorCode; + data['ErrorEndUserMessage'] = this.errorEndUserMessage; + data['ErrorEndUserMessageN'] = this.errorEndUserMessageN; + data['ErrorMessage'] = this.errorMessage; + data['ErrorType'] = this.errorType; + data['FoodCategory'] = this.foodCategory; + data['IOSLink'] = this.iOSLink; + data['IsAuthenticated'] = this.isAuthenticated; + data['MealOrderStatus'] = this.mealOrderStatus; + data['MealType'] = this.mealType; + data['MessageStatus'] = this.messageStatus; + data['NumberOfResultRecords'] = this.numberOfResultRecords; + data['PatientBlodType'] = this.patientBlodType; + data['SuccessMsg'] = this.successMsg; + data['SuccessMsgN'] = this.successMsgN; + data['AccountStatus'] = this.accountStatus; + data['ActiveArchiveObject'] = this.activeArchiveObject; + data['ActiveMedicationCount'] = this.activeMedicationCount; + data['AllMedicationTakenDuringAdmission_List'] = + this.allMedicationTakenDuringAdmissionList; + data['AppointmentNo'] = this.appointmentNo; + data['ArePatientsOnlineList'] = this.arePatientsOnlineList; + data['BalanceAmount'] = this.balanceAmount; + data['BloodGroupList'] = this.bloodGroupList; + data['CVI_UnreadCount'] = this.cVIUnreadCount; + data['CheckUserHasAccount'] = this.checkUserHasAccount; + data['ComplaintNo'] = this.complaintNo; + data['DischargeList'] = this.dischargeList; + data['EpisodeID'] = this.episodeID; + data['FinalRadiologyList'] = this.finalRadiologyList; + data['FullName'] = this.fullName; + data['GeoF_PointsList'] = this.geoFPointsList; + data['GeoGetPateintInfo'] = this.geoGetPateintInfo; + data['GetAllDoctorsByProjectAndClinicList'] = + this.getAllDoctorsByProjectAndClinicList; + data['GetAppointmentNumbersForDoctorList'] = + this.getAppointmentNumbersForDoctorList; + data['GetCheckUpItemsList'] = this.getCheckUpItemsList; + data['GetCosmeticConferenceForTodayList'] = + this.getCosmeticConferenceForTodayList; + data['GetDoctorERClinicResult'] = this.getDoctorERClinicResult; + data['GetInvoiceApprovalList'] = this.getInvoiceApprovalList; + data['GetNearestProjectList'] = this.getNearestProjectList; + data['GetPatientAdmissionOrAppoinmentNo_List'] = + this.getPatientAdmissionOrAppoinmentNoList; + data['GetPatientBloodType'] = this.getPatientBloodType; + data['GetPatientInsuranceCardStatusStatisticsList'] = + this.getPatientInsuranceCardStatusStatisticsList; + data['GetSurveyList'] = this.getSurveyList; + data['GetTotalRegisteredPatientList'] = this.getTotalRegisteredPatientList; + data['GetUserDetailsList'] = this.getUserDetailsList; + data['Get_CustomerPointInfo'] = this.getCustomerPointInfo; + data['HIS_Approval_List'] = this.hISApprovalList; + data['HIS_InpAdmission_List'] = this.hISInpAdmissionList; + data['HIS_ProgNoteAssesmentModel_List'] = + this.hISProgNoteAssesmentModelList; + data['HMG_GetAllOffersList'] = this.hMGGetAllOffersList; + data['Has_Approval'] = this.hasApproval; + data['Has_Consultation'] = this.hasConsultation; + data['Has_Dental'] = this.hasDental; + data['Has_Lab'] = this.hasLab; + data['Has_Pharmacy'] = this.hasPharmacy; + data['Has_Rad'] = this.hasRad; + data['Hmg_SMS_Get_By_ProjectID_And_PatientIDList'] = + this.hmgSMSGetByProjectIDAndPatientIDList; + data['HoursLeft'] = this.hoursLeft; + data['INPM_GetAllAdmission_List'] = this.iNPMGetAllAdmissionList; + data['INPM_GetPatientInfoForSickLeaveReport_List'] = + this.iNPMGetPatientInfoForSickLeaveReportList; + data['INPM_HIS_PatientMedicalStatus_UnreadCount'] = + this.iNPMHISPatientMedicalStatusUnreadCount; + data['INPM_LAB_GetPatientLabOrdersResults_List'] = + this.iNPMLABGetPatientLabOrdersResultsList; + data['INPM_LAB_GetPatientLabResults_List'] = + this.iNPMLABGetPatientLabResultsList; + data['INPM_LAB_GetPatientRADReport_List'] = + this.iNPMLABGetPatientRADReportList; + data['INPM_LAB_GetPatientRadResults_List'] = + this.iNPMLABGetPatientRadResultsList; + data['INPM_Rad_GetPatientRadOrders_CVI_List'] = + this.iNPMRadGetPatientRadOrdersCVIList; + data['INPM_Rad_GetPatientRadOrders_List'] = + this.iNPMRadGetPatientRadOrdersList; + data['INPM_Rad_GetRadMedicalRecords_List'] = + this.iNPMRadGetRadMedicalRecordsList; + data['INP_GetPrescriptionDischarges_List'] = + this.iNPGetPrescriptionDischargesList; + data['INP_GetPrescriptionReport_List'] = this.iNPGetPrescriptionReportList; + data['IdentificationNo'] = this.identificationNo; + data['IsHomeMedicineDeliverySupported'] = + this.isHomeMedicineDeliverySupported; + data['IsInsertedOrUpdated'] = this.isInsertedOrUpdated; + data['IsMainAcoountEqualPatienID'] = this.isMainAcoountEqualPatienID; + data['IsPatientAlreadyAgreed'] = this.isPatientAlreadyAgreed; + data['IsPatientCallBackBlackList'] = this.isPatientCallBackBlackList; + data['IsPatientHaveFingerPrint'] = this.isPatientHaveFingerPrint; + data['IsPatientOnline'] = this.isPatientOnline; + data['IsPatientTokenRemoved'] = this.isPatientTokenRemoved; + data['IsPaused'] = this.isPaused; + data['IsProjectWorkingHours'] = this.isProjectWorkingHours; + data['IsStoreRateAllowed'] = this.isStoreRateAllowed; + data['IsStoreRateInserted'] = this.isStoreRateInserted; + data['IsStoreRateUpdated'] = this.isStoreRateUpdated; + data['LabRadUpdatedToRead'] = this.labRadUpdatedToRead; + data['LabReportUnreadNo'] = this.labReportUnreadNo; + data['LakumInquiryInformationObj'] = this.lakumInquiryInformationObj; + if (this.lakumInquiryInformationObjVersion != null) { + data['LakumInquiryInformationObjVersion'] = + this.lakumInquiryInformationObjVersion.toJson(); + } + data['LakumResponseList'] = this.lakumResponseList; + data['Laser_GetBodyPartsByCategoryList'] = + this.laserGetBodyPartsByCategoryList; + data['Laser_GetCategoriesList'] = this.laserGetCategoriesList; + data['List'] = this.list; + data['ListCount'] = this.listCount; + data['ListCountDeliverd'] = this.listCountDeliverd; + data['ListCountUnDeliverd'] = this.listCountUnDeliverd; + data['ListDeviceInfo'] = this.listDeviceInfo; + data['ListFamilyAppointments'] = this.listFamilyAppointments; + data['ListLabResultsByAppNo'] = this.listLabResultsByAppNo; + data['ListLakumInquiryInformationObj'] = + this.listLakumInquiryInformationObj; + data['ListOpinion_GetAllPeriod'] = this.listOpinionGetAllPeriod; + data['ListOpinion_GetAllServices'] = this.listOpinionGetAllServices; + data['ListOpinion_GetIsAgreeValue'] = this.listOpinionGetIsAgreeValue; + data['ListOpinion_GetOpinionLogin'] = this.listOpinionGetOpinionLogin; + data['ListOpinion_GetRequestedSerives'] = + this.listOpinionGetRequestedSerives; + data['ListOpinion_GetShareServicesDetails'] = + this.listOpinionGetShareServicesDetails; + data['ListOpinion_UserTerms'] = this.listOpinionUserTerms; + data['ListPLO'] = this.listPLO; + data['ListPLR'] = this.listPLR; + data['ListPLSR'] = this.listPLSR; + data['ListPRM'] = this.listPRM; + data['ListPatientFamilyFiles'] = this.listPatientFamilyFiles; + data['ListPatientFileInfo'] = this.listPatientFileInfo; + data['ListRAD'] = this.listRAD; + data['ListRADAPI'] = this.listRADAPI; + data['List_ActiveGetPrescriptionReportByPatientID'] = + this.listActiveGetPrescriptionReportByPatientID; + data['List_AppointmentsForDentalClinic'] = + this.listAppointmentsForDentalClinic; + data['List_BabyInfoResult'] = this.listBabyInfoResult; + data['List_CheckInsuranceCoverage'] = this.listCheckInsuranceCoverage; + data['List_CompanyClass'] = this.listCompanyClass; + data['List_ConsentMedicalReport'] = this.listConsentMedicalReport; + data['List_DentalAppointments'] = this.listDentalAppointments; + data['List_DeviceTokenIDByAppointmentNo'] = + this.listDeviceTokenIDByAppointmentNo; + data['List_DischargeDiagnosis'] = this.listDischargeDiagnosis; + data['List_DischargeMedicine'] = this.listDischargeMedicine; + data['List_DischargeSummary'] = this.listDischargeSummary; + data['List_DoctorResponse'] = this.listDoctorResponse; + data['List_DoneVaccines'] = this.listDoneVaccines; + data['List_EReferralResult'] = this.listEReferralResult; + data['List_EReferrals'] = this.listEReferrals; + data['List_GetAllPatients_LiveCare_Admin'] = + this.listGetAllPatientsLiveCareAdmin; + data['List_GetDataForExcel'] = this.listGetDataForExcel; + data['List_GetMainCountID'] = this.listGetMainCountID; + data['List_GetPrescriptionReportByPatientID'] = + this.listGetPrescriptionReportByPatientID; + data['List_GetSickLeave'] = this.listGetSickLeave; + data['List_HISInvoice'] = this.listHISInvoice; + data['List_HISInvoiceProcedures'] = this.listHISInvoiceProcedures; + data['List_InpatientInvoices'] = this.listInpatientInvoices; + data['List_InsuranceCheckList'] = this.listInsuranceCheckList; + data['List_InsuranceCompanies'] = this.listInsuranceCompanies; + data['List_InsuranceCompaniesGroup'] = this.listInsuranceCompaniesGroup; + data['List_InsuranceUpdateDetails'] = this.listInsuranceUpdateDetails; + data['List_InvoiceApprovalProcedureInfo'] = + this.listInvoiceApprovalProcedureInfo; + data['List_IsLastSatisfactionSurveyReviewedModel'] = + this.listIsLastSatisfactionSurveyReviewedModel; + data['List_LabOrderDetailsModel'] = this.listLabOrderDetailsModel; + data['List_MedicalReport'] = this.listMedicalReport; + data['List_MedicalReportApprovals'] = this.listMedicalReportApprovals; + data['List_MedicalReportStatus'] = this.listMedicalReportStatus; + data['List_MonthBloodPressureResult'] = this.listMonthBloodPressureResult; + data['List_MonthBloodPressureResultAverage'] = + this.listMonthBloodPressureResultAverage; + data['List_MonthDiabtecPatientResult'] = this.listMonthDiabtecPatientResult; + data['List_MonthDiabtectResultAverage'] = + this.listMonthDiabtectResultAverage; + data['List_MonthWeightMeasurementResult'] = + this.listMonthWeightMeasurementResult; + data['List_MonthWeightMeasurementResultAverage'] = + this.listMonthWeightMeasurementResultAverage; + data['List_OnlinePrescriptionResult'] = this.listOnlinePrescriptionResult; + data['List_OutPatientInvoices'] = this.listOutPatientInvoices; + data['List_PHRInvoice'] = this.listPHRInvoice; + data['List_PHRInvoiceItems'] = this.listPHRInvoiceItems; + data['List_PHRPaymentMethods'] = this.listPHRPaymentMethods; + data['List_PateintDetails'] = this.listPateintDetails; + data['List_PateintInformation'] = this.listPateintInformation; + data['List_PatientAdmissionInfo'] = this.listPatientAdmissionInfo; + data['List_PatientAdvanceBalanceAmount'] = + this.listPatientAdvanceBalanceAmount; + data['List_PatientCallBackLogs'] = this.listPatientCallBackLogs; + data['List_PatientCallBackToUpdateFromICServer'] = + this.listPatientCallBackToUpdateFromICServer; + data['List_PatientCount'] = this.listPatientCount; + data['List_PatientDashboard'] = this.listPatientDashboard; + data['List_PatientER_GetAdminClinicsModel'] = + this.listPatientERGetAdminClinicsModel; + data['List_PatientER_GetAdminProjectsModel'] = + this.listPatientERGetAdminProjectsModel; + data['List_PatientER_GetAllClinicsModel'] = + this.listPatientERGetAllClinicsModel; + data['List_PatientHISInvoices'] = this.listPatientHISInvoices; + data['List_PatientICProjects'] = this.listPatientICProjects; + data['List_PatientICProjectsByID'] = this.listPatientICProjectsByID; + data['List_PatientICProjectsTimings'] = this.listPatientICProjectsTimings; + data['List_PatientIDByUID'] = this.listPatientIDByUID; + data['List_PatientIDForSurveyResult'] = this.listPatientIDForSurveyResult; + data['List_PatientInfo'] = this.listPatientInfo; + data['List_PatientInfoForDDScreen'] = this.listPatientInfoForDDScreen; + data['List_PatientInfoForSickleaveReport'] = + this.listPatientInfoForSickleaveReport; + data['List_PatientInsuranceCard'] = this.listPatientInsuranceCard; + data['List_PatientInsuranceCardHistory'] = + this.listPatientInsuranceCardHistory; + data['List_PatientInsuranceDetails'] = this.listPatientInsuranceDetails; + data['List_PatientPHRInvoices'] = this.listPatientPHRInvoices; + data['List_PatientServicePoint'] = this.listPatientServicePoint; + data['List_PatientStatusCount'] = this.listPatientStatusCount; + data['List_Patient_ChatRequestMapModel'] = + this.listPatientChatRequestMapModel; + data['List_Patient_ChatRequestModel'] = this.listPatientChatRequestModel; + data['List_Patient_ChatRequestVCModel'] = + this.listPatientChatRequestVCModel; + data['List_PaymentMethods'] = this.listPaymentMethods; + data['List_PointServices'] = this.listPointServices; + data['List_PregnancyStagesInfo'] = this.listPregnancyStagesInfo; + data['List_ProjectAvgERWaitingTime'] = this.listProjectAvgERWaitingTime; + data['List_ProjectAvgERWaitingTimeHourly'] = + this.listProjectAvgERWaitingTimeHourly; + data['List_RadMedicalRecords'] = this.listRadMedicalRecords; + data['List_RadMedicalRecordsAPI'] = this.listRadMedicalRecordsAPI; + data['List_RadMedicalRecordsCVI'] = this.listRadMedicalRecordsCVI; + data['List_RadMedicalRecordsCVIAPI'] = this.listRadMedicalRecordsCVIAPI; + data['List_RadMedicalRecordsResults'] = this.listRadMedicalRecordsResults; + data['List_SickLeave'] = this.listSickLeave; + data['List_Transaction'] = this.listTransaction; + data['List_VideoConferenceSessions'] = this.listVideoConferenceSessions; + data['List_WeekBloodPressureResult'] = this.listWeekBloodPressureResult; + data['List_WeekBloodPressureResultAverage'] = + this.listWeekBloodPressureResultAverage; + data['List_WeekDiabtecPatientResult'] = this.listWeekDiabtecPatientResult; + data['List_WeekDiabtectResultAverage'] = this.listWeekDiabtectResultAverage; + data['List_WeekWeightMeasurementResult'] = + this.listWeekWeightMeasurementResult; + data['List_WeekWeightMeasurementResultAverage'] = + this.listWeekWeightMeasurementResultAverage; + data['List_YearBloodPressureResult'] = this.listYearBloodPressureResult; + data['List_YearBloodPressureResultAverage'] = + this.listYearBloodPressureResultAverage; + data['List_YearDiabtecPatientResult'] = this.listYearDiabtecPatientResult; + data['List_YearDiabtecResultAverage'] = this.listYearDiabtecResultAverage; + data['List_YearWeightMeasurementResult'] = + this.listYearWeightMeasurementResult; + data['List_YearWeightMeasurementResultAverage'] = + this.listYearWeightMeasurementResultAverage; + data['List_eInvoiceForDental'] = this.listEInvoiceForDental; + data['List_eInvoiceForOnlineCheckIn'] = this.listEInvoiceForOnlineCheckIn; + data['Med_GetActivitiesTransactionsStsList'] = + this.medGetActivitiesTransactionsStsList; + data['Med_GetAvgMonthTransactionsStsList'] = + this.medGetAvgMonthTransactionsStsList; + data['Med_GetAvgWeekTransactionsStsList'] = + this.medGetAvgWeekTransactionsStsList; + data['Med_GetCategoriesList'] = this.medGetCategoriesList; + data['Med_GetMonthActivitiesTransactionsStsList'] = + this.medGetMonthActivitiesTransactionsStsList; + data['Med_GetMonthStepsTransactionsStsList'] = + this.medGetMonthStepsTransactionsStsList; + data['Med_GetMonthTransactionsStsList'] = + this.medGetMonthTransactionsStsList; + data['Med_GetPatientLastRecordList'] = this.medGetPatientLastRecordList; + data['Med_GetSubCategoriesList'] = this.medGetSubCategoriesList; + data['Med_GetTransactionsAndActTransactionsResult'] = + this.medGetTransactionsAndActTransactionsResult; + data['Med_GetTransactionsList'] = this.medGetTransactionsList; + data['Med_GetWeekActivitiesTransactionsStsList'] = + this.medGetWeekActivitiesTransactionsStsList; + data['Med_GetWeekStepsTransactionsStsList'] = + this.medGetWeekStepsTransactionsStsList; + data['Med_GetWeekTransactionsStsList'] = this.medGetWeekTransactionsStsList; + data['Med_GetYearActivitiesTransactionsStsList'] = + this.medGetYearActivitiesTransactionsStsList; + data['Med_GetYearSleepTransactionsStsList'] = + this.medGetYearSleepTransactionsStsList; + data['Med_GetYearStepsTransactionsStsList'] = + this.medGetYearStepsTransactionsStsList; + data['Med_GetYearTransactionsStsList'] = this.medGetYearTransactionsStsList; + data['Med_InsertTransactionsOutputsList'] = + this.medInsertTransactionsOutputsList; + data['MedicalRecordImages'] = this.medicalRecordImages; + data['MedicalReportToRead'] = this.medicalReportToRead; + data['MedicalReportUnreadNo'] = this.medicalReportUnreadNo; + data['Missing_IDCardAttachment'] = this.missingIDCardAttachment; + data['Missing_InsuranceCardAttachment'] = + this.missingInsuranceCardAttachment; + data['Missing_MedicalReportAttachment'] = + this.missingMedicalReportAttachment; + data['Missing_OtherRelationship'] = this.missingOtherRelationship; + data['Missing_PatientContactNo'] = this.missingPatientContactNo; + data['Missing_PatientId'] = this.missingPatientId; + data['Missing_PatientIdentityNumber'] = this.missingPatientIdentityNumber; + data['Missing_PatientName'] = this.missingPatientName; + data['Missing_ReferralContactNo'] = this.missingReferralContactNo; + data['Missing_ReferralRelationship'] = this.missingReferralRelationship; + data['Missing_ReferralRequesterName'] = this.missingReferralRequesterName; + data['MobileNumber'] = this.mobileNumber; + data['NationalityNumber'] = this.nationalityNumber; + data['OnlineCheckInAppointments'] = this.onlineCheckInAppointments; + data['Opinion_UserAgreementContent'] = this.opinionUserAgreementContent; + data['OrderInsert'] = this.orderInsert; + data['PateintInfoForUpdateList'] = this.pateintInfoForUpdateList; + data['PateintUpatedList'] = this.pateintUpatedList; + data['PatientBirthdayCertificate'] = this.patientBirthdayCertificate; + data['PatientER_CMCRequestSummaryByProject'] = + this.patientERCMCRequestSummaryByProject; + data['PatientER_CMCRequestWithTotal'] = this.patientERCMCRequestWithTotal; + data['PatientER_CMC_GetAllServicesList'] = + this.patientERCMCGetAllServicesList; + data['PatientER_CMC_GetTransactionsForOrderList'] = + this.patientERCMCGetTransactionsForOrderList; + data['PatientER_Coordinates'] = this.patientERCoordinates; + data['PatientER_CountOrderList'] = this.patientERCountOrderList; + data['PatientER_CountsForApprovalOffice'] = + this.patientERCountsForApprovalOffice; + data['PatientER_DeleteOldCurrentDoctorsOutputsList'] = + this.patientERDeleteOldCurrentDoctorsOutputsList; + data['PatientER_Delivery_GetAllDeliverdOrderList'] = + this.patientERDeliveryGetAllDeliverdOrderList; + data['PatientER_Delivery_GetAllOrderList'] = + this.patientERDeliveryGetAllOrderList; + data['PatientER_Delivery_IsOrderInserted'] = + this.patientERDeliveryIsOrderInserted; + data['PatientER_Delivery_IsOrderUpdated'] = + this.patientERDeliveryIsOrderUpdated; + data['PatientER_Delivery_IsPausedChanged'] = + this.patientERDeliveryIsPausedChanged; + data['PatientER_Delivery_NextOrder'] = this.patientERDeliveryNextOrder; + data['PatientER_Delivery_OrderInsert'] = this.patientERDeliveryOrderInsert; + data['PatientER_Delivery_UpdateOrderStatus'] = + this.patientERDeliveryUpdateOrderStatus; + data['PatientER_DriverUpdate'] = this.patientERDriverUpdate; + data['PatientER_Exacart_CheckIsDispenseAccpetableList'] = + this.patientERExacartCheckIsDispenseAccpetableList; + data['PatientER_Exacart_GetDispenseQuantitiesByOrderIDList'] = + this.patientERExacartGetDispenseQuantitiesByOrderIDList; + data['PatientER_Exacart_GetOrderDetailsByePharmacyOrderNoList'] = + this.patientERExacartGetOrderDetailsByePharmacyOrderNoList; + data['PatientER_Exacart_GetOrderDetailsList'] = + this.patientERExacartGetOrderDetailsList; + data['PatientER_Exacart_GetTotalDispenseQuantitiesByPresNoList'] = + this.patientERExacartGetTotalDispenseQuantitiesByPresNoList; + data['PatientER_Exacart_IsDispenseAdded'] = + this.patientERExacartIsDispenseAdded; + data['PatientER_Exacart_IsDispenseAddedList'] = + this.patientERExacartIsDispenseAddedList; + data['PatientER_Exacart_IsOrderCompleted'] = + this.patientERExacartIsOrderCompleted; + data['PatientER_GetAdminByProjectAndRoleList'] = + this.patientERGetAdminByProjectAndRoleList; + data['PatientER_GetAdminProjectsList'] = this.patientERGetAdminProjectsList; + data['PatientER_GetAllDriversList'] = this.patientERGetAllDriversList; + data['PatientER_GetAllNeedAproveStatusList'] = + this.patientERGetAllNeedAproveStatusList; + data['PatientER_GetAllPresOrdersStatusList'] = + this.patientERGetAllPresOrdersStatusList; + data['PatientER_GetAllProjectsList'] = this.patientERGetAllProjectsList; + data['PatientER_GetArchiveInformation_List'] = + this.patientERGetArchiveInformationList; + data['PatientER_GetAskDoctorTotalByDateFilterList'] = + this.patientERGetAskDoctorTotalByDateFilterList; + data['PatientER_GetBookScheduleConfigsList'] = + this.patientERGetBookScheduleConfigsList; + data['PatientER_GetClinicAndTimeAndEpisodeForAppointmentList'] = + this.patientERGetClinicAndTimeAndEpisodeForAppointmentList; + data['PatientER_GetClinicAndTimeForDischargeList'] = + this.patientERGetClinicAndTimeForDischargeList; + data['PatientER_GetDashboardDataforApporvalSectionForAdminList'] = + this.patientERGetDashboardDataforApporvalSectionForAdminList; + data['PatientER_GetDashboardDataforApporvalSectionList'] = + this.patientERGetDashboardDataforApporvalSectionList; + data['PatientER_GetDashboardDataforHHCSectionForAdminList'] = + this.patientERGetDashboardDataforHHCSectionForAdminList; + data['PatientER_GetDashboardDataforHHCSectionList'] = + this.patientERGetDashboardDataforHHCSectionList; + data['PatientER_GetDashboardDataforPrescriptionSectionForAdminList'] = + this.patientERGetDashboardDataforPrescriptionSectionForAdminList; + data['PatientER_GetDashboardDataforPrescriptionSectionList'] = + this.patientERGetDashboardDataforPrescriptionSectionList; + data['PatientER_GetDoctorDashboardDataModelList'] = + this.patientERGetDoctorDashboardDataModelList; + data['PatientER_GetDriverLocationList'] = + this.patientERGetDriverLocationList; + data['PatientER_GetInsuranceCardRequestByDateFilterList'] = + this.patientERGetInsuranceCardRequestByDateFilterList; + data['PatientER_GetLiveCareSummaryBookedAppoinmentStatusList'] = + this.patientERGetLiveCareSummaryBookedAppoinmentStatusList; + data['PatientER_GetLiveCareSummaryCovidList'] = + this.patientERGetLiveCareSummaryCovidList; + data['PatientER_GetLiveCareSummaryForCMCList'] = + this.patientERGetLiveCareSummaryForCMCList; + data['PatientER_GetLiveCareSummaryForHHCList'] = + this.patientERGetLiveCareSummaryForHHCList; + data['PatientER_GetLiveCareSummaryForHomeDeliveryList'] = + this.patientERGetLiveCareSummaryForHomeDeliveryList; + data['PatientER_GetLiveCareSummaryForInsuranceCardRequestList'] = + this.patientERGetLiveCareSummaryForInsuranceCardRequestList; + data['PatientER_GetLiveCareSummaryForNewFilesList'] = + this.patientERGetLiveCareSummaryForNewFilesList; + data['PatientER_GetLiveCareSummaryForOnlinePaymetRequestList'] = + this.patientERGetLiveCareSummaryForOnlinePaymetRequestList; + data['PatientER_GetLiveCareSummaryForOnlinePharmacyOrdersList'] = + this.patientERGetLiveCareSummaryForOnlinePharmacyOrdersList; + data['PatientER_GetLiveCareSummaryForTrasnportationList'] = + this.patientERGetLiveCareSummaryForTrasnportationList; + data['PatientER_GetLiveCareSummaryLiveCareCountsList'] = + this.patientERGetLiveCareSummaryLiveCareCountsList; + data['PatientER_GetMedicalRequestTotalByDateFilterList'] = + this.patientERGetMedicalRequestTotalByDateFilterList; + data['PatientER_GetNearestPendingOrdersList'] = + this.patientERGetNearestPendingOrdersList; + data['PatientER_GetNeedAproveHistoryForOrderList'] = + this.patientERGetNeedAproveHistoryForOrderList; + data['PatientER_GetNeedAprovePendingOrdersList'] = + this.patientERGetNeedAprovePendingOrdersList; + data['PatientER_GetNeedAproveStatusStatisticsList'] = + this.patientERGetNeedAproveStatusStatisticsList; + data['PatientER_GetPatientAllPresOrdersList'] = + this.patientERGetPatientAllPresOrdersList; + data['PatientER_GetPendingPatientsCountList'] = + this.patientERGetPendingPatientsCountList; + data['PatientER_GetPresOrdersHistoryForAdminList'] = + this.patientERGetPresOrdersHistoryForAdminList; + data['PatientER_GetPresOrdersHistoryForOrderList'] = + this.patientERGetPresOrdersHistoryForOrderList; + data['PatientER_GetPresOrdersStatusStatisticsList'] = + this.patientERGetPresOrdersStatusStatisticsList; + data['PatientER_HHCRequest'] = this.patientERHHCRequest; + data['PatientER_HHCRequestSummaryByProject'] = + this.patientERHHCRequestSummaryByProject; + data['PatientER_HHCRequestWithTotal'] = this.patientERHHCRequestWithTotal; + data['PatientER_HHC_GetAllServicesList'] = + this.patientERHHCGetAllServicesList; + data['PatientER_HHC_GetTransactionsForOrderList'] = + this.patientERHHCGetTransactionsForOrderList; + data['PatientER_HomeDeliveryCounts'] = this.patientERHomeDeliveryCounts; + data['PatientER_InsertDriver'] = this.patientERInsertDriver; + data['PatientER_InsertNewCurrentDoctorsOutputsList'] = + this.patientERInsertNewCurrentDoctorsOutputsList; + data['PatientER_InsuranceStatusCountList'] = + this.patientERInsuranceStatusCountList; + data['PatientER_IsNearestProjectUpdated'] = + this.patientERIsNearestProjectUpdated; + data['PatientER_IsNeedAproveReturnedToQueue'] = + this.patientERIsNeedAproveReturnedToQueue; + data['PatientER_IsNeedAproveUpdated'] = this.patientERIsNeedAproveUpdated; + data['PatientER_IsOrderClientRequestUpdated'] = + this.patientERIsOrderClientRequestUpdated; + data['PatientER_IsOrderReturnedToQueue'] = + this.patientERIsOrderReturnedToQueue; + data['PatientER_IsPresOrderInserted'] = this.patientERIsPresOrderInserted; + data['PatientER_IsPresOrderUpdated'] = this.patientERIsPresOrderUpdated; + data['PatientER_IsProjectUpdated'] = this.patientERIsProjectUpdated; + data['PatientER_NotCompletedDetails'] = this.patientERNotCompletedDetails; + data['PatientER_PatientsCountByCallStatus'] = + this.patientERPatientsCountByCallStatus; + data['PatientER_PeakHourCounts'] = this.patientERPeakHourCounts; + data['PatientER_PresOrderInfo'] = this.patientERPresOrderInfo; + data['PatientER_PrescriptionCounts'] = this.patientERPrescriptionCounts; + data['PatientER_ProjectsContribution'] = this.patientERProjectsContribution; + data['PatientER_RRT_GetAllQuestionsList'] = + this.patientERRRTGetAllQuestionsList; + data['PatientER_RRT_GetAllTransportationMethodList'] = + this.patientERRRTGetAllTransportationMethodList; + data['PatientER_RRT_GetPickUpRequestByPresOrderIDList'] = + this.patientERRRTGetPickUpRequestByPresOrderIDList; + data['PatientER_RealRRT_GetAllServicesList'] = + this.patientERRealRRTGetAllServicesList; + data['PatientER_RealRRT_GetOrderDetailsList'] = + this.patientERRealRRTGetOrderDetailsList; + data['PatientER_RealRRT_GetTransactionsForOrderList'] = + this.patientERRealRRTGetTransactionsForOrderList; + data['PatientER_RealRRT_IsTransInserted'] = + this.patientERRealRRTIsTransInserted; + data['PatientER_RequestList'] = this.patientERRequestList; + data['PatientER_TransportationRequestWithTotal'] = + this.patientERTransportationRequestWithTotal; + data['PatientE_RealRRT_GetServicePriceList'] = + this.patientERealRRTGetServicePriceList; + data['PatientInfoByAdmissionNo_List'] = this.patientInfoByAdmissionNoList; + data['PatientMonitor_GetPatientHeartRate'] = + this.patientMonitorGetPatientHeartRate; + data['PatientNotServedCounts'] = this.patientNotServedCounts; + data['PatientPrescriptionList'] = this.patientPrescriptionList; + data['Patient_Allergies'] = this.patientAllergies; + data['Patient_CheckAppointmentValidationList'] = + this.patientCheckAppointmentValidationList; + data['Patient_LoginTokenList'] = this.patientLoginTokenList; + data['Patient_QRLoginInfoList'] = this.patientQRLoginInfoList; + data['Patient_SELECTDeviceIMEIbyIMEIList'] = + this.patientSELECTDeviceIMEIbyIMEIList; + data['PharmList'] = this.pharmList; + data['PrefLang'] = this.prefLang; + data['RadReportUnreadNo'] = this.radReportUnreadNo; + data['Rad_GetPatientRadOrdersForDental_List'] = + this.radGetPatientRadOrdersForDentalList; + data['ReferralNumber'] = this.referralNumber; + data['ReminderConfigurations'] = this.reminderConfigurations; + data['RequestNo'] = this.requestNo; + data['RowCount'] = this.rowCount; + data['ServicePrivilegeList'] = this.servicePrivilegeList; + data['ShareFamilyFileObj'] = this.shareFamilyFileObj; + data['Status'] = this.status; + data['SuccessCode'] = this.successCode; + data['SurveyRate'] = this.surveyRate; + data['SymptomChecker_ConditionList'] = this.symptomCheckerConditionList; + data['SymptomChecker_GetAllDefaultQuestionsList'] = + this.symptomCheckerGetAllDefaultQuestionsList; + data['SymptomChecker_GetBodyPartSymptomsList'] = + this.symptomCheckerGetBodyPartSymptomsList; + data['SymptomChecker_GetBodyPartsByCodeList'] = + this.symptomCheckerGetBodyPartsByCodeList; + data['SymptomChecker_GetBodyPartsList'] = + this.symptomCheckerGetBodyPartsList; + data['SymptomChecker_JsonResponseInString'] = + this.symptomCheckerJsonResponseInString; + data['TimerTime'] = this.timerTime; + data['TotalAdvanceBalanceAmount'] = this.totalAdvanceBalanceAmount; + data['TotalPatientsCount'] = this.totalPatientsCount; + data['TotalPendingApprovalCount'] = this.totalPendingApprovalCount; + data['TotalUnUsedCount'] = this.totalUnUsedCount; + data['TransactionNo'] = this.transactionNo; + data['UnReadCounts'] = this.unReadCounts; + data['UpdateStatus'] = this.updateStatus; + data['UserAgreementContent'] = this.userAgreementContent; + data['YahalaAccountNo'] = this.yahalaAccountNo; + data['check24HourComplaint'] = this.check24HourComplaint; + data['currency'] = this.currency; + data['message'] = this.message; + data['patientID'] = this.patientID; + data['returnValue'] = this.returnValue; + data['returnValueStr'] = this.returnValueStr; + data['statusCode'] = this.statusCode; + return data; + } +} \ No newline at end of file diff --git a/lib/core/model/pharmacies/LakumInquiryInformationObjVersion.dart b/lib/core/model/pharmacies/LakumInquiryInformationObjVersion.dart new file mode 100644 index 00000000..c609fa0b --- /dev/null +++ b/lib/core/model/pharmacies/LakumInquiryInformationObjVersion.dart @@ -0,0 +1,179 @@ +import 'PointsAmountPerYear.dart'; +import 'PointsDetails.dart'; + +class LakumInquiryInformationObjVersion { + int accountNumber; + String accountStatus; + String barCode; + int consumedPoints; + String consumedPointsAmount; + List consumedPointsAmountPerYear; + List consumedPointsDetails; + String createdDate; + int expiredPoints; + String expiryDate; + int gainedPoints; + List gainedPointsAmountPerYear; + List gainedPointsDetails; + String lakumMessageStatus; + String memberName; + String memberUniversalId; + String mobileNumber; + int pointsBalance; + int pointsBalanceAmount; + int pointsWillBeExpired; + String prefLang; + int statusCode; + int transferPoints; + List transferPointsAmountPerYear; + List transferPointsDetails; + dynamic waitingPoints; + dynamic loyalityAmount; + dynamic loyalityPoints; + int purchaseRate; + + LakumInquiryInformationObjVersion( + {this.accountNumber, + this.accountStatus, + this.barCode, + this.consumedPoints, + this.consumedPointsAmount, + this.consumedPointsAmountPerYear, + this.consumedPointsDetails, + this.createdDate, + this.expiredPoints, + this.expiryDate, + this.gainedPoints, + this.gainedPointsAmountPerYear, + this.gainedPointsDetails, + this.lakumMessageStatus, + this.memberName, + this.memberUniversalId, + this.mobileNumber, + this.pointsBalance, + this.pointsBalanceAmount, + this.pointsWillBeExpired, + this.prefLang, + this.statusCode, + this.transferPoints, + this.transferPointsAmountPerYear, + this.transferPointsDetails, + this.waitingPoints, + this.loyalityAmount, + this.loyalityPoints, + this.purchaseRate}); + + LakumInquiryInformationObjVersion.fromJson(Map json) { + accountNumber = json['AccountNumber']; + accountStatus = json['AccountStatus']; + barCode = json['BarCode']; + consumedPoints = json['ConsumedPoints']; + consumedPointsAmount = json['ConsumedPointsAmount']; + if (json['ConsumedPointsAmountPerYear'] != null) { + consumedPointsAmountPerYear = new List(); + json['ConsumedPointsAmountPerYear'].forEach((v) { + consumedPointsAmountPerYear.add(PointsAmountPerYear.fromJson(v)); + }); + } + if (json['ConsumedPointsDetails'] != null) { + consumedPointsDetails = new List(); + json['ConsumedPointsDetails'].forEach((v) { + consumedPointsDetails.add(PointsDetails.fromJson(v)); + }); + } + createdDate = json['CreatedDate']; + expiredPoints = json['ExpiredPoints']; + expiryDate = json['ExpiryDate']; + gainedPoints = json['GainedPoints']; + if (json['GainedPointsAmountPerYear'] != null) { + gainedPointsAmountPerYear = new List(); + json['GainedPointsAmountPerYear'].forEach((v) { + gainedPointsAmountPerYear.add(PointsAmountPerYear.fromJson(v)); + }); + } + if (json['GainedPointsDetails'] != null) { + gainedPointsDetails = new List(); + json['GainedPointsDetails'].forEach((v) { + gainedPointsDetails.add(PointsDetails.fromJson(v)); + }); + } + lakumMessageStatus = json['LakumMessageStatus']; + memberName = json['MemberName']; + memberUniversalId = json['MemberUniversalId']; + mobileNumber = json['MobileNumber']; + pointsBalance = json['PointsBalance']; + pointsBalanceAmount = json['PointsBalanceAmount']; + pointsWillBeExpired = json['PointsWillBeExpired']; + prefLang = json['PrefLang']; + statusCode = json['StatusCode']; + transferPoints = json['TransferPoints']; + if (json['TransferPointsAmountPerYear'] != null) { + transferPointsAmountPerYear = new List(); + json['TransferPointsAmountPerYear'].forEach((v) { + transferPointsAmountPerYear.add(PointsAmountPerYear.fromJson(v)); + }); + } + if (json['TransferPointsDetails'] != null) { + transferPointsDetails = new List(); + json['TransferPointsDetails'].forEach((v) { + transferPointsDetails.add(PointsDetails.fromJson(v)); + }); + } + waitingPoints = json['WaitingPoints']; + loyalityAmount = json['loyalityAmount']; + loyalityPoints = json['loyalityPoints']; + purchaseRate = json['purchaseRate']; + } + + Map toJson() { + final Map data = new Map(); + data['AccountNumber'] = this.accountNumber; + data['AccountStatus'] = this.accountStatus; + data['BarCode'] = this.barCode; + data['ConsumedPoints'] = this.consumedPoints; + data['ConsumedPointsAmount'] = this.consumedPointsAmount; + if (this.consumedPointsAmountPerYear != null) { + data['ConsumedPointsAmountPerYear'] = + this.consumedPointsAmountPerYear.map((v) => v).toList(); + } + if (this.consumedPointsDetails != null) { + data['ConsumedPointsDetails'] = + this.consumedPointsDetails.map((v) => v).toList(); + } + data['CreatedDate'] = this.createdDate; + data['ExpiredPoints'] = this.expiredPoints; + data['ExpiryDate'] = this.expiryDate; + data['GainedPoints'] = this.gainedPoints; + if (this.gainedPointsAmountPerYear != null) { + data['GainedPointsAmountPerYear'] = + this.gainedPointsAmountPerYear.map((v) => v).toList(); + } + if (this.gainedPointsDetails != null) { + data['GainedPointsDetails'] = + this.gainedPointsDetails.map((v) => v).toList(); + } + data['LakumMessageStatus'] = this.lakumMessageStatus; + data['MemberName'] = this.memberName; + data['MemberUniversalId'] = this.memberUniversalId; + data['MobileNumber'] = this.mobileNumber; + data['PointsBalance'] = this.pointsBalance; + data['PointsBalanceAmount'] = this.pointsBalanceAmount; + data['PointsWillBeExpired'] = this.pointsWillBeExpired; + data['PrefLang'] = this.prefLang; + data['StatusCode'] = this.statusCode; + data['TransferPoints'] = this.transferPoints; + if (this.transferPointsAmountPerYear != null) { + data['TransferPointsAmountPerYear'] = + this.transferPointsAmountPerYear.map((v) => v).toList(); + } + if (this.transferPointsDetails != null) { + data['TransferPointsDetails'] = + this.transferPointsDetails.map((v) => v).toList(); + } + data['WaitingPoints'] = this.waitingPoints; + data['loyalityAmount'] = this.loyalityAmount; + data['loyalityPoints'] = this.loyalityPoints; + data['purchaseRate'] = this.purchaseRate; + return data; + } +} \ No newline at end of file diff --git a/lib/core/model/pharmacies/ListUserAgreement.dart b/lib/core/model/pharmacies/ListUserAgreement.dart new file mode 100644 index 00000000..4237e304 --- /dev/null +++ b/lib/core/model/pharmacies/ListUserAgreement.dart @@ -0,0 +1,28 @@ +class ListUserAgreement { + String userAgreementLAKUM; + String userAgreementLAKUMn; + String userAgreementTxt; + String userAgreementTxtn; + + ListUserAgreement( + {this.userAgreementLAKUM, + this.userAgreementLAKUMn, + this.userAgreementTxt, + this.userAgreementTxtn}); + + ListUserAgreement.fromJson(Map json) { + userAgreementLAKUM = json['UserAgreementLAKUM']; + userAgreementLAKUMn = json['UserAgreementLAKUMn']; + userAgreementTxt = json['UserAgreementTxt']; + userAgreementTxtn = json['UserAgreementTxtn']; + } + + Map toJson() { + final Map data = new Map(); + data['UserAgreementLAKUM'] = this.userAgreementLAKUM; + data['UserAgreementLAKUMn'] = this.userAgreementLAKUMn; + data['UserAgreementTxt'] = this.userAgreementTxt; + data['UserAgreementTxtn'] = this.userAgreementTxtn; + return data; + } +} diff --git a/lib/core/model/pharmacies/PharmacyAddressesModel.dart b/lib/core/model/pharmacies/PharmacyAddressesModel.dart new file mode 100644 index 00000000..db9c20ae --- /dev/null +++ b/lib/core/model/pharmacies/PharmacyAddressesModel.dart @@ -0,0 +1,170 @@ + +import 'dart:convert'; + +PharmacyAddressesModel pharmacyAddressesModelFromJson(String str) => PharmacyAddressesModel.fromJson(json.decode(str)); + +String pharmacyAddressesModelToJson(PharmacyAddressesModel data) => json.encode(data.toJson()); + +class PharmacyAddressesModel { + PharmacyAddressesModel({ + this.customers, + }); + + List customers; + + factory PharmacyAddressesModel.fromJson(Map json) => PharmacyAddressesModel( + customers: List.from(json["customers"].map((x) => Customer.fromJson(x))), + ); + + Map toJson() => { + "customers": List.from(customers.map((x) => x.toJson())), + }; +} + +class Customer { + Customer({ + this.addresses, + }); + + List

addresses; + + factory Customer.fromJson(Map json) => Customer( + addresses: List
.from(json["addresses"].map((x) => Address.fromJson(x))), + ); + + Map toJson() => { + "addresses": List.from(addresses.map((x) => x.toJson())), + }; +} + +class Address { + Address({ + this.id, + this.firstName, + this.lastName, + this.email, + this.company, + this.countryId, + this.country, + this.stateProvinceId, + this.city, + this.address1, + this.address2, + this.zipPostalCode, + this.phoneNumber, + this.faxNumber, + this.customerAttributes, + this.createdOnUtc, + this.province, + this.latLong, + }); + + String id; + FirstName firstName; + LastName lastName; + Email email; + dynamic company; + int countryId; + Country country; + dynamic stateProvinceId; + City city; + String address1; + String address2; + String zipPostalCode; + String phoneNumber; + dynamic faxNumber; + String customerAttributes; + DateTime createdOnUtc; + dynamic province; + String latLong; + + factory Address.fromJson(Map json) => Address( + id: json["id"], + firstName: firstNameValues.map[json["first_name"]], + lastName: lastNameValues.map[json["last_name"]], + email: emailValues.map[json["email"]], + company: json["company"], + countryId: json["country_id"], + country: countryValues.map[json["country"]], + stateProvinceId: json["state_province_id"], + city: cityValues.map[json["city"]], + address1: json["address1"], + address2: json["address2"], + zipPostalCode: json["zip_postal_code"], + phoneNumber: json["phone_number"], + faxNumber: json["fax_number"], + customerAttributes: json["customer_attributes"], + createdOnUtc: DateTime.parse(json["created_on_utc"]), + province: json["province"], + latLong: json["lat_long"], + ); + + Map toJson() => { + "id": id, + "first_name": firstNameValues.reverse[firstName], + "last_name": lastNameValues.reverse[lastName], + "email": emailValues.reverse[email], + "company": company, + "country_id": countryId, + "country": countryValues.reverse[country], + "state_province_id": stateProvinceId, + "city": cityValues.reverse[city], + "address1": address1, + "address2": address2, + "zip_postal_code": zipPostalCode, + "phone_number": phoneNumber, + "fax_number": faxNumber, + "customer_attributes": customerAttributes, + "created_on_utc": createdOnUtc.toIso8601String(), + "province": province, + "lat_long": latLong, + }; +} + +enum City { RIYADH, AL_OYUN } + +final cityValues = EnumValues({ + "Al Oyun": City.AL_OYUN, + "Riyadh": City.RIYADH +}); + +enum Country { SAUDI_ARABIA } + +final countryValues = EnumValues({ + "Saudi Arabia": Country.SAUDI_ARABIA +}); + +enum Email { TAMER_FANASHEH_GMAIL_COM, TAMER_DASDASDAS_GMAIL_COM } + +final emailValues = EnumValues({ + "Tamer.dasdasdas@gmail.com": Email.TAMER_DASDASDAS_GMAIL_COM, + "Tamer.fanasheh@gmail.com": Email.TAMER_FANASHEH_GMAIL_COM +}); + +enum FirstName { TAMER, TAMER_FANASHEH } + +final firstNameValues = EnumValues({ + "TAMER": FirstName.TAMER, + "TAMER FANASHEH": FirstName.TAMER_FANASHEH +}); + +enum LastName { FANASHEH, MUSA } + +final lastNameValues = EnumValues({ + "FANASHEH": LastName.FANASHEH, + "MUSA": LastName.MUSA +}); + +class EnumValues { + Map map; + Map reverseMap; + + EnumValues(this.map); + + Map get reverse { + if (reverseMap == null) { + reverseMap = map.map((k, v) => new MapEntry(v, k)); + } + return reverseMap; + } +} diff --git a/lib/core/model/pharmacies/PharmacyProduct.dart b/lib/core/model/pharmacies/PharmacyProduct.dart index cd461ae5..c472cb4c 100644 --- a/lib/core/model/pharmacies/PharmacyProduct.dart +++ b/lib/core/model/pharmacies/PharmacyProduct.dart @@ -1,149 +1,538 @@ +import 'package:diplomaticquarterapp/core/model/pharmacies/Specifications.dart'; + import 'PharmacyImageObject.dart'; import 'Reviews.dart'; class PharmacyProduct { String id; + bool visibleIndividually; String name; String namen; String shortDescription; + String shortDescriptionn; String fullDescription; String fullDescriptionn; + bool markasNew; + bool showOnHomePage; + String metaKeywords; + String metaDescription; + String metaTitle; + bool allowCustomerReviews; int approvedRatingSum; + int notApprovedRatingSum; int approvedTotalReviews; + int notApprovedTotalReviews; String sku; bool isRx; + bool prescriptionRequired; String rxMessage; String rxMessagen; + String manufacturerPartNumber; + String gtin; + bool isGiftCard; + bool requireOtherProducts; + bool automaticallyAddRequiredProducts; + bool isDownload; + bool unlimitedDownloads; + int maxNumberOfDownloads; + String downloadExpirationDays; + bool hasSampleDownload; + bool hasUserAgreement; + bool isRecurring; + int recurringCycleLength; + int recurringTotalCycles; + bool isRental; + int rentalPriceLength; + bool isShipEnabled; + bool isFreeShipping; + bool shipSeparately; + double additionalShippingCharge; + bool isTaxExempt; + bool isTelecommunicationsOrBroadcastingOrElectronicServices; + bool useMultipleWarehouses; + int manageInventoryMethodId; int stockQuantity; String stockAvailability; String stockAvailabilityn; + bool displayStockAvailability; + bool displayStockQuantity; + int minStockQuantity; + int notifyAdminForQuantityBelow; bool allowBackInStockSubscriptions; int orderMinimumQuantity; int orderMaximumQuantity; + String allowedQuantities; + bool allowAddingOnlyExistingAttributeCombinations; + bool disableBuyButton; + bool disableWishlistButton; + bool availableForPreOrder; + String preOrderAvailabilityStartDateTimeUtc; + bool callForPrice; double price; double oldPrice; + double productCost; + String specialPrice; + String specialPriceStartDateTimeUtc; + String specialPriceEndDateTimeUtc; + bool customerEntersPrice; + double minimumCustomerEnteredPrice; + double maximumCustomerEnteredPrice; + bool basepriceEnabled; + double basepriceAmount; + double basepriceBaseAmount; + bool hasTierPrices; + bool hasDiscountsApplied; String discountName; String discountNamen; + String discountDescription; + String discountDescriptionn; String discountPercentage; + String currency; + String currencyn; + double weight; + double length; + double width; + double height; + String availableStartDateTimeUtc; + String availableEndDateTimeUtc; int displayOrder; + bool published; + bool deleted; + String createdOnUtc; + String updatedOnUtc; + String productType; + int parentGroupedProductId; + List roleIds; List discountIds; + List storeIds; + List manufacturerIds; List reviews; List images; + List attributes; + List specifications; + List associatedProductIds; + List tags; + int vendorId; + String seName; + PharmacyProduct( {this.id, + this.visibleIndividually, this.name, this.namen, this.shortDescription, + this.shortDescriptionn, this.fullDescription, this.fullDescriptionn, + this.markasNew, + this.showOnHomePage, + this.metaKeywords, + this.metaDescription, + this.metaTitle, + this.allowCustomerReviews, this.approvedRatingSum, + this.notApprovedRatingSum, this.approvedTotalReviews, + this.notApprovedTotalReviews, this.sku, this.isRx, + this.prescriptionRequired, this.rxMessage, this.rxMessagen, + this.manufacturerPartNumber, + this.gtin, + this.isGiftCard, + this.requireOtherProducts, + this.automaticallyAddRequiredProducts, + this.isDownload, + this.unlimitedDownloads, + this.maxNumberOfDownloads, + this.downloadExpirationDays, + this.hasSampleDownload, + this.hasUserAgreement, + this.isRecurring, + this.recurringCycleLength, + this.recurringTotalCycles, + this.isRental, + this.rentalPriceLength, + this.isShipEnabled, + this.isFreeShipping, + this.shipSeparately, + this.additionalShippingCharge, + this.isTaxExempt, + this.isTelecommunicationsOrBroadcastingOrElectronicServices, + this.useMultipleWarehouses, + this.manageInventoryMethodId, this.stockQuantity, this.stockAvailability, this.stockAvailabilityn, + this.displayStockAvailability, + this.displayStockQuantity, + this.minStockQuantity, + this.notifyAdminForQuantityBelow, this.allowBackInStockSubscriptions, this.orderMinimumQuantity, this.orderMaximumQuantity, + this.allowedQuantities, + this.allowAddingOnlyExistingAttributeCombinations, + this.disableBuyButton, + this.disableWishlistButton, + this.availableForPreOrder, + this.preOrderAvailabilityStartDateTimeUtc, + this.callForPrice, this.price, this.oldPrice, + this.productCost, + this.specialPrice, + this.specialPriceStartDateTimeUtc, + this.specialPriceEndDateTimeUtc, + this.customerEntersPrice, + this.minimumCustomerEnteredPrice, + this.maximumCustomerEnteredPrice, + this.basepriceEnabled, + this.basepriceAmount, + this.basepriceBaseAmount, + this.hasTierPrices, + this.hasDiscountsApplied, this.discountName, this.discountNamen, + this.discountDescription, + this.discountDescriptionn, this.discountPercentage, + this.currency, + this.currencyn, + this.weight, + this.length, + this.width, + this.height, + this.availableStartDateTimeUtc, + this.availableEndDateTimeUtc, this.displayOrder, + this.published, + this.deleted, + this.createdOnUtc, + this.updatedOnUtc, + this.productType, + this.parentGroupedProductId, + this.roleIds, this.discountIds, + this.storeIds, + this.manufacturerIds, this.reviews, - this.images}); + this.images, + this.attributes, + this.specifications, + this.associatedProductIds, + this.tags, + this.vendorId, + this.seName}); PharmacyProduct.fromJson(Map json) { - try { - id = json['id']; - name = json['name']; - namen = json['namen']; - shortDescription = json['short_description']; - fullDescription = json['full_description']; - fullDescriptionn = json['full_descriptionn']; - approvedRatingSum = json['approved_rating_sum']; - approvedTotalReviews = json['approved_total_reviews']; - sku = json['sku']; - isRx = json['is_rx']; - rxMessage = json['rx_message']; - rxMessagen = json['rx_messagen']; - stockQuantity = json['stock_quantity']; - stockAvailability = json['stock_availability']; - stockAvailabilityn = json['stock_availabilityn']; - allowBackInStockSubscriptions = json['allow_back_in_stock_subscriptions']; - orderMinimumQuantity = json['order_minimum_quantity']; - orderMaximumQuantity = json['order_maximum_quantity']; - price = json['price']; - oldPrice = json['old_price']; - discountName = json['discount_name']; - discountNamen = json['discount_namen']; - discountPercentage = json['discount_percentage']; - displayOrder = json['display_order']; - if (json['discount_ids'] != null) { - discountIds = new List(); - json['discount_ids'].forEach((v) { - discountIds.add(v); - }); - } - if (json['reviews'] != null) { - reviews = new List(); - json['reviews'].forEach((v) { - reviews.add(new Reviews.fromJson(v)); - }); - } - if (json['images'] != null) { - images = new List(); - json['images'].forEach((v) { - images.add(new PharmacyImageObject.fromJson(v)); - }); - } - } catch (e) { - print(e); + id = json['id']; + visibleIndividually = json['visible_individually']; + name = json['name']; + namen = json['namen']; + shortDescription = json['short_description']; + shortDescriptionn = json['short_descriptionn']; + fullDescription = json['full_description']; + fullDescriptionn = json['full_descriptionn']; + markasNew = json['markas_new']; + showOnHomePage = json['show_on_home_page']; + metaKeywords = json['meta_keywords']; + metaDescription = json['meta_description']; + metaTitle = json['meta_title']; + allowCustomerReviews = json['allow_customer_reviews']; + approvedRatingSum = json['approved_rating_sum']; + notApprovedRatingSum = json['not_approved_rating_sum']; + approvedTotalReviews = json['approved_total_reviews']; + notApprovedTotalReviews = json['not_approved_total_reviews']; + sku = json['sku']; + isRx = json['is_rx']; + prescriptionRequired = json['prescription_required']; + rxMessage = json['rx_message']; + rxMessagen = json['rx_messagen']; + manufacturerPartNumber = json['manufacturer_part_number']; + gtin = json['gtin']; + isGiftCard = json['is_gift_card']; + requireOtherProducts = json['require_other_products']; + automaticallyAddRequiredProducts = + json['automatically_add_required_products']; + isDownload = json['is_download']; + unlimitedDownloads = json['unlimited_downloads']; + maxNumberOfDownloads = json['max_number_of_downloads']; + downloadExpirationDays = json['download_expiration_days']; + hasSampleDownload = json['has_sample_download']; + hasUserAgreement = json['has_user_agreement']; + isRecurring = json['is_recurring']; + recurringCycleLength = json['recurring_cycle_length']; + recurringTotalCycles = json['recurring_total_cycles']; + isRental = json['is_rental']; + rentalPriceLength = json['rental_price_length']; + isShipEnabled = json['is_ship_enabled']; + isFreeShipping = json['is_free_shipping']; + shipSeparately = json['ship_separately']; + additionalShippingCharge = json['additional_shipping_charge']; + isTaxExempt = json['is_tax_exempt']; + isTelecommunicationsOrBroadcastingOrElectronicServices = + json['is_telecommunications_or_broadcasting_or_electronic_services']; + useMultipleWarehouses = json['use_multiple_warehouses']; + manageInventoryMethodId = json['manage_inventory_method_id']; + stockQuantity = json['stock_quantity']; + stockAvailability = json['stock_availability']; + stockAvailabilityn = json['stock_availabilityn']; + displayStockAvailability = json['display_stock_availability']; + displayStockQuantity = json['display_stock_quantity']; + minStockQuantity = json['min_stock_quantity']; + notifyAdminForQuantityBelow = json['notify_admin_for_quantity_below']; + allowBackInStockSubscriptions = json['allow_back_in_stock_subscriptions']; + orderMinimumQuantity = json['order_minimum_quantity']; + orderMaximumQuantity = json['order_maximum_quantity']; + allowedQuantities = json['allowed_quantities']; + allowAddingOnlyExistingAttributeCombinations = + json['allow_adding_only_existing_attribute_combinations']; + disableBuyButton = json['disable_buy_button']; + disableWishlistButton = json['disable_wishlist_button']; + availableForPreOrder = json['available_for_pre_order']; + preOrderAvailabilityStartDateTimeUtc = + json['pre_order_availability_start_date_time_utc']; + callForPrice = json['call_for_price']; + price = json['price']; + oldPrice = json['old_price']; + productCost = json['product_cost']; + specialPrice = json['special_price']; + specialPriceStartDateTimeUtc = json['special_price_start_date_time_utc']; + specialPriceEndDateTimeUtc = json['special_price_end_date_time_utc']; + customerEntersPrice = json['customer_enters_price']; + minimumCustomerEnteredPrice = json['minimum_customer_entered_price']; + maximumCustomerEnteredPrice = json['maximum_customer_entered_price']; + basepriceEnabled = json['baseprice_enabled']; + basepriceAmount = json['baseprice_amount']; + basepriceBaseAmount = json['baseprice_base_amount']; + hasTierPrices = json['has_tier_prices']; + hasDiscountsApplied = json['has_discounts_applied']; + discountName = json['discount_name']; + discountNamen = json['discount_namen']; + discountDescription = json['discount_description']; + discountDescriptionn = json['discount_Descriptionn']; + discountPercentage = json['discount_percentage']; + currency = json['currency']; + currencyn = json['currencyn']; + weight = json['weight']; + length = json['length']; + width = json['width']; + height = json['height']; + availableStartDateTimeUtc = json['available_start_date_time_utc']; + availableEndDateTimeUtc = json['available_end_date_time_utc']; + displayOrder = json['display_order']; + published = json['published']; + deleted = json['deleted']; + createdOnUtc = json['created_on_utc']; + updatedOnUtc = json['updated_on_utc']; + productType = json['product_type']; + parentGroupedProductId = json['parent_grouped_product_id']; + if (json['role_ids'] != null) { + roleIds = new List(); + json['role_ids'].forEach((v) { + roleIds.add(v); + }); + } + if (json['discount_ids'] != null) { + discountIds = new List(); + json['discount_ids'].forEach((v) { + discountIds.add(v); + }); + } + if (json['store_ids'] != null) { + storeIds = new List(); + json['store_ids'].forEach((v) { + storeIds.add(v); + }); + } + if (json['manufacturer_ids'] != null) { + manufacturerIds = new List(); + json['manufacturer_ids'].forEach((v) { + manufacturerIds.add(v); + }); + } + if (json['reviews'] != null) { + reviews = new List(); + json['reviews'].forEach((v) { + reviews.add(new Reviews.fromJson(v)); + }); + } + if (json['images'] != null) { + images = new List(); + json['images'].forEach((v) { + images.add(new PharmacyImageObject.fromJson(v)); + }); + } + if (json['attributes'] != null) { + attributes = new List(); + json['attributes'].forEach((v) { + attributes.add(v); + }); + } + if (json['specifications'] != null) { + specifications = new List(); + json['specifications'].forEach((v) { + specifications.add(new Specifications.fromJson(v)); + }); } + if (json['associated_product_ids'] != null) { + associatedProductIds = new List(); + json['associated_product_ids'].forEach((v) { + associatedProductIds.add(v); + }); + } + if (json['tags'] != null) { + tags = new List(); + json['tags'].forEach((v) { + tags.add(v); + }); + } + vendorId = json['vendor_id']; + seName = json['se_name']; } Map toJson() { final Map data = new Map(); data['id'] = this.id; + data['visible_individually'] = this.visibleIndividually; data['name'] = this.name; data['namen'] = this.namen; data['short_description'] = this.shortDescription; + data['short_descriptionn'] = this.shortDescriptionn; data['full_description'] = this.fullDescription; data['full_descriptionn'] = this.fullDescriptionn; + data['markas_new'] = this.markasNew; + data['show_on_home_page'] = this.showOnHomePage; + data['meta_keywords'] = this.metaKeywords; + data['meta_description'] = this.metaDescription; + data['meta_title'] = this.metaTitle; + data['allow_customer_reviews'] = this.allowCustomerReviews; data['approved_rating_sum'] = this.approvedRatingSum; + data['not_approved_rating_sum'] = this.notApprovedRatingSum; data['approved_total_reviews'] = this.approvedTotalReviews; + data['not_approved_total_reviews'] = this.notApprovedTotalReviews; data['sku'] = this.sku; data['is_rx'] = this.isRx; + data['prescription_required'] = this.prescriptionRequired; data['rx_message'] = this.rxMessage; data['rx_messagen'] = this.rxMessagen; + data['manufacturer_part_number'] = this.manufacturerPartNumber; + data['gtin'] = this.gtin; + data['is_gift_card'] = this.isGiftCard; + data['require_other_products'] = this.requireOtherProducts; + data['automatically_add_required_products'] = + this.automaticallyAddRequiredProducts; + data['is_download'] = this.isDownload; + data['unlimited_downloads'] = this.unlimitedDownloads; + data['max_number_of_downloads'] = this.maxNumberOfDownloads; + data['download_expiration_days'] = this.downloadExpirationDays; + data['has_sample_download'] = this.hasSampleDownload; + data['has_user_agreement'] = this.hasUserAgreement; + data['is_recurring'] = this.isRecurring; + data['recurring_cycle_length'] = this.recurringCycleLength; + data['recurring_total_cycles'] = this.recurringTotalCycles; + data['is_rental'] = this.isRental; + data['rental_price_length'] = this.rentalPriceLength; + data['is_ship_enabled'] = this.isShipEnabled; + data['is_free_shipping'] = this.isFreeShipping; + data['ship_separately'] = this.shipSeparately; + data['additional_shipping_charge'] = this.additionalShippingCharge; + data['is_tax_exempt'] = this.isTaxExempt; + data['is_telecommunications_or_broadcasting_or_electronic_services'] = + this.isTelecommunicationsOrBroadcastingOrElectronicServices; + data['use_multiple_warehouses'] = this.useMultipleWarehouses; + data['manage_inventory_method_id'] = this.manageInventoryMethodId; data['stock_quantity'] = this.stockQuantity; data['stock_availability'] = this.stockAvailability; data['stock_availabilityn'] = this.stockAvailabilityn; + data['display_stock_availability'] = this.displayStockAvailability; + data['display_stock_quantity'] = this.displayStockQuantity; + data['min_stock_quantity'] = this.minStockQuantity; + data['notify_admin_for_quantity_below'] = this.notifyAdminForQuantityBelow; data['allow_back_in_stock_subscriptions'] = this.allowBackInStockSubscriptions; data['order_minimum_quantity'] = this.orderMinimumQuantity; data['order_maximum_quantity'] = this.orderMaximumQuantity; + data['allowed_quantities'] = this.allowedQuantities; + data['allow_adding_only_existing_attribute_combinations'] = + this.allowAddingOnlyExistingAttributeCombinations; + data['disable_buy_button'] = this.disableBuyButton; + data['disable_wishlist_button'] = this.disableWishlistButton; + data['available_for_pre_order'] = this.availableForPreOrder; + data['pre_order_availability_start_date_time_utc'] = + this.preOrderAvailabilityStartDateTimeUtc; + data['call_for_price'] = this.callForPrice; data['price'] = this.price; data['old_price'] = this.oldPrice; + data['product_cost'] = this.productCost; + data['special_price'] = this.specialPrice; + data['special_price_start_date_time_utc'] = + this.specialPriceStartDateTimeUtc; + data['special_price_end_date_time_utc'] = this.specialPriceEndDateTimeUtc; + data['customer_enters_price'] = this.customerEntersPrice; + data['minimum_customer_entered_price'] = this.minimumCustomerEnteredPrice; + data['maximum_customer_entered_price'] = this.maximumCustomerEnteredPrice; + data['baseprice_enabled'] = this.basepriceEnabled; + data['baseprice_amount'] = this.basepriceAmount; + data['baseprice_base_amount'] = this.basepriceBaseAmount; + data['has_tier_prices'] = this.hasTierPrices; + data['has_discounts_applied'] = this.hasDiscountsApplied; data['discount_name'] = this.discountName; data['discount_namen'] = this.discountNamen; + data['discount_description'] = this.discountDescription; + data['discount_Descriptionn'] = this.discountDescriptionn; data['discount_percentage'] = this.discountPercentage; + data['currency'] = this.currency; + data['currencyn'] = this.currencyn; + data['weight'] = this.weight; + data['length'] = this.length; + data['width'] = this.width; + data['height'] = this.height; + data['available_start_date_time_utc'] = this.availableStartDateTimeUtc; + data['available_end_date_time_utc'] = this.availableEndDateTimeUtc; data['display_order'] = this.displayOrder; - if (this.discountIds != String) { + data['published'] = this.published; + data['deleted'] = this.deleted; + data['created_on_utc'] = this.createdOnUtc; + data['updated_on_utc'] = this.updatedOnUtc; + data['product_type'] = this.productType; + data['parent_grouped_product_id'] = this.parentGroupedProductId; + if (this.roleIds != null) { + data['role_ids'] = this.roleIds.map((v) => v).toList(); + } + if (this.discountIds != null) { data['discount_ids'] = this.discountIds.map((v) => v).toList(); } - if (this.reviews != String) { + if (this.storeIds != null) { + data['store_ids'] = this.storeIds.map((v) => v).toList(); + } + data['manufacturer_ids'] = this.manufacturerIds; + if (this.reviews != null) { data['reviews'] = this.reviews.map((v) => v.toJson()).toList(); } - if (this.images != String) { + if (this.images != null) { data['images'] = this.images.map((v) => v.toJson()).toList(); } + if (this.attributes != null) { + data['attributes'] = this.attributes.map((v) => v).toList(); + } + if (this.specifications != null) { + data['specifications'] = + this.specifications.map((v) => v.toJson()).toList(); + } + if (this.associatedProductIds != null) { + data['associated_product_ids'] = + this.associatedProductIds.map((v) => v).toList(); + } + if (this.tags != null) { + data['tags'] = this.tags.map((v) => v).toList(); + } + data['vendor_id'] = this.vendorId; + data['se_name'] = this.seName; return data; } } diff --git a/lib/core/model/pharmacies/PointsAmountPerMonth.dart b/lib/core/model/pharmacies/PointsAmountPerMonth.dart new file mode 100644 index 00000000..71cf3498 --- /dev/null +++ b/lib/core/model/pharmacies/PointsAmountPerMonth.dart @@ -0,0 +1,42 @@ +import 'PointsAmountPerday.dart'; + +class PointsAmountPerMonth { + double amountPerMonth; + String month; + int monthNumber; + List pointsAmountPerday; + double pointsPerMonth; + + PointsAmountPerMonth( + {this.amountPerMonth, + this.month, + this.monthNumber, + this.pointsAmountPerday, + this.pointsPerMonth}); + + PointsAmountPerMonth.fromJson(Map json) { + amountPerMonth = json['AmountPerMonth']; + month = json['Month']; + monthNumber = json['MonthNumber']; + if (json['PointsAmountPerday'] != null) { + pointsAmountPerday = new List(); + json['PointsAmountPerday'].forEach((v) { + pointsAmountPerday.add(new PointsAmountPerday.fromJson(v)); + }); + } + pointsPerMonth = json['PointsPerMonth']; + } + + Map toJson() { + final Map data = new Map(); + data['AmountPerMonth'] = this.amountPerMonth; + data['Month'] = this.month; + data['MonthNumber'] = this.monthNumber; + if (this.pointsAmountPerday != null) { + data['PointsAmountPerday'] = + this.pointsAmountPerday.map((v) => v.toJson()).toList(); + } + data['PointsPerMonth'] = this.pointsPerMonth; + return data; + } +} diff --git a/lib/core/model/pharmacies/PointsAmountPerYear.dart b/lib/core/model/pharmacies/PointsAmountPerYear.dart new file mode 100644 index 00000000..eef74064 --- /dev/null +++ b/lib/core/model/pharmacies/PointsAmountPerYear.dart @@ -0,0 +1,38 @@ +import 'PointsAmountPerMonth.dart'; + +class PointsAmountPerYear { + int amountPerYear; + List pointsAmountPerMonth; + int pointsPerYear; + int year; + + PointsAmountPerYear( + {this.amountPerYear, + this.pointsAmountPerMonth, + this.pointsPerYear, + this.year}); + + PointsAmountPerYear.fromJson(Map json) { + amountPerYear = json['AmountPerYear']; + if (json['PointsAmountPerMonth'] != null) { + pointsAmountPerMonth = new List(); + json['PointsAmountPerMonth'].forEach((v) { + pointsAmountPerMonth.add(new PointsAmountPerMonth.fromJson(v)); + }); + } + pointsPerYear = json['PointsPerYear']; + year = json['Year']; + } + + Map toJson() { + final Map data = new Map(); + data['AmountPerYear'] = this.amountPerYear; + if (this.pointsAmountPerMonth != null) { + data['PointsAmountPerMonth'] = + this.pointsAmountPerMonth.map((v) => v.toJson()).toList(); + } + data['PointsPerYear'] = this.pointsPerYear; + data['Year'] = this.year; + return data; + } +} diff --git a/lib/core/model/pharmacies/PointsAmountPerday.dart b/lib/core/model/pharmacies/PointsAmountPerday.dart new file mode 100644 index 00000000..e78e87b7 --- /dev/null +++ b/lib/core/model/pharmacies/PointsAmountPerday.dart @@ -0,0 +1,42 @@ +import 'PointsDetails.dart'; + +class PointsAmountPerday { + double amountPerDay; + String day; + List pointsDetails; + double pointsPerDay; + String transationDate; + + PointsAmountPerday( + {this.amountPerDay, + this.day, + this.pointsDetails, + this.pointsPerDay, + this.transationDate}); + + PointsAmountPerday.fromJson(Map json) { + amountPerDay = json['AmountPerDay']; + day = json['Day']; + if (json['PointsDetails'] != null) { + pointsDetails = new List(); + json['PointsDetails'].forEach((v) { + pointsDetails.add(new PointsDetails.fromJson(v)); + }); + } + pointsPerDay = json['PointsPerDay']; + transationDate = json['TransationDate']; + } + + Map toJson() { + final Map data = new Map(); + data['AmountPerDay'] = this.amountPerDay; + data['Day'] = this.day; + if (this.pointsDetails != null) { + data['PointsDetails'] = + this.pointsDetails.map((v) => v.toJson()).toList(); + } + data['PointsPerDay'] = this.pointsPerDay; + data['TransationDate'] = this.transationDate; + return data; + } +} \ No newline at end of file diff --git a/lib/core/model/pharmacies/PointsDetails.dart b/lib/core/model/pharmacies/PointsDetails.dart new file mode 100644 index 00000000..7b342af9 --- /dev/null +++ b/lib/core/model/pharmacies/PointsDetails.dart @@ -0,0 +1,57 @@ +class PointsDetails { + int accNumber; + String accountStatus; + double amount; + int lineItemNo; + String operationType; + double points; + double purchasePoints; + int subTransactionType; + String subTransactionTypeDescription; + String transactionDate; + + PointsDetails( + {this.accNumber, + this.accountStatus, + this.amount, + this.lineItemNo, + this.operationType, + this.points, + this.purchasePoints, + this.subTransactionType, + this.subTransactionTypeDescription, + this.transactionDate}); + + PointsDetails.fromJson(Map json) { + accNumber = json['AccNumber']; + accountStatus = json['AccountStatus']; + amount = json['Amount']; + lineItemNo = json['LineItemNo']; + operationType = json['OperationType']; + points = json['Points']; + var purchasePoints = json['PurchasePoints']; + if(purchasePoints is int){ + this.purchasePoints = (purchasePoints).roundToDouble(); + }else { + this.purchasePoints = purchasePoints; + } + subTransactionType = json['SubTransactionType']; + subTransactionTypeDescription = json['SubTransactionTypeDescription']; + transactionDate = json['TransactionDate']; + } + + Map toJson() { + final Map data = new Map(); + data['AccNumber'] = this.accNumber; + data['AccountStatus'] = this.accountStatus; + data['Amount'] = this.amount; + data['LineItemNo'] = this.lineItemNo; + data['OperationType'] = this.operationType; + data['Points'] = this.points; + data['PurchasePoints'] = this.purchasePoints; + data['SubTransactionType'] = this.subTransactionType; + data['SubTransactionTypeDescription'] = this.subTransactionTypeDescription; + data['TransactionDate'] = this.transactionDate; + return data; + } +} diff --git a/lib/core/model/pharmacies/ShippingOption.dart b/lib/core/model/pharmacies/ShippingOption.dart new file mode 100644 index 00000000..1b589537 --- /dev/null +++ b/lib/core/model/pharmacies/ShippingOption.dart @@ -0,0 +1,97 @@ +class ShippingOption { + String shippingRateComputationMethodSystemName; + double rate; + double rateVat; + double rateVatPercent; + String name; + String namen; + String description; + String descriptionn; + bool allowShippingSunday; + bool allowShippingMonday; + bool allowShippingTuesday; + bool allowShippingWednesday; + bool allowShippingThursday; + bool allowShippingFriday; + bool allowShippingSaturday; + String allowShippingTime1From; + String allowShippingTime1To; + String allowShippingTime2From; + String allowShippingTime2To; + String allowShippingNote; + String allowShippingNoten; + + ShippingOption( + {this.shippingRateComputationMethodSystemName, + this.rate, + this.rateVat, + this.rateVatPercent, + this.name, + this.namen, + this.description, + this.descriptionn, + this.allowShippingSunday, + this.allowShippingMonday, + this.allowShippingTuesday, + this.allowShippingWednesday, + this.allowShippingThursday, + this.allowShippingFriday, + this.allowShippingSaturday, + this.allowShippingTime1From, + this.allowShippingTime1To, + this.allowShippingTime2From, + this.allowShippingTime2To, + this.allowShippingNote, + this.allowShippingNoten}); + + ShippingOption.fromJson(Map json) { + shippingRateComputationMethodSystemName = json['shipping_rate_computation_method_system_name']; + rate = json['rate']; + rateVat = json['rate_vat']; + rateVatPercent = json['rate_vat_percent']; + name = json['name']; + namen = json['namen']; + description = json['description']; + descriptionn = json['descriptionn']; + allowShippingSunday = json['AllowShippingSunday']; + allowShippingMonday = json['AllowShippingMonday']; + allowShippingTuesday = json['AllowShippingTuesday']; + allowShippingWednesday = json['AllowShippingWednesday']; + allowShippingThursday = json['AllowShippingThursday']; + allowShippingFriday = json['AllowShippingFriday']; + allowShippingSaturday = json['AllowShippingSaturday']; + allowShippingTime1From = json['AllowShippingTime1From']; + allowShippingTime1To = json['AllowShippingTime1To']; + allowShippingTime2From = json['AllowShippingTime2From']; + allowShippingTime2To = json['AllowShippingTime2To']; + allowShippingNote = json['AllowShippingNote']; + allowShippingNoten = json['AllowShippingNoten']; + } + + Map toJson() { + final Map data = new Map(); + data['shipping_rate_computation_method_system_name'] = + this.shippingRateComputationMethodSystemName; + data['rate'] = this.rate; + data['rate_vat'] = this.rateVat; + data['rate_vat_percent'] = this.rateVatPercent; + data['name'] = this.name; + data['namen'] = this.namen; + data['description'] = this.description; + data['descriptionn'] = this.descriptionn; + data['AllowShippingSunday'] = this.allowShippingSunday; + data['AllowShippingMonday'] = this.allowShippingMonday; + data['AllowShippingTuesday'] = this.allowShippingTuesday; + data['AllowShippingWednesday'] = this.allowShippingWednesday; + data['AllowShippingThursday'] = this.allowShippingThursday; + data['AllowShippingFriday'] = this.allowShippingFriday; + data['AllowShippingSaturday'] = this.allowShippingSaturday; + data['AllowShippingTime1From'] = this.allowShippingTime1From; + data['AllowShippingTime1To'] = this.allowShippingTime1To; + data['AllowShippingTime2From'] = this.allowShippingTime2From; + data['AllowShippingTime2To'] = this.allowShippingTime2To; + data['AllowShippingNote'] = this.allowShippingNote; + data['AllowShippingNoten'] = this.allowShippingNoten; + return data; + } +} diff --git a/lib/core/model/pharmacies/ShoppingCart.dart b/lib/core/model/pharmacies/ShoppingCart.dart new file mode 100644 index 00000000..f965203a --- /dev/null +++ b/lib/core/model/pharmacies/ShoppingCart.dart @@ -0,0 +1,115 @@ +import 'package:diplomaticquarterapp/core/model/pharmacies/Customer.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/PharmacyProduct.dart'; + +class ShoppingCart { + int languageId; + String id; + // List productAttributes; + double customerEnteredPrice; + int quantity; + String discountAmountInclTax; + String subtotal; + String subtotalWithVat; + String subtotalVatAmount; + String subtotalVatRate; + String currency; + String currencyn; + String rentalStartDateUtc; + String rentalEndDateUtc; + String createdOnUtc; + String updatedOnUtc; + String shoppingCartType; + int productId; + PharmacyProduct product; + int customerId; + Customer customer; + + ShoppingCart( + {this.languageId, + this.id, + // this.productAttributes, + this.customerEnteredPrice, + this.quantity, + this.discountAmountInclTax, + this.subtotal, + this.subtotalWithVat, + this.subtotalVatAmount, + this.subtotalVatRate, + this.currency, + this.currencyn, + this.rentalStartDateUtc, + this.rentalEndDateUtc, + this.createdOnUtc, + this.updatedOnUtc, + this.shoppingCartType, + this.productId, + this.product, + this.customerId, + this.customer}); + + ShoppingCart.fromJson(Map json) { + languageId = json['language_id']; + id = json['id']; + /*if (json['product_attributes'] != null) { + productAttributes = new List(); + json['product_attributes'].forEach((v) { + productAttributes.add(new Null.fromJson(v)); + }); + }*/ + customerEnteredPrice = json['customer_entered_price']; + quantity = json['quantity']; + discountAmountInclTax = json['discount_amount_incl_tax']; + subtotal = json['subtotal']; + subtotalWithVat = json['subtotal_with_vat']; + subtotalVatAmount = json['subtotal_vat_amount']; + subtotalVatRate = json['subtotal_vat_rate']; + currency = json['currency']; + currencyn = json['currencyn']; + rentalStartDateUtc = json['rental_start_date_utc']; + rentalEndDateUtc = json['rental_end_date_utc']; + createdOnUtc = json['created_on_utc']; + updatedOnUtc = json['updated_on_utc']; + shoppingCartType = json['shopping_cart_type']; + productId = json['product_id']; + product = json['product'] != null + ? new PharmacyProduct.fromJson(json['product']) + : null; + customerId = json['customer_id']; + customer = json['customer'] != null + ? new Customer.fromJson(json['customer']) + : null; + } + + Map toJson() { + final Map data = new Map(); + data['language_id'] = this.languageId; + data['id'] = this.id; + /*if (this.productAttributes != null) { + data['product_attributes'] = + this.productAttributes.map((v) => v.toJson()).toList(); + }*/ + data['customer_entered_price'] = this.customerEnteredPrice; + data['quantity'] = this.quantity; + data['discount_amount_incl_tax'] = this.discountAmountInclTax; + data['subtotal'] = this.subtotal; + data['subtotal_with_vat'] = this.subtotalWithVat; + data['subtotal_vat_amount'] = this.subtotalVatAmount; + data['subtotal_vat_rate'] = this.subtotalVatRate; + data['currency'] = this.currency; + data['currencyn'] = this.currencyn; + data['rental_start_date_utc'] = this.rentalStartDateUtc; + data['rental_end_date_utc'] = this.rentalEndDateUtc; + data['created_on_utc'] = this.createdOnUtc; + data['updated_on_utc'] = this.updatedOnUtc; + data['shopping_cart_type'] = this.shoppingCartType; + data['product_id'] = this.productId; + if (this.product != null) { + data['product'] = this.product.toJson(); + } + data['customer_id'] = this.customerId; + if (this.customer != null) { + data['customer'] = this.customer.toJson(); + } + return data; + } +} diff --git a/lib/core/model/pharmacies/ShoppingCartResponse.dart b/lib/core/model/pharmacies/ShoppingCartResponse.dart new file mode 100644 index 00000000..96b751ae --- /dev/null +++ b/lib/core/model/pharmacies/ShoppingCartResponse.dart @@ -0,0 +1,55 @@ +import 'package:diplomaticquarterapp/core/model/pharmacies/ShoppingCart.dart'; +import 'package:flutter/material.dart'; + +class ShoppingCartResponse with ChangeNotifier { + int itemCount; + int quantityCount; + double subtotal; + double subtotalWithVat; + double subtotalVatAmount; + double subtotalVatRate; + List shoppingCarts; + + ShoppingCartResponse( + {this.itemCount, + this.quantityCount, + this.subtotal, + this.subtotalWithVat, + this.subtotalVatAmount, + this.subtotalVatRate, + this.shoppingCarts}); + + void updateShoppingCard() { + notifyListeners(); + } + + ShoppingCartResponse.fromJson(Map json) { + itemCount = json['item_count']; + quantityCount = json['quantity_count']; + subtotal = json['subtotal']; + subtotalWithVat = json['subtotal_with_vat']; + subtotalVatAmount = json['subtotal_vat_amount']; + subtotalVatRate = json['subtotal_vat_rate']; + if (json['shopping_carts'] != null) { + shoppingCarts = new List(); + json['shopping_carts'].forEach((v) { + shoppingCarts.add(new ShoppingCart.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = new Map(); + data['item_count'] = this.itemCount; + data['quantity_count'] = this.quantityCount; + data['subtotal'] = this.subtotal; + data['subtotal_with_vat'] = this.subtotalWithVat; + data['subtotal_vat_amount'] = this.subtotalVatAmount; + data['subtotal_vat_rate'] = this.subtotalVatRate; + if (this.shoppingCarts != null) { + data['shopping_carts'] = + this.shoppingCarts.map((v) => v.toJson()).toList(); + } + return data; + } +} diff --git a/lib/core/model/pharmacies/Specifications.dart b/lib/core/model/pharmacies/Specifications.dart new file mode 100644 index 00000000..f227de69 --- /dev/null +++ b/lib/core/model/pharmacies/Specifications.dart @@ -0,0 +1,36 @@ +class Specifications { + int id; + int displayOrder; + String defaultValue; + String defaultValuen; + String name; + String nameN; + + Specifications( + {this.id, + this.displayOrder, + this.defaultValue, + this.defaultValuen, + this.name, + this.nameN}); + + Specifications.fromJson(Map json) { + id = json['id']; + displayOrder = json['display_order']; + defaultValue = json['default_value']; + defaultValuen = json['default_valuen']; + name = json['name']; + nameN = json['nameN']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['display_order'] = this.displayOrder; + data['default_value'] = this.defaultValue; + data['default_valuen'] = this.defaultValuen; + data['name'] = this.name; + data['nameN'] = this.nameN; + return data; + } +} diff --git a/lib/core/model/pharmacies/order_model.dart b/lib/core/model/pharmacies/order_model.dart new file mode 100644 index 00000000..027d1f81 --- /dev/null +++ b/lib/core/model/pharmacies/order_model.dart @@ -0,0 +1,1456 @@ + +import 'dart:convert'; + +import 'package:diplomaticquarterapp/core/model/pharmacies/PharmacyImageObject.dart'; + +List orderModelFromJson(String str) => List.from(json.decode(str).map((x) => OrderModel.fromJson(x))); + +String orderModelToJson(List data) => json.encode(List.from(data.map((x) => x.toJson()))); + +class OrderModel { + OrderModel({ + this.id, + this.storeId, + this.orderGuid, + this.pickUpInStore, + this.paymentMethodSystemName, + this.paymentName, + this.paymentNamen, + this.customerCurrencyCode, + this.currencyRate, + this.customerTaxDisplayTypeId, + this.vatNumber, + this.orderSubtotalInclTax, + this.orderSubtotalExclTax, + this.orderSubTotalDiscountInclTax, + this.orderSubTotalDiscountExclTax, + this.orderShippingInclTax, + this.orderShippingExclTax, + this.paymentMethodAdditionalFeeInclTax, + this.paymentMethodAdditionalFeeExclTax, + this.taxRates, + this.orderTax, + this.orderDiscount, + this.orderTotal, + this.refundedAmount, + this.rewardPointsWereAdded, + this.rxAttachments, + this.checkoutAttributeDescription, + this.customerLanguageId, + this.affiliateId, + this.customerIp, + this.authorizationTransactionId, + this.authorizationTransactionCode, + this.authorizationTransactionResult, + this.captureTransactionId, + this.captureTransactionResult, + this.subscriptionTransactionId, + this.paidDateUtc, + this.shippingMethod, + this.shippingRateComputationMethodSystemName, + this.customValuesXml, + this.deleted, + this.createdOnUtc, + this.customer, + this.customerId, + this.billingAddress, + this.shippingAddress, + this.orderItems, + this.orderStatusId, + this.orderStatus, + this.orderStatusn, + this.paymentStatusId, + this.paymentStatus, + this.paymentStatusn, + this.shippingStatus, + this.shippingStatusn, + this.customerTaxDisplayType, + this.canCancel, + this.canRefund, + this.lakumAmount, + this.preferDeliveryDate, + this.preferDeliveryTime, + this.preferDeliveryTimen, + }); + + String id; + dynamic storeId; + String orderGuid; + bool pickUpInStore; + PaymentMethodSystemName paymentMethodSystemName; + PaymentName paymentName; + PaymentName paymentNamen; + CustomerCurrencyCode customerCurrencyCode; + dynamic currencyRate; + dynamic customerTaxDisplayTypeId; + dynamic vatNumber; + double orderSubtotalInclTax; + double orderSubtotalExclTax; + dynamic orderSubTotalDiscountInclTax; + dynamic orderSubTotalDiscountExclTax; + double orderShippingInclTax; + dynamic orderShippingExclTax; + dynamic paymentMethodAdditionalFeeInclTax; + dynamic paymentMethodAdditionalFeeExclTax; + String taxRates; + double orderTax; + dynamic orderDiscount; + double orderTotal; + dynamic refundedAmount; + dynamic rewardPointsWereAdded; + String rxAttachments; + CheckoutAttributeDescription checkoutAttributeDescription; + dynamic customerLanguageId; + dynamic affiliateId; + CustomerIp customerIp; + String authorizationTransactionId; + dynamic authorizationTransactionCode; + dynamic authorizationTransactionResult; + dynamic captureTransactionId; + dynamic captureTransactionResult; + dynamic subscriptionTransactionId; + DateTime paidDateUtc; + ShippingMethod shippingMethod; + ShippingRateComputationMethodSystemName shippingRateComputationMethodSystemName; + String customValuesXml; + bool deleted; + DateTime createdOnUtc; + OrderModelCustomer customer; + dynamic customerId; + IngAddress billingAddress; + IngAddress shippingAddress; + List orderItems; + dynamic orderStatusId; + OrderStatus orderStatus; + OrderStatusn orderStatusn; + dynamic paymentStatusId; + PaymentStatus paymentStatus; + PaymentStatusn paymentStatusn; + ShippingStatus shippingStatus; + ShippingStatusn shippingStatusn; + CustomerTaxDisplayType customerTaxDisplayType; + bool canCancel; + bool canRefund; + dynamic lakumAmount; + DateTime preferDeliveryDate; + PreferDeliveryTime preferDeliveryTime; + PreferDeliveryTimen preferDeliveryTimen; + + factory OrderModel.fromJson(Map json) => OrderModel( + id: json["id"], + storeId: json["store_id"], + orderGuid: json["order_guid"], + pickUpInStore: json["pick_up_in_store"], + paymentMethodSystemName: paymentMethodSystemNameValues.map[json["payment_method_system_name"]], + paymentName: paymentNameValues.map[json["payment_name"]], + paymentNamen: paymentNameValues.map[json["payment_namen"]], + customerCurrencyCode: customerCurrencyCodeValues.map[json["customer_currency_code"]], + currencyRate: json["currency_rate"], + customerTaxDisplayTypeId: json["customer_tax_display_type_id"], + vatNumber: json["vat_number"], + orderSubtotalInclTax: json["order_subtotal_incl_tax"].toDouble(), + orderSubtotalExclTax: json["order_subtotal_excl_tax"].toDouble(), + orderSubTotalDiscountInclTax: json["order_sub_total_discount_incl_tax"], + orderSubTotalDiscountExclTax: json["order_sub_total_discount_excl_tax"], + orderShippingInclTax: json["order_shipping_incl_tax"].toDouble(), + orderShippingExclTax: json["order_shipping_excl_tax"], + paymentMethodAdditionalFeeInclTax: json["payment_method_additional_fee_incl_tax"], + paymentMethodAdditionalFeeExclTax: json["payment_method_additional_fee_excl_tax"], + taxRates: json["tax_rates"], + orderTax: json["order_tax"].toDouble(), + orderDiscount: json["order_discount"], + orderTotal: json["order_total"].toDouble(), + refundedAmount: json["refunded_amount"], + rewardPointsWereAdded: json["reward_points_were_added"], + rxAttachments: json["rx_attachments"] == null ? null : json["rx_attachments"], + checkoutAttributeDescription: checkoutAttributeDescriptionValues.map[json["checkout_attribute_description"]], + customerLanguageId: json["customer_language_id"], + affiliateId: json["affiliate_id"], + customerIp: customerIpValues.map[json["customer_ip"]], + authorizationTransactionId: json["authorization_transaction_id"] == null ? null : json["authorization_transaction_id"], + authorizationTransactionCode: json["authorization_transaction_code"], + authorizationTransactionResult: json["authorization_transaction_result"], + captureTransactionId: json["capture_transaction_id"], + captureTransactionResult: json["capture_transaction_result"], + subscriptionTransactionId: json["subscription_transaction_id"], + paidDateUtc: json["paid_date_utc"] == null ? null : DateTime.parse(json["paid_date_utc"]), + shippingMethod: shippingMethodValues.map[json["shipping_method"]], + shippingRateComputationMethodSystemName: shippingRateComputationMethodSystemNameValues.map[json["shipping_rate_computation_method_system_name"]], + customValuesXml: json["custom_values_xml"], + deleted: json["deleted"], + createdOnUtc: DateTime.parse(json["created_on_utc"]), + customer: OrderModelCustomer.fromJson(json["customer"]), + customerId: json["customer_id"], + billingAddress: IngAddress.fromJson(json["billing_address"]), + shippingAddress: IngAddress.fromJson(json["shipping_address"]), + orderItems: List.from(json["order_items"].map((x) => OrderItem.fromJson(x))), + orderStatusId: json["order_status_id"], + orderStatus: orderStatusValues.map[json["order_status"]], + orderStatusn: orderStatusnValues.map[json["order_statusn"]], + paymentStatusId: json["payment_status_id"], + paymentStatus: paymentStatusValues.map[json["payment_status"]], + paymentStatusn: paymentStatusnValues.map[json["payment_statusn"]], + shippingStatus: shippingStatusValues.map[json["shipping_status"]], + shippingStatusn: shippingStatusnValues.map[json["shipping_statusn"]], + customerTaxDisplayType: customerTaxDisplayTypeValues.map[json["customer_tax_display_type"]], + canCancel: json["can_cancel"], + canRefund: json["can_refund"], + lakumAmount: json["lakum_amount"], + preferDeliveryDate: json["prefer_delivery_date"] == null ? null : DateTime.parse(json["prefer_delivery_date"]), + preferDeliveryTime: json["prefer_delivery_time"] == null ? null : preferDeliveryTimeValues.map[json["prefer_delivery_time"]], + preferDeliveryTimen: json["prefer_delivery_timen"] == null ? null : preferDeliveryTimenValues.map[json["prefer_delivery_timen"]], + ); + + Map toJson() => { + "id": id, + "store_id": storeId, + "order_guid": orderGuid, + "pick_up_in_store": pickUpInStore, + "payment_method_system_name": paymentMethodSystemNameValues.reverse[paymentMethodSystemName], + "payment_name": paymentNameValues.reverse[paymentName], + "payment_namen": paymentNameValues.reverse[paymentNamen], + "customer_currency_code": customerCurrencyCodeValues.reverse[customerCurrencyCode], + "currency_rate": currencyRate, + "customer_tax_display_type_id": customerTaxDisplayTypeId, + "vat_number": vatNumber, + "order_subtotal_incl_tax": orderSubtotalInclTax, + "order_subtotal_excl_tax": orderSubtotalExclTax, + "order_sub_total_discount_incl_tax": orderSubTotalDiscountInclTax, + "order_sub_total_discount_excl_tax": orderSubTotalDiscountExclTax, + "order_shipping_incl_tax": orderShippingInclTax, + "order_shipping_excl_tax": orderShippingExclTax, + "payment_method_additional_fee_incl_tax": paymentMethodAdditionalFeeInclTax, + "payment_method_additional_fee_excl_tax": paymentMethodAdditionalFeeExclTax, + "tax_rates": taxRates, + "order_tax": orderTax, + "order_discount": orderDiscount, + "order_total": orderTotal, + "refunded_amount": refundedAmount, + "reward_points_were_added": rewardPointsWereAdded, + "rx_attachments": rxAttachments == null ? null : rxAttachments, + "checkout_attribute_description": checkoutAttributeDescriptionValues.reverse[checkoutAttributeDescription], + "customer_language_id": customerLanguageId, + "affiliate_id": affiliateId, + "customer_ip": customerIpValues.reverse[customerIp], + "authorization_transaction_id": authorizationTransactionId == null ? null : authorizationTransactionId, + "authorization_transaction_code": authorizationTransactionCode, + "authorization_transaction_result": authorizationTransactionResult, + "capture_transaction_id": captureTransactionId, + "capture_transaction_result": captureTransactionResult, + "subscription_transaction_id": subscriptionTransactionId, + "paid_date_utc": paidDateUtc == null ? null : paidDateUtc.toIso8601String(), + "shipping_method": shippingMethodValues.reverse[shippingMethod], + "shipping_rate_computation_method_system_name": shippingRateComputationMethodSystemNameValues.reverse[shippingRateComputationMethodSystemName], + "custom_values_xml": customValuesXml, + "deleted": deleted, + "created_on_utc": createdOnUtc.toIso8601String(), + "customer": customer.toJson(), + "customer_id": customerId, + "billing_address": billingAddress.toJson(), + "shipping_address": shippingAddress.toJson(), + "order_items": List.from(orderItems.map((x) => x.toJson())), + "order_status_id": orderStatusId, + "order_status": orderStatusValues.reverse[orderStatus], + "order_statusn": orderStatusnValues.reverse[orderStatusn], + "payment_status_id": paymentStatusId, + "payment_status": paymentStatusValues.reverse[paymentStatus], + "payment_statusn": paymentStatusnValues.reverse[paymentStatusn], + "shipping_status": shippingStatusValues.reverse[shippingStatus], + "shipping_statusn": shippingStatusnValues.reverse[shippingStatusn], + "customer_tax_display_type": customerTaxDisplayTypeValues.reverse[customerTaxDisplayType], + "can_cancel": canCancel, + "can_refund": canRefund, + "lakum_amount": lakumAmount, + "prefer_delivery_date": preferDeliveryDate == null ? null : "${preferDeliveryDate.year.toString().padLeft(4, '0')}-${preferDeliveryDate.month.toString().padLeft(2, '0')}-${preferDeliveryDate.day.toString().padLeft(2, '0')}", + "prefer_delivery_time": preferDeliveryTime == null ? null : preferDeliveryTimeValues.reverse[preferDeliveryTime], + "prefer_delivery_timen": preferDeliveryTimen == null ? null : preferDeliveryTimenValues.reverse[preferDeliveryTimen], + }; +} + +class IngAddress { + IngAddress({ + this.id, + this.firstName, + this.lastName, + this.email, + this.company, + this.countryId, + this.country, + this.stateProvinceId, + this.city, + this.address1, + this.address2, + this.zipPostalCode, + this.phoneNumber, + this.faxNumber, + this.customerAttributes, + this.createdOnUtc, + this.province, + this.latLong, + }); + + String id; + FirstName firstName; + LastName lastName; + BillingAddressEmail email; + dynamic company; + dynamic countryId; + Country country; + dynamic stateProvinceId; + City city; + Address1 address1; + Address2 address2; + String zipPostalCode; + String phoneNumber; + dynamic faxNumber; + String customerAttributes; + DateTime createdOnUtc; + dynamic province; + LatLong latLong; + + factory IngAddress.fromJson(Map json) => IngAddress( + id: json["id"], + firstName: firstNameValues.map[json["first_name"]], + lastName: lastNameValues.map[json["last_name"]], + email: billingAddressEmailValues.map[json["email"]], + company: json["company"], + countryId: json["country_id"], + country: countryValues.map[json["country"]], + stateProvinceId: json["state_province_id"], + city: cityValues.map[json["city"]], + address1: address1Values.map[json["address1"]], + address2: address2Values.map[json["address2"]], + zipPostalCode: json["zip_postal_code"], + phoneNumber: json["phone_number"], + faxNumber: json["fax_number"], + customerAttributes: json["customer_attributes"], + createdOnUtc: DateTime.parse(json["created_on_utc"]), + province: json["province"], + latLong: latLongValues.map[json["lat_long"]], + ); + + Map toJson() => { + "id": id, + "first_name": firstNameValues.reverse[firstName], + "last_name": lastNameValues.reverse[lastName], + "email": billingAddressEmailValues.reverse[email], + "company": company, + "country_id": countryId, + "country": countryValues.reverse[country], + "state_province_id": stateProvinceId, + "city": cityValues.reverse[city], + "address1": address1Values.reverse[address1], + "address2": address2Values.reverse[address2], + "zip_postal_code": zipPostalCode, + "phone_number": phoneNumber, + "fax_number": faxNumber, + "customer_attributes": customerAttributes, + "created_on_utc": createdOnUtc.toIso8601String(), + "province": province, + "lat_long": latLongValues.reverse[latLong], + }; +} + +enum Address1 { THE_7960_MOSAB_IBN_UMAIR_STREET_AL_RIYADH, THE_6500_AL_AMEEN_ABDULLAH_AL_ALI_AL_NAEEM_STREET_AL_RIYADH, THE_6603_IBRAHIM_IBN_AL_HAMASI_AR_RIYAD, THE_9626_SALAH_AD_DIN_AL_AYYUBI_ROAD_AL_RIYADH, THE_3075_PRINCE_MANSUR_BIN_ABDULAZIZ_STREET_AL_RIYADH, THE_40, THE_7801_AL_IHSA_AL_RIYADH } + +final address1Values = EnumValues({ + "3075, Prince Mansur Bin Abdulaziz Street, Al Riyadh, ": Address1.THE_3075_PRINCE_MANSUR_BIN_ABDULAZIZ_STREET_AL_RIYADH, + "40,": Address1.THE_40, + "6500, Al Ameen Abdullah Al Ali Al Naeem Street, Al Riyadh, ": Address1.THE_6500_AL_AMEEN_ABDULLAH_AL_ALI_AL_NAEEM_STREET_AL_RIYADH, + "6603, Ibrahim Ibn Al Hamasi, Ar-Riyad, ": Address1.THE_6603_IBRAHIM_IBN_AL_HAMASI_AR_RIYAD, + "7801, Al Ihsa, Al Riyadh, ": Address1.THE_7801_AL_IHSA_AL_RIYADH, + "7960, Mosab Ibn Umair Street, Al Riyadh, ": Address1.THE_7960_MOSAB_IBN_UMAIR_STREET_AL_RIYADH, + "9626, Salah Ad Din Al Ayyubi Road, Al Riyadh, ": Address1.THE_9626_SALAH_AD_DIN_AL_AYYUBI_ROAD_AL_RIYADH +}); + +enum Address2 { AL_MALAZ_RIYADH_PROVINCE_3460, AL_MALAZ_RIYADH_PROVINCE_2817, AR_RAHMANIYYAH_RIYADH_PROVINCE_3816, AL_MALAZ_RIYADH_PROVINCE_3815, AL_WIZARAT_RIYADH_PROVINCE_7039, EASTERN_PROVINCE, AL_MALAZ_RIYADH_PROVINCE_3084 } + +final address2Values = EnumValues({ + "Al Malaz, Riyadh Province, 2817, ": Address2.AL_MALAZ_RIYADH_PROVINCE_2817, + "Al Malaz, Riyadh Province, 3084, ": Address2.AL_MALAZ_RIYADH_PROVINCE_3084, + "Al Malaz, Riyadh Province, 3460, ": Address2.AL_MALAZ_RIYADH_PROVINCE_3460, + "Al Malaz, Riyadh Province, 3815, ": Address2.AL_MALAZ_RIYADH_PROVINCE_3815, + "Al Wizarat, Riyadh Province, 7039, ": Address2.AL_WIZARAT_RIYADH_PROVINCE_7039, + "Ar Rahmaniyyah, Riyadh Province, 3816, ": Address2.AR_RAHMANIYYAH_RIYADH_PROVINCE_3816, + "Eastern Province,": Address2.EASTERN_PROVINCE +}); + +enum City { RIYADH, DAMMAM } + +final cityValues = EnumValues({ + "Dammam": City.DAMMAM, + "Riyadh": City.RIYADH +}); + +enum Country { SAUDI_ARABIA } + +final countryValues = EnumValues({ + "Saudi Arabia": Country.SAUDI_ARABIA +}); + +enum BillingAddressEmail { TAMER_FANASHEH_GMAIL_COM, TAMER_DASDASDAS_GMAIL_COM, TAMER_FANASHEH_DRSULAIMANALHABIB_COM } + +final billingAddressEmailValues = EnumValues({ + "Tamer.dasdasdas@gmail.com": BillingAddressEmail.TAMER_DASDASDAS_GMAIL_COM, + "tamer.fanasheh@drsulaimanalhabib.com": BillingAddressEmail.TAMER_FANASHEH_DRSULAIMANALHABIB_COM, + "Tamer.fanasheh@gmail.com": BillingAddressEmail.TAMER_FANASHEH_GMAIL_COM +}); + +enum FirstName { TAMER, TAMER_FANASHEH, FIRST_NAME_TAMER } + +final firstNameValues = EnumValues({ + "tamer": FirstName.FIRST_NAME_TAMER, + "TAMER": FirstName.TAMER, + "TAMER FANASHEH": FirstName.TAMER_FANASHEH +}); + +enum LastName { FANASHEH, MUSA, LAST_NAME_FANASHEH } + +final lastNameValues = EnumValues({ + "FANASHEH": LastName.FANASHEH, + "Fanasheh": LastName.LAST_NAME_FANASHEH, + "MUSA": LastName.MUSA +}); + +enum LatLong { THE_246784385694919524674091019299842, THE_24664749106968054673501121876645, THE_2470993657522702246664724647270134, THE_246626170308533764673348444086107, THE_24664875225999005467347443322574, THE_24674331807435784671024726818286, THE_263430228396836664991113909164471, THE_246767400793488074673774399406786, THE_24665374673515 } + +final latLongValues = EnumValues({ + "24.662617030853376,46.73348444086107": LatLong.THE_246626170308533764673348444086107, + "24.66474910696805,46.73501121876645": LatLong.THE_24664749106968054673501121876645, + "24.664875225999005,46.7347443322574": LatLong.THE_24664875225999005467347443322574, + "24.66537,46.73515": LatLong.THE_24665374673515, + "24.67433180743578,46.71024726818286": LatLong.THE_24674331807435784671024726818286, + "24.676740079348807,46.73774399406786": LatLong.THE_246767400793488074673774399406786, + "24.678438569491952,46.74091019299842": LatLong.THE_246784385694919524674091019299842, + "24.709936575227022,46.664724647270134": LatLong.THE_2470993657522702246664724647270134, + "26.343022839683666, 49.91113909164471": LatLong.THE_263430228396836664991113909164471 +}); + +enum CheckoutAttributeDescription { EMPTY, CHECKOUT_ATTRIBUTE_DESCRIPTION } + +final checkoutAttributeDescriptionValues = EnumValues({ + "ارفاق وصفة: ": CheckoutAttributeDescription.CHECKOUT_ATTRIBUTE_DESCRIPTION, + "": CheckoutAttributeDescription.EMPTY +}); + +class OrderModelCustomer { + OrderModelCustomer({ + this.id, + this.username, + this.email, + this.firstName, + this.lastName, + this.languageId, + this.adminComment, + this.isTaxExempt, + this.hasShoppingCartItems, + this.active, + this.deleted, + this.isSystemAccount, + this.systemName, + this.lastIpAddress, + this.createdOnUtc, + this.lastLoginDateUtc, + this.lastActivityDateUtc, + this.registeredInStoreId, + this.roleIds, + }); + + String id; + Username username; + BillingAddressEmail email; + FirstName firstName; + LastName lastName; + String languageId; + dynamic adminComment; + bool isTaxExempt; + bool hasShoppingCartItems; + bool active; + bool deleted; + bool isSystemAccount; + dynamic systemName; + LastIpAddress lastIpAddress; + DateTime createdOnUtc; + DateTime lastLoginDateUtc; + DateTime lastActivityDateUtc; + dynamic registeredInStoreId; + List roleIds; + + factory OrderModelCustomer.fromJson(Map json) => OrderModelCustomer( + id: json["id"], + username: usernameValues.map[json["username"]], + email: billingAddressEmailValues.map[json["email"]], + firstName: firstNameValues.map[json["first_name"]], + lastName: lastNameValues.map[json["last_name"]], + languageId: json["language_id"], + adminComment: json["admin_comment"], + isTaxExempt: json["is_tax_exempt"], + hasShoppingCartItems: json["has_shopping_cart_items"], + active: json["active"], + deleted: json["deleted"], + isSystemAccount: json["is_system_account"], + systemName: json["system_name"], + lastIpAddress: lastIpAddressValues.map[json["last_ip_address"]], + createdOnUtc: DateTime.parse(json["created_on_utc"]), + lastLoginDateUtc: DateTime.parse(json["last_login_date_utc"]), + lastActivityDateUtc: DateTime.parse(json["last_activity_date_utc"]), + registeredInStoreId: json["registered_in_store_id"], + roleIds: List.from(json["role_ids"].map((x) => x)), + ); + + Map toJson() => { + "id": id, + "username": usernameValues.reverse[username], + "email": billingAddressEmailValues.reverse[email], + "first_name": firstNameValues.reverse[firstName], + "last_name": lastNameValues.reverse[lastName], + "language_id": languageId, + "admin_comment": adminComment, + "is_tax_exempt": isTaxExempt, + "has_shopping_cart_items": hasShoppingCartItems, + "active": active, + "deleted": deleted, + "is_system_account": isSystemAccount, + "system_name": systemName, + "last_ip_address": lastIpAddressValues.reverse[lastIpAddress], + "created_on_utc": createdOnUtc.toIso8601String(), + "last_login_date_utc": lastLoginDateUtc.toIso8601String(), + "last_activity_date_utc": lastActivityDateUtc.toIso8601String(), + "registered_in_store_id": registeredInStoreId, + "role_ids": List.from(roleIds.map((x) => x)), + }; +} + +enum LastIpAddress { THE_1050220126 } + +final lastIpAddressValues = EnumValues({ + "10.50.220.126": LastIpAddress.THE_1050220126 +}); + +enum Username { TAMERF } + +final usernameValues = EnumValues({ + "tamerf": Username.TAMERF +}); + +enum CustomerCurrencyCode { SAR } + +final customerCurrencyCodeValues = EnumValues({ + "SAR": CustomerCurrencyCode.SAR +}); + +enum CustomerIp { THE_105010210, THE_127001, THE_1020200101, THE_102020041, THE_10501028, THE_102020033, THE_1020200170, THE_102020011 } + +final customerIpValues = EnumValues({ + "10.20.200.101": CustomerIp.THE_1020200101, + "10.20.200.11": CustomerIp.THE_102020011, + "10.20.200.170": CustomerIp.THE_1020200170, + "10.20.200.33": CustomerIp.THE_102020033, + "10.20.200.41": CustomerIp.THE_102020041, + "10.50.102.10": CustomerIp.THE_105010210, + "10.50.102.8": CustomerIp.THE_10501028, + "127.0.0.1": CustomerIp.THE_127001 +}); + +enum CustomerTaxDisplayType { EXCLUDING_TAX } + +final customerTaxDisplayTypeValues = EnumValues({ + "ExcludingTax": CustomerTaxDisplayType.EXCLUDING_TAX +}); + +class OrderItem { + OrderItem({ + this.quantity, + this.unitPriceInclTax, + this.unitPriceExclTax, + this.priceInclTax, + this.priceExclTax, + this.discountAmountInclTax, + this.discountAmountExclTax, + this.originalProductCost, + this.attributeDescription, + this.downloadCount, + this.isDownloadActivated, + this.licenseDownloadId, + this.itemWeight, + this.rentalStartDateUtc, + this.rentalEndDateUtc, + this.product, + this.productId, + }); + + dynamic quantity; + double unitPriceInclTax; + double unitPriceExclTax; + double priceInclTax; + double priceExclTax; + double discountAmountInclTax; + double discountAmountExclTax; + double originalProductCost; + String attributeDescription; + dynamic downloadCount; + bool isDownloadActivated; + dynamic licenseDownloadId; + double itemWeight; + dynamic rentalStartDateUtc; + dynamic rentalEndDateUtc; + Product product; + dynamic productId; + + factory OrderItem.fromJson(Map json) => OrderItem( + quantity: json["quantity"], + unitPriceInclTax: json["unit_price_incl_tax"].toDouble(), + unitPriceExclTax: json["unit_price_excl_tax"].toDouble(), + priceInclTax: json["price_incl_tax"].toDouble(), + priceExclTax: json["price_excl_tax"].toDouble(), + discountAmountInclTax: json["discount_amount_incl_tax"].toDouble(), + discountAmountExclTax: json["discount_amount_excl_tax"].toDouble(), + originalProductCost: json["original_product_cost"].toDouble(), + attributeDescription: json["attribute_description"], + downloadCount: json["download_count"], + isDownloadActivated: json["isDownload_activated"], + licenseDownloadId: json["license_download_id"], + itemWeight: json["item_weight"].toDouble(), + rentalStartDateUtc: json["rental_start_date_utc"], + rentalEndDateUtc: json["rental_end_date_utc"], + product: Product.fromJson(json["product"]), + productId: json["product_id"], + ); + + Map toJson() => { + "quantity": quantity, + "unit_price_incl_tax": unitPriceInclTax, + "unit_price_excl_tax": unitPriceExclTax, + "price_incl_tax": priceInclTax, + "price_excl_tax": priceExclTax, + "discount_amount_incl_tax": discountAmountInclTax, + "discount_amount_excl_tax": discountAmountExclTax, + "original_product_cost": originalProductCost, + "attribute_description": attributeDescription, + "download_count": downloadCount, + "isDownload_activated": isDownloadActivated, + "license_download_id": licenseDownloadId, + "item_weight": itemWeight, + "rental_start_date_utc": rentalStartDateUtc, + "rental_end_date_utc": rentalEndDateUtc, + "product": product.toJson(), + "product_id": productId, + }; +} + +class Product { + Product({ + this.id, + this.visibleIndividually, + this.name, + this.namen, + this.localizedNames, + this.shortDescription, + this.shortDescriptionn, + this.fullDescription, + this.fullDescriptionn, + this.markasNew, + this.showOnHomePage, + this.metaKeywords, + this.metaDescription, + this.metaTitle, + this.allowCustomerReviews, + this.approvedRatingSum, + this.notApprovedRatingSum, + this.approvedTotalReviews, + this.notApprovedTotalReviews, + this.sku, + this.isRx, + this.prescriptionRequired, + this.rxMessage, + this.rxMessagen, + this.manufacturerPartNumber, + this.gtin, + this.isGiftCard, + this.requireOtherProducts, + this.automaticallyAddRequiredProducts, + this.isDownload, + this.unlimitedDownloads, + this.maxNumberOfDownloads, + this.downloadExpirationDays, + this.hasSampleDownload, + this.hasUserAgreement, + this.isRecurring, + this.recurringCycleLength, + this.recurringTotalCycles, + this.isRental, + this.rentalPriceLength, + this.isShipEnabled, + this.isFreeShipping, + this.shipSeparately, + this.additionalShippingCharge, + this.isTaxExempt, + this.isTelecommunicationsOrBroadcastingOrElectronicServices, + this.useMultipleWarehouses, + this.manageInventoryMethodId, + this.stockQuantity, + this.stockAvailability, + this.stockAvailabilityn, + this.displayStockAvailability, + this.displayStockQuantity, + this.minStockQuantity, + this.notifyAdminForQuantityBelow, + this.allowBackInStockSubscriptions, + this.orderMinimumQuantity, + this.orderMaximumQuantity, + this.allowedQuantities, + this.allowAddingOnlyExistingAttributeCombinations, + this.disableBuyButton, + this.disableWishlistButton, + this.availableForPreOrder, + this.preOrderAvailabilityStartDateTimeUtc, + this.callForPrice, + this.price, + this.oldPrice, + this.productCost, + this.specialPrice, + this.specialPriceStartDateTimeUtc, + this.specialPriceEndDateTimeUtc, + this.customerEntersPrice, + this.minimumCustomerEnteredPrice, + this.maximumCustomerEnteredPrice, + this.basepriceEnabled, + this.basepriceAmount, + this.basepriceBaseAmount, + this.hasTierPrices, + this.hasDiscountsApplied, + this.discountName, + this.discountNamen, + this.discountDescription, + this.discountDescriptionn, + this.discountPercentage, + this.currency, + this.currencyn, + this.weight, + this.length, + this.width, + this.height, + this.availableStartDateTimeUtc, + this.availableEndDateTimeUtc, + this.displayOrder, + this.published, + this.deleted, + this.createdOnUtc, + this.updatedOnUtc, + this.productType, + this.parentGroupedProductId, + this.roleIds, + this.discountIds, + this.storeIds, + this.manufacturerIds, + this.reviews, + this.images, + this.attributes, + this.specifications, + this.associatedProductIds, + this.tags, + this.vendorId, + this.seName, + }); + + String id; + bool visibleIndividually; + String name; + String namen; + dynamic localizedNames; + String shortDescription; + String shortDescriptionn; + String fullDescription; + String fullDescriptionn; + bool markasNew; + bool showOnHomePage; + String metaKeywords; + String metaDescription; + String metaTitle; + bool allowCustomerReviews; + dynamic approvedRatingSum; + dynamic notApprovedRatingSum; + dynamic approvedTotalReviews; + dynamic notApprovedTotalReviews; + String sku; + bool isRx; + bool prescriptionRequired; + dynamic rxMessage; + dynamic rxMessagen; + dynamic manufacturerPartNumber; + dynamic gtin; + bool isGiftCard; + bool requireOtherProducts; + bool automaticallyAddRequiredProducts; + bool isDownload; + bool unlimitedDownloads; + dynamic maxNumberOfDownloads; + dynamic downloadExpirationDays; + bool hasSampleDownload; + bool hasUserAgreement; + bool isRecurring; + dynamic recurringCycleLength; + dynamic recurringTotalCycles; + bool isRental; + dynamic rentalPriceLength; + bool isShipEnabled; + bool isFreeShipping; + bool shipSeparately; + dynamic additionalShippingCharge; + bool isTaxExempt; + bool isTelecommunicationsOrBroadcastingOrElectronicServices; + bool useMultipleWarehouses; + dynamic manageInventoryMethodId; + dynamic stockQuantity; + dynamic stockAvailability; + dynamic stockAvailabilityn; + bool displayStockAvailability; + bool displayStockQuantity; + dynamic minStockQuantity; + dynamic notifyAdminForQuantityBelow; + bool allowBackInStockSubscriptions; + dynamic orderMinimumQuantity; + dynamic orderMaximumQuantity; + dynamic allowedQuantities; + bool allowAddingOnlyExistingAttributeCombinations; + bool disableBuyButton; + bool disableWishlistButton; + bool availableForPreOrder; + dynamic preOrderAvailabilityStartDateTimeUtc; + bool callForPrice; + double price; + dynamic oldPrice; + double productCost; + dynamic specialPrice; + dynamic specialPriceStartDateTimeUtc; + dynamic specialPriceEndDateTimeUtc; + bool customerEntersPrice; + dynamic minimumCustomerEnteredPrice; + dynamic maximumCustomerEnteredPrice; + bool basepriceEnabled; + dynamic basepriceAmount; + dynamic basepriceBaseAmount; + bool hasTierPrices; + bool hasDiscountsApplied; + dynamic discountName; + dynamic discountNamen; + dynamic discountDescription; + dynamic discountDescriptionn; + dynamic discountPercentage; + dynamic currency; + dynamic currencyn; + double weight; + dynamic length; + dynamic width; + dynamic height; + dynamic availableStartDateTimeUtc; + dynamic availableEndDateTimeUtc; + dynamic displayOrder; + bool published; + bool deleted; + DateTime createdOnUtc; + DateTime updatedOnUtc; + ProductType productType; + dynamic parentGroupedProductId; + dynamic roleIds; + dynamic discountIds; + dynamic storeIds; + dynamic manufacturerIds; + List reviews; + List images; + dynamic attributes; + dynamic specifications; + dynamic associatedProductIds; + List tags; + dynamic vendorId; + String seName; + + factory Product.fromJson(Map json) => Product( + id: json["id"], + visibleIndividually: json["visible_individually"], + name: json["name"], + namen: json["namen"], + localizedNames: json["localized_names"], + shortDescription: json["short_description"] == null ? null : json["short_description"], + shortDescriptionn: json["short_descriptionn"] == null ? null : json["short_descriptionn"], + fullDescription: json["full_description"], + fullDescriptionn: json["full_descriptionn"], + markasNew: json["markas_new"], + showOnHomePage: json["show_on_home_page"], + metaKeywords: json["meta_keywords"] == null ? null : json["meta_keywords"], + metaDescription: json["meta_description"] == null ? null : json["meta_description"], + metaTitle: json["meta_title"] == null ? null : json["meta_title"], + allowCustomerReviews: json["allow_customer_reviews"], + approvedRatingSum: json["approved_rating_sum"], + notApprovedRatingSum: json["not_approved_rating_sum"], + approvedTotalReviews: json["approved_total_reviews"], + notApprovedTotalReviews: json["not_approved_total_reviews"], + sku: json["sku"], + isRx: json["is_rx"], + prescriptionRequired: json["prescription_required"], + rxMessage: json["rx_message"], + rxMessagen: json["rx_messagen"], + manufacturerPartNumber: json["manufacturer_part_number"], + gtin: json["gtin"], + isGiftCard: json["is_gift_card"], + requireOtherProducts: json["require_other_products"], + automaticallyAddRequiredProducts: json["automatically_add_required_products"], + isDownload: json["is_download"], + unlimitedDownloads: json["unlimited_downloads"], + maxNumberOfDownloads: json["max_number_of_downloads"], + downloadExpirationDays: json["download_expiration_days"], + hasSampleDownload: json["has_sample_download"], + hasUserAgreement: json["has_user_agreement"], + isRecurring: json["is_recurring"], + recurringCycleLength: json["recurring_cycle_length"], + recurringTotalCycles: json["recurring_total_cycles"], + isRental: json["is_rental"], + rentalPriceLength: json["rental_price_length"], + isShipEnabled: json["is_ship_enabled"], + isFreeShipping: json["is_free_shipping"], + shipSeparately: json["ship_separately"], + additionalShippingCharge: json["additional_shipping_charge"], + isTaxExempt: json["is_tax_exempt"], + isTelecommunicationsOrBroadcastingOrElectronicServices: json["is_telecommunications_or_broadcasting_or_electronic_services"], + useMultipleWarehouses: json["use_multiple_warehouses"], + manageInventoryMethodId: json["manage_inventory_method_id"], + stockQuantity: json["stock_quantity"], + stockAvailability: json["stock_availability"], + stockAvailabilityn: json["stock_availabilityn"], + displayStockAvailability: json["display_stock_availability"], + displayStockQuantity: json["display_stock_quantity"], + minStockQuantity: json["min_stock_quantity"], + notifyAdminForQuantityBelow: json["notify_admin_for_quantity_below"], + allowBackInStockSubscriptions: json["allow_back_in_stock_subscriptions"], + orderMinimumQuantity: json["order_minimum_quantity"], + orderMaximumQuantity: json["order_maximum_quantity"], + allowedQuantities: json["allowed_quantities"], + allowAddingOnlyExistingAttributeCombinations: json["allow_adding_only_existing_attribute_combinations"], + disableBuyButton: json["disable_buy_button"], + disableWishlistButton: json["disable_wishlist_button"], + availableForPreOrder: json["available_for_pre_order"], + preOrderAvailabilityStartDateTimeUtc: json["pre_order_availability_start_date_time_utc"], + callForPrice: json["call_for_price"], + price: json["price"].toDouble(), + oldPrice: json["old_price"], + productCost: json["product_cost"].toDouble(), + specialPrice: json["special_price"], + specialPriceStartDateTimeUtc: json["special_price_start_date_time_utc"], + specialPriceEndDateTimeUtc: json["special_price_end_date_time_utc"], + customerEntersPrice: json["customer_enters_price"], + minimumCustomerEnteredPrice: json["minimum_customer_entered_price"], + maximumCustomerEnteredPrice: json["maximum_customer_entered_price"], + basepriceEnabled: json["baseprice_enabled"], + basepriceAmount: json["baseprice_amount"], + basepriceBaseAmount: json["baseprice_base_amount"], + hasTierPrices: json["has_tier_prices"], + hasDiscountsApplied: json["has_discounts_applied"], + discountName: json["discount_name"], + discountNamen: json["discount_namen"], + discountDescription: json["discount_description"], + discountDescriptionn: json["discount_Descriptionn"], + discountPercentage: json["discount_percentage"], + currency: json["currency"], + currencyn: json["currencyn"], + weight: json["weight"].toDouble(), + length: json["length"], + width: json["width"], + height: json["height"], + availableStartDateTimeUtc: json["available_start_date_time_utc"], + availableEndDateTimeUtc: json["available_end_date_time_utc"], + displayOrder: json["display_order"], + published: json["published"], + deleted: json["deleted"], + createdOnUtc: DateTime.parse(json["created_on_utc"]), + updatedOnUtc: DateTime.parse(json["updated_on_utc"]), + productType: productTypeValues.map[json["product_type"]], + parentGroupedProductId: json["parent_grouped_product_id"], + roleIds: json["role_ids"], + discountIds: json["discount_ids"], + storeIds: json["store_ids"], + manufacturerIds: json["manufacturer_ids"], + reviews: List.from(json["reviews"].map((x) => Review.fromJson(x))), + images: List.from(json["images"].map((x) => PharmacyImageObject.fromJson(x))), + attributes: json["attributes"], + specifications: json["specifications"], + associatedProductIds: json["associated_product_ids"], + tags: List.from(json["tags"].map((x) => x)), + vendorId: json["vendor_id"], + seName: json["se_name"], + ); + + Map toJson() => { + "id": id, + "visible_individually": visibleIndividually, + "name": name, + "namen": namen, + "localized_names": localizedNames, + "short_description": shortDescription == null ? null : shortDescription, + "short_descriptionn": shortDescriptionn == null ? null : shortDescriptionn, + "full_description": fullDescription, + "full_descriptionn": fullDescriptionn, + "markas_new": markasNew, + "show_on_home_page": showOnHomePage, + "meta_keywords": metaKeywords == null ? null : metaKeywords, + "meta_description": metaDescription == null ? null : metaDescription, + "meta_title": metaTitle == null ? null : metaTitle, + "allow_customer_reviews": allowCustomerReviews, + "approved_rating_sum": approvedRatingSum, + "not_approved_rating_sum": notApprovedRatingSum, + "approved_total_reviews": approvedTotalReviews, + "not_approved_total_reviews": notApprovedTotalReviews, + "sku": sku, + "is_rx": isRx, + "prescription_required": prescriptionRequired, + "rx_message": rxMessage, + "rx_messagen": rxMessagen, + "manufacturer_part_number": manufacturerPartNumber, + "gtin": gtin, + "is_gift_card": isGiftCard, + "require_other_products": requireOtherProducts, + "automatically_add_required_products": automaticallyAddRequiredProducts, + "is_download": isDownload, + "unlimited_downloads": unlimitedDownloads, + "max_number_of_downloads": maxNumberOfDownloads, + "download_expiration_days": downloadExpirationDays, + "has_sample_download": hasSampleDownload, + "has_user_agreement": hasUserAgreement, + "is_recurring": isRecurring, + "recurring_cycle_length": recurringCycleLength, + "recurring_total_cycles": recurringTotalCycles, + "is_rental": isRental, + "rental_price_length": rentalPriceLength, + "is_ship_enabled": isShipEnabled, + "is_free_shipping": isFreeShipping, + "ship_separately": shipSeparately, + "additional_shipping_charge": additionalShippingCharge, + "is_tax_exempt": isTaxExempt, + "is_telecommunications_or_broadcasting_or_electronic_services": isTelecommunicationsOrBroadcastingOrElectronicServices, + "use_multiple_warehouses": useMultipleWarehouses, + "manage_inventory_method_id": manageInventoryMethodId, + "stock_quantity": stockQuantity, + "stock_availability": stockAvailability, + "stock_availabilityn": stockAvailabilityn, + "display_stock_availability": displayStockAvailability, + "display_stock_quantity": displayStockQuantity, + "min_stock_quantity": minStockQuantity, + "notify_admin_for_quantity_below": notifyAdminForQuantityBelow, + "allow_back_in_stock_subscriptions": allowBackInStockSubscriptions, + "order_minimum_quantity": orderMinimumQuantity, + "order_maximum_quantity": orderMaximumQuantity, + "allowed_quantities": allowedQuantities, + "allow_adding_only_existing_attribute_combinations": allowAddingOnlyExistingAttributeCombinations, + "disable_buy_button": disableBuyButton, + "disable_wishlist_button": disableWishlistButton, + "available_for_pre_order": availableForPreOrder, + "pre_order_availability_start_date_time_utc": preOrderAvailabilityStartDateTimeUtc, + "call_for_price": callForPrice, + "price": price, + "old_price": oldPrice, + "product_cost": productCost, + "special_price": specialPrice, + "special_price_start_date_time_utc": specialPriceStartDateTimeUtc, + "special_price_end_date_time_utc": specialPriceEndDateTimeUtc, + "customer_enters_price": customerEntersPrice, + "minimum_customer_entered_price": minimumCustomerEnteredPrice, + "maximum_customer_entered_price": maximumCustomerEnteredPrice, + "baseprice_enabled": basepriceEnabled, + "baseprice_amount": basepriceAmount, + "baseprice_base_amount": basepriceBaseAmount, + "has_tier_prices": hasTierPrices, + "has_discounts_applied": hasDiscountsApplied, + "discount_name": discountName, + "discount_namen": discountNamen, + "discount_description": discountDescription, + "discount_Descriptionn": discountDescriptionn, + "discount_percentage": discountPercentage, + "currency": currency, + "currencyn": currencyn, + "weight": weight, + "length": length, + "width": width, + "height": height, + "available_start_date_time_utc": availableStartDateTimeUtc, + "available_end_date_time_utc": availableEndDateTimeUtc, + "display_order": displayOrder, + "published": published, + "deleted": deleted, + "created_on_utc": createdOnUtc.toIso8601String(), + "updated_on_utc": updatedOnUtc.toIso8601String(), + "product_type": productTypeValues.reverse[productType], + "parent_grouped_product_id": parentGroupedProductId, + "role_ids": roleIds, + "discount_ids": discountIds, + "store_ids": storeIds, + "manufacturer_ids": manufacturerIds, + "reviews": List.from(reviews.map((x) => x.toJson())), + "images": List.from(images.map((x) => x.toJson())), + "attributes": attributes, + "specifications": specifications, + "associated_product_ids": associatedProductIds, + "tags": List.from(tags.map((x) => x)), + "vendor_id": vendorId, + "se_name": seName, + }; +} + +enum ProductType { SIMPLE_PRODUCT } + +final productTypeValues = EnumValues({ + "SimpleProduct": ProductType.SIMPLE_PRODUCT +}); + +class Review { + Review({ + this.id, + this.position, + this.reviewId, + this.customerId, + this.productId, + this.storeId, + this.isApproved, + this.title, + this.reviewText, + this.replyText, + this.rating, + this.helpfulYesTotal, + this.helpfulNoTotal, + this.createdOnUtc, + this.customer, + this.product, + }); + + dynamic id; + dynamic position; + dynamic reviewId; + dynamic customerId; + dynamic productId; + dynamic storeId; + bool isApproved; + Title title; + ReviewText reviewText; + dynamic replyText; + dynamic rating; + dynamic helpfulYesTotal; + dynamic helpfulNoTotal; + DateTime createdOnUtc; + ReviewCustomer customer; + dynamic product; + + factory Review.fromJson(Map json) => Review( + id: json["id"], + position: json["position"], + reviewId: json["review_id"], + customerId: json["customer_id"], + productId: json["product_id"], + storeId: json["store_id"], + isApproved: json["is_approved"], + title: titleValues.map[json["title"]], + reviewText: reviewTextValues.map[json["review_text"]], + replyText: json["reply_text"], + rating: json["rating"], + helpfulYesTotal: json["helpful_yes_total"], + helpfulNoTotal: json["helpful_no_total"], + createdOnUtc: DateTime.parse(json["created_on_utc"]), + customer: ReviewCustomer.fromJson(json["customer"]), + product: json["product"], + ); + + Map toJson() => { + "id": id, + "position": position, + "review_id": reviewId, + "customer_id": customerId, + "product_id": productId, + "store_id": storeId, + "is_approved": isApproved, + "title": titleValues.reverse[title], + "review_text": reviewTextValues.reverse[reviewText], + "reply_text": replyText, + "rating": rating, + "helpful_yes_total": helpfulYesTotal, + "helpful_no_total": helpfulNoTotal, + "created_on_utc": createdOnUtc.toIso8601String(), + "customer": customer.toJson(), + "product": product, + }; +} + +class ReviewCustomer { + ReviewCustomer({ + this.fileNumber, + this.iqamaNumber, + this.isOutSa, + this.patientType, + this.gender, + this.birthDate, + this.phone, + this.countryCode, + this.yahalaAccountno, + this.billingAddress, + this.shippingAddress, + this.addresses, + this.id, + this.username, + this.email, + this.firstName, + this.lastName, + this.languageId, + this.adminComment, + this.isTaxExempt, + this.hasShoppingCartItems, + this.active, + this.deleted, + this.isSystemAccount, + this.systemName, + this.lastIpAddress, + this.createdOnUtc, + this.lastLoginDateUtc, + this.lastActivityDateUtc, + this.registeredInStoreId, + this.roleIds, + }); + + dynamic fileNumber; + dynamic iqamaNumber; + dynamic isOutSa; + dynamic patientType; + dynamic gender; + DateTime birthDate; + dynamic phone; + dynamic countryCode; + dynamic yahalaAccountno; + dynamic billingAddress; + dynamic shippingAddress; + List addresses; + String id; + String username; + PurpleEmail email; + dynamic firstName; + dynamic lastName; + dynamic languageId; + dynamic adminComment; + dynamic isTaxExempt; + dynamic hasShoppingCartItems; + dynamic active; + dynamic deleted; + dynamic isSystemAccount; + dynamic systemName; + dynamic lastIpAddress; + dynamic createdOnUtc; + dynamic lastLoginDateUtc; + dynamic lastActivityDateUtc; + dynamic registeredInStoreId; + List roleIds; + + factory ReviewCustomer.fromJson(Map json) => ReviewCustomer( + fileNumber: json["file_number"], + iqamaNumber: json["iqama_number"], + isOutSa: json["is_out_sa"], + patientType: json["patient_type"], + gender: json["gender"], + birthDate: DateTime.parse(json["birth_date"]), + phone: json["phone"], + countryCode: json["country_code"], + yahalaAccountno: json["yahala_accountno"], + billingAddress: json["billing_address"], + shippingAddress: json["shipping_address"], + addresses: List.from(json["addresses"].map((x) => x)), + id: json["id"], + username: json["username"], + email: purpleEmailValues.map[json["email"]], + firstName: json["first_name"], + lastName: json["last_name"], + languageId: json["language_id"], + adminComment: json["admin_comment"], + isTaxExempt: json["is_tax_exempt"], + hasShoppingCartItems: json["has_shopping_cart_items"], + active: json["active"], + deleted: json["deleted"], + isSystemAccount: json["is_system_account"], + systemName: json["system_name"], + lastIpAddress: json["last_ip_address"], + createdOnUtc: json["created_on_utc"], + lastLoginDateUtc: json["last_login_date_utc"], + lastActivityDateUtc: json["last_activity_date_utc"], + registeredInStoreId: json["registered_in_store_id"], + roleIds: List.from(json["role_ids"].map((x) => x)), + ); + + Map toJson() => { + "file_number": fileNumber, + "iqama_number": iqamaNumber, + "is_out_sa": isOutSa, + "patient_type": patientType, + "gender": gender, + "birth_date": birthDate.toIso8601String(), + "phone": phone, + "country_code": countryCode, + "yahala_accountno": yahalaAccountno, + "billing_address": billingAddress, + "shipping_address": shippingAddress, + "addresses": List.from(addresses.map((x) => x)), + "id": id, + "username": username, + "email": purpleEmailValues.reverse[email], + "first_name": firstName, + "last_name": lastName, + "language_id": languageId, + "admin_comment": adminComment, + "is_tax_exempt": isTaxExempt, + "has_shopping_cart_items": hasShoppingCartItems, + "active": active, + "deleted": deleted, + "is_system_account": isSystemAccount, + "system_name": systemName, + "last_ip_address": lastIpAddress, + "created_on_utc": createdOnUtc, + "last_login_date_utc": lastLoginDateUtc, + "last_activity_date_utc": lastActivityDateUtc, + "registered_in_store_id": registeredInStoreId, + "role_ids": List.from(roleIds.map((x) => x)), + }; +} + +enum PurpleEmail { STEVE_GATES_NOP_COMMERCE_COM, TAMER_FANASHEH_DRSULAIMANALHABIB_COM, ASIF_RAZA_DRSULAIMANALHABIB_COM, ABOSAMI_YMAIL_COM } + +final purpleEmailValues = EnumValues({ + "abosami@ymail.com": PurpleEmail.ABOSAMI_YMAIL_COM, + "asif.raza@drsulaimanalhabib.com": PurpleEmail.ASIF_RAZA_DRSULAIMANALHABIB_COM, + "steve_gates@nopCommerce.com": PurpleEmail.STEVE_GATES_NOP_COMMERCE_COM, + "tamer.fanasheh@drsulaimanalhabib.com": PurpleEmail.TAMER_FANASHEH_DRSULAIMANALHABIB_COM +}); + +enum ReviewText { GOOD, NICE_PRICE, GREAT, REVIEW_TEXT_GOOD, GG, ENAD_TEST_REVIEW_001, ENAD, ENADDD, ENAD_TEST_0001, PURPLE_GOOD, EMPTY } + +final reviewTextValues = EnumValues({ + "افضل علاج للزكام": ReviewText.EMPTY, + "ENAD ": ReviewText.ENAD, + "enaddd": ReviewText.ENADDD, + "ENAD TEST 0001": ReviewText.ENAD_TEST_0001, + "Enad Test Review 001": ReviewText.ENAD_TEST_REVIEW_001, + "gg": ReviewText.GG, + "good ": ReviewText.GOOD, + "great": ReviewText.GREAT, + "nice price": ReviewText.NICE_PRICE, + "Good": ReviewText.PURPLE_GOOD, + "good": ReviewText.REVIEW_TEXT_GOOD +}); + +enum Title { EMPTY, GOOD, TITLE } + +final titleValues = EnumValues({ + "": Title.EMPTY, + "Good": Title.GOOD, + "ممتاز": Title.TITLE +}); + +enum OrderStatus { ORDER_SUBMITTED, PENDING, ORDER_IN_PROGRESS, ORDER_COMPLETED, CANCELLED, PROCESSING, ORDER_REFUNDED, COMPLETE } + +final orderStatusValues = EnumValues({ + "Cancelled": OrderStatus.CANCELLED, + "Complete": OrderStatus.COMPLETE, + "OrderCompleted": OrderStatus.ORDER_COMPLETED, + "OrderInProgress": OrderStatus.ORDER_IN_PROGRESS, + "OrderRefunded": OrderStatus.ORDER_REFUNDED, + "OrderSubmitted": OrderStatus.ORDER_SUBMITTED, + "Pending": OrderStatus.PENDING, + "Processing": OrderStatus.PROCESSING +}); + +enum OrderStatusn { ORDER_SUBMITTED, EMPTY, ORDER_IN_PROGRESS, ORDER_COMPLETED, ORDER_STATUSN, PURPLE, FLUFFY, TENTACLED } + +final orderStatusnValues = EnumValues({ + "معلقة": OrderStatusn.EMPTY, + "تم ارجاع مبلغ الطلبية المدفوع للعميل": OrderStatusn.FLUFFY, + "Order Completed": OrderStatusn.ORDER_COMPLETED, + "Order In Progress": OrderStatusn.ORDER_IN_PROGRESS, + "ملغي": OrderStatusn.ORDER_STATUSN, + "Order Submitted": OrderStatusn.ORDER_SUBMITTED, + "قيد التنفيذ": OrderStatusn.PURPLE, + "مكتمل": OrderStatusn.TENTACLED +}); + +enum PaymentMethodSystemName { PAYMENTS_PAY_FORT, PAYMENTS_CASH_ON_DELIVERY } + +final paymentMethodSystemNameValues = EnumValues({ + "Payments.CashOnDelivery": PaymentMethodSystemName.PAYMENTS_CASH_ON_DELIVERY, + "Payments.PayFort": PaymentMethodSystemName.PAYMENTS_PAY_FORT +}); + +enum PaymentName { CREDIT_DEBIT_CARD_PAYFORT, CASH_ON_DELIVERY_COD } + +final paymentNameValues = EnumValues({ + "Cash On Delivery (COD)": PaymentName.CASH_ON_DELIVERY_COD, + "Credit / Debit Card Payfort": PaymentName.CREDIT_DEBIT_CARD_PAYFORT +}); + +enum PaymentStatus { PAID, PENDING } + +final paymentStatusValues = EnumValues({ + "Paid": PaymentStatus.PAID, + "Pending": PaymentStatus.PENDING +}); + +enum PaymentStatusn { EMPTY, PAYMENT_STATUSN } + +final paymentStatusnValues = EnumValues({ + "تم الدفع": PaymentStatusn.EMPTY, + "قيد الإنتظار": PaymentStatusn.PAYMENT_STATUSN +}); + +enum PreferDeliveryTime { THE_1000_AM_330_PM, THE_530_PM_730_PM } + +final preferDeliveryTimeValues = EnumValues({ + "10:00 AM - 3:30 PM": PreferDeliveryTime.THE_1000_AM_330_PM, + "5:30 PM - 7:30 PM": PreferDeliveryTime.THE_530_PM_730_PM +}); + +enum PreferDeliveryTimen { THE_1000330, THE_530730 } + +final preferDeliveryTimenValues = EnumValues({ + "10:00 ص - 3:30 م": PreferDeliveryTimen.THE_1000330, + "5:30 م - 7:30 م": PreferDeliveryTimen.THE_530730 +}); + +enum ShippingMethod { EMPTY, FIXED_PRICE } + +final shippingMethodValues = EnumValues({ + "سعر ثابت ": ShippingMethod.EMPTY, + "Fixed Price": ShippingMethod.FIXED_PRICE +}); + +enum ShippingRateComputationMethodSystemName { SHIPPING_FIXED_OR_BY_WEIGHT } + +final shippingRateComputationMethodSystemNameValues = EnumValues({ + "Shipping.FixedOrByWeight": ShippingRateComputationMethodSystemName.SHIPPING_FIXED_OR_BY_WEIGHT +}); + +enum ShippingStatus { NOT_YET_SHIPPED } + +final shippingStatusValues = EnumValues({ + "NotYetShipped": ShippingStatus.NOT_YET_SHIPPED +}); + +enum ShippingStatusn { EMPTY } + +final shippingStatusnValues = EnumValues({ + "لم يتم شحنها بعد": ShippingStatusn.EMPTY +}); + +class EnumValues { + Map map; + Map reverseMap; + + EnumValues(this.map); + + Map get reverse { + if (reverseMap == null) { + reverseMap = map.map((k, v) => new MapEntry(v, k)); + } + return reverseMap; + } +} + + + diff --git a/lib/core/model/pharmacies/payment-checkout-data.dart b/lib/core/model/pharmacies/payment-checkout-data.dart new file mode 100644 index 00000000..dd9e0e54 --- /dev/null +++ b/lib/core/model/pharmacies/payment-checkout-data.dart @@ -0,0 +1,21 @@ +import 'package:diplomaticquarterapp/core/model/pharmacies/Addresses.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/LacumAccountInformation.dart'; +import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/OrderPreviewViewModel.dart'; +import 'package:flutter/material.dart'; + +import 'ShippingOption.dart'; + +class PaymentCheckoutData with ChangeNotifier{ + Addresses address; + PaymentOption paymentOption; + LacumAccountInformation lacumInformation; + bool cartDataVisible; + ShippingOption shippingOption; + int usedLakumPoints; + + PaymentCheckoutData({this.address, this.paymentOption, this.lacumInformation, this.cartDataVisible = false, this.shippingOption, this.usedLakumPoints = 0}); + + void updateData() { + notifyListeners(); + } +} diff --git a/lib/core/model/pharmacies/pharmacies_list_model.dart b/lib/core/model/pharmacies/pharmacies_list_model.dart index a10389b5..01a43a0a 100644 --- a/lib/core/model/pharmacies/pharmacies_list_model.dart +++ b/lib/core/model/pharmacies/pharmacies_list_model.dart @@ -4,7 +4,7 @@ class PharmaciesListModel { int languageID; String stamp; String iPAdress; - dynamic versionID; + double versionID; String tokenID; String sessionID; bool isLoginForDoctorApp; @@ -14,7 +14,7 @@ class PharmaciesListModel { int editedBy; int projectID; int clinicID; - dynamic price; + double price; String imageLocation; String desLocation; String itemDes; diff --git a/lib/core/model/pharmacy/brands_model.dart b/lib/core/model/pharmacy/brands_model.dart new file mode 100644 index 00000000..03cd689e --- /dev/null +++ b/lib/core/model/pharmacy/brands_model.dart @@ -0,0 +1,24 @@ +class BrandsModel { + String id; + String name; + String namen; + Null image; + + BrandsModel({this.id, this.name, this.namen, this.image}); + + BrandsModel.fromJson(Map json) { + id = json['id']; + name = json['name']; + namen = json['namen']; + image = json['image']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['name'] = this.name; + data['namen'] = this.namen; + data['image'] = this.image; + return data; + } +} diff --git a/lib/core/model/pharmacy/categorise_parent_model.dart b/lib/core/model/pharmacy/categorise_parent_model.dart new file mode 100644 index 00000000..82c5b55f --- /dev/null +++ b/lib/core/model/pharmacy/categorise_parent_model.dart @@ -0,0 +1,75 @@ +class CategoriseParentModel { + String id; + String name; + String namen; + List localizedNames; + dynamic description; + int parentCategoryId; + int displayOrder; + dynamic image; + bool isLeaf; + + CategoriseParentModel( + {this.id, + this.name, + this.namen, + this.localizedNames, + this.description, + this.parentCategoryId, + this.displayOrder, + this.image, + this.isLeaf}); + + CategoriseParentModel.fromJson(Map json) { + id = json['id']; + name = json['name']; + namen = json['namen']; + if (json['localized_names'] != null) { + localizedNames = new List(); + json['localized_names'].forEach((v) { + localizedNames.add(new LocalizedNames.fromJson(v)); + }); + } + description = json['description']; + parentCategoryId = json['parent_category_id']; + displayOrder = json['display_order']; + image = json['image']; + isLeaf = json['is_leaf']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['name'] = this.name; + data['namen'] = this.namen; + if (this.localizedNames != null) { + data['localized_names'] = + this.localizedNames.map((v) => v.toJson()).toList(); + } + data['description'] = this.description; + data['parent_category_id'] = this.parentCategoryId; + data['display_order'] = this.displayOrder; + data['image'] = this.image; + data['is_leaf'] = this.isLeaf; + return data; + } +} + +class LocalizedNames { + int languageId; + String localizedName; + + LocalizedNames({this.languageId, this.localizedName}); + + LocalizedNames.fromJson(Map json) { + languageId = json['language_id']; + localizedName = json['localized_name']; + } + + Map toJson() { + final Map data = new Map(); + data['language_id'] = this.languageId; + data['localized_name'] = this.localizedName; + return data; + } +} diff --git a/lib/core/model/pharmacy/final_products_model.dart b/lib/core/model/pharmacy/final_products_model.dart new file mode 100644 index 00000000..52ab1d2d --- /dev/null +++ b/lib/core/model/pharmacy/final_products_model.dart @@ -0,0 +1,184 @@ +class FinalProductsModel { + String id; + String name; + String namen; + List localizedNames; + String shortDescription; + String fullDescription; + String fullDescriptionn; + dynamic approvedRatingSum; + dynamic approvedTotalReviews; + String sku; + bool isRx; + dynamic rxMessage; + dynamic rxMessagen; + dynamic stockQuantity; + String stockAvailability; + String stockAvailabilityn; + bool allowBackInStockSubscriptions; + dynamic orderMinimumQuantity; + dynamic orderMaximumQuantity; + dynamic price; + dynamic oldPrice; + dynamic discountName; + dynamic discountNamen; + dynamic discountPercentage; + dynamic displayOrder; + List discountIds; + List reviews; + List images; + + FinalProductsModel( + {this.id, + this.name, + this.namen, + this.localizedNames, + this.shortDescription, + this.fullDescription, + this.fullDescriptionn, + this.approvedRatingSum, + this.approvedTotalReviews, + this.sku, + this.isRx, + this.rxMessage, + this.rxMessagen, + this.stockQuantity, + this.stockAvailability, + this.stockAvailabilityn, + this.allowBackInStockSubscriptions, + this.orderMinimumQuantity, + this.orderMaximumQuantity, + this.price, + this.oldPrice, + this.discountName, + this.discountNamen, + this.discountPercentage, + this.displayOrder, + this.discountIds, + this.reviews, + this.images}); + + FinalProductsModel.fromJson(Map json) { + id = json['id']; + name = json['name']; + if (json['images'] != null) { + images = new List(); + json['images'].forEach((v) { + images.add(new Images.fromJson(v)); + }); + } + namen = json['namen']; + if (json['localized_names'] != null) { + localizedNames = new List(); + json['localized_names'].forEach((v) { + localizedNames.add(new LocalizedNames.fromJson(v)); + }); + } + shortDescription = json['short_description']; + fullDescription = json['full_description']; + fullDescriptionn = json['full_descriptionn']; + approvedRatingSum = json['approved_rating_sum']; + approvedTotalReviews = json['approved_total_reviews']; + sku = json['sku']; + isRx = json['is_rx']; + rxMessage = json['rx_message']; + rxMessagen = json['rx_messagen']; + stockQuantity = json['stock_quantity']; + stockAvailability = json['stock_availability']; + stockAvailabilityn = json['stock_availabilityn']; + allowBackInStockSubscriptions = json['allow_back_in_stock_subscriptions']; + orderMinimumQuantity = json['order_minimum_quantity']; + orderMaximumQuantity = json['order_maximum_quantity']; + price = json['price']; + oldPrice = json['old_price']; + discountName = json['discount_name']; + discountNamen = json['discount_namen']; + discountPercentage = json['discount_percentage']; + displayOrder = json['display_order']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['name'] = this.name; + data['namen'] = this.namen; + if (this.localizedNames != null) { + data['localized_names'] = + this.localizedNames.map((v) => v.toJson()).toList(); + } + data['short_description'] = this.shortDescription; + data['full_description'] = this.fullDescription; + data['full_descriptionn'] = this.fullDescriptionn; + data['approved_rating_sum'] = this.approvedRatingSum; + data['approved_total_reviews'] = this.approvedTotalReviews; + data['sku'] = this.sku; + data['is_rx'] = this.isRx; + data['rx_message'] = this.rxMessage; + data['rx_messagen'] = this.rxMessagen; + data['stock_quantity'] = this.stockQuantity; + data['stock_availability'] = this.stockAvailability; + data['stock_availabilityn'] = this.stockAvailabilityn; + data['allow_back_in_stock_subscriptions'] = + this.allowBackInStockSubscriptions; + data['order_minimum_quantity'] = this.orderMinimumQuantity; + data['order_maximum_quantity'] = this.orderMaximumQuantity; + data['price'] = this.price; + data['old_price'] = this.oldPrice; + data['discount_name'] = this.discountName; + data['discount_namen'] = this.discountNamen; + data['discount_percentage'] = this.discountPercentage; + data['display_order'] = this.displayOrder; + + if (this.images != null) { + data['images'] = this.images.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class LocalizedNames { + int languageId; + String localizedName; + + LocalizedNames({this.languageId, this.localizedName}); + + LocalizedNames.fromJson(Map json) { + languageId = json['language_id']; + localizedName = json['localized_name']; + } + + Map toJson() { + final Map data = new Map(); + data['language_id'] = this.languageId; + data['localized_name'] = this.localizedName; + return data; + } +} + +class Images { + int id; + int position; + String src; + String thumb; + String attachment; + + Images({this.id, this.position, this.src, this.thumb, this.attachment}); + + Images.fromJson(Map json) { + id = json['id']; + position = json['position']; + src = json['src']; + thumb = json['thumb']; + attachment = json['attachment']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['position'] = this.position; + data['src'] = this.src; + data['thumb'] = this.thumb; + data['attachment'] = this.attachment; + return data; + } +} diff --git a/lib/core/model/pharmacy/offer_products_model.dart b/lib/core/model/pharmacy/offer_products_model.dart new file mode 100644 index 00000000..f41b731b --- /dev/null +++ b/lib/core/model/pharmacy/offer_products_model.dart @@ -0,0 +1,579 @@ +class OfferProductsModel { + String id; + bool visibleIndividually; + String name; + String namen; + List localizedNames; + String shortDescription; + String shortDescriptionn; + String fullDescription; + String fullDescriptionn; + bool markasNew; + bool showOnHomePage; + dynamic metaKeywords; + dynamic metaDescription; + dynamic metaTitle; + bool allowCustomerReviews; + dynamic approvedRatingSum; + dynamic notApprovedRatingSum; + dynamic approvedTotalReviews; + dynamic notApprovedTotalReviews; + String sku; + bool isRx; + bool prescriptionRequired; + dynamic rxMessage; + dynamic rxMessagen; + dynamic manufacturerPartNumber; + dynamic gtin; + bool isGiftCard; + bool requireOtherProducts; + bool automaticallyAddRequiredProducts; + bool isDownload; + bool unlimitedDownloads; + dynamic maxNumberOfDownloads; + dynamic downloadExpirationDays; + bool hasSampleDownload; + bool hasUserAgreement; + bool isRecurring; + dynamic recurringCycleLength; + dynamic recurringTotalCycles; + bool isRental; + dynamic rentalPriceLength; + bool isShipEnabled; + bool isFreeShipping; + bool shipSeparately; + dynamic additionalShippingCharge; + bool isTaxExempt; + bool isTelecommunicationsOrBroadcastingOrElectronicServices; + bool useMultipleWarehouses; + dynamic manageInventoryMethodId; + dynamic stockQuantity; + String stockAvailability; + String stockAvailabilityn; + bool displayStockAvailability; + bool displayStockQuantity; + dynamic minStockQuantity; + dynamic notifyAdminForQuantityBelow; + bool allowBackInStockSubscriptions; + dynamic orderMinimumQuantity; + dynamic orderMaximumQuantity; + dynamic allowedQuantities; + bool allowAddingOnlyExistingAttributeCombinations; + bool disableBuyButton; + bool disableWishlistButton; + bool availableForPreOrder; + dynamic preOrderAvailabilityStartDateTimeUtc; + bool callForPrice; + dynamic price; + dynamic oldPrice; + dynamic productCost; + dynamic specialPrice; + dynamic specialPriceStartDateTimeUtc; + dynamic specialPriceEndDateTimeUtc; + bool customerEntersPrice; + dynamic minimumCustomerEnteredPrice; + dynamic maximumCustomerEnteredPrice; + bool basepriceEnabled; + dynamic basepriceAmount; + dynamic basepriceBaseAmount; + bool hasTierPrices; + bool hasDiscountsApplied; + String discountName; + String discountNamen; + String discountDescription; + String discountDescriptionn; + dynamic discountPercentage; + String currency; + String currencyn; + dynamic weight; + dynamic length; + dynamic width; + dynamic height; + dynamic availableStartDateTimeUtc; + dynamic availableEndDateTimeUtc; + dynamic displayOrder; + bool published; + bool deleted; + String createdOnUtc; + String updatedOnUtc; + String productType; + dynamic parentGroupedProductId; + List roleIds; + List discountIds; + List storeIds; + List manufacturerIds; + List reviews; + List images; + List attributes; + List specifications; + List associatedProductIds; + List tags; + dynamic vendorId; + String seName; + + OfferProductsModel( + {this.id, + this.visibleIndividually, + this.name, + this.namen, + this.localizedNames, + this.shortDescription, + this.shortDescriptionn, + this.fullDescription, + this.fullDescriptionn, + this.markasNew, + this.showOnHomePage, + this.metaKeywords, + this.metaDescription, + this.metaTitle, + this.allowCustomerReviews, + this.approvedRatingSum, + this.notApprovedRatingSum, + this.approvedTotalReviews, + this.notApprovedTotalReviews, + this.sku, + this.isRx, + this.prescriptionRequired, + this.rxMessage, + this.rxMessagen, + this.manufacturerPartNumber, + this.gtin, + this.isGiftCard, + this.requireOtherProducts, + this.automaticallyAddRequiredProducts, + this.isDownload, + this.unlimitedDownloads, + this.maxNumberOfDownloads, + this.downloadExpirationDays, + this.hasSampleDownload, + this.hasUserAgreement, + this.isRecurring, + this.recurringCycleLength, + this.recurringTotalCycles, + this.isRental, + this.rentalPriceLength, + this.isShipEnabled, + this.isFreeShipping, + this.shipSeparately, + this.additionalShippingCharge, + this.isTaxExempt, + this.isTelecommunicationsOrBroadcastingOrElectronicServices, + this.useMultipleWarehouses, + this.manageInventoryMethodId, + this.stockQuantity, + this.stockAvailability, + this.stockAvailabilityn, + this.displayStockAvailability, + this.displayStockQuantity, + this.minStockQuantity, + this.notifyAdminForQuantityBelow, + this.allowBackInStockSubscriptions, + this.orderMinimumQuantity, + this.orderMaximumQuantity, + this.allowedQuantities, + this.allowAddingOnlyExistingAttributeCombinations, + this.disableBuyButton, + this.disableWishlistButton, + this.availableForPreOrder, + this.preOrderAvailabilityStartDateTimeUtc, + this.callForPrice, + this.price, + this.oldPrice, + this.productCost, + this.specialPrice, + this.specialPriceStartDateTimeUtc, + this.specialPriceEndDateTimeUtc, + this.customerEntersPrice, + this.minimumCustomerEnteredPrice, + this.maximumCustomerEnteredPrice, + this.basepriceEnabled, + this.basepriceAmount, + this.basepriceBaseAmount, + this.hasTierPrices, + this.hasDiscountsApplied, + this.discountName, + this.discountNamen, + this.discountDescription, + this.discountDescriptionn, + this.discountPercentage, + this.currency, + this.currencyn, + this.weight, + this.length, + this.width, + this.height, + this.availableStartDateTimeUtc, + this.availableEndDateTimeUtc, + this.displayOrder, + this.published, + this.deleted, + this.createdOnUtc, + this.updatedOnUtc, + this.productType, + this.parentGroupedProductId, + this.roleIds, + this.discountIds, + this.storeIds, + this.manufacturerIds, + this.reviews, + this.images, + this.attributes, + this.specifications, + this.associatedProductIds, + this.tags, + this.vendorId, + this.seName}); + + OfferProductsModel.fromJson(Map json) { + id = json['id']; + visibleIndividually = json['visible_individually']; + name = json['name']; + namen = json['namen']; + if (json['localized_names'] != null) { + localizedNames = new List(); + json['localized_names'].forEach((v) { + localizedNames.add(new LocalizedNames.fromJson(v)); + }); + } + shortDescription = json['short_description']; + shortDescriptionn = json['short_descriptionn']; + fullDescription = json['full_description']; + fullDescriptionn = json['full_descriptionn']; + markasNew = json['markas_new']; + showOnHomePage = json['show_on_home_page']; + metaKeywords = json['meta_keywords']; + metaDescription = json['meta_description']; + metaTitle = json['meta_title']; + allowCustomerReviews = json['allow_customer_reviews']; + approvedRatingSum = json['approved_rating_sum']; + notApprovedRatingSum = json['not_approved_rating_sum']; + approvedTotalReviews = json['approved_total_reviews']; + notApprovedTotalReviews = json['not_approved_total_reviews']; + sku = json['sku']; + isRx = json['is_rx']; + prescriptionRequired = json['prescription_required']; + rxMessage = json['rx_message']; + rxMessagen = json['rx_messagen']; + manufacturerPartNumber = json['manufacturer_part_number']; + gtin = json['gtin']; + isGiftCard = json['is_gift_card']; + requireOtherProducts = json['require_other_products']; + automaticallyAddRequiredProducts = + json['automatically_add_required_products']; + isDownload = json['is_download']; + unlimitedDownloads = json['unlimited_downloads']; + maxNumberOfDownloads = json['max_number_of_downloads']; + downloadExpirationDays = json['download_expiration_days']; + hasSampleDownload = json['has_sample_download']; + hasUserAgreement = json['has_user_agreement']; + isRecurring = json['is_recurring']; + recurringCycleLength = json['recurring_cycle_length']; + recurringTotalCycles = json['recurring_total_cycles']; + isRental = json['is_rental']; + rentalPriceLength = json['rental_price_length']; + isShipEnabled = json['is_ship_enabled']; + isFreeShipping = json['is_free_shipping']; + shipSeparately = json['ship_separately']; + additionalShippingCharge = json['additional_shipping_charge']; + isTaxExempt = json['is_tax_exempt']; + isTelecommunicationsOrBroadcastingOrElectronicServices = + json['is_telecommunications_or_broadcasting_or_electronic_services']; + useMultipleWarehouses = json['use_multiple_warehouses']; + manageInventoryMethodId = json['manage_inventory_method_id']; + stockQuantity = json['stock_quantity']; + stockAvailability = json['stock_availability']; + stockAvailabilityn = json['stock_availabilityn']; + displayStockAvailability = json['display_stock_availability']; + displayStockQuantity = json['display_stock_quantity']; + minStockQuantity = json['min_stock_quantity']; + notifyAdminForQuantityBelow = json['notify_admin_for_quantity_below']; + allowBackInStockSubscriptions = json['allow_back_in_stock_subscriptions']; + orderMinimumQuantity = json['order_minimum_quantity']; + orderMaximumQuantity = json['order_maximum_quantity']; + allowedQuantities = json['allowed_quantities']; + allowAddingOnlyExistingAttributeCombinations = + json['allow_adding_only_existing_attribute_combinations']; + disableBuyButton = json['disable_buy_button']; + disableWishlistButton = json['disable_wishlist_button']; + availableForPreOrder = json['available_for_pre_order']; + preOrderAvailabilityStartDateTimeUtc = + json['pre_order_availability_start_date_time_utc']; + callForPrice = json['call_for_price']; + price = json['price']; + oldPrice = json['old_price']; + productCost = json['product_cost']; + specialPrice = json['special_price']; + specialPriceStartDateTimeUtc = json['special_price_start_date_time_utc']; + specialPriceEndDateTimeUtc = json['special_price_end_date_time_utc']; + customerEntersPrice = json['customer_enters_price']; + minimumCustomerEnteredPrice = json['minimum_customer_entered_price']; + maximumCustomerEnteredPrice = json['maximum_customer_entered_price']; + basepriceEnabled = json['baseprice_enabled']; + basepriceAmount = json['baseprice_amount']; + basepriceBaseAmount = json['baseprice_base_amount']; + hasTierPrices = json['has_tier_prices']; + hasDiscountsApplied = json['has_discounts_applied']; + discountName = json['discount_name']; + discountNamen = json['discount_namen']; + discountDescription = json['discount_description']; + discountDescriptionn = json['discount_Descriptionn']; + discountPercentage = json['discount_percentage']; + currency = json['currency']; + currencyn = json['currencyn']; + weight = json['weight']; + length = json['length']; + width = json['width']; + height = json['height']; + availableStartDateTimeUtc = json['available_start_date_time_utc']; + availableEndDateTimeUtc = json['available_end_date_time_utc']; + displayOrder = json['display_order']; + published = json['published']; + deleted = json['deleted']; + createdOnUtc = json['created_on_utc']; + updatedOnUtc = json['updated_on_utc']; + productType = json['product_type']; + parentGroupedProductId = json['parent_grouped_product_id']; + + discountIds = json['discount_ids'].cast(); + + if (json['images'] != null) { + images = new List(); + json['images'].forEach((v) { + images.add(new Images.fromJson(v)); + }); + } + + vendorId = json['vendor_id']; + seName = json['se_name']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['visible_individually'] = this.visibleIndividually; + data['name'] = this.name; + data['namen'] = this.namen; + if (this.localizedNames != null) { + data['localized_names'] = + this.localizedNames.map((v) => v.toJson()).toList(); + } + data['short_description'] = this.shortDescription; + data['short_descriptionn'] = this.shortDescriptionn; + data['full_description'] = this.fullDescription; + data['full_descriptionn'] = this.fullDescriptionn; + data['markas_new'] = this.markasNew; + data['show_on_home_page'] = this.showOnHomePage; + data['meta_keywords'] = this.metaKeywords; + data['meta_description'] = this.metaDescription; + data['meta_title'] = this.metaTitle; + data['allow_customer_reviews'] = this.allowCustomerReviews; + data['approved_rating_sum'] = this.approvedRatingSum; + data['not_approved_rating_sum'] = this.notApprovedRatingSum; + data['approved_total_reviews'] = this.approvedTotalReviews; + data['not_approved_total_reviews'] = this.notApprovedTotalReviews; + data['sku'] = this.sku; + data['is_rx'] = this.isRx; + data['prescription_required'] = this.prescriptionRequired; + data['rx_message'] = this.rxMessage; + data['rx_messagen'] = this.rxMessagen; + data['manufacturer_part_number'] = this.manufacturerPartNumber; + data['gtin'] = this.gtin; + data['is_gift_card'] = this.isGiftCard; + data['require_other_products'] = this.requireOtherProducts; + data['automatically_add_required_products'] = + this.automaticallyAddRequiredProducts; + data['is_download'] = this.isDownload; + data['unlimited_downloads'] = this.unlimitedDownloads; + data['max_number_of_downloads'] = this.maxNumberOfDownloads; + data['download_expiration_days'] = this.downloadExpirationDays; + data['has_sample_download'] = this.hasSampleDownload; + data['has_user_agreement'] = this.hasUserAgreement; + data['is_recurring'] = this.isRecurring; + data['recurring_cycle_length'] = this.recurringCycleLength; + data['recurring_total_cycles'] = this.recurringTotalCycles; + data['is_rental'] = this.isRental; + data['rental_price_length'] = this.rentalPriceLength; + data['is_ship_enabled'] = this.isShipEnabled; + data['is_free_shipping'] = this.isFreeShipping; + data['ship_separately'] = this.shipSeparately; + data['additional_shipping_charge'] = this.additionalShippingCharge; + data['is_tax_exempt'] = this.isTaxExempt; + data['is_telecommunications_or_broadcasting_or_electronic_services'] = + this.isTelecommunicationsOrBroadcastingOrElectronicServices; + data['use_multiple_warehouses'] = this.useMultipleWarehouses; + data['manage_inventory_method_id'] = this.manageInventoryMethodId; + data['stock_quantity'] = this.stockQuantity; + data['stock_availability'] = this.stockAvailability; + data['stock_availabilityn'] = this.stockAvailabilityn; + data['display_stock_availability'] = this.displayStockAvailability; + data['display_stock_quantity'] = this.displayStockQuantity; + data['min_stock_quantity'] = this.minStockQuantity; + data['notify_admin_for_quantity_below'] = this.notifyAdminForQuantityBelow; + data['allow_back_in_stock_subscriptions'] = + this.allowBackInStockSubscriptions; + data['order_minimum_quantity'] = this.orderMinimumQuantity; + data['order_maximum_quantity'] = this.orderMaximumQuantity; + data['allowed_quantities'] = this.allowedQuantities; + data['allow_adding_only_existing_attribute_combinations'] = + this.allowAddingOnlyExistingAttributeCombinations; + data['disable_buy_button'] = this.disableBuyButton; + data['disable_wishlist_button'] = this.disableWishlistButton; + data['available_for_pre_order'] = this.availableForPreOrder; + data['pre_order_availability_start_date_time_utc'] = + this.preOrderAvailabilityStartDateTimeUtc; + data['call_for_price'] = this.callForPrice; + data['price'] = this.price; + data['old_price'] = this.oldPrice; + data['product_cost'] = this.productCost; + data['special_price'] = this.specialPrice; + data['special_price_start_date_time_utc'] = + this.specialPriceStartDateTimeUtc; + data['special_price_end_date_time_utc'] = this.specialPriceEndDateTimeUtc; + data['customer_enters_price'] = this.customerEntersPrice; + data['minimum_customer_entered_price'] = this.minimumCustomerEnteredPrice; + data['maximum_customer_entered_price'] = this.maximumCustomerEnteredPrice; + data['baseprice_enabled'] = this.basepriceEnabled; + data['baseprice_amount'] = this.basepriceAmount; + data['baseprice_base_amount'] = this.basepriceBaseAmount; + data['has_tier_prices'] = this.hasTierPrices; + data['has_discounts_applied'] = this.hasDiscountsApplied; + data['discount_name'] = this.discountName; + data['discount_namen'] = this.discountNamen; + data['discount_description'] = this.discountDescription; + data['discount_Descriptionn'] = this.discountDescriptionn; + data['discount_percentage'] = this.discountPercentage; + data['currency'] = this.currency; + data['currencyn'] = this.currencyn; + data['weight'] = this.weight; + data['length'] = this.length; + data['width'] = this.width; + data['height'] = this.height; + data['available_start_date_time_utc'] = this.availableStartDateTimeUtc; + data['available_end_date_time_utc'] = this.availableEndDateTimeUtc; + data['display_order'] = this.displayOrder; + data['published'] = this.published; + data['deleted'] = this.deleted; + data['created_on_utc'] = this.createdOnUtc; + data['updated_on_utc'] = this.updatedOnUtc; + data['product_type'] = this.productType; + data['parent_grouped_product_id'] = this.parentGroupedProductId; + if (this.roleIds != null) { + data['role_ids'] = this.roleIds.map((v) => v.toJson()).toList(); + } + data['discount_ids'] = this.discountIds; + if (this.storeIds != null) { + data['store_ids'] = this.storeIds.map((v) => v.toJson()).toList(); + } + if (this.manufacturerIds != null) { + data['manufacturer_ids'] = + this.manufacturerIds.map((v) => v.toJson()).toList(); + } + if (this.reviews != null) { + data['reviews'] = this.reviews.map((v) => v.toJson()).toList(); + } + if (this.images != null) { + data['images'] = this.images.map((v) => v.toJson()).toList(); + } + if (this.attributes != null) { + data['attributes'] = this.attributes.map((v) => v.toJson()).toList(); + } + if (this.specifications != null) { + data['specifications'] = + this.specifications.map((v) => v.toJson()).toList(); + } + if (this.associatedProductIds != null) { + data['associated_product_ids'] = + this.associatedProductIds.map((v) => v.toJson()).toList(); + } + if (this.tags != null) { + data['tags'] = this.tags.map((v) => v.toJson()).toList(); + } + data['vendor_id'] = this.vendorId; + data['se_name'] = this.seName; + return data; + } +} + +class LocalizedNames { + int languageId; + String localizedName; + + LocalizedNames({this.languageId, this.localizedName}); + + LocalizedNames.fromJson(Map json) { + languageId = json['language_id']; + localizedName = json['localized_name']; + } + + Map toJson() { + final Map data = new Map(); + data['language_id'] = this.languageId; + data['localized_name'] = this.localizedName; + return data; + } +} + +class Images { + int id; + int position; + String src; + String thumb; + String attachment; + + Images({this.id, this.position, this.src, this.thumb, this.attachment}); + + Images.fromJson(Map json) { + id = json['id']; + position = json['position']; + src = json['src']; + thumb = json['thumb']; + attachment = json['attachment']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['position'] = this.position; + data['src'] = this.src; + data['thumb'] = this.thumb; + data['attachment'] = this.attachment; + return data; + } +} + +class Specifications { + int id; + int displayOrder; + String defaultValue; + String defaultValuen; + String name; + String nameN; + + Specifications( + {this.id, + this.displayOrder, + this.defaultValue, + this.defaultValuen, + this.name, + this.nameN}); + + Specifications.fromJson(Map json) { + id = json['id']; + displayOrder = json['display_order']; + defaultValue = json['default_value']; + defaultValuen = json['default_valuen']; + name = json['name']; + nameN = json['nameN']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['display_order'] = this.displayOrder; + data['default_value'] = this.defaultValue; + data['default_valuen'] = this.defaultValuen; + data['name'] = this.name; + data['nameN'] = this.nameN; + return data; + } +} diff --git a/lib/core/model/pharmacy/offers_model.dart b/lib/core/model/pharmacy/offers_model.dart new file mode 100644 index 00000000..3add1d3d --- /dev/null +++ b/lib/core/model/pharmacy/offers_model.dart @@ -0,0 +1,175 @@ +class OffersModel { + String id; + String name; + String namen; + List localizedNames; + Null description; + int categoryTemplateId; + String metaKeywords; + String metaDescription; + String metaTitle; + int parentCategoryId; + int pageSize; + String pageSizeOptions; + Null priceRanges; + bool showOnHomePage; + bool includeInTopMenu; + Null hasDiscountsApplied; + bool published; + bool deleted; + int displayOrder; + String createdOnUtc; + String updatedOnUtc; + List roleIds; + List discountIds; + List storeIds; + Image image; + String seName; + bool isLeaf; + + OffersModel( + {this.id, + this.name, + this.namen, + this.localizedNames, + this.description, + this.categoryTemplateId, + this.metaKeywords, + this.metaDescription, + this.metaTitle, + this.parentCategoryId, + this.pageSize, + this.pageSizeOptions, + this.priceRanges, + this.showOnHomePage, + this.includeInTopMenu, + this.hasDiscountsApplied, + this.published, + this.deleted, + this.displayOrder, + this.createdOnUtc, + this.updatedOnUtc, + this.roleIds, + this.discountIds, + this.storeIds, + this.image, + this.seName, + this.isLeaf}); + + OffersModel.fromJson(Map json) { + id = json['id']; + name = json['name']; + namen = json['namen']; + if (json['localized_names'] != null) { + localizedNames = new List(); + json['localized_names'].forEach((v) { + localizedNames.add(new LocalizedNames.fromJson(v)); + }); + } + description = json['description']; + categoryTemplateId = json['category_template_id']; + metaKeywords = json['meta_keywords']; + metaDescription = json['meta_description']; + metaTitle = json['meta_title']; + parentCategoryId = json['parent_category_id']; + pageSize = json['page_size']; + pageSizeOptions = json['page_size_options']; + priceRanges = json['price_ranges']; + showOnHomePage = json['show_on_home_page']; + includeInTopMenu = json['include_in_top_menu']; + hasDiscountsApplied = json['has_discounts_applied']; + published = json['published']; + deleted = json['deleted']; + displayOrder = json['display_order']; + createdOnUtc = json['created_on_utc']; + updatedOnUtc = json['updated_on_utc']; + + image = json['image'] != null ? new Image.fromJson(json['image']) : null; + seName = json['se_name']; + isLeaf = json['is_leaf']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['name'] = this.name; + data['namen'] = this.namen; + if (this.localizedNames != null) { + data['localized_names'] = + this.localizedNames.map((v) => v.toJson()).toList(); + } + data['description'] = this.description; + data['category_template_id'] = this.categoryTemplateId; + data['meta_keywords'] = this.metaKeywords; + data['meta_description'] = this.metaDescription; + data['meta_title'] = this.metaTitle; + data['parent_category_id'] = this.parentCategoryId; + data['page_size'] = this.pageSize; + data['page_size_options'] = this.pageSizeOptions; + data['price_ranges'] = this.priceRanges; + data['show_on_home_page'] = this.showOnHomePage; + data['include_in_top_menu'] = this.includeInTopMenu; + data['has_discounts_applied'] = this.hasDiscountsApplied; + data['published'] = this.published; + data['deleted'] = this.deleted; + data['display_order'] = this.displayOrder; + data['created_on_utc'] = this.createdOnUtc; + data['updated_on_utc'] = this.updatedOnUtc; + if (this.roleIds != null) { + data['role_ids'] = this.roleIds.map((v) => v.toJson()).toList(); + } + if (this.discountIds != null) { + data['discount_ids'] = this.discountIds.map((v) => v.toJson()).toList(); + } + if (this.storeIds != null) { + data['store_ids'] = this.storeIds.map((v) => v.toJson()).toList(); + } + if (this.image != null) { + data['image'] = this.image.toJson(); + } + data['se_name'] = this.seName; + data['is_leaf'] = this.isLeaf; + return data; + } +} + +class LocalizedNames { + int languageId; + String localizedName; + + LocalizedNames({this.languageId, this.localizedName}); + + LocalizedNames.fromJson(Map json) { + languageId = json['language_id']; + localizedName = json['localized_name']; + } + + Map toJson() { + final Map data = new Map(); + data['language_id'] = this.languageId; + data['localized_name'] = this.localizedName; + return data; + } +} + +class Image { + String src; + Null thumb; + Null attachment; + + Image({this.src, this.thumb, this.attachment}); + + Image.fromJson(Map json) { + src = json['src']; + thumb = json['thumb']; + attachment = json['attachment']; + } + + Map toJson() { + final Map data = new Map(); + data['src'] = this.src; + data['thumb'] = this.thumb; + data['attachment'] = this.attachment; + return data; + } +} diff --git a/lib/core/model/pharmacy/parent_products_model.dart b/lib/core/model/pharmacy/parent_products_model.dart new file mode 100644 index 00000000..55495416 --- /dev/null +++ b/lib/core/model/pharmacy/parent_products_model.dart @@ -0,0 +1,566 @@ +class ParentProductsModel { + dynamic id; + dynamic visibleIndividually; + dynamic name; + dynamic namen; + List localizedNames; + dynamic shortDescription; + dynamic shortDescriptionn; + dynamic fullDescription; + dynamic fullDescriptionn; + dynamic markasNew; + dynamic showOnHomePage; + dynamic metaKeywords; + dynamic metaDescription; + dynamic metaTitle; + dynamic allowCustomerReviews; + dynamic approvedRatingSum; + dynamic notApprovedRatingSum; + dynamic approvedTotalReviews; + dynamic notApprovedTotalReviews; + dynamic sku; + dynamic isRx; + dynamic prescriptionRequired; + dynamic rxMessage; + dynamic rxMessagen; + dynamic manufacturerPartNumber; + dynamic gtin; + dynamic isGiftCard; + dynamic requireOtherProducts; + dynamic automaticallyAddRequiredProducts; + dynamic isDownload; + dynamic unlimitedDownloads; + dynamic maxNumberOfDownloads; + dynamic downloadExpirationDays; + dynamic hasSampleDownload; + dynamic hasUserAgreement; + dynamic isRecurring; + dynamic recurringCycleLength; + dynamic recurringTotalCycles; + dynamic isRental; + dynamic rentalPriceLength; + dynamic isShipEnabled; + dynamic isFreeShipping; + dynamic shipSeparately; + dynamic additionalShippingCharge; + dynamic isTaxExempt; + dynamic isTelecommunicationsOrBroadcastingOrElectronicServices; + dynamic useMultipleWarehouses; + dynamic manageInventoryMethodId; + dynamic stockQuantity; + dynamic stockAvailability; + dynamic stockAvailabilityn; + dynamic displayStockAvailability; + dynamic displayStockQuantity; + dynamic minStockQuantity; + dynamic notifyAdminForQuantityBelow; + dynamic allowBackInStockSubscriptions; + dynamic orderMinimumQuantity; + dynamic orderMaximumQuantity; + dynamic allowedQuantities; + dynamic allowAddingOnlyExistingAttributeCombinations; + dynamic disableBuyButton; + dynamic disableWishlistButton; + dynamic availableForPreOrder; + dynamic preOrderAvailabilityStartDateTimeUtc; + dynamic callForPrice; + dynamic price; + dynamic oldPrice; + dynamic productCost; + dynamic specialPrice; + dynamic specialPriceStartDateTimeUtc; + dynamic specialPriceEndDateTimeUtc; + dynamic customerEntersPrice; + dynamic minimumCustomerEnteredPrice; + dynamic maximumCustomerEnteredPrice; + dynamic basepriceEnabled; + dynamic basepriceAmount; + dynamic basepriceBaseAmount; + dynamic hasTierPrices; + dynamic hasDiscountsApplied; + dynamic discountName; + dynamic discountNamen; + dynamic discountDescription; + dynamic discountDescriptionn; + dynamic discountPercentage; + dynamic currency; + dynamic currencyn; + dynamic weight; + dynamic length; + dynamic width; + dynamic height; + dynamic availableStartDateTimeUtc; + dynamic availableEndDateTimeUtc; + dynamic displayOrder; + dynamic published; + dynamic deleted; + dynamic createdOnUtc; + dynamic updatedOnUtc; + dynamic productType; + dynamic parentGroupedProductId; + List roleIds; + List discountIds; + List storeIds; + List manufacturerIds; + List reviews; + List images; + List attributes; + List specifications; + List associatedProductIds; + List tags; + dynamic vendorId; + String seName; + + ParentProductsModel( + {this.id, + this.visibleIndividually, + this.name, + this.namen, + this.localizedNames, + this.shortDescription, + this.shortDescriptionn, + this.fullDescription, + this.fullDescriptionn, + this.markasNew, + this.showOnHomePage, + this.metaKeywords, + this.metaDescription, + this.metaTitle, + this.allowCustomerReviews, + this.approvedRatingSum, + this.notApprovedRatingSum, + this.approvedTotalReviews, + this.notApprovedTotalReviews, + this.sku, + this.isRx, + this.prescriptionRequired, + this.rxMessage, + this.rxMessagen, + this.manufacturerPartNumber, + this.gtin, + this.isGiftCard, + this.requireOtherProducts, + this.automaticallyAddRequiredProducts, + this.isDownload, + this.unlimitedDownloads, + this.maxNumberOfDownloads, + this.downloadExpirationDays, + this.hasSampleDownload, + this.hasUserAgreement, + this.isRecurring, + this.recurringCycleLength, + this.recurringTotalCycles, + this.isRental, + this.rentalPriceLength, + this.isShipEnabled, + this.isFreeShipping, + this.shipSeparately, + this.additionalShippingCharge, + this.isTaxExempt, + this.isTelecommunicationsOrBroadcastingOrElectronicServices, + this.useMultipleWarehouses, + this.manageInventoryMethodId, + this.stockQuantity, + this.stockAvailability, + this.stockAvailabilityn, + this.displayStockAvailability, + this.displayStockQuantity, + this.minStockQuantity, + this.notifyAdminForQuantityBelow, + this.allowBackInStockSubscriptions, + this.orderMinimumQuantity, + this.orderMaximumQuantity, + this.allowedQuantities, + this.allowAddingOnlyExistingAttributeCombinations, + this.disableBuyButton, + this.disableWishlistButton, + this.availableForPreOrder, + this.preOrderAvailabilityStartDateTimeUtc, + this.callForPrice, + this.price, + this.oldPrice, + this.productCost, + this.specialPrice, + this.specialPriceStartDateTimeUtc, + this.specialPriceEndDateTimeUtc, + this.customerEntersPrice, + this.minimumCustomerEnteredPrice, + this.maximumCustomerEnteredPrice, + this.basepriceEnabled, + this.basepriceAmount, + this.basepriceBaseAmount, + this.hasTierPrices, + this.hasDiscountsApplied, + this.discountName, + this.discountNamen, + this.discountDescription, + this.discountDescriptionn, + this.discountPercentage, + this.currency, + this.currencyn, + this.weight, + this.length, + this.width, + this.height, + this.availableStartDateTimeUtc, + this.availableEndDateTimeUtc, + this.displayOrder, + this.published, + this.deleted, + this.createdOnUtc, + this.updatedOnUtc, + this.productType, + this.parentGroupedProductId, + this.roleIds, + this.discountIds, + this.storeIds, + this.manufacturerIds, + this.reviews, + this.images, + this.attributes, + this.specifications, + this.associatedProductIds, + this.tags, + this.vendorId, + this.seName}); + + ParentProductsModel.fromJson(Map json) { + id = json['id']; + visibleIndividually = json['visible_individually']; + name = json['name']; + if (json['images'] != null) { + images = new List(); + json['images'].forEach((v) { + images.add(new Images.fromJson(v)); + }); + } + namen = json['namen']; + if (json['localized_names'] != null) { + localizedNames = new List(); + json['localized_names'].forEach((v) { + localizedNames.add(new LocalizedNames.fromJson(v)); + }); + } + shortDescription = json['short_description']; + shortDescriptionn = json['short_descriptionn']; + fullDescription = json['full_description']; + fullDescriptionn = json['full_descriptionn']; + markasNew = json['markas_new']; + showOnHomePage = json['show_on_home_page']; + metaKeywords = json['meta_keywords']; + metaDescription = json['meta_description']; + metaTitle = json['meta_title']; + allowCustomerReviews = json['allow_customer_reviews']; + approvedRatingSum = json['approved_rating_sum']; + notApprovedRatingSum = json['not_approved_rating_sum']; + approvedTotalReviews = json['approved_total_reviews']; + notApprovedTotalReviews = json['not_approved_total_reviews']; + sku = json['sku']; + isRx = json['is_rx']; + prescriptionRequired = json['prescription_required']; + rxMessage = json['rx_message']; + rxMessagen = json['rx_messagen']; + manufacturerPartNumber = json['manufacturer_part_number']; + gtin = json['gtin']; + isGiftCard = json['is_gift_card']; + requireOtherProducts = json['require_other_products']; + automaticallyAddRequiredProducts = + json['automatically_add_required_products']; + isDownload = json['is_download']; + unlimitedDownloads = json['unlimited_downloads']; + maxNumberOfDownloads = json['max_number_of_downloads']; + downloadExpirationDays = json['download_expiration_days']; + hasSampleDownload = json['has_sample_download']; + hasUserAgreement = json['has_user_agreement']; + isRecurring = json['is_recurring']; + recurringCycleLength = json['recurring_cycle_length']; + recurringTotalCycles = json['recurring_total_cycles']; + isRental = json['is_rental']; + rentalPriceLength = json['rental_price_length']; + isShipEnabled = json['is_ship_enabled']; + isFreeShipping = json['is_free_shipping']; + shipSeparately = json['ship_separately']; + additionalShippingCharge = json['additional_shipping_charge']; + isTaxExempt = json['is_tax_exempt']; + isTelecommunicationsOrBroadcastingOrElectronicServices = + json['is_telecommunications_or_broadcasting_or_electronic_services']; + useMultipleWarehouses = json['use_multiple_warehouses']; + manageInventoryMethodId = json['manage_inventory_method_id']; + stockQuantity = json['stock_quantity']; + stockAvailability = json['stock_availability']; + stockAvailabilityn = json['stock_availabilityn']; + displayStockAvailability = json['display_stock_availability']; + displayStockQuantity = json['display_stock_quantity']; + minStockQuantity = json['min_stock_quantity']; + notifyAdminForQuantityBelow = json['notify_admin_for_quantity_below']; + allowBackInStockSubscriptions = json['allow_back_in_stock_subscriptions']; + orderMinimumQuantity = json['order_minimum_quantity']; + orderMaximumQuantity = json['order_maximum_quantity']; + allowedQuantities = json['allowed_quantities']; + allowAddingOnlyExistingAttributeCombinations = + json['allow_adding_only_existing_attribute_combinations']; + disableBuyButton = json['disable_buy_button']; + disableWishlistButton = json['disable_wishlist_button']; + availableForPreOrder = json['available_for_pre_order']; + preOrderAvailabilityStartDateTimeUtc = + json['pre_order_availability_start_date_time_utc']; + callForPrice = json['call_for_price']; + price = json['price']; + oldPrice = json['old_price']; + productCost = json['product_cost']; + specialPrice = json['special_price']; + specialPriceStartDateTimeUtc = json['special_price_start_date_time_utc']; + specialPriceEndDateTimeUtc = json['special_price_end_date_time_utc']; + customerEntersPrice = json['customer_enters_price']; + minimumCustomerEnteredPrice = json['minimum_customer_entered_price']; + maximumCustomerEnteredPrice = json['maximum_customer_entered_price']; + basepriceEnabled = json['baseprice_enabled']; + basepriceAmount = json['baseprice_amount']; + basepriceBaseAmount = json['baseprice_base_amount']; + hasTierPrices = json['has_tier_prices']; + hasDiscountsApplied = json['has_discounts_applied']; + discountName = json['discount_name']; + discountNamen = json['discount_namen']; + discountDescription = json['discount_description']; + discountDescriptionn = json['discount_Descriptionn']; + discountPercentage = json['discount_percentage']; + currency = json['currency']; + currencyn = json['currencyn']; + weight = json['weight']; + length = json['length']; + width = json['width']; + height = json['height']; + availableStartDateTimeUtc = json['available_start_date_time_utc']; + availableEndDateTimeUtc = json['available_end_date_time_utc']; + displayOrder = json['display_order']; + published = json['published']; + deleted = json['deleted']; + createdOnUtc = json['created_on_utc']; + updatedOnUtc = json['updated_on_utc']; + productType = json['product_type']; + parentGroupedProductId = json['parent_grouped_product_id']; + + manufacturerIds = json['manufacturer_ids'].cast(); + + if (json['specifications'] != null) { + specifications = new List(); + json['specifications'].forEach((v) { + specifications.add(new Specifications.fromJson(v)); + }); + } + + vendorId = json['vendor_id']; + seName = json['se_name']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['visible_individually'] = this.visibleIndividually; + data['name'] = this.name; + data['namen'] = this.namen; + if (this.localizedNames != null) { + data['localized_names'] = + this.localizedNames.map((v) => v.toJson()).toList(); + } + data['short_description'] = this.shortDescription; + data['short_descriptionn'] = this.shortDescriptionn; + data['full_description'] = this.fullDescription; + data['full_descriptionn'] = this.fullDescriptionn; + data['markas_new'] = this.markasNew; + data['show_on_home_page'] = this.showOnHomePage; + data['meta_keywords'] = this.metaKeywords; + data['meta_description'] = this.metaDescription; + data['meta_title'] = this.metaTitle; + data['allow_customer_reviews'] = this.allowCustomerReviews; + data['approved_rating_sum'] = this.approvedRatingSum; + data['not_approved_rating_sum'] = this.notApprovedRatingSum; + data['approved_total_reviews'] = this.approvedTotalReviews; + data['not_approved_total_reviews'] = this.notApprovedTotalReviews; + data['sku'] = this.sku; + data['is_rx'] = this.isRx; + data['prescription_required'] = this.prescriptionRequired; + data['rx_message'] = this.rxMessage; + data['rx_messagen'] = this.rxMessagen; + data['manufacturer_part_number'] = this.manufacturerPartNumber; + data['gtin'] = this.gtin; + data['is_gift_card'] = this.isGiftCard; + data['require_other_products'] = this.requireOtherProducts; + data['automatically_add_required_products'] = + this.automaticallyAddRequiredProducts; + data['is_download'] = this.isDownload; + data['unlimited_downloads'] = this.unlimitedDownloads; + data['max_number_of_downloads'] = this.maxNumberOfDownloads; + data['download_expiration_days'] = this.downloadExpirationDays; + data['has_sample_download'] = this.hasSampleDownload; + data['has_user_agreement'] = this.hasUserAgreement; + data['is_recurring'] = this.isRecurring; + data['recurring_cycle_length'] = this.recurringCycleLength; + data['recurring_total_cycles'] = this.recurringTotalCycles; + data['is_rental'] = this.isRental; + data['rental_price_length'] = this.rentalPriceLength; + data['is_ship_enabled'] = this.isShipEnabled; + data['is_free_shipping'] = this.isFreeShipping; + data['ship_separately'] = this.shipSeparately; + data['additional_shipping_charge'] = this.additionalShippingCharge; + data['is_tax_exempt'] = this.isTaxExempt; + data['is_telecommunications_or_broadcasting_or_electronic_services'] = + this.isTelecommunicationsOrBroadcastingOrElectronicServices; + data['use_multiple_warehouses'] = this.useMultipleWarehouses; + data['manage_inventory_method_id'] = this.manageInventoryMethodId; + data['stock_quantity'] = this.stockQuantity; + data['stock_availability'] = this.stockAvailability; + data['stock_availabilityn'] = this.stockAvailabilityn; + data['display_stock_availability'] = this.displayStockAvailability; + data['display_stock_quantity'] = this.displayStockQuantity; + data['min_stock_quantity'] = this.minStockQuantity; + data['notify_admin_for_quantity_below'] = this.notifyAdminForQuantityBelow; + data['allow_back_in_stock_subscriptions'] = + this.allowBackInStockSubscriptions; + data['order_minimum_quantity'] = this.orderMinimumQuantity; + data['order_maximum_quantity'] = this.orderMaximumQuantity; + data['allowed_quantities'] = this.allowedQuantities; + data['allow_adding_only_existing_attribute_combinations'] = + this.allowAddingOnlyExistingAttributeCombinations; + data['disable_buy_button'] = this.disableBuyButton; + data['disable_wishlist_button'] = this.disableWishlistButton; + data['available_for_pre_order'] = this.availableForPreOrder; + data['pre_order_availability_start_date_time_utc'] = + this.preOrderAvailabilityStartDateTimeUtc; + data['call_for_price'] = this.callForPrice; + data['price'] = this.price; + data['old_price'] = this.oldPrice; + data['product_cost'] = this.productCost; + data['special_price'] = this.specialPrice; + data['special_price_start_date_time_utc'] = + this.specialPriceStartDateTimeUtc; + data['special_price_end_date_time_utc'] = this.specialPriceEndDateTimeUtc; + data['customer_enters_price'] = this.customerEntersPrice; + data['minimum_customer_entered_price'] = this.minimumCustomerEnteredPrice; + data['maximum_customer_entered_price'] = this.maximumCustomerEnteredPrice; + data['baseprice_enabled'] = this.basepriceEnabled; + data['baseprice_amount'] = this.basepriceAmount; + data['baseprice_base_amount'] = this.basepriceBaseAmount; + data['has_tier_prices'] = this.hasTierPrices; + data['has_discounts_applied'] = this.hasDiscountsApplied; + data['discount_name'] = this.discountName; + data['discount_namen'] = this.discountNamen; + data['discount_description'] = this.discountDescription; + data['discount_Descriptionn'] = this.discountDescriptionn; + data['discount_percentage'] = this.discountPercentage; + data['currency'] = this.currency; + data['currencyn'] = this.currencyn; + data['weight'] = this.weight; + data['length'] = this.length; + data['width'] = this.width; + data['height'] = this.height; + data['available_start_date_time_utc'] = this.availableStartDateTimeUtc; + data['available_end_date_time_utc'] = this.availableEndDateTimeUtc; + data['display_order'] = this.displayOrder; + data['published'] = this.published; + data['deleted'] = this.deleted; + data['created_on_utc'] = this.createdOnUtc; + data['updated_on_utc'] = this.updatedOnUtc; + data['product_type'] = this.productType; + data['parent_grouped_product_id'] = this.parentGroupedProductId; + + data['manufacturer_ids'] = this.manufacturerIds; + + if (this.images != null) { + data['images'] = this.images.map((v) => v.toJson()).toList(); + } + + if (this.specifications != null) { + data['specifications'] = + this.specifications.map((v) => v.toJson()).toList(); + } + + data['vendor_id'] = this.vendorId; + data['se_name'] = this.seName; + return data; + } +} + +class LocalizedNames { + int languageId; + String localizedName; + + LocalizedNames({this.languageId, this.localizedName}); + + LocalizedNames.fromJson(Map json) { + languageId = json['language_id']; + localizedName = json['localized_name']; + } + + Map toJson() { + final Map data = new Map(); + data['language_id'] = this.languageId; + data['localized_name'] = this.localizedName; + return data; + } +} + +class Images { + int id; + int position; + String src; + String thumb; + String attachment; + + Images({this.id, this.position, this.src, this.thumb, this.attachment}); + + Images.fromJson(Map json) { + id = json['id']; + position = json['position']; + src = json['src']; + thumb = json['thumb']; + attachment = json['attachment']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['position'] = this.position; + data['src'] = this.src; + data['thumb'] = this.thumb; + data['attachment'] = this.attachment; + return data; + } +} + +class Specifications { + int id; + int displayOrder; + String defaultValue; + String defaultValuen; + String name; + String nameN; + + Specifications( + {this.id, + this.displayOrder, + this.defaultValue, + this.defaultValuen, + this.name, + this.nameN}); + + Specifications.fromJson(Map json) { + id = json['id']; + displayOrder = json['display_order']; + defaultValue = json['default_value']; + defaultValuen = json['default_valuen']; + name = json['name']; + nameN = json['nameN']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['display_order'] = this.displayOrder; + data['default_value'] = this.defaultValue; + data['default_valuen'] = this.defaultValuen; + data['name'] = this.name; + data['nameN'] = this.nameN; + return data; + } +} diff --git a/lib/core/model/pharmacy/pharmacy_categorise.dart b/lib/core/model/pharmacy/pharmacy_categorise.dart new file mode 100644 index 00000000..33ac26f1 --- /dev/null +++ b/lib/core/model/pharmacy/pharmacy_categorise.dart @@ -0,0 +1,103 @@ +class PharmacyCategorise { + dynamic id; + String name; + dynamic namen; + List localizedNames; + dynamic description; + dynamic parentCategoryId; + dynamic displayOrder; + dynamic image; + dynamic isLeaf; + + PharmacyCategorise( + {this.id, + this.name, + this.namen, + this.localizedNames, + this.description, + this.parentCategoryId, + this.displayOrder, + this.image, + this.isLeaf}); + + PharmacyCategorise.fromJson(Map json) { + try { + id = json['id']; + name = json['name']; + namen = json['namen']; + if (json['localized_names'] != null) { + localizedNames = new List(); + json['localized_names'].forEach((v) { + localizedNames.add(new LocalizedNames.fromJson(v)); + }); + } + description = json['description']; + parentCategoryId = json['parent_category_id']; + displayOrder = json['display_order']; + image = json['image'] != null ? new Image.fromJson(json['image']) : null; + isLeaf = json['is_leaf']; + } catch (e) { + print(e); + } + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['name'] = this.name; + data['namen'] = this.namen; + if (this.localizedNames != null) { + data['localized_names'] = + this.localizedNames.map((v) => v.toJson()).toList(); + } + data['description'] = this.description; + data['parent_category_id'] = this.parentCategoryId; + data['display_order'] = this.displayOrder; + if (this.image != null) { + data['image'] = this.image.toJson(); + } + data['is_leaf'] = this.isLeaf; + return data; + } +} + +class LocalizedNames { + int languageId; + String localizedName; + + LocalizedNames({this.languageId, this.localizedName}); + + LocalizedNames.fromJson(Map json) { + languageId = json['language_id']; + localizedName = json['localized_name']; + } + + Map toJson() { + final Map data = new Map(); + data['language_id'] = this.languageId; + data['localized_name'] = this.localizedName; + return data; + } +} + +class Image { + String src; + Null thumb; + Null attachment; + + Image({this.src, this.thumb, this.attachment}); + + Image.fromJson(Map json) { + src = json['src']; + thumb = json['thumb']; + attachment = json['attachment']; + } + + Map toJson() { + final Map data = new Map(); + data['src'] = this.src; + data['thumb'] = this.thumb; + data['attachment'] = this.attachment; + return data; + } +} diff --git a/lib/core/model/pharmacy/scan_qr_model.dart b/lib/core/model/pharmacy/scan_qr_model.dart new file mode 100644 index 00000000..71e25e8d --- /dev/null +++ b/lib/core/model/pharmacy/scan_qr_model.dart @@ -0,0 +1,584 @@ +class ScanQrModel { + String id; + bool visibleIndividually; + String name; + String namen; + List localizedNames; + String shortDescription; + String shortDescriptionn; + String fullDescription; + String fullDescriptionn; + bool markasNew; + bool showOnHomePage; + dynamic metaKeywords; + dynamic metaDescription; + dynamic metaTitle; + bool allowCustomerReviews; + dynamic approvedRatingSum; + dynamic notApprovedRatingSum; + dynamic approvedTotalReviews; + dynamic notApprovedTotalReviews; + String sku; + bool isRx; + bool prescriptionRequired; + dynamic rxMessage; + dynamic rxMessagen; + dynamic manufacturerPartNumber; + dynamic gtin; + bool isGiftCard; + bool requireOtherProducts; + bool automaticallyAddRequiredProducts; + bool isDownload; + bool unlimitedDownloads; + dynamic maxNumberOfDownloads; + dynamic downloadExpirationDays; + bool hasSampleDownload; + bool hasUserAgreement; + bool isRecurring; + dynamic recurringCycleLength; + dynamic recurringTotalCycles; + bool isRental; + dynamic rentalPriceLength; + bool isShipEnabled; + bool isFreeShipping; + bool shipSeparately; + dynamic additionalShippingCharge; + bool isTaxExempt; + bool isTelecommunicationsOrBroadcastingOrElectronicServices; + bool useMultipleWarehouses; + dynamic manageInventoryMethodId; + dynamic stockQuantity; + String stockAvailability; + String stockAvailabilityn; + bool displayStockAvailability; + bool displayStockQuantity; + dynamic minStockQuantity; + dynamic notifyAdminForQuantityBelow; + bool allowBackInStockSubscriptions; + dynamic orderMinimumQuantity; + dynamic orderMaximumQuantity; + dynamic allowedQuantities; + bool allowAddingOnlyExistingAttributeCombinations; + bool disableBuyButton; + bool disableWishlistButton; + bool availableForPreOrder; + dynamic preOrderAvailabilityStartDateTimeUtc; + bool callForPrice; + dynamic price; + dynamic oldPrice; + dynamic productCost; + dynamic specialPrice; + dynamic specialPriceStartDateTimeUtc; + dynamic specialPriceEndDateTimeUtc; + bool customerEntersPrice; + dynamic minimumCustomerEnteredPrice; + dynamic maximumCustomerEnteredPrice; + bool basepriceEnabled; + dynamic basepriceAmount; + dynamic basepriceBaseAmount; + bool hasTierPrices; + bool hasDiscountsApplied; + dynamic discountName; + dynamic discountNamen; + dynamic discountDescription; + dynamic discountDescriptionn; + dynamic discountPercentage; + String currency; + String currencyn; + double weight; + dynamic length; + dynamic width; + dynamic height; + dynamic availableStartDateTimeUtc; + dynamic availableEndDateTimeUtc; + dynamic displayOrder; + bool published; + bool deleted; + String createdOnUtc; + String updatedOnUtc; + String productType; + dynamic parentGroupedProductId; + List roleIds; + List discountIds; + List storeIds; + List manufacturerIds; + List reviews; + List images; + List attributes; + List specifications; + List associatedProductIds; + List tags; + dynamic vendorId; + String seName; + + ScanQrModel( + {this.id, + this.visibleIndividually, + this.name, + this.namen, + this.localizedNames, + this.shortDescription, + this.shortDescriptionn, + this.fullDescription, + this.fullDescriptionn, + this.markasNew, + this.showOnHomePage, + this.metaKeywords, + this.metaDescription, + this.metaTitle, + this.allowCustomerReviews, + this.approvedRatingSum, + this.notApprovedRatingSum, + this.approvedTotalReviews, + this.notApprovedTotalReviews, + this.sku, + this.isRx, + this.prescriptionRequired, + this.rxMessage, + this.rxMessagen, + this.manufacturerPartNumber, + this.gtin, + this.isGiftCard, + this.requireOtherProducts, + this.automaticallyAddRequiredProducts, + this.isDownload, + this.unlimitedDownloads, + this.maxNumberOfDownloads, + this.downloadExpirationDays, + this.hasSampleDownload, + this.hasUserAgreement, + this.isRecurring, + this.recurringCycleLength, + this.recurringTotalCycles, + this.isRental, + this.rentalPriceLength, + this.isShipEnabled, + this.isFreeShipping, + this.shipSeparately, + this.additionalShippingCharge, + this.isTaxExempt, + this.isTelecommunicationsOrBroadcastingOrElectronicServices, + this.useMultipleWarehouses, + this.manageInventoryMethodId, + this.stockQuantity, + this.stockAvailability, + this.stockAvailabilityn, + this.displayStockAvailability, + this.displayStockQuantity, + this.minStockQuantity, + this.notifyAdminForQuantityBelow, + this.allowBackInStockSubscriptions, + this.orderMinimumQuantity, + this.orderMaximumQuantity, + this.allowedQuantities, + this.allowAddingOnlyExistingAttributeCombinations, + this.disableBuyButton, + this.disableWishlistButton, + this.availableForPreOrder, + this.preOrderAvailabilityStartDateTimeUtc, + this.callForPrice, + this.price, + this.oldPrice, + this.productCost, + this.specialPrice, + this.specialPriceStartDateTimeUtc, + this.specialPriceEndDateTimeUtc, + this.customerEntersPrice, + this.minimumCustomerEnteredPrice, + this.maximumCustomerEnteredPrice, + this.basepriceEnabled, + this.basepriceAmount, + this.basepriceBaseAmount, + this.hasTierPrices, + this.hasDiscountsApplied, + this.discountName, + this.discountNamen, + this.discountDescription, + this.discountDescriptionn, + this.discountPercentage, + this.currency, + this.currencyn, + this.weight, + this.length, + this.width, + this.height, + this.availableStartDateTimeUtc, + this.availableEndDateTimeUtc, + this.displayOrder, + this.published, + this.deleted, + this.createdOnUtc, + this.updatedOnUtc, + this.productType, + this.parentGroupedProductId, + this.roleIds, + this.discountIds, + this.storeIds, + this.manufacturerIds, + this.reviews, + this.images, + this.attributes, + this.specifications, + this.associatedProductIds, + this.tags, + this.vendorId, + this.seName}); + + ScanQrModel.fromJson(Map json) { + id = json['id']; + visibleIndividually = json['visible_individually']; + name = json['name']; + namen = json['namen']; + if (json['localized_names'] != null) { + localizedNames = new List(); + json['localized_names'].forEach((v) { + localizedNames.add(new LocalizedNames.fromJson(v)); + }); + } + shortDescription = json['short_description']; + shortDescriptionn = json['short_descriptionn']; + fullDescription = json['full_description']; + fullDescriptionn = json['full_descriptionn']; + markasNew = json['markas_new']; + showOnHomePage = json['show_on_home_page']; + metaKeywords = json['meta_keywords']; + metaDescription = json['meta_description']; + metaTitle = json['meta_title']; + allowCustomerReviews = json['allow_customer_reviews']; + approvedRatingSum = json['approved_rating_sum']; + notApprovedRatingSum = json['not_approved_rating_sum']; + approvedTotalReviews = json['approved_total_reviews']; + notApprovedTotalReviews = json['not_approved_total_reviews']; + sku = json['sku']; + isRx = json['is_rx']; + prescriptionRequired = json['prescription_required']; + rxMessage = json['rx_message']; + rxMessagen = json['rx_messagen']; + manufacturerPartNumber = json['manufacturer_part_number']; + gtin = json['gtin']; + isGiftCard = json['is_gift_card']; + requireOtherProducts = json['require_other_products']; + automaticallyAddRequiredProducts = + json['automatically_add_required_products']; + isDownload = json['is_download']; + unlimitedDownloads = json['unlimited_downloads']; + maxNumberOfDownloads = json['max_number_of_downloads']; + downloadExpirationDays = json['download_expiration_days']; + hasSampleDownload = json['has_sample_download']; + hasUserAgreement = json['has_user_agreement']; + isRecurring = json['is_recurring']; + recurringCycleLength = json['recurring_cycle_length']; + recurringTotalCycles = json['recurring_total_cycles']; + isRental = json['is_rental']; + rentalPriceLength = json['rental_price_length']; + isShipEnabled = json['is_ship_enabled']; + isFreeShipping = json['is_free_shipping']; + shipSeparately = json['ship_separately']; + additionalShippingCharge = json['additional_shipping_charge']; + isTaxExempt = json['is_tax_exempt']; + isTelecommunicationsOrBroadcastingOrElectronicServices = + json['is_telecommunications_or_broadcasting_or_electronic_services']; + useMultipleWarehouses = json['use_multiple_warehouses']; + manageInventoryMethodId = json['manage_inventory_method_id']; + stockQuantity = json['stock_quantity']; + stockAvailability = json['stock_availability']; + stockAvailabilityn = json['stock_availabilityn']; + displayStockAvailability = json['display_stock_availability']; + displayStockQuantity = json['display_stock_quantity']; + minStockQuantity = json['min_stock_quantity']; + notifyAdminForQuantityBelow = json['notify_admin_for_quantity_below']; + allowBackInStockSubscriptions = json['allow_back_in_stock_subscriptions']; + orderMinimumQuantity = json['order_minimum_quantity']; + orderMaximumQuantity = json['order_maximum_quantity']; + allowedQuantities = json['allowed_quantities']; + allowAddingOnlyExistingAttributeCombinations = + json['allow_adding_only_existing_attribute_combinations']; + disableBuyButton = json['disable_buy_button']; + disableWishlistButton = json['disable_wishlist_button']; + availableForPreOrder = json['available_for_pre_order']; + preOrderAvailabilityStartDateTimeUtc = + json['pre_order_availability_start_date_time_utc']; + callForPrice = json['call_for_price']; + price = json['price']; + oldPrice = json['old_price']; + productCost = json['product_cost']; + specialPrice = json['special_price']; + specialPriceStartDateTimeUtc = json['special_price_start_date_time_utc']; + specialPriceEndDateTimeUtc = json['special_price_end_date_time_utc']; + customerEntersPrice = json['customer_enters_price']; + minimumCustomerEnteredPrice = json['minimum_customer_entered_price']; + maximumCustomerEnteredPrice = json['maximum_customer_entered_price']; + basepriceEnabled = json['baseprice_enabled']; + basepriceAmount = json['baseprice_amount']; + basepriceBaseAmount = json['baseprice_base_amount']; + hasTierPrices = json['has_tier_prices']; + hasDiscountsApplied = json['has_discounts_applied']; + discountName = json['discount_name']; + discountNamen = json['discount_namen']; + discountDescription = json['discount_description']; + discountDescriptionn = json['discount_Descriptionn']; + discountPercentage = json['discount_percentage']; + currency = json['currency']; + currencyn = json['currencyn']; + weight = json['weight']; + length = json['length']; + width = json['width']; + height = json['height']; + availableStartDateTimeUtc = json['available_start_date_time_utc']; + availableEndDateTimeUtc = json['available_end_date_time_utc']; + displayOrder = json['display_order']; + published = json['published']; + deleted = json['deleted']; + createdOnUtc = json['created_on_utc']; + updatedOnUtc = json['updated_on_utc']; + productType = json['product_type']; + parentGroupedProductId = json['parent_grouped_product_id']; + if (json['role_ids'] != null) { + roleIds = new List(); + } + if (json['discount_ids'] != null) { + discountIds = new List(); + } + if (json['store_ids'] != null) { + storeIds = new List(); + } + manufacturerIds = json['manufacturer_ids'].cast(); + if (json['reviews'] != null) { + reviews = new List(); + } + if (json['images'] != null) { + images = new List(); + json['images'].forEach((v) { + images.add(new Images.fromJson(v)); + }); + } + if (json['attributes'] != null) { + attributes = new List(); + } + if (json['specifications'] != null) { + specifications = new List(); + json['specifications'].forEach((v) { + specifications.add(new Specifications.fromJson(v)); + }); + } + if (json['associated_product_ids'] != null) { + associatedProductIds = new List(); + } + if (json['tags'] != null) { + tags = new List(); + } + vendorId = json['vendor_id']; + seName = json['se_name']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['visible_individually'] = this.visibleIndividually; + data['name'] = this.name; + data['namen'] = this.namen; + if (this.localizedNames != null) { + data['localized_names'] = + this.localizedNames.map((v) => v.toJson()).toList(); + } + data['short_description'] = this.shortDescription; + data['short_descriptionn'] = this.shortDescriptionn; + data['full_description'] = this.fullDescription; + data['full_descriptionn'] = this.fullDescriptionn; + data['markas_new'] = this.markasNew; + data['show_on_home_page'] = this.showOnHomePage; + data['meta_keywords'] = this.metaKeywords; + data['meta_description'] = this.metaDescription; + data['meta_title'] = this.metaTitle; + data['allow_customer_reviews'] = this.allowCustomerReviews; + data['approved_rating_sum'] = this.approvedRatingSum; + data['not_approved_rating_sum'] = this.notApprovedRatingSum; + data['approved_total_reviews'] = this.approvedTotalReviews; + data['not_approved_total_reviews'] = this.notApprovedTotalReviews; + data['sku'] = this.sku; + data['is_rx'] = this.isRx; + data['prescription_required'] = this.prescriptionRequired; + data['rx_message'] = this.rxMessage; + data['rx_messagen'] = this.rxMessagen; + data['manufacturer_part_number'] = this.manufacturerPartNumber; + data['gtin'] = this.gtin; + data['is_gift_card'] = this.isGiftCard; + data['require_other_products'] = this.requireOtherProducts; + data['automatically_add_required_products'] = + this.automaticallyAddRequiredProducts; + data['is_download'] = this.isDownload; + data['unlimited_downloads'] = this.unlimitedDownloads; + data['max_number_of_downloads'] = this.maxNumberOfDownloads; + data['download_expiration_days'] = this.downloadExpirationDays; + data['has_sample_download'] = this.hasSampleDownload; + data['has_user_agreement'] = this.hasUserAgreement; + data['is_recurring'] = this.isRecurring; + data['recurring_cycle_length'] = this.recurringCycleLength; + data['recurring_total_cycles'] = this.recurringTotalCycles; + data['is_rental'] = this.isRental; + data['rental_price_length'] = this.rentalPriceLength; + data['is_ship_enabled'] = this.isShipEnabled; + data['is_free_shipping'] = this.isFreeShipping; + data['ship_separately'] = this.shipSeparately; + data['additional_shipping_charge'] = this.additionalShippingCharge; + data['is_tax_exempt'] = this.isTaxExempt; + data['is_telecommunications_or_broadcasting_or_electronic_services'] = + this.isTelecommunicationsOrBroadcastingOrElectronicServices; + data['use_multiple_warehouses'] = this.useMultipleWarehouses; + data['manage_inventory_method_id'] = this.manageInventoryMethodId; + data['stock_quantity'] = this.stockQuantity; + data['stock_availability'] = this.stockAvailability; + data['stock_availabilityn'] = this.stockAvailabilityn; + data['display_stock_availability'] = this.displayStockAvailability; + data['display_stock_quantity'] = this.displayStockQuantity; + data['min_stock_quantity'] = this.minStockQuantity; + data['notify_admin_for_quantity_below'] = this.notifyAdminForQuantityBelow; + data['allow_back_in_stock_subscriptions'] = + this.allowBackInStockSubscriptions; + data['order_minimum_quantity'] = this.orderMinimumQuantity; + data['order_maximum_quantity'] = this.orderMaximumQuantity; + data['allowed_quantities'] = this.allowedQuantities; + data['allow_adding_only_existing_attribute_combinations'] = + this.allowAddingOnlyExistingAttributeCombinations; + data['disable_buy_button'] = this.disableBuyButton; + data['disable_wishlist_button'] = this.disableWishlistButton; + data['available_for_pre_order'] = this.availableForPreOrder; + data['pre_order_availability_start_date_time_utc'] = + this.preOrderAvailabilityStartDateTimeUtc; + data['call_for_price'] = this.callForPrice; + data['price'] = this.price; + data['old_price'] = this.oldPrice; + data['product_cost'] = this.productCost; + data['special_price'] = this.specialPrice; + data['special_price_start_date_time_utc'] = + this.specialPriceStartDateTimeUtc; + data['special_price_end_date_time_utc'] = this.specialPriceEndDateTimeUtc; + data['customer_enters_price'] = this.customerEntersPrice; + data['minimum_customer_entered_price'] = this.minimumCustomerEnteredPrice; + data['maximum_customer_entered_price'] = this.maximumCustomerEnteredPrice; + data['baseprice_enabled'] = this.basepriceEnabled; + data['baseprice_amount'] = this.basepriceAmount; + data['baseprice_base_amount'] = this.basepriceBaseAmount; + data['has_tier_prices'] = this.hasTierPrices; + data['has_discounts_applied'] = this.hasDiscountsApplied; + data['discount_name'] = this.discountName; + data['discount_namen'] = this.discountNamen; + data['discount_description'] = this.discountDescription; + data['discount_Descriptionn'] = this.discountDescriptionn; + data['discount_percentage'] = this.discountPercentage; + data['currency'] = this.currency; + data['currencyn'] = this.currencyn; + data['weight'] = this.weight; + data['length'] = this.length; + data['width'] = this.width; + data['height'] = this.height; + data['available_start_date_time_utc'] = this.availableStartDateTimeUtc; + data['available_end_date_time_utc'] = this.availableEndDateTimeUtc; + data['display_order'] = this.displayOrder; + data['published'] = this.published; + data['deleted'] = this.deleted; + data['created_on_utc'] = this.createdOnUtc; + data['updated_on_utc'] = this.updatedOnUtc; + data['product_type'] = this.productType; + data['parent_grouped_product_id'] = this.parentGroupedProductId; + + data['manufacturer_ids'] = this.manufacturerIds; + + if (this.images != null) { + data['images'] = this.images.map((v) => v.toJson()).toList(); + } + + if (this.specifications != null) { + data['specifications'] = + this.specifications.map((v) => v.toJson()).toList(); + } + + data['vendor_id'] = this.vendorId; + data['se_name'] = this.seName; + return data; + } +} + +class LocalizedNames { + int languageId; + String localizedName; + + LocalizedNames({this.languageId, this.localizedName}); + + LocalizedNames.fromJson(Map json) { + languageId = json['language_id']; + localizedName = json['localized_name']; + } + + Map toJson() { + final Map data = new Map(); + data['language_id'] = this.languageId; + data['localized_name'] = this.localizedName; + return data; + } +} + +class Images { + int id; + int position; + String src; + String thumb; + String attachment; + + Images({this.id, this.position, this.src, this.thumb, this.attachment}); + + Images.fromJson(Map json) { + id = json['id']; + position = json['position']; + src = json['src']; + thumb = json['thumb']; + attachment = json['attachment']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['position'] = this.position; + data['src'] = this.src; + data['thumb'] = this.thumb; + data['attachment'] = this.attachment; + return data; + } +} + +class Specifications { + int id; + int displayOrder; + String defaultValue; + String defaultValuen; + String name; + String nameN; + + Specifications( + {this.id, + this.displayOrder, + this.defaultValue, + this.defaultValuen, + this.name, + this.nameN}); + + Specifications.fromJson(Map json) { + id = json['id']; + displayOrder = json['display_order']; + defaultValue = json['default_value']; + defaultValuen = json['default_valuen']; + name = json['name']; + nameN = json['nameN']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['display_order'] = this.displayOrder; + data['default_value'] = this.defaultValue; + data['default_valuen'] = this.defaultValuen; + data['name'] = this.name; + data['nameN'] = this.nameN; + return data; + } +} diff --git a/lib/core/model/pharmacy/sub_categories_model.dart b/lib/core/model/pharmacy/sub_categories_model.dart new file mode 100644 index 00000000..916ec023 --- /dev/null +++ b/lib/core/model/pharmacy/sub_categories_model.dart @@ -0,0 +1,75 @@ +class SubCategoriesModel { + String id; + String name; + String namen; + List localizedNames; + String description; + int parentCategoryId; + int displayOrder; + dynamic image; + bool isLeaf; + + SubCategoriesModel( + {this.id, + this.name, + this.namen, + this.localizedNames, + this.description, + this.parentCategoryId, + this.displayOrder, + this.image, + this.isLeaf}); + + SubCategoriesModel.fromJson(Map json) { + id = json['id']; + name = json['name']; + namen = json['namen']; + if (json['localized_names'] != null) { + localizedNames = new List(); + json['localized_names'].forEach((v) { + localizedNames.add(new LocalizedNames.fromJson(v)); + }); + } + description = json['description']; + parentCategoryId = json['parent_category_id']; + displayOrder = json['display_order']; + image = json['image']; + isLeaf = json['is_leaf']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['name'] = this.name; + data['namen'] = this.namen; + if (this.localizedNames != null) { + data['localized_names'] = + this.localizedNames.map((v) => v.toJson()).toList(); + } + data['description'] = this.description; + data['parent_category_id'] = this.parentCategoryId; + data['display_order'] = this.displayOrder; + data['image'] = this.image; + data['is_leaf'] = this.isLeaf; + return data; + } +} + +class LocalizedNames { + int languageId; + String localizedName; + + LocalizedNames({this.languageId, this.localizedName}); + + LocalizedNames.fromJson(Map json) { + languageId = json['language_id']; + localizedName = json['localized_name']; + } + + Map toJson() { + final Map data = new Map(); + data['language_id'] = this.languageId; + data['localized_name'] = this.localizedName; + return data; + } +} diff --git a/lib/core/model/pharmacy/sub_products_model.dart b/lib/core/model/pharmacy/sub_products_model.dart new file mode 100644 index 00000000..6e8964c9 --- /dev/null +++ b/lib/core/model/pharmacy/sub_products_model.dart @@ -0,0 +1,562 @@ +class SubProductsModel { + String id; + bool visibleIndividually; + String name; + String namen; + List localizedNames; + String shortDescription; + String shortDescriptionn; + String fullDescription; + String fullDescriptionn; + bool markasNew; + bool showOnHomePage; + dynamic metaKeywords; + dynamic metaDescription; + dynamic metaTitle; + bool allowCustomerReviews; + dynamic approvedRatingSum; + dynamic notApprovedRatingSum; + dynamic approvedTotalReviews; + dynamic notApprovedTotalReviews; + String sku; + bool isRx; + bool prescriptionRequired; + dynamic rxMessage; + dynamic rxMessagen; + dynamic manufacturerPartNumber; + dynamic gtin; + bool isGiftCard; + bool requireOtherProducts; + bool automaticallyAddRequiredProducts; + bool isDownload; + bool unlimitedDownloads; + dynamic maxNumberOfDownloads; + dynamic downloadExpirationDays; + bool hasSampleDownload; + bool hasUserAgreement; + bool isRecurring; + dynamic recurringCycleLength; + dynamic recurringTotalCycles; + bool isRental; + dynamic rentalPriceLength; + bool isShipEnabled; + bool isFreeShipping; + bool shipSeparately; + dynamic additionalShippingCharge; + bool isTaxExempt; + bool isTelecommunicationsOrBroadcastingOrElectronicServices; + bool useMultipleWarehouses; + dynamic manageInventoryMethodId; + dynamic stockQuantity; + String stockAvailability; + String stockAvailabilityn; + bool displayStockAvailability; + bool displayStockQuantity; + dynamic minStockQuantity; + dynamic notifyAdminForQuantityBelow; + bool allowBackInStockSubscriptions; + dynamic orderMinimumQuantity; + dynamic orderMaximumQuantity; + dynamic allowedQuantities; + bool allowAddingOnlyExistingAttributeCombinations; + bool disableBuyButton; + bool disableWishlistButton; + bool availableForPreOrder; + dynamic preOrderAvailabilityStartDateTimeUtc; + bool callForPrice; + dynamic price; + dynamic oldPrice; + dynamic productCost; + dynamic specialPrice; + dynamic specialPriceStartDateTimeUtc; + dynamic specialPriceEndDateTimeUtc; + bool customerEntersPrice; + dynamic minimumCustomerEnteredPrice; + dynamic maximumCustomerEnteredPrice; + bool basepriceEnabled; + dynamic basepriceAmount; + dynamic basepriceBaseAmount; + bool hasTierPrices; + bool hasDiscountsApplied; + dynamic discountName; + dynamic discountNamen; + dynamic discountDescription; + dynamic discountDescriptionn; + dynamic discountPercentage; + String currency; + String currencyn; + double weight; + dynamic length; + dynamic width; + dynamic height; + dynamic availableStartDateTimeUtc; + dynamic availableEndDateTimeUtc; + dynamic displayOrder; + bool published; + bool deleted; + String createdOnUtc; + String updatedOnUtc; + String productType; + dynamic parentGroupedProductId; + List roleIds; + List discountIds; + List storeIds; + List manufacturerIds; + List reviews; + List images; + List attributes; + List specifications; + List associatedProductIds; + List tags; + dynamic vendorId; + String seName; + + SubProductsModel( + {this.id, + this.visibleIndividually, + this.name, + this.namen, + this.localizedNames, + this.shortDescription, + this.shortDescriptionn, + this.fullDescription, + this.fullDescriptionn, + this.markasNew, + this.showOnHomePage, + this.metaKeywords, + this.metaDescription, + this.metaTitle, + this.allowCustomerReviews, + this.approvedRatingSum, + this.notApprovedRatingSum, + this.approvedTotalReviews, + this.notApprovedTotalReviews, + this.sku, + this.isRx, + this.prescriptionRequired, + this.rxMessage, + this.rxMessagen, + this.manufacturerPartNumber, + this.gtin, + this.isGiftCard, + this.requireOtherProducts, + this.automaticallyAddRequiredProducts, + this.isDownload, + this.unlimitedDownloads, + this.maxNumberOfDownloads, + this.downloadExpirationDays, + this.hasSampleDownload, + this.hasUserAgreement, + this.isRecurring, + this.recurringCycleLength, + this.recurringTotalCycles, + this.isRental, + this.rentalPriceLength, + this.isShipEnabled, + this.isFreeShipping, + this.shipSeparately, + this.additionalShippingCharge, + this.isTaxExempt, + this.isTelecommunicationsOrBroadcastingOrElectronicServices, + this.useMultipleWarehouses, + this.manageInventoryMethodId, + this.stockQuantity, + this.stockAvailability, + this.stockAvailabilityn, + this.displayStockAvailability, + this.displayStockQuantity, + this.minStockQuantity, + this.notifyAdminForQuantityBelow, + this.allowBackInStockSubscriptions, + this.orderMinimumQuantity, + this.orderMaximumQuantity, + this.allowedQuantities, + this.allowAddingOnlyExistingAttributeCombinations, + this.disableBuyButton, + this.disableWishlistButton, + this.availableForPreOrder, + this.preOrderAvailabilityStartDateTimeUtc, + this.callForPrice, + this.price, + this.oldPrice, + this.productCost, + this.specialPrice, + this.specialPriceStartDateTimeUtc, + this.specialPriceEndDateTimeUtc, + this.customerEntersPrice, + this.minimumCustomerEnteredPrice, + this.maximumCustomerEnteredPrice, + this.basepriceEnabled, + this.basepriceAmount, + this.basepriceBaseAmount, + this.hasTierPrices, + this.hasDiscountsApplied, + this.discountName, + this.discountNamen, + this.discountDescription, + this.discountDescriptionn, + this.discountPercentage, + this.currency, + this.currencyn, + this.weight, + this.length, + this.width, + this.height, + this.availableStartDateTimeUtc, + this.availableEndDateTimeUtc, + this.displayOrder, + this.published, + this.deleted, + this.createdOnUtc, + this.updatedOnUtc, + this.productType, + this.parentGroupedProductId, + this.roleIds, + this.discountIds, + this.storeIds, + this.manufacturerIds, + this.reviews, + this.images, + this.attributes, + this.specifications, + this.associatedProductIds, + this.tags, + this.vendorId, + this.seName}); + + SubProductsModel.fromJson(Map json) { + id = json['id']; + visibleIndividually = json['visible_individually']; + name = json['name']; + if (json['images'] != null) { + images = new List(); + json['images'].forEach((v) { + images.add(new Images.fromJson(v)); + }); + } + namen = json['namen']; + if (json['localized_names'] != null) { + localizedNames = new List(); + json['localized_names'].forEach((v) { + localizedNames.add(new LocalizedNames.fromJson(v)); + }); + } + shortDescription = json['short_description']; + shortDescriptionn = json['short_descriptionn']; + fullDescription = json['full_description']; + fullDescriptionn = json['full_descriptionn']; + markasNew = json['markas_new']; + showOnHomePage = json['show_on_home_page']; + metaKeywords = json['meta_keywords']; + metaDescription = json['meta_description']; + metaTitle = json['meta_title']; + allowCustomerReviews = json['allow_customer_reviews']; + approvedRatingSum = json['approved_rating_sum']; + notApprovedRatingSum = json['not_approved_rating_sum']; + approvedTotalReviews = json['approved_total_reviews']; + notApprovedTotalReviews = json['not_approved_total_reviews']; + sku = json['sku']; + isRx = json['is_rx']; + prescriptionRequired = json['prescription_required']; + rxMessage = json['rx_message']; + rxMessagen = json['rx_messagen']; + manufacturerPartNumber = json['manufacturer_part_number']; + gtin = json['gtin']; + isGiftCard = json['is_gift_card']; + requireOtherProducts = json['require_other_products']; + automaticallyAddRequiredProducts = + json['automatically_add_required_products']; + isDownload = json['is_download']; + unlimitedDownloads = json['unlimited_downloads']; + maxNumberOfDownloads = json['max_number_of_downloads']; + downloadExpirationDays = json['download_expiration_days']; + hasSampleDownload = json['has_sample_download']; + hasUserAgreement = json['has_user_agreement']; + isRecurring = json['is_recurring']; + recurringCycleLength = json['recurring_cycle_length']; + recurringTotalCycles = json['recurring_total_cycles']; + isRental = json['is_rental']; + rentalPriceLength = json['rental_price_length']; + isShipEnabled = json['is_ship_enabled']; + isFreeShipping = json['is_free_shipping']; + shipSeparately = json['ship_separately']; + additionalShippingCharge = json['additional_shipping_charge']; + isTaxExempt = json['is_tax_exempt']; + isTelecommunicationsOrBroadcastingOrElectronicServices = + json['is_telecommunications_or_broadcasting_or_electronic_services']; + useMultipleWarehouses = json['use_multiple_warehouses']; + manageInventoryMethodId = json['manage_inventory_method_id']; + stockQuantity = json['stock_quantity']; + stockAvailability = json['stock_availability']; + stockAvailabilityn = json['stock_availabilityn']; + displayStockAvailability = json['display_stock_availability']; + displayStockQuantity = json['display_stock_quantity']; + minStockQuantity = json['min_stock_quantity']; + notifyAdminForQuantityBelow = json['notify_admin_for_quantity_below']; + allowBackInStockSubscriptions = json['allow_back_in_stock_subscriptions']; + orderMinimumQuantity = json['order_minimum_quantity']; + orderMaximumQuantity = json['order_maximum_quantity']; + allowedQuantities = json['allowed_quantities']; + allowAddingOnlyExistingAttributeCombinations = + json['allow_adding_only_existing_attribute_combinations']; + disableBuyButton = json['disable_buy_button']; + disableWishlistButton = json['disable_wishlist_button']; + availableForPreOrder = json['available_for_pre_order']; + preOrderAvailabilityStartDateTimeUtc = + json['pre_order_availability_start_date_time_utc']; + callForPrice = json['call_for_price']; + price = json['price']; + oldPrice = json['old_price']; + productCost = json['product_cost']; + specialPrice = json['special_price']; + specialPriceStartDateTimeUtc = json['special_price_start_date_time_utc']; + specialPriceEndDateTimeUtc = json['special_price_end_date_time_utc']; + customerEntersPrice = json['customer_enters_price']; + minimumCustomerEnteredPrice = json['minimum_customer_entered_price']; + maximumCustomerEnteredPrice = json['maximum_customer_entered_price']; + basepriceEnabled = json['baseprice_enabled']; + basepriceAmount = json['baseprice_amount']; + basepriceBaseAmount = json['baseprice_base_amount']; + hasTierPrices = json['has_tier_prices']; + hasDiscountsApplied = json['has_discounts_applied']; + discountName = json['discount_name']; + discountNamen = json['discount_namen']; + discountDescription = json['discount_description']; + discountDescriptionn = json['discount_Descriptionn']; + discountPercentage = json['discount_percentage']; + currency = json['currency']; + currencyn = json['currencyn']; + weight = json['weight']; + length = json['length']; + width = json['width']; + height = json['height']; + availableStartDateTimeUtc = json['available_start_date_time_utc']; + availableEndDateTimeUtc = json['available_end_date_time_utc']; + displayOrder = json['display_order']; + published = json['published']; + deleted = json['deleted']; + createdOnUtc = json['created_on_utc']; + updatedOnUtc = json['updated_on_utc']; + productType = json['product_type']; + parentGroupedProductId = json['parent_grouped_product_id']; + + manufacturerIds = json['manufacturer_ids'].cast(); + + if (json['specifications'] != null) { + specifications = new List(); + json['specifications'].forEach((v) { + specifications.add(new Specifications.fromJson(v)); + }); + } + + vendorId = json['vendor_id']; + seName = json['se_name']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['visible_individually'] = this.visibleIndividually; + data['name'] = this.name; + data['namen'] = this.namen; + if (this.localizedNames != null) { + data['localized_names'] = + this.localizedNames.map((v) => v.toJson()).toList(); + } + data['short_description'] = this.shortDescription; + data['short_descriptionn'] = this.shortDescriptionn; + data['full_description'] = this.fullDescription; + data['full_descriptionn'] = this.fullDescriptionn; + data['markas_new'] = this.markasNew; + data['show_on_home_page'] = this.showOnHomePage; + data['meta_keywords'] = this.metaKeywords; + data['meta_description'] = this.metaDescription; + data['meta_title'] = this.metaTitle; + data['allow_customer_reviews'] = this.allowCustomerReviews; + data['approved_rating_sum'] = this.approvedRatingSum; + data['not_approved_rating_sum'] = this.notApprovedRatingSum; + data['approved_total_reviews'] = this.approvedTotalReviews; + data['not_approved_total_reviews'] = this.notApprovedTotalReviews; + data['sku'] = this.sku; + data['is_rx'] = this.isRx; + data['prescription_required'] = this.prescriptionRequired; + data['rx_message'] = this.rxMessage; + data['rx_messagen'] = this.rxMessagen; + data['manufacturer_part_number'] = this.manufacturerPartNumber; + data['gtin'] = this.gtin; + data['is_gift_card'] = this.isGiftCard; + data['require_other_products'] = this.requireOtherProducts; + data['automatically_add_required_products'] = + this.automaticallyAddRequiredProducts; + data['is_download'] = this.isDownload; + data['unlimited_downloads'] = this.unlimitedDownloads; + data['max_number_of_downloads'] = this.maxNumberOfDownloads; + data['download_expiration_days'] = this.downloadExpirationDays; + data['has_sample_download'] = this.hasSampleDownload; + data['has_user_agreement'] = this.hasUserAgreement; + data['is_recurring'] = this.isRecurring; + data['recurring_cycle_length'] = this.recurringCycleLength; + data['recurring_total_cycles'] = this.recurringTotalCycles; + data['is_rental'] = this.isRental; + data['rental_price_length'] = this.rentalPriceLength; + data['is_ship_enabled'] = this.isShipEnabled; + data['is_free_shipping'] = this.isFreeShipping; + data['ship_separately'] = this.shipSeparately; + data['additional_shipping_charge'] = this.additionalShippingCharge; + data['is_tax_exempt'] = this.isTaxExempt; + data['is_telecommunications_or_broadcasting_or_electronic_services'] = + this.isTelecommunicationsOrBroadcastingOrElectronicServices; + data['use_multiple_warehouses'] = this.useMultipleWarehouses; + data['manage_inventory_method_id'] = this.manageInventoryMethodId; + data['stock_quantity'] = this.stockQuantity; + data['stock_availability'] = this.stockAvailability; + data['stock_availabilityn'] = this.stockAvailabilityn; + data['display_stock_availability'] = this.displayStockAvailability; + data['display_stock_quantity'] = this.displayStockQuantity; + data['min_stock_quantity'] = this.minStockQuantity; + data['notify_admin_for_quantity_below'] = this.notifyAdminForQuantityBelow; + data['allow_back_in_stock_subscriptions'] = + this.allowBackInStockSubscriptions; + data['order_minimum_quantity'] = this.orderMinimumQuantity; + data['order_maximum_quantity'] = this.orderMaximumQuantity; + data['allowed_quantities'] = this.allowedQuantities; + data['allow_adding_only_existing_attribute_combinations'] = + this.allowAddingOnlyExistingAttributeCombinations; + data['disable_buy_button'] = this.disableBuyButton; + data['disable_wishlist_button'] = this.disableWishlistButton; + data['available_for_pre_order'] = this.availableForPreOrder; + data['pre_order_availability_start_date_time_utc'] = + this.preOrderAvailabilityStartDateTimeUtc; + data['call_for_price'] = this.callForPrice; + data['price'] = this.price; + data['old_price'] = this.oldPrice; + data['product_cost'] = this.productCost; + data['special_price'] = this.specialPrice; + data['special_price_start_date_time_utc'] = + this.specialPriceStartDateTimeUtc; + data['special_price_end_date_time_utc'] = this.specialPriceEndDateTimeUtc; + data['customer_enters_price'] = this.customerEntersPrice; + data['minimum_customer_entered_price'] = this.minimumCustomerEnteredPrice; + data['maximum_customer_entered_price'] = this.maximumCustomerEnteredPrice; + data['baseprice_enabled'] = this.basepriceEnabled; + data['baseprice_amount'] = this.basepriceAmount; + data['baseprice_base_amount'] = this.basepriceBaseAmount; + data['has_tier_prices'] = this.hasTierPrices; + data['has_discounts_applied'] = this.hasDiscountsApplied; + data['discount_name'] = this.discountName; + data['discount_namen'] = this.discountNamen; + data['discount_description'] = this.discountDescription; + data['discount_Descriptionn'] = this.discountDescriptionn; + data['discount_percentage'] = this.discountPercentage; + data['currency'] = this.currency; + data['currencyn'] = this.currencyn; + data['weight'] = this.weight; + data['length'] = this.length; + data['width'] = this.width; + data['height'] = this.height; + data['available_start_date_time_utc'] = this.availableStartDateTimeUtc; + data['available_end_date_time_utc'] = this.availableEndDateTimeUtc; + data['display_order'] = this.displayOrder; + data['published'] = this.published; + data['deleted'] = this.deleted; + data['created_on_utc'] = this.createdOnUtc; + data['updated_on_utc'] = this.updatedOnUtc; + data['product_type'] = this.productType; + data['parent_grouped_product_id'] = this.parentGroupedProductId; + + data['manufacturer_ids'] = this.manufacturerIds; + + if (this.specifications != null) { + data['specifications'] = + this.specifications.map((v) => v.toJson()).toList(); + } + + data['vendor_id'] = this.vendorId; + data['se_name'] = this.seName; + return data; + } +} + +class LocalizedNames { + int languageId; + String localizedName; + + LocalizedNames({this.languageId, this.localizedName}); + + LocalizedNames.fromJson(Map json) { + languageId = json['language_id']; + localizedName = json['localized_name']; + } + + Map toJson() { + final Map data = new Map(); + data['language_id'] = this.languageId; + data['localized_name'] = this.localizedName; + return data; + } +} + +class Images { + int id; + int position; + String src; + String thumb; + String attachment; + + Images({this.id, this.position, this.src, this.thumb, this.attachment}); + + Images.fromJson(Map json) { + id = json['id']; + position = json['position']; + src = json['src']; + thumb = json['thumb']; + attachment = json['attachment']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['position'] = this.position; + data['src'] = this.src; + data['thumb'] = this.thumb; + data['attachment'] = this.attachment; + return data; + } +} + +class Specifications { + int id; + int displayOrder; + String defaultValue; + String defaultValuen; + String name; + String nameN; + + Specifications( + {this.id, + this.displayOrder, + this.defaultValue, + this.defaultValuen, + this.name, + this.nameN}); + + Specifications.fromJson(Map json) { + id = json['id']; + displayOrder = json['display_order']; + defaultValue = json['default_value']; + defaultValuen = json['default_valuen']; + name = json['name']; + nameN = json['nameN']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['display_order'] = this.displayOrder; + data['default_value'] = this.defaultValue; + data['default_valuen'] = this.defaultValuen; + data['name'] = this.name; + data['nameN'] = this.nameN; + return data; + } +} diff --git a/lib/core/model/prescriptions/Prescriptions.dart b/lib/core/model/prescriptions/Prescriptions.dart index 1362f1c2..0169010f 100644 --- a/lib/core/model/prescriptions/Prescriptions.dart +++ b/lib/core/model/prescriptions/Prescriptions.dart @@ -27,6 +27,7 @@ class Prescriptions { bool isDoctorAllowVedioCall; bool isExecludeDoctor; bool isInOutPatient; + bool isLiveCareAppointment; String isInOutPatientDescription; String isInOutPatientDescriptionN; bool isInsurancePatient; @@ -68,7 +69,7 @@ class Prescriptions { this.nationalityFlagURL, this.noOfPatientsRate, this.qR, - this.speciality}); + this.speciality,this.isLiveCareAppointment}); Prescriptions.fromJson(Map json) { setupID = json['SetupID']; @@ -103,6 +104,7 @@ class Prescriptions { nationalityFlagURL = json['NationalityFlagURL']; noOfPatientsRate = json['NoOfPatientsRate']; qR = json['QR']; + isLiveCareAppointment = json['IsLiveCareAppointment']; // speciality = json['Speciality'].cast(); } @@ -141,6 +143,7 @@ class Prescriptions { data['NoOfPatientsRate'] = this.noOfPatientsRate; data['QR'] = this.qR; data['Speciality'] = this.speciality; + data['IsLiveCareAppointment'] = this.isLiveCareAppointment; return data; } } diff --git a/lib/core/model/prescriptions/request_prescription_report.dart b/lib/core/model/prescriptions/request_prescription_report.dart index df901a99..c8323740 100644 --- a/lib/core/model/prescriptions/request_prescription_report.dart +++ b/lib/core/model/prescriptions/request_prescription_report.dart @@ -82,7 +82,7 @@ class RequestPrescriptionReport { data['EpisodeID'] = this.episodeID; data['ClinicID'] = this.clinicID; data['ProjectID'] = this.projectID; - // data['DischargeNo'] = this.dischargeNo; + data['DischargeNo'] = this.dischargeNo; return data; } } diff --git a/lib/core/model/radiology/final_radiology.dart b/lib/core/model/radiology/final_radiology.dart index 2efe4481..ed47b51d 100644 --- a/lib/core/model/radiology/final_radiology.dart +++ b/lib/core/model/radiology/final_radiology.dart @@ -41,6 +41,7 @@ class FinalRadiology { List speciality; bool isCVI; bool isRadMedicalReport; + bool isLiveCareAppointment; FinalRadiology( {this.setupID, @@ -82,7 +83,7 @@ class FinalRadiology { this.reportDataTextString, this.speciality, this.isCVI, - this.isRadMedicalReport}); + this.isRadMedicalReport,this.isLiveCareAppointment}); FinalRadiology.fromJson(Map json) { try { @@ -121,11 +122,13 @@ class FinalRadiology { orderNo = json['OrderNo']; projectName = json['ProjectName']; qR = json['QR']; + isLiveCareAppointment = json['IsLiveCareAppointment']; reportDataHTML = json['ReportDataHTML']; reportDataTextString = json['ReportDataTextString']; // speciality = json['Speciality'].cast(); isCVI = json['isCVI']; isRadMedicalReport = json['isRadMedicalReport']; + } catch (e) { print(e); } diff --git a/lib/core/model/reports/Reports.dart b/lib/core/model/reports/Reports.dart index a8a5869d..6791a3d4 100644 --- a/lib/core/model/reports/Reports.dart +++ b/lib/core/model/reports/Reports.dart @@ -11,24 +11,24 @@ class Reports { String setupId; int patientID; int doctorID; - Null clinicID; + dynamic clinicID; DateTime requestDate; bool isRead; DateTime isReadOn; int actualDoctorRate; String clinicDescription; - Null clinicDescriptionN; + dynamic clinicDescriptionN; String docName; Null docNameN; String doctorImageURL; - Null doctorName; - Null doctorNameN; + dynamic doctorName; + dynamic doctorNameN; int doctorRate; bool isDoctorAllowVedioCall; bool isExecludeDoctor; int noOfPatientsRate; String projectName; - Null projectNameN; + dynamic projectNameN; Reports( {this.status, @@ -61,37 +61,41 @@ class Reports { this.projectNameN}); Reports.fromJson(Map json) { - status = json['Status']; - encounterDate = DateUtil.convertStringToDate( - json['EncounterDate']); //json['EncounterDate']; - projectID = json['ProjectID']; - invoiceNo = json['InvoiceNo']; - encounterNo = json['EncounterNo']; - procedureId = json['ProcedureId']; - requestType = json['RequestType']; - setupId = json['SetupId']; - patientID = json['PatientID']; - doctorID = json['DoctorID']; - clinicID = json['ClinicID']; - requestDate = DateUtil.convertStringToDate( - json['RequestDate']); //json['RequestDate']; - isRead = json['IsRead']; - isReadOn = - DateUtil.convertStringToDate(json['IsReadOn']); //json['IsReadOn']; - actualDoctorRate = json['ActualDoctorRate']; - clinicDescription = json['ClinicDescription']; - clinicDescriptionN = json['ClinicDescriptionN']; - docName = json['DocName']; - docNameN = json['DocNameN']; - doctorImageURL = json['DoctorImageURL']; - doctorName = json['DoctorName']; - doctorNameN = json['DoctorNameN']; - doctorRate = json['DoctorRate']; - isDoctorAllowVedioCall = json['IsDoctorAllowVedioCall']; - isExecludeDoctor = json['IsExecludeDoctor']; - noOfPatientsRate = json['NoOfPatientsRate']; - projectName = json['ProjectName']; - projectNameN = json['ProjectNameN']; + try { + status = json['Status']; + encounterDate = DateUtil.convertStringToDate( + json['EncounterDate']); //json['EncounterDate']; + projectID = json['ProjectID']; + invoiceNo = json['InvoiceNo']; + encounterNo = json['EncounterNo']; + procedureId = json['ProcedureId']; + requestType = json['RequestType']; + setupId = json['SetupId']; + patientID = json['PatientID']; + doctorID = json['DoctorID']; + clinicID = json['ClinicID']; + requestDate = DateUtil.convertStringToDate( + json['RequestDate']); //json['RequestDate']; + isRead = json['IsRead']; + isReadOn = + DateUtil.convertStringToDate(json['IsReadOn']); //json['IsReadOn']; + actualDoctorRate = json['ActualDoctorRate']; + clinicDescription = json['ClinicDescription']; + clinicDescriptionN = json['ClinicDescriptionN']; + docName = json['DocName']; + docNameN = json['DocNameN']; + doctorImageURL = json['DoctorImageURL']; + doctorName = json['DoctorName']; + doctorNameN = json['DoctorNameN']; + doctorRate = json['DoctorRate']; + isDoctorAllowVedioCall = json['IsDoctorAllowVedioCall']; + isExecludeDoctor = json['IsExecludeDoctor']; + noOfPatientsRate = json['NoOfPatientsRate']; + projectName = json['ProjectName']; + projectNameN = json['ProjectNameN']; + }catch(e){ + print(e); + } } Map toJson() { diff --git a/lib/core/model/search_products_model.dart b/lib/core/model/search_products_model.dart new file mode 100644 index 00000000..d63fd4b0 --- /dev/null +++ b/lib/core/model/search_products_model.dart @@ -0,0 +1,185 @@ +class SearchProductsModel { + String id; + String name; + String namen; + List localizedNames; + String shortDescription; + String fullDescription; + String fullDescriptionn; + dynamic approvedRatingSum; + dynamic approvedTotalReviews; + String sku; + bool isRx; + dynamic rxMessage; + dynamic rxMessagen; + dynamic stockQuantity; + String stockAvailability; + String stockAvailabilityn; + bool allowBackInStockSubscriptions; + dynamic orderMinimumQuantity; + dynamic orderMaximumQuantity; + double price; + dynamic oldPrice; + dynamic discountName; + dynamic discountNamen; + dynamic discountPercentage; + dynamic displayOrder; + List discountIds; + List reviews; + List images; + + SearchProductsModel( + {this.id, + this.name, + this.namen, + this.localizedNames, + this.shortDescription, + this.fullDescription, + this.fullDescriptionn, + this.approvedRatingSum, + this.approvedTotalReviews, + this.sku, + this.isRx, + this.rxMessage, + this.rxMessagen, + this.stockQuantity, + this.stockAvailability, + this.stockAvailabilityn, + this.allowBackInStockSubscriptions, + this.orderMinimumQuantity, + this.orderMaximumQuantity, + this.price, + this.oldPrice, + this.discountName, + this.discountNamen, + this.discountPercentage, + this.displayOrder, + this.discountIds, + this.reviews, + this.images}); + + SearchProductsModel.fromJson(Map json) { + id = json['id']; + name = json['name']; + namen = json['namen']; + if (json['localized_names'] != null) { + localizedNames = new List(); + json['localized_names'].forEach((v) { + localizedNames.add(new LocalizedNames.fromJson(v)); + }); + } + shortDescription = json['short_description']; + fullDescription = json['full_description']; + fullDescriptionn = json['full_descriptionn']; + approvedRatingSum = json['approved_rating_sum']; + approvedTotalReviews = json['approved_total_reviews']; + sku = json['sku']; + isRx = json['is_rx']; + rxMessage = json['rx_message']; + rxMessagen = json['rx_messagen']; + stockQuantity = json['stock_quantity']; + stockAvailability = json['stock_availability']; + stockAvailabilityn = json['stock_availabilityn']; + allowBackInStockSubscriptions = json['allow_back_in_stock_subscriptions']; + orderMinimumQuantity = json['order_minimum_quantity']; + orderMaximumQuantity = json['order_maximum_quantity']; + price = json['price']; + oldPrice = json['old_price']; + discountName = json['discount_name']; + discountNamen = json['discount_namen']; + discountPercentage = json['discount_percentage']; + displayOrder = json['display_order']; + + if (json['images'] != null) { + images = new List(); + json['images'].forEach((v) { + images.add(new Images.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['name'] = this.name; + data['namen'] = this.namen; + if (this.localizedNames != null) { + data['localized_names'] = + this.localizedNames.map((v) => v.toJson()).toList(); + } + data['short_description'] = this.shortDescription; + data['full_description'] = this.fullDescription; + data['full_descriptionn'] = this.fullDescriptionn; + data['approved_rating_sum'] = this.approvedRatingSum; + data['approved_total_reviews'] = this.approvedTotalReviews; + data['sku'] = this.sku; + data['is_rx'] = this.isRx; + data['rx_message'] = this.rxMessage; + data['rx_messagen'] = this.rxMessagen; + data['stock_quantity'] = this.stockQuantity; + data['stock_availability'] = this.stockAvailability; + data['stock_availabilityn'] = this.stockAvailabilityn; + data['allow_back_in_stock_subscriptions'] = + this.allowBackInStockSubscriptions; + data['order_minimum_quantity'] = this.orderMinimumQuantity; + data['order_maximum_quantity'] = this.orderMaximumQuantity; + data['price'] = this.price; + data['old_price'] = this.oldPrice; + data['discount_name'] = this.discountName; + data['discount_namen'] = this.discountNamen; + data['discount_percentage'] = this.discountPercentage; + data['display_order'] = this.displayOrder; + + if (this.images != null) { + data['images'] = this.images.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class LocalizedNames { + int languageId; + String localizedName; + + LocalizedNames({this.languageId, this.localizedName}); + + LocalizedNames.fromJson(Map json) { + languageId = json['language_id']; + localizedName = json['localized_name']; + } + + Map toJson() { + final Map data = new Map(); + data['language_id'] = this.languageId; + data['localized_name'] = this.localizedName; + return data; + } +} + +class Images { + int id; + int position; + String src; + String thumb; + String attachment; + + Images({this.id, this.position, this.src, this.thumb, this.attachment}); + + Images.fromJson(Map json) { + id = json['id']; + position = json['position']; + src = json['src']; + thumb = json['thumb']; + attachment = json['attachment']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['position'] = this.position; + data['src'] = this.src; + data['thumb'] = this.thumb; + data['attachment'] = this.attachment; + return data; + } +} diff --git a/lib/core/model/sick_leave/sick_leave.dart b/lib/core/model/sick_leave/sick_leave.dart index ff73e1da..6811a552 100644 --- a/lib/core/model/sick_leave/sick_leave.dart +++ b/lib/core/model/sick_leave/sick_leave.dart @@ -32,6 +32,7 @@ class SickLeave { String projectName; String qR; List speciality; + bool isLiveCareAppointment; SickLeave( {this.setupID, @@ -64,7 +65,7 @@ class SickLeave { this.patientName, this.projectName, this.qR, - this.speciality}); + this.speciality,this.isLiveCareAppointment}); SickLeave.fromJson(Map json) { setupID = json['SetupID']; @@ -97,6 +98,7 @@ class SickLeave { patientName = json['PatientName']; projectName = json['ProjectName']; qR = json['QR']; + isLiveCareAppointment = json['IsLiveCareAppointment']; if(json['Speciality']!=null) speciality = json['Speciality'].cast(); } diff --git a/lib/core/model/weahter/weather_model.dart b/lib/core/model/weahter/weather_model.dart index 7ee84bac..37ee5983 100644 --- a/lib/core/model/weahter/weather_model.dart +++ b/lib/core/model/weahter/weather_model.dart @@ -32,35 +32,35 @@ class WeatherIndicatorModel { WeatherIndicatorModel( {this.date, - this.languageID, - this.serviceName, - this.time, - this.androidLink, - this.authenticationTokenID, - this.data, - this.dataw, - this.dietType, - this.errorCode, - this.errorEndUserMessage, - this.errorEndUserMessageN, - this.errorMessage, - this.errorType, - this.foodCategory, - this.iOSLink, - this.isAuthenticated, - this.mealOrderStatus, - this.mealType, - this.messageStatus, - this.numberOfResultRecords, - this.patientBlodType, - this.successMsg, - this.successMsgN, - this.citiesList, - this.cityName, - this.get5DaysWeatherForecastList, - this.getCityInfoList, - this.getTodayWeatherForecastList, - this.iniciesList}); + this.languageID, + this.serviceName, + this.time, + this.androidLink, + this.authenticationTokenID, + this.data, + this.dataw, + this.dietType, + this.errorCode, + this.errorEndUserMessage, + this.errorEndUserMessageN, + this.errorMessage, + this.errorType, + this.foodCategory, + this.iOSLink, + this.isAuthenticated, + this.mealOrderStatus, + this.mealType, + this.messageStatus, + this.numberOfResultRecords, + this.patientBlodType, + this.successMsg, + this.successMsgN, + this.citiesList, + this.cityName, + this.get5DaysWeatherForecastList, + this.getCityInfoList, + this.getTodayWeatherForecastList, + this.iniciesList}); WeatherIndicatorModel.fromJson(Map json) { date = json['Date']; @@ -162,24 +162,24 @@ class GetCityInfoList { GetCityInfoList( {this.categoriesNames, - this.category, - this.categoryValue, - this.cityID, - this.cityName, - this.cityNameN, - this.colorName, - this.createdOn, - this.iD, - this.iniceID, - this.isOrderEmpty, - this.isValuesReversed, - this.language, - this.latitude, - this.longitude, - this.name, - this.orderNum, - this.temperature, - this.value}); + this.category, + this.categoryValue, + this.cityID, + this.cityName, + this.cityNameN, + this.colorName, + this.createdOn, + this.iD, + this.iniceID, + this.isOrderEmpty, + this.isValuesReversed, + this.language, + this.latitude, + this.longitude, + this.name, + this.orderNum, + this.temperature, + this.value}); GetCityInfoList.fromJson(Map json) { categoriesNames = json['CategoriesNames'] != null @@ -241,10 +241,10 @@ class CategoriesNames { CategoriesNames( {this.category1, - this.category2, - this.category3, - this.category4, - this.category5}); + this.category2, + this.category3, + this.category4, + this.category5}); CategoriesNames.fromJson(Map json) { category1 = json['Category1']; @@ -264,3 +264,4 @@ class CategoriesNames { return data; } } + diff --git a/lib/core/service/AlHabibMedicalService/customer_addresses_service.dart b/lib/core/service/AlHabibMedicalService/customer_addresses_service.dart index cb457735..da12b48b 100644 --- a/lib/core/service/AlHabibMedicalService/customer_addresses_service.dart +++ b/lib/core/service/AlHabibMedicalService/customer_addresses_service.dart @@ -1,13 +1,4 @@ import 'package:diplomaticquarterapp/config/config.dart'; -import 'package:diplomaticquarterapp/core/enum/OrderService.dart'; -import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/HomeHealthCare/HHC_get_all_services_request_modle.dart'; -import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/HomeHealthCare/HHC_get_all_services_response_model.dart'; -import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/HomeHealthCare/get_hHC_all_pres_orders_request_model.dart'; -import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/HomeHealthCare/get_hhc_all_pres_orders_response_model.dart'; -import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/HomeHealthCare/get_order_detail_by_order_iD_request_model.dart'; -import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/HomeHealthCare/get_order_detail_by_order_iD_response_model.dart'; -import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/HomeHealthCare/patient_er_insert_pres_order_request_model.dart'; -import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/HomeHealthCare/update_pres_oreder_request_model.dart'; import 'package:diplomaticquarterapp/core/viewModels/AlHabibMedicalService/add_new_address_Request_Model.dart'; import 'package:intl/intl.dart'; @@ -41,10 +32,10 @@ class CustomerAddressesService extends BaseService { addressesList .add(AddressInfo.fromJson(data)); }); - }, onFailure: (String error, int statusCode) { - hasError = true; - super.error = error; - }, body: addNewAddressRequestModel.toJson(), isExternal: true, isAllowAny: true); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body: addNewAddressRequestModel.toJson(), isExternal: true, isAllowAny: true); } Future getCustomerAddresses() async { @@ -59,10 +50,10 @@ class CustomerAddressesService extends BaseService { addressesList .add(AddressInfo.fromJson(data)); }); - }, onFailure: (String error, int statusCode) { - hasError = true; - super.error = error; - }, queryParams: queryParams, isExternal: true); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, queryParams: queryParams, isExternal: true); } diff --git a/lib/core/service/AlHabibMedicalService/e_referral_service.dart b/lib/core/service/AlHabibMedicalService/e_referral_service.dart index 3670e965..6c356f5c 100644 --- a/lib/core/service/AlHabibMedicalService/e_referral_service.dart +++ b/lib/core/service/AlHabibMedicalService/e_referral_service.dart @@ -2,7 +2,6 @@ import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/EReferral/check_activation_code_for_e_referral_request_model.dart'; import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/EReferral/create_e_referral_request_model.dart'; import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/EReferral/get_all_cities_response_model.dart'; -import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/EReferral/get_all_projects_response_model.dart'; import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/EReferral/get_all_relationship_types_response_model.dart'; import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/EReferral/search_e_referral_request_model.dart'; import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/EReferral/search_e_referral_response_model.dart'; @@ -11,18 +10,11 @@ import 'package:diplomaticquarterapp/core/service/base_service.dart'; class EReferralService extends BaseService { List _relationTypes = List(); - List get relationTypes => _relationTypes; List _allCities = List(); - List get allCities => _allCities; - List _allProjects = List(); - - List get allProjects => _allProjects; - List _allReferral = List(); - List get allReferral => _allReferral; String _activationCode; String _logInTokenID; @@ -50,106 +42,84 @@ class EReferralService extends BaseService { Future getAllCities() async { await baseAppClient.post(GET_ALL_CITIES, onSuccess: (dynamic response, int statusCode) { - _allCities.clear(); - response['ListCities'].forEach((city) { - _allCities.add(GetAllCitiesResponseModel.fromJson(city)); - }); - }, onFailure: (String error, int statusCode) { - hasError = true; - super.error = error; - }, body: {}); - } - - Future getAllProjects() async { - await baseAppClient.post(GET_PROJECT, - onSuccess: (dynamic response, int statusCode) { - _allProjects.clear(); - response['ListProject'].forEach((city) { - _allProjects.add(GetAllProjectsResponseModel.fromJson(city)); - }); - }, onFailure: (String error, int statusCode) { - hasError = true; - super.error = error; - }, body: {}); + _allCities.clear(); + response['ListCities'].forEach((city) { + _allCities + .add(GetAllCitiesResponseModel.fromJson(city)); + }); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body: {}); } Future sendActivationCodeForEReferral( + SendActivationCodeForEReferralRequestModel sendActivationCodeForEReferralRequestModel) async { hasError = false; await baseAppClient.post(SEND_ACTIVATION_CODE_FOR_E_REFERRAL, onSuccess: (dynamic response, int statusCode) { - print(response["VerificationCode"]); _activationCode = response["VerificationCode"]; _logInTokenID = response["LogInTokenID"]; + }, onFailure: (String error, int statusCode) { hasError = true; super.error = error; }, body: sendActivationCodeForEReferralRequestModel.toJson()); } + + Future checkActivationCodeForEReferral( CheckActivationCodeForEReferralResponseModel checkActivationCodeForEReferralRequestModel) async { checkActivationCodeForEReferralRequestModel.isDentalAllowedBackend = false; - checkActivationCodeForEReferralRequestModel.logInTokenID = _logInTokenID; - hasError = false; + checkActivationCodeForEReferralRequestModel.logInTokenID= _logInTokenID; + hasError =false; await baseAppClient.post(CHECK_ACTIVATION_CODE_FOR_E_REFERRAL, onSuccess: (dynamic response, int statusCode) { - _isActivationCodeValid = true; + _isActivationCodeValid = true; }, onFailure: (String error, int statusCode) { hasError = true; super.error = error; }, body: checkActivationCodeForEReferralRequestModel.toJson()); } - Future createEReferral( - CreateEReferralRequestModel createEReferralRequestModel) async { - hasError = false; - dynamic localRes; - await baseAppClient.post( - CREATE_E_REFERRAL /*'Services/Patients.svc/REST/CreateEReferral'*/, - onSuccess: (dynamic response, int statusCode) { - // TODO Waiting for fix service - localRes = response; - }, onFailure: (String error, int statusCode) { - hasError = true; - super.error = error; - }, body: createEReferralRequestModel.toJson()); - return Future.value(localRes); - } - - Future getEReferrals( - SearchEReferralRequestModel searchEReferralRequestModel) async { - hasError = false; - dynamic localRes; - await baseAppClient.post(GET_E_REFERRALS, + Future createEReferral( + CreateEReferralRequestModel createEReferralRequestModel + ) async { + hasError = false; + await baseAppClient.post(CREATE_E_REFERRAL/*'Services/Patients.svc/REST/CreateEReferral'*/, onSuccess: (dynamic response, int statusCode) { - print("EEEEEE"); - _allReferral.clear(); - localRes = response; - }, onFailure: (String error, int statusCode) { - hasError = true; - super.error = error; - }, body: searchEReferralRequestModel.toJson()); - return Future.value(localRes); - } + // TODO Waiting for fix service + var asd= ("EEEEEE"); - Future getEReferralsIfLogin(String mobileNo) async { - hasError = false; - dynamic localRes; - Map request = {}; - request['PatientMobileNumber'] = mobileNo; - await baseAppClient.post(GET_E_REFERRALS, - onSuccess: (dynamic response, int statusCode) { - print("EEEEEE"); - _allReferral.clear(); - localRes = response; }, onFailure: (String error, int statusCode) { hasError = true; super.error = error; - }, body: request); - return Future.value(localRes); + }, body: createEReferralRequestModel.toJson()); } + Future getEReferrals( + SearchEReferralRequestModel searchEReferralRequestModel + ) async { + hasError = false; + // TODO return this code when the fix the server + // await baseAppClient.post(GET_E_REFERRALS, + // onSuccess: (dynamic response, int statusCode) { + // print("EEEEEE"); + // // TODO Waiting for fix service + // // ToDo change this one when you have data + // _allReferral.clear(); + // // response['ListCities'].forEach((city) { + // // _allReferral + // // .add(SearchEReferralResponseModel.fromJson(city)); + // // }); + // + // }, onFailure: (String error, int statusCode) { + // hasError = true; + // super.error = error; + // }, body: searchEReferralRequestModel.toJson()); + } } diff --git a/lib/core/service/AuthenticatedUserObject.dart b/lib/core/service/AuthenticatedUserObject.dart index f48b1179..8dd2583d 100644 --- a/lib/core/service/AuthenticatedUserObject.dart +++ b/lib/core/service/AuthenticatedUserObject.dart @@ -11,14 +11,14 @@ class AuthenticatedUserObject { getUser(); } - getUser() async { - if (user == null) { + getUser({bool getUser = false}) async { + if (getUser) { + var userData = await sharedPref.getObject(USER_PROFILE); + if (userData != null) user = AuthenticatedUser.fromJson(userData); + } else if (user == null) { var userData = await sharedPref.getObject(USER_PROFILE); if (userData != null) user = AuthenticatedUser.fromJson(userData); } - - // var isLogin = await sharedPref.getString(LOGIN_TOKEN_ID); - this.isLogin = user != null; } logout() async { diff --git a/lib/core/service/childvaccines/add_new_child_service.dart b/lib/core/service/childvaccines/add_new_child_service.dart index 98e87100..5e4a4d86 100644 --- a/lib/core/service/childvaccines/add_new_child_service.dart +++ b/lib/core/service/childvaccines/add_new_child_service.dart @@ -14,12 +14,19 @@ class CreteNewBabyService extends BaseService { Future getCreateNewBabyOrders({CreateNewBaby newChild,int userID}) async { hasError = false; + await getUser(); Map body = Map.from(newChild.toJson()); body['CreatedBy'] = 102; body['EditedBy'] = 102; body['UserID'] = userID; body['AlertBy'] = 2; + body['EmailAddress'] = user.emailAddress; body['IsLogin'] = true; + body['LogInTokenID'] = await sharedPref.getString(TOKEN); + body['MobileNumber'] = user.mobileNumber; + body['NationalID'] = user.nationalityID; + body['ZipCode'] = user.zipCode; + body['isDentalAllowedBackend'] = false; await baseAppClient.post(GET_NEWCHILD_REQUEST, diff --git a/lib/core/service/childvaccines/delete_baby_service.dart b/lib/core/service/childvaccines/delete_baby_service.dart index 49cbd29e..115d13c5 100644 --- a/lib/core/service/childvaccines/delete_baby_service.dart +++ b/lib/core/service/childvaccines/delete_baby_service.dart @@ -1,5 +1,4 @@ import 'package:diplomaticquarterapp/config/config.dart'; -import 'package:diplomaticquarterapp/core/model/childvaccines/List_BabyInformationModel.dart'; import 'package:diplomaticquarterapp/core/model/childvaccines/add_newchild_model.dart'; import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/core/model/childvaccines/create_new_user_model.dart'; @@ -18,13 +17,22 @@ class DeleteBabyService extends BaseService{ List deleteBabyModelList= List(); - Future getDeleteBabyOrder({List_BabyInformationModel babyInfo}) async { + Future getDeleteBabyOrder({DeleteBaby deleteChild,int babyID}) async { hasError = false; await getUser(); - Map body = Map(); + Map body = Map.from(deleteChild.toJson()); + // body['CreatedBy'] = 102; body['EditedBy'] = 102; + //body['BabyID'] = babyID; + //body['BabyID'] = createNewBabyModelList ; + // body['AlertBy'] = 2; + // body['EmailAddress'] = user.emailAddress; body['IsLogin'] = true; - body['BabyID'] = babyInfo.babyID; + body['LogInTokenID'] = await sharedPref.getString(TOKEN); + body['MobileNumber'] = user.mobileNumber; + body['NationalID'] = user.nationalityID; + body['ZipCode'] = user.zipCode; + body['isDentalAllowedBackend'] = false; await baseAppClient.post(DELETE_CHILD_REQUEST, @@ -37,6 +45,31 @@ class DeleteBabyService extends BaseService{ }, body: body); } - + // Future getCreateNewBabyOrders({CreateNewBaby newChild,int userID}) async { + // hasError = false; + // await getUser(); + // Map body = Map.from(newChild.toJson()); + // body['CreatedBy'] = 102; + // body['EditedBy'] = 102; + // body['UserID'] = userID; + // body['AlertBy'] = 2; + // body['EmailAddress'] = user.emailAddress; + // body['IsLogin'] = true; + // body['LogInTokenID'] = await sharedPref.getString(TOKEN); + // body['MobileNumber'] = user.mobileNumber; + // body['NationalID'] = user.nationalityID; + // body['ZipCode'] = user.zipCode; + // + // body['isDentalAllowedBackend'] = false; + // + // await baseAppClient.post(GET_NEWCHILD_REQUEST, + // onSuccess: (dynamic response, int statusCode) { + // var asd =""; + // }, + // onFailure: (String error, int statusCode) { + // hasError = true; + // super.error = error; + // }, body: body); + // } } \ No newline at end of file diff --git a/lib/core/service/childvaccines/get_vaccinations_item_services.dart b/lib/core/service/childvaccines/get_vaccinations_item_services.dart new file mode 100644 index 00000000..5ff936af --- /dev/null +++ b/lib/core/service/childvaccines/get_vaccinations_item_services.dart @@ -0,0 +1,27 @@ +import 'package:diplomaticquarterapp/config/config.dart'; +import 'package:diplomaticquarterapp/core/model/childvaccines/get_vacainations_itemsmodel.dart'; + +import '../base_service.dart'; + +class GetVccinationsItemsService extends BaseService { + List getVaccinationsItemModelList = List(); + Map body = Map(); + + + + Future getaccinationsitemOrders() async { + hasError = false; + await baseAppClient.post(GET_TABLE_REQUEST, + onSuccess: (dynamic response, int statusCode) { + getVaccinationsItemModelList.clear(); + response['List_CreateVaccinationTableModel'].forEach((vital) { + getVaccinationsItemModelList.add( + GET_VACCINATIONS_ITEMSMODEL.fromJson(vital)); + }); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body: body); + } + +} \ No newline at end of file diff --git a/lib/core/service/childvaccines/user_information_service.dart b/lib/core/service/childvaccines/user_information_service.dart index 55ddc259..0628920c 100644 --- a/lib/core/service/childvaccines/user_information_service.dart +++ b/lib/core/service/childvaccines/user_information_service.dart @@ -4,11 +4,11 @@ import 'package:diplomaticquarterapp/core/model/childvaccines/user_information_m import '../base_service.dart'; class UserInformationService extends BaseService { - List_UserInformationModel userInformationModel = List_UserInformationModel(); + List userInformationModelList = List(); + Map body = Map(); Future getUserInformationOrders() async { hasError = false; - Map body = Map(); await getUser(); body['CreatedBy'] = 102; body['EditedBy'] = 102; @@ -22,44 +22,14 @@ class UserInformationService extends BaseService { await baseAppClient.post(GET_USERINFORMATION_REQUEST, onSuccess: (dynamic response, int statusCode) { + userInformationModelList.clear(); + response['List_UserInformationModel_New'].forEach((vital) { - userInformationModel = List_UserInformationModel.fromJson(vital); + userInformationModelList.add(List_UserInformationModel.fromJson(vital)); }); }, onFailure: (String error, int statusCode) { hasError = true; super.error = error; }, body: body); } - - Future updateEmail(String email) async { - hasError = false; - Map body = Map(); - body['IsInternalRequest'] = true; - body['EmailAddress'] = email; - body['IsLogin'] = true; - body['isDentalAllowedBackend'] = false; - await baseAppClient.post(UPDATE_PATENT_EMAIL, - onSuccess: (dynamic response, int statusCode) { - var asd = ""; - }, onFailure: (String error, int statusCode) { - hasError = true; - super.error = error; - }, body: body); - } - - Future updateUserInfo(String email) async { - hasError = false; - Map body = Map(); - body['IsInternalRequest'] = true; - body['EmailAddress'] = email; - body['IsLogin'] = true; - body['isDentalAllowedBackend'] = false; - await baseAppClient.post(UPDATE_PATENT_INFO, - onSuccess: (dynamic response, int statusCode) { - var asd = ""; - }, onFailure: (String error, int statusCode) { - hasError = true; - super.error = error; - }, body: body); - } } diff --git a/lib/core/service/childvaccines/vaccination_table_service.dart b/lib/core/service/childvaccines/vaccination_table_service.dart index da3c8518..7f987b76 100644 --- a/lib/core/service/childvaccines/vaccination_table_service.dart +++ b/lib/core/service/childvaccines/vaccination_table_service.dart @@ -1,9 +1,7 @@ import 'package:diplomaticquarterapp/config/config.dart'; -import 'package:diplomaticquarterapp/core/model/childvaccines/List_BabyInformationModel.dart'; import 'package:diplomaticquarterapp/core/model/childvaccines/add_newchild_model.dart'; import 'package:diplomaticquarterapp/core/model/childvaccines/create_vaccination_table.dart'; import 'package:diplomaticquarterapp/core/model/childvaccines/user_information_model.dart'; -import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; import '../base_service.dart'; class VaccinationTableService extends BaseService { @@ -12,16 +10,19 @@ class VaccinationTableService extends BaseService { - Future getCreateVaccinationTableOrders({List_BabyInformationModel babyInfo, List_UserInformationModel informationModel, bool isSendEmail=false}) async { + Future getCreateVaccinationTableOrders() async { hasError = false; await getUser(); - body['BabyName']=babyInfo.babyName; - body['DOB'] = DateUtil.convertDateToString(babyInfo.dOB); - body['EmailAddress'] = informationModel.emailAddress; + body['BabyName']="fffffffffff eeeeeeeeeeeeee"; + body['DOB'] = "/Date(1585774800000+0300)/"; + body['EmailAddress'] = user.emailAddress; body['isDentalAllowedBackend'] = false; - body['SendEmail'] = isSendEmail; + body['SendEmail'] = false; body['IsLogin'] =true; + + + await baseAppClient.post(GET_TABLE_REQUEST, onSuccess: (dynamic response, int statusCode) { createVaccinationTableModelList.clear(); diff --git a/lib/core/service/client/base_app_client.dart b/lib/core/service/client/base_app_client.dart index 89c0775c..3788cf98 100644 --- a/lib/core/service/client/base_app_client.dart +++ b/lib/core/service/client/base_app_client.dart @@ -4,8 +4,9 @@ import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/core/service/medical/vital_sign_service.dart'; import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; -import 'package:diplomaticquarterapp/pages/appUpdatePage/app_update_page.dart'; +import 'package:diplomaticquarterapp/models/Appointments/toDoCountProviderModel.dart'; import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; +import 'package:diplomaticquarterapp/pages/appUpdatePage/app_update_page.dart'; import 'package:diplomaticquarterapp/uitl/utils.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -58,15 +59,7 @@ class BaseAppClient { body['VersionID'] = VERSION_ID; body['Channel'] = CHANNEL; - body['LanguageID'] = body.containsKey('LanguageID') - ? body['LanguageID'] != null - ? body['LanguageID'] - : languageID == 'ar' - ? 1 - : 2 - : languageID == 'en' - ? 2 - : 1; + body['LanguageID'] = languageID == 'ar' ? 1 : 2; body['IPAdress'] = IP_ADDRESS; body['generalid'] = GENERAL_ID; @@ -148,13 +141,25 @@ class BaseAppClient { } else if (parsed['Result'] == 'OK') { onSuccess(parsed, statusCode); } else { - onFailure( - parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], - statusCode); + if (parsed != null) { + onSuccess(parsed, statusCode); + } else { + onFailure( + parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], + statusCode); + logout(); + } } } else if (parsed['MessageStatus'] == 1 || parsed['SMSLoginRequired'] == true) { onSuccess(parsed, statusCode); + } else if (parsed['MessageStatus'] == 2 && + parsed['IsAuthenticated']) { + onFailure( + parsed['message'] ?? + parsed['ErrorEndUserMessage'] ?? + parsed['ErrorMessage'], + statusCode); } else if (!parsed['IsAuthenticated']) { await logout(); @@ -163,9 +168,13 @@ class BaseAppClient { if (parsed['SameClinicApptList'] != null) { onSuccess(parsed, statusCode); } else { - onFailure( - parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], - statusCode); + if (parsed['message'] != null) { + onFailure(parsed['message'] ?? parsed['message'], statusCode); + } else { + onFailure( + parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], + statusCode); + } } } } @@ -175,8 +184,7 @@ class BaseAppClient { } } catch (e) { print(e); - onFailure('Failed to connect to the server', -1); - // onFailure(e.toString(), -1); + onFailure(e.toString(), -1); } } @@ -227,18 +235,110 @@ class BaseAppClient { } } + getPharmacy(String endPoint, + {Function(dynamic response, int statusCode) onSuccess, + Function(String error, int statusCode) onFailure, + bool isAllowAny = false, + Map queryParams}) async { + String url = PHARMACY_BASE_URL + endPoint; + if (queryParams != null) { + String queryString = Uri(queryParameters: queryParams).query; + url += '?' + queryString; + } + + print("URL : $url"); + + if (await Utils.checkConnection()) { + final response = await http.get(url.trim(), headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json' + }); + final int statusCode = response.statusCode; + print("statusCode :$statusCode"); + + if (statusCode < 200 || statusCode >= 400 || json == null) { + onFailure('Error While Fetching data', statusCode); + } else { + var parsed = json.decode(response.body.toString()); + onSuccess(parsed, statusCode); + } + } else { + onFailure('Please Check The Internet Connection', -1); + } + } + + simpleGet(String fullUrl, + {Function(dynamic response, int statusCode) onSuccess, + Function(String error, int statusCode) onFailure, + Map queryParams}) async { + String url = fullUrl; + var haveParams = (queryParams != null); + if (haveParams) { + String queryString = Uri(queryParameters: queryParams).query; + url += '?' + queryString; + print("URL Query String: $url"); + } + + if (await Utils.checkConnection()) { + final response = await http.get( + url.trim(), + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json' + }, + ); + + final int statusCode = response.statusCode; + print("statusCode :$statusCode"); + + if (statusCode < 200 || statusCode >= 400 || json == null) { + onFailure('Error While Fetching data', statusCode); + } else { + onSuccess(response.body.toString(), statusCode); + } + } else { + onFailure('Please Check The Internet Connection', -1); + } + } + logout() async { await sharedPref.remove(LOGIN_TOKEN_ID); + await sharedPref.remove(PHARMACY_CUSTOMER_ID); await authenticatedUserObject.getUser(); Provider.of(AppGlobal.context, listen: false).isLogin = false; + var model = + Provider.of(AppGlobal.context, listen: false); _vitalSignService.weightKg = ""; _vitalSignService.heightCm = ""; + model.setState(0, false); Navigator.of(AppGlobal.context).pushReplacementNamed(HOME); } String getSessionId(String id) { ///return id.replaceAll(RegExp('/[^\w\s]/'), ''); - // return id.replaceAll(RegExp('/[^a-zA-Z ]'), ''); + return id.replaceAll(RegExp('/[^a-zA-Z ]'), ''); + } + + static defaultHttpParameters() async { + String token = await sharedPref.getString(TOKEN); + var languageID = + await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar'); + var user = await sharedPref.getObject(USER_PROFILE); + var params = {}; + if (user != null) { + params['TokenID'] = token; + params['PatientID'] = user['PatientID']; + params['PatientOutSA'] = user['OutSA']; + params['SessionID'] = SESSION_ID; //getSessionId(token); + } + + params['IPAdress'] = IP_ADDRESS; + params['generalid'] = GENERAL_ID; + params['VersionID'] = VERSION_ID; + params['Channel'] = CHANNEL; + params['LanguageID'] = languageID == 'ar' ? 1 : 2; + + return params; } } diff --git a/lib/core/service/contactus/livechat_service.dart b/lib/core/service/contactus/livechat_service.dart index b806d56b..025073ca 100644 --- a/lib/core/service/contactus/livechat_service.dart +++ b/lib/core/service/contactus/livechat_service.dart @@ -8,6 +8,7 @@ class LiveChatService extends BaseService { List LivechatModelList = List(); Map body = Map(); + // body['body'] Future getAllLiveChatOrders() async { hasError = false; diff --git a/lib/core/service/geofencing/GeofencingServices.dart b/lib/core/service/geofencing/GeofencingServices.dart new file mode 100644 index 00000000..56b4f56e --- /dev/null +++ b/lib/core/service/geofencing/GeofencingServices.dart @@ -0,0 +1,66 @@ +import 'dart:convert'; +import 'dart:developer'; + +import 'package:diplomaticquarterapp/config/config.dart'; +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/core/model/geofencing/requests/GeoZonesRequestModel.dart'; +import 'package:diplomaticquarterapp/core/model/geofencing/requests/LogGeoZoneRequestModel.dart'; +import 'package:diplomaticquarterapp/core/model/geofencing/responses/GeoZonesResponseModel.dart'; +import 'package:diplomaticquarterapp/core/model/geofencing/responses/LogGeoZoneResponseModel.dart'; +import 'package:diplomaticquarterapp/core/service/base_service.dart'; +import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; + +import '../../../locator.dart'; + +class GeofencingServices extends BaseService { + List geoZones = List(); + bool testZones = true; + + Future> getAllGeoZones(GeoZonesRequestModel request) async { + hasError = false; + + var _zonesJsonString; + await baseAppClient.post(GET_GEO_ZONES, onSuccess: (dynamic response, int statusCode) { + var zones = response['GeoF_PointsList']; + zones.forEach((json) { + geoZones.add(GeoZonesResponseModel().fromJson(json)); + }); + + if (kDebugMode || testZones) addTestingGeoZones(zones); + + _zonesJsonString = json.encode(zones); + }, onFailure: (String error, int statusCode) { + hasError = true; + return Future.error(error); + }, body: request.toFlatMap()); + + AppSharedPreferences pref = AppSharedPreferences(); + await pref.setString(HMG_GEOFENCES, _zonesJsonString); + debugPrint("Finished Fetching GEO ZONES from HMG service..."); + debugPrint("GEO ZONES saved to AppPreferences with key '$HMG_GEOFENCES'"); + + return geoZones; + } + + LogGeoZoneResponseModel logResponse; + Future logGeoZone(LogGeoZoneRequestModel request) async { + hasError = false; + await baseAppClient.post(LOG_GEO_ZONES, onSuccess: (dynamic response, int statusCode) { + logResponse = LogGeoZoneResponseModel().fromJson(response); + }, onFailure: (String error, int statusCode) { + hasError = true; + return Future.error(error); + }, body: request.toFlatMap()); + return logResponse; + } + + addTestingGeoZones(List zones) { + // zones.add({"GEOF_ID": 12, "Description": "ZiK Home", "Latitude": "24.691136", "Longitude": "46.650116", "Radius": 100, "Type": 1}); + // zones.add({"GEOF_ID": 13, "Description": "CS Office", "Latitude": "24.7087913", "Longitude": "46.6656461", "Radius": 100, "Type": 1}); + // zones.add({"GEOF_ID": 14, "Description": "Mahmoud Shrouf Home", "Latitude": "24.777577", "Longitude": "46.652675", "Radius": 100, "Type": 1}); + // zones.add({"GEOF_ID": 14, "Description": "Panorama Mall", "Latitude": "24.692453", "Longitude": "46.669168", "Radius": 450, "Type": 1}); + // zones.add({"GEOF_ID": 16, "Description": "Saudi Architects Crossing", "Latitude": "24.698375", "Longitude": "46.668567", "Radius": 140, "Type": 1}); + } +} diff --git a/lib/core/service/hospital_service.dart b/lib/core/service/hospital_service.dart index 194b8256..312d7fd7 100644 --- a/lib/core/service/hospital_service.dart +++ b/lib/core/service/hospital_service.dart @@ -13,14 +13,13 @@ class HospitalService extends BaseService { double _longitude; _getCurrentLocation() async { - await getLastKnownPosition().then((value) { + await Geolocator.getLastKnownPosition().then((value) { _latitude = value.latitude; _longitude = value.longitude; }).catchError((e) { _longitude = 0; _latitude = 0; }); - // currentLocation = LatLng(position.latitude, position.longitude); } Future getHospitals() async { @@ -28,6 +27,8 @@ class HospitalService extends BaseService { Map body = Map(); body['Latitude'] = _latitude; body['Longitude'] = _longitude; + body['IsOnlineCheckIn'] = true; + body['PatientOutSA'] = 0; await baseAppClient.post(GET_PROJECT, onSuccess: (dynamic response, int statusCode) { diff --git a/lib/core/service/insurance_service.dart b/lib/core/service/insurance_service.dart index 790003e9..0b626342 100644 --- a/lib/core/service/insurance_service.dart +++ b/lib/core/service/insurance_service.dart @@ -1,8 +1,9 @@ import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/core/model/insurance/Insurance_card_details.dart'; import 'package:diplomaticquarterapp/core/model/insurance/insurance_approval.dart'; import 'package:diplomaticquarterapp/core/model/insurance/insurance_card.dart'; -import 'package:diplomaticquarterapp/core/model/insurance/insurance_card_update.dart'; +import 'package:diplomaticquarterapp/core/model/insurance/insurance_card_update_model.dart'; import 'package:diplomaticquarterapp/core/service/base_service.dart'; import 'package:diplomaticquarterapp/models/FamilyFiles/GetAllSharedRecordByStatusResponse.dart'; import 'package:diplomaticquarterapp/models/FamilyFiles/GetAllSharedRecordsByStatusReq.dart'; @@ -20,6 +21,10 @@ class InsuranceCardService extends BaseService { List get insuranceApproval => _insuranceApproval; + InsuranceCardDetailsModel insuranceCardDetails; + List insuranceCardDetailsList = List(); + bool isHaveInsuranceCard = false; + GetAllSharedRecordsByStatusResponse getAllSharedRecordsByStatusResponse = GetAllSharedRecordsByStatusResponse(); @@ -136,4 +141,42 @@ class InsuranceCardService extends BaseService { }, body:{'CompanyID': data.companyID,'SubCategoryID':data.subCategoryID },); return Future.value(localRes); } + + Future getPatientInsuranceDetails({String setupID, int projectID, String patientIdentificationID,int patientID}) async{ + error = ""; + hasError = false; + insuranceCardDetails = null; + isHaveInsuranceCard = false; + await baseAppClient.post(GET_PATIENT_INSURANCE_DETAILS, + onSuccess: (dynamic response, int statusCode) { + insuranceCardDetailsList.clear(); + isHaveInsuranceCard = true; + response['List_PatientInsuranceDetails'].forEach((item) { + insuranceCardDetailsList.add(InsuranceCardDetailsModel.fromJson(item)); + }); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body:{'SetupID': setupID,'ProjectID':projectID,'PatientIdentificationID':patientIdentificationID ,'isDentalAllowedBackend':false,'PatientID':patientID},); + + } + + Future uploadInsuranceCard({ String patientIdentificationID,int patientID,String image=""}) async{ + error = ""; + Map body = Map(); + body['PatientID']=patientID; + body['PatientType']=user.patientType; + body['MobileNo']=user.mobileNumber; + body['PatientIdentificationID']=patientIdentificationID; + body['InsuranceCardImage']= image; + + await baseAppClient.post(UPLOAD_INSURANCE_CARD, + onSuccess: (dynamic response, int statusCode) { + + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body:body,); + + } } diff --git a/lib/core/service/medical/PatientSickLeaveService.dart b/lib/core/service/medical/PatientSickLeaveService.dart index b2bb16ef..bb60ee3b 100644 --- a/lib/core/service/medical/PatientSickLeaveService.dart +++ b/lib/core/service/medical/PatientSickLeaveService.dart @@ -21,7 +21,11 @@ class PatientSickLeaveService extends BaseService { } sendSickLeaveEmail( - {int requestNo, String projectName, String doctorName, int projectID,String setupID}) async { + {int requestNo, + String projectName, + String doctorName, + int projectID, + String setupID}) async { hasError = false; super.error = ""; Map body = Map(); @@ -33,8 +37,8 @@ class PatientSickLeaveService extends BaseService { body['PatientName'] = user.firstName + " " + user.firstName; body['ProjectName'] = projectName; body['DoctorName'] = doctorName; - body['ProjectID'] = 12; - body['SetupID'] = 12; + body['ProjectID'] = projectID; + body['SetupID'] = setupID; await baseAppClient .post(SendSickLeaveEmail, onSuccess: (response, statusCode) async {}, onFailure: (String error, int statusCode) { diff --git a/lib/core/service/medical/labs_service.dart b/lib/core/service/medical/labs_service.dart index b9b9a16c..11592956 100644 --- a/lib/core/service/medical/labs_service.dart +++ b/lib/core/service/medical/labs_service.dart @@ -1,4 +1,5 @@ import 'package:diplomaticquarterapp/config/config.dart'; +import 'package:diplomaticquarterapp/core/model/labs/LabOrderResult.dart'; import 'package:diplomaticquarterapp/core/model/labs/lab_result.dart'; import 'package:diplomaticquarterapp/core/model/labs/patient_lab_orders.dart'; import 'package:diplomaticquarterapp/core/model/labs/patient_lab_special_result.dart'; @@ -32,6 +33,7 @@ class LabsService extends BaseService { List patientLabSpecialResult = List(); List labResultList = List(); + List labOrdersResultsList = List(); Future getLaboratoryResult( {String projectID, @@ -68,6 +70,7 @@ class LabsService extends BaseService { await baseAppClient.post(GET_Patient_LAB_RESULT, onSuccess: (dynamic response, int statusCode) { patientLabSpecialResult.clear(); + labResultList.clear(); response['ListPLR'].forEach((lab) { labResultList.add(LabResult.fromJson(lab)); }); @@ -77,6 +80,28 @@ class LabsService extends BaseService { }, body: body); } + Future getPatientLabOrdersResults({PatientLabOrders patientLabOrder,String procedure}) async { + hasError = false; + Map body = Map(); + body['InvoiceNo'] = patientLabOrder.invoiceNo; + body['OrderNo'] = patientLabOrder.orderNo; + body['isDentalAllowedBackend'] = false; + body['SetupID'] = patientLabOrder.setupID; + body['ProjectID'] = patientLabOrder.projectID; + body['ClinicID'] = patientLabOrder.clinicID; + body['Procedure'] = procedure; + await baseAppClient.post(GET_Patient_LAB_ORDERS_RESULT, + onSuccess: (dynamic response, int statusCode) { + labOrdersResultsList.clear(); + response['ListPLR'].forEach((lab) { + labOrdersResultsList.add(LabOrderResult.fromJson(lab)); + }); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body: body); + } + RequestSendLabReportEmail _requestSendLabReportEmail = RequestSendLabReportEmail(); @@ -85,19 +110,19 @@ class LabsService extends BaseService { _requestSendLabReportEmail.invoiceNo = patientLabOrder.invoiceNo; _requestSendLabReportEmail.doctorName = patientLabOrder.doctorName; _requestSendLabReportEmail.clinicName = patientLabOrder.clinicDescription; - _requestSendLabReportEmail.patientName = user.firstName + user.lastName; + _requestSendLabReportEmail.patientName = user.firstName +" "+ user.lastName; _requestSendLabReportEmail.patientIditificationNum = user.patientIdentificationNo; _requestSendLabReportEmail.dateofBirth = user.dateofBirth; _requestSendLabReportEmail.to = user.emailAddress; - _requestSendLabReportEmail.orderDate = - '${patientLabOrder.orderDate.year}-${patientLabOrder.orderDate.month}-${patientLabOrder.orderDate.day}'; + _requestSendLabReportEmail.orderDate = '${patientLabOrder.orderDate.year}-${patientLabOrder.orderDate.month}-${patientLabOrder.orderDate.day}'; _requestSendLabReportEmail.patientMobileNumber = user.mobileNumber; _requestSendLabReportEmail.projectName = patientLabOrder.projectName; + _requestSendLabReportEmail.setupID = user.setupID; - await baseAppClient.post(GET_Patient_LAB_SPECIAL_RESULT, + await baseAppClient.post(SEND_LAB_RESULT_EMAIL, onSuccess: (dynamic response, int statusCode) { - AppToast.showSuccessToast(message: 'A copy has been sent to the email'); + }, onFailure: (String error, int statusCode) { hasError = true; super.error = error; diff --git a/lib/core/service/medical/my_balance_service.dart b/lib/core/service/medical/my_balance_service.dart index e3be9bcf..86e925b8 100644 --- a/lib/core/service/medical/my_balance_service.dart +++ b/lib/core/service/medical/my_balance_service.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/core/model/my_balance/AdvanceModel.dart'; @@ -25,6 +27,10 @@ class MyBalanceService extends BaseService { AuthenticatedUserObject authenticatedUserObject = locator(); + MyBalanceService(){ + getFamilyFiles(); + } + getPatientAdvanceBalanceAmount() async { hasError = false; super.error = ""; diff --git a/lib/core/service/medical/prescriptions_service.dart b/lib/core/service/medical/prescriptions_service.dart index d6ad3732..e9741a7f 100644 --- a/lib/core/service/medical/prescriptions_service.dart +++ b/lib/core/service/medical/prescriptions_service.dart @@ -72,6 +72,7 @@ class PrescriptionsService extends BaseService { prescriptionReportEnhList.clear(); if(prescriptions.isInOutPatient){ response['ListPRM'].forEach((prescriptions) { + prescriptionReportList.add(PrescriptionReport.fromJson(prescriptions)); prescriptionReportEnhList.add(PrescriptionReportEnh.fromJson(prescriptions)); }); }else{ diff --git a/lib/core/service/medical/radiology_service.dart b/lib/core/service/medical/radiology_service.dart index b3cb737b..965fa752 100644 --- a/lib/core/service/medical/radiology_service.dart +++ b/lib/core/service/medical/radiology_service.dart @@ -67,7 +67,7 @@ class RadiologyService extends BaseService { _requestSendRadReportEmail.patientName = user.firstName + " " + user.lastName; _requestSendRadReportEmail.patientIditificationNum = user.patientIdentificationNo; _requestSendRadReportEmail.projectName = finalRadiology.projectName; - _requestSendRadReportEmail.radResult = 'asd'; //finalRadiology.reportData; + _requestSendRadReportEmail.radResult = finalRadiology.reportData; _requestSendRadReportEmail.to = user.emailAddress; _requestSendRadReportEmail.dateofBirth = user.dateofBirth; diff --git a/lib/core/service/medical/reports_service.dart b/lib/core/service/medical/reports_service.dart index 19f86e2e..bf340814 100644 --- a/lib/core/service/medical/reports_service.dart +++ b/lib/core/service/medical/reports_service.dart @@ -9,11 +9,11 @@ class ReportsService extends BaseService { List appointHistoryList = List(); String userAgreementContent = ""; RequestReports _requestReports = RequestReports( - isReport: true, - encounterType: 1, - requestType: 1, - patientOutSA: 0, - ); + isReport: true, + encounterType: 1, + requestType: 1, + patientOutSA: 0, + ); Future getReports() async { hasError = false; @@ -56,22 +56,31 @@ class ReportsService extends BaseService { }, body: Map()); } - Future updatePatientHealthSummaryReport({bool isSummary}) async { Map body = Map(); body['RSummaryReport'] = isSummary; hasError = false; await baseAppClient.post(UPDATE_HEALTH_TERMS, - onSuccess: (dynamic response, int statusCode) { + onSuccess: (dynamic response, int statusCode) {}, + onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body: body); + } - }, onFailure: (String error, int statusCode) { + Future updateEmail({String email}) async { + Map body = Map(); + body['EmailAddress'] = email; + body['isDentalAllowedBackend'] = false; + hasError = false; + await baseAppClient.post(UPDATE_PATENT_EMAIL, + onSuccess: (dynamic response, int statusCode) {}, + onFailure: (String error, int statusCode) { hasError = true; super.error = error; }, body: body); } - - Future insertRequestForMedicalReport( AppointmentHistory appointmentHistory) async { Map body = new Map(); @@ -96,4 +105,44 @@ class ReportsService extends BaseService { super.error = error; }, body: body); } + + Future sendEmailForMedicalReport( + String projectName, + String clinicName, + String doctorName, + String requestDate, + String invoiceNo, + int projectID, + String stamp, + String setupID) async { + Map body = new Map(); + body['SetupID'] = setupID; + body['PrintDate'] = requestDate; + body['ProcedureID'] = "05005009"; + body['Reporttype'] = "MEDICAL REPORT"; + body['stamp'] = stamp; + body['To'] = user.emailAddress; + body['DateofBirth'] = user.dateofBirth; + body['PatientIditificationNum'] = user.patientIdentificationNo; + body['PatientMobileNumber'] = user.mobileNumber; + body['PatientName'] = user.firstName + " " + user.lastName; + body['ProjectName'] = projectName; + body['ClinicName'] = clinicName; + body['ProjectID'] = projectID; + body['InvoiceNo'] = invoiceNo; + body['PrintedByName'] = user.firstName + " " + user.lastName; + + dynamic response; + + hasError = false; + await baseAppClient.post(SEND_MEDICAL_REPORT_EMAIL, + onSuccess: (dynamic res, int statusCode) { + response = res; + }, + onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body: body); + return response; + } } diff --git a/lib/core/service/medical/vital_sign_service.dart b/lib/core/service/medical/vital_sign_service.dart index 16909fd9..d1fbbf1c 100644 --- a/lib/core/service/medical/vital_sign_service.dart +++ b/lib/core/service/medical/vital_sign_service.dart @@ -5,14 +5,14 @@ import '../base_service.dart'; class VitalSignService extends BaseService { List vitalSignResModelList = List(); - Map body = Map(); + String weightKg = ""; String heightCm = ""; String bloadType = ""; Future getPatientRadOrders({int appointmentNo, int projectID}) async { hasError = false; - + Map body = Map(); if (appointmentNo != null && projectID != null) { body['TransNo'] = appointmentNo; body['ProjectID'] = projectID; @@ -24,9 +24,17 @@ class VitalSignService extends BaseService { response['List_DoctorPatientVitalSign'].forEach((vital) { vitalSignResModelList.add(VitalSignResModel.fromJson(vital)); }); + bool isHaveWeight = false; + bool isHaveHeight = false; vitalSignResModelList.forEach((element) { - weightKg = '${element.weightKg}'; - heightCm = '${element.heightCm}'; + if (element.weightKg != 0 && !isHaveWeight) { + weightKg = '${element.weightKg}'; + isHaveWeight = true; + } + if (element.heightCm != 0 && !isHaveHeight) { + heightCm = '${element.heightCm}'; + isHaveHeight = true; + } }); }, onFailure: (String error, int statusCode) { hasError = true; diff --git a/lib/core/service/offers_service.dart b/lib/core/service/offers_service.dart new file mode 100644 index 00000000..2247c833 --- /dev/null +++ b/lib/core/service/offers_service.dart @@ -0,0 +1,56 @@ +import 'package:diplomaticquarterapp/config/config.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacy/offer_products_model.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacy/offers_model.dart'; + +import 'base_service.dart'; + +class OffersCategoriseService extends BaseService { + List _offersList = List(); + List get offersList => _offersList; + List _offerProducts = List(); + List get offersProducts => _offerProducts; + + clearCategorise() { + _offerProducts.clear(); + } + + // clearCategorise2() { + // _offersList.clear(); + // } + + Future getOffersCategorise() async { + hasError = false; + _offersList.clear(); + await baseAppClient.get( + GET_OFFERS_CATEGORISE, + onSuccess: (dynamic response, int statusCode) { + response['categories'].forEach((item) { + _offersList.add(OffersModel.fromJson(item)); + }); + }, + onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, + ); + } + + Future getOffersProducts({String id}) async { + hasError = false; + _offerProducts.clear(); + String endPoint = + id != null ? GET_OFFERS_PRODUCTS + "$id" : GET_OFFERS_PRODUCTS + "1"; + await baseAppClient.get( + endPoint, + onSuccess: (dynamic response, int statusCode) { + response['products'].forEach((item) { + _offerProducts.add(OfferProductsModel.fromJson(item)); + }); + }, + onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, + ); + } +} diff --git a/lib/core/service/packages_offers/PackagesOffersServices.dart b/lib/core/service/packages_offers/PackagesOffersServices.dart new file mode 100644 index 00000000..e58c3fa3 --- /dev/null +++ b/lib/core/service/packages_offers/PackagesOffersServices.dart @@ -0,0 +1,51 @@ +import 'dart:convert'; +import 'dart:developer'; + +import 'package:diplomaticquarterapp/config/config.dart'; +import 'package:diplomaticquarterapp/core/model/packages_offers/requests/OffersCategoriesRequestModel.dart'; +import 'package:diplomaticquarterapp/core/model/packages_offers/requests/OffersProductsRequestModel.dart'; +import 'package:diplomaticquarterapp/core/model/packages_offers/responses/OfferCategoriesResponseModel.dart'; +import 'package:diplomaticquarterapp/core/model/packages_offers/responses/OfferProductsResponseModel.dart'; +import 'package:diplomaticquarterapp/core/service/base_service.dart'; +import 'package:diplomaticquarterapp/core/service/client/base_app_client.dart'; + +import '../../../locator.dart'; + +class OffersAndPackagesServices extends BaseService { + List categoryList = List(); + + Future> getAllCategories(OffersCategoriesRequestModel request) async { + hasError = false; + var url = EXA_CART_API_BASE_URL + PACKAGES_CATEGORIES; + await baseAppClient.simpleGet(url, onSuccess: (dynamic stringResponse, int statusCode) { + if (statusCode == 200) { + var jsonResponse = json.decode(stringResponse); + jsonResponse['categories'].forEach((json) { + categoryList.add(OfferCategoriesResponseModel().fromJson(json)); + }); + } + }, onFailure: (String error, int statusCode) { + log(error); + }, queryParams: request.toFlatMap()); + + return categoryList; + } + + List productList = List(); + Future> getAllProducts(OffersProductsRequestModel request) async { + hasError = false; + var url = EXA_CART_API_BASE_URL + PACKAGES_PRODUCTS; + await baseAppClient.simpleGet(url, onSuccess: (dynamic stringResponse, int statusCode) { + if (statusCode == 200) { + var jsonResponse = json.decode(stringResponse); + jsonResponse['products'].forEach((json) { + productList.add(OfferProductsResponseModel().fromJson(json)); + }); + } + }, onFailure: (String error, int statusCode) { + log(error); + }, queryParams: request.toFlatMap()); + + return productList; + } +} diff --git a/lib/core/service/parmacyModule/lacum-registration-service.dart b/lib/core/service/parmacyModule/lacum-registration-service.dart new file mode 100644 index 00000000..b3e64e69 --- /dev/null +++ b/lib/core/service/parmacyModule/lacum-registration-service.dart @@ -0,0 +1,50 @@ +import 'package:diplomaticquarterapp/config/config.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/LacumAccountInformation.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/ListUserAgreement.dart'; + +import 'lacum-service.dart'; + +class LacumRegistrationService extends LacumService{ + + ListUserAgreement listUserAgreement; + + Future getLacumAccountInformationById(String patientIdentificationNo) async { + hasError = false; + super.error = ""; + + Map body = Map(); + body['IdentificationNo'] = patientIdentificationNo; + + try { + await baseAppClient.post(GET_LACUM_ACCOUNT_INFORMATION, + onSuccess: (response, statusCode) async { + lacumInformation = LacumAccountInformation.fromJson(response); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body: body); + } catch (error) { + throw error; + } + } + + Future getUserTermsAndConditionsForEPharmcy() async { + hasError = false; + super.error = ""; + + Map body = Map(); + + try { + await baseAppClient.post(LAKUM_GET_USER_TERMS_AND_CONDITIONS, + onSuccess: (response, statusCode) async { + listUserAgreement = ListUserAgreement.fromJson(response['ListUserAgreement'][0]); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body: body); + } catch (error) { + throw error; + } + } + +} \ No newline at end of file diff --git a/lib/core/service/parmacyModule/lacum-service.dart b/lib/core/service/parmacyModule/lacum-service.dart new file mode 100644 index 00000000..c7117303 --- /dev/null +++ b/lib/core/service/parmacyModule/lacum-service.dart @@ -0,0 +1,133 @@ +import 'package:diplomaticquarterapp/config/config.dart'; +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/LacumAccountInformation.dart'; +import 'package:diplomaticquarterapp/core/service/base_service.dart'; + +class LacumService extends BaseService{ + bool isFinished = true; + bool hasError = false; + String errorMsg = ''; + String successMsg = ''; + + LacumAccountInformation lacumInformation; + LacumAccountInformation lacumGroupInformation; + + Future getLacumAccountInformation() async { + hasError = false; + super.error = ""; + + Map body = Map(); + body['IdentificationNo'] = user.patientIdentificationNo; + + try { + await baseAppClient.post(GET_LACUM_ACCOUNT_INFORMATION, + onSuccess: (response, statusCode) async { + lacumInformation = LacumAccountInformation.fromJson(response); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body: body); + } catch (error) { + throw error; + } + } + + Future getLacumGroupInformation() async { + hasError = false; + super.error = ""; + + Map body = Map(); + body['IdentificationNo'] = user.patientIdentificationNo; + body['AccountNumber'] = "${lacumInformation.yahalaAccountNo}"; + body['IsDetailsRequired'] = true; + + try { + await baseAppClient.post(GET_LACUM_GROUP_INFORMATION, + onSuccess: (response, statusCode) async { + lacumGroupInformation = LacumAccountInformation.fromJson(response); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body: body); + } catch (error) { + throw error; + } + } + + Future makeAccountActivate() async { + hasError = false; + super.error = ""; + int yahalaAccountNo = lacumInformation.yahalaAccountNo; + + Map body = Map(); + body['CreatedBy'] = 103; + body['YahalaAccountNumber'] = yahalaAccountNo; + + try { + await baseAppClient.post(LACUM_ACCOUNT_ACTIVATE, + onSuccess: (response, statusCode) async { + // lacumInformation = LacumAccountInformation.fromJson(response); + // lacumInformation.yahalaAccountNo = yahalaAccountNo; + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body: body); + } catch (error) { + throw error; + } + } + + Future makeAccountDeactivate() async { + hasError = false; + super.error = ""; + int yahalaAccountNo = lacumInformation.yahalaAccountNo; + + Map body = Map(); + body['CreatedBy'] = 103; + body['YahalaAccountNumber'] = yahalaAccountNo; + + try { + await baseAppClient.post(LACUM_ACCOUNT_DEACTIVATE, + onSuccess: (response, statusCode) async { + // lacumInformation = LacumAccountInformation.fromJson(response); + // lacumInformation.yahalaAccountNo = yahalaAccountNo; + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body: body); + } catch (error) { + throw error; + } + } + + Future createLakumAccount(String name, String phone, int accountID, String patientIdentificationID, var prefLang) async { + hasError = false; + super.error = ""; + if(prefLang == null){ + var languageID = + await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'en'); + prefLang = languageID == 'ar' ? 1 : 2; + } + + + Map body = Map(); + body['PrefLang'] = prefLang; + body['AccountID'] = accountID; + body['FullName'] = name; + body['MobileNo'] = phone; + body['PatientIdentificationID'] = patientIdentificationID; + body['PatientID'] = user.patientID; + + try { + await baseAppClient.post(CREATE_LAKUM_ACCOUNT, + onSuccess: (response, statusCode) async { + successMsg = LacumAccountInformation.fromJson(response).message; + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body: body); + } catch (error) { + throw error; + } + } +} \ No newline at end of file diff --git a/lib/core/service/parmacyModule/lacum-transfer-service.dart b/lib/core/service/parmacyModule/lacum-transfer-service.dart new file mode 100644 index 00000000..b15696f9 --- /dev/null +++ b/lib/core/service/parmacyModule/lacum-transfer-service.dart @@ -0,0 +1,57 @@ +import 'package:diplomaticquarterapp/config/config.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/LacumAccountInformation.dart'; + +import 'lacum-service.dart'; + +class LacumTransferService extends LacumService{ + LacumAccountInformation lacumReceiverInformation; + + Future getLacumGroupDataBuAccountId(String accountId) async { + hasError = false; + super.error = ""; + + Map body = Map(); + body['IdentificationNo'] = user.patientIdentificationNo; + body['AccountNumber'] = accountId; + + try { + await baseAppClient.post(GET_LACUM_GROUP_INFORMATION, + onSuccess: (response, statusCode) async { + lacumReceiverInformation = LacumAccountInformation.fromJson(response); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + return null; + }, body: body); + } catch (error) { + throw error; + } + } + + Future transferYaHalaLoyaltyPoints(String points) async { + hasError = false; + super.error = ""; + + Map body = Map(); + body['MobileNo'] = lacumGroupInformation.lakumInquiryInformationObjVersion.mobileNumber; + body['UserName'] = lacumGroupInformation.lakumInquiryInformationObjVersion.memberName; + body['YaHalaSenderAccNumber'] = lacumGroupInformation.lakumInquiryInformationObjVersion.accountNumber; + body['Yahala_IdentificationNo'] = lacumGroupInformation.lakumInquiryInformationObjVersion.memberUniversalId; + body['YaHalaPointsToTransfer'] = points; + body['YaHalaReceiverAccNumber'] = lacumReceiverInformation.lakumInquiryInformationObjVersion.accountNumber; + body['YaHalaReceiverMobileNumber'] = lacumReceiverInformation.lakumInquiryInformationObjVersion.mobileNumber; + body['YaHalaReceiverName'] = lacumReceiverInformation.lakumInquiryInformationObjVersion.memberName; + + try { + await baseAppClient.post(TRANSFER_YAHALA_LOYALITY_POINTS, + onSuccess: (response, statusCode) async { + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body: body); + } catch (error) { + throw error; + } + } + +} \ No newline at end of file diff --git a/lib/core/service/parmacyModule/order-preview-service.dart b/lib/core/service/parmacyModule/order-preview-service.dart index 1f3f9ddd..5648ff6d 100644 --- a/lib/core/service/parmacyModule/order-preview-service.dart +++ b/lib/core/service/parmacyModule/order-preview-service.dart @@ -1,29 +1,248 @@ import 'package:diplomaticquarterapp/config/config.dart'; +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/core/model/pharmacies/Addresses.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/LacumAccountInformation.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/ShoppingCart.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/payment-checkout-data.dart'; import 'package:diplomaticquarterapp/core/service/base_service.dart'; +import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/OrderPreviewViewModel.dart'; -class OrderPreviewService extends BaseService{ +class OrderPreviewService extends BaseService { bool isFinished = true; bool hasError = false; String errorMsg = ''; List addresses = List(); + LacumAccountInformation lacumInformation; + LacumAccountInformation lacumGroupInformation; - Future getBannerListList() async { + Future getAddresses() async { + var customerId = await sharedPref.getString(PHARMACY_CUSTOMER_ID); + Map queryParams = {'fields': 'addresses'}; hasError = false; try { - await baseAppClient.get(GET_CUSTOMERS_ADDRESSES, + await baseAppClient.get("$GET_CUSTOMERS_ADDRESSES$customerId", onSuccess: (dynamic response, int statusCode) { - addresses.clear(); - response['customers'][0]['addresses'].forEach((item) { - addresses.add(Addresses.fromJson(item)); - }); + addresses.clear(); + response['customers'][0]['addresses'].forEach((item) { + addresses.add(Addresses.fromJson(item)); + }); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, queryParams: queryParams); + } catch (error) { + throw error; + } + } + + Future getShippingOption(Addresses selectedAddress) async { + var customerId = await sharedPref.getString(PHARMACY_CUSTOMER_ID); + Map queryParams = Map(); + dynamic localRes; + hasError = false; + try { + await baseAppClient.get("$GET_SHIPPING_OPTIONS$customerId/${selectedAddress.id}", + onSuccess: (dynamic response, int statusCode) { + localRes = response['shipping_option'][0]; }, onFailure: (String error, int statusCode) { hasError = true; super.error = error; - }); + }, queryParams: queryParams); } catch (error) { throw error; } + return Future.value(localRes); + } + + Future getShoppingCart() async { + var customerId = await sharedPref.getString(PHARMACY_CUSTOMER_ID); + Map queryParams = {'shopping_cart_type': '1'}; + dynamic localRes; + hasError = false; + try { + await baseAppClient.get("$GET_SHOPPING_CART$customerId", + onSuccess: (dynamic response, int statusCode) { + localRes = response; + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, queryParams: queryParams); + } catch (error) { + throw error; + } + return Future.value(localRes); + } + + Future changeProductQuantity( + String productId, ShoppingCart product) async { + hasError = false; + super.error = ""; + dynamic localRes; + Map choppingCartObject = Map(); + choppingCartObject['id'] = product.id; + choppingCartObject['quantity'] = product.quantity; + choppingCartObject['shopping_cart_type'] = "1"; + choppingCartObject['product_id'] = product.productId; + choppingCartObject['customer_id'] = product.customerId; + + Map body = Map(); + body["shopping_cart_item"] = choppingCartObject; + + await baseAppClient.post("$GET_SHOPPING_CART$productId", + onSuccess: (response, statusCode) async { + localRes = response; + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body: body); + + return Future.value(localRes); + } + + Future deleteProduct(String productId) async { + hasError = false; + super.error = ""; + dynamic localRes; + + Map body = Map(); + + await baseAppClient.post("$DELETE_SHOPPING_CART$productId", + onSuccess: (response, statusCode) async { + localRes = response; + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body: body); + + return Future.value(localRes); + } + + Future deleteShoppingCart() async { + var customerId = await sharedPref.getString(PHARMACY_CUSTOMER_ID); + + hasError = false; + super.error = ""; + dynamic localRes; + + await baseAppClient.get("$DELETE_SHOPPING_CART_ALL$customerId/ShoppingCart", + onSuccess: (response, statusCode) async { + localRes = response; + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }); + + return Future.value(localRes); + } + + Future getLacumAccountInformation() async { + hasError = false; + super.error = ""; + + Map body = Map(); + body['IdentificationNo'] = user.patientIdentificationNo; + + try { + await baseAppClient.post(GET_LACUM_ACCOUNT_INFORMATION, + onSuccess: (response, statusCode) async { + lacumInformation = LacumAccountInformation.fromJson(response); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body: body); + } catch (error) { + throw error; + } + } + + Future getLacumGroupInformation() async { + hasError = false; + super.error = ""; + + Map body = Map(); + body['IdentificationNo'] = user.patientIdentificationNo; + body['AccountNumber'] = "${lacumInformation.yahalaAccountNo}"; + + try { + await baseAppClient.post(GET_LACUM_GROUP_INFORMATION, + onSuccess: (response, statusCode) async { + lacumGroupInformation = LacumAccountInformation.fromJson(response); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body: body); + } catch (error) { + throw error; + } + } + + Future makeOrder(PaymentCheckoutData paymentCheckoutData, List shoppingCarts) async { + paymentCheckoutData.address.isChecked = true; + hasError = false; + super.error = ""; + + var languageID = + await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'en'); + var customerId = await sharedPref.getString(PHARMACY_CUSTOMER_ID); + + Map orderBody = Map(); + orderBody['rx_attachments'] = ""; + orderBody['customer_language_id'] = languageID == 'ar' ? 1 : 2; + orderBody['billing_address'] = paymentCheckoutData.address; + orderBody['pick_up_in_store'] = false; + orderBody['payment_method_system_name'] = "Payments.PayFort"; + orderBody['shipping_method'] = languageID == 'ar' ? paymentCheckoutData.shippingOption.namen : paymentCheckoutData.shippingOption.name ; + orderBody['shipping_rate_computation_method_system_name'] = paymentCheckoutData.shippingOption.shippingRateComputationMethodSystemName; + orderBody['customer_id'] = customerId; + orderBody['custom_values_xml'] = "PaymentOption:${getPaymentOptionName(paymentCheckoutData.paymentOption)}"; + orderBody['shippingOption'] = paymentCheckoutData.shippingOption; + orderBody['shipping_address'] = paymentCheckoutData.address; + orderBody['lakum_amount'] = paymentCheckoutData.usedLakumPoints; + + List> itemsList = List(); + shoppingCarts.forEach((item) { + Map orderItemsBody = Map(); + orderItemsBody['product_id'] = item.product.id; + orderItemsBody['quantity'] = item.quantity; + itemsList.add(orderItemsBody); + }); + orderBody['order_items'] = itemsList; + + Map body = Map(); + body['order'] = orderBody; + + try { + await baseAppClient.post(ORDER_SHOPPING_CART, + onSuccess: (response, statusCode) async { + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body: body); + } catch (error) { + throw error; + } + } + + String getPaymentOptionName(PaymentOption paymentOption) { + switch (paymentOption.index) { + case 0: + return "MADA"; + break; + case 1: + return "SADAD"; + break; + case 2: + return "VISA"; + break; + case 3: + return "MASTERCARD"; + break; + case 4: + return "INSTALLMENT"; + break; + default: + return ""; + } } -} \ No newline at end of file +} diff --git a/lib/core/service/parmacyModule/parmacy_module_service.dart b/lib/core/service/parmacyModule/parmacy_module_service.dart index 8584e140..c3bce324 100644 --- a/lib/core/service/parmacyModule/parmacy_module_service.dart +++ b/lib/core/service/parmacyModule/parmacy_module_service.dart @@ -4,8 +4,10 @@ import 'package:diplomaticquarterapp/core/model/pharmacies/Manufacturer.dart'; import 'package:diplomaticquarterapp/core/model/pharmacies/PharmacyImageObject.dart'; import 'package:diplomaticquarterapp/core/model/pharmacies/PharmacyProduct.dart'; import 'package:diplomaticquarterapp/core/service/base_service.dart'; +import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; class PharmacyModuleService extends BaseService { + final AppSharedPreferences sharedPref = AppSharedPreferences(); bool isFinished = true; bool hasError = false; String errorMsg = ''; @@ -15,6 +17,55 @@ class PharmacyModuleService extends BaseService { List bestSellerProducts = List(); List lastVisitedProducts = List(); + Future makeVerifyCustomer(dynamic data) async { + Map queryParams = {'FileNumber': data['PatientID'].toString()}; + hasError = false; + try { + await baseAppClient.get(PHARMACY_VERIFY_CUSTOMER, + onSuccess: (dynamic response, int statusCode) { + if (response['UserName'] != null) { + sharedPref.setString(PHARMACY_CUSTOMER_ID, response['CustomerId'].toString()); + print(response); + } else { + createUser(); + } + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, queryParams: queryParams); + } catch (error) { + throw error; + } + } + + Future createUser() async { + var data = await sharedPref.getObject(USER_PROFILE); + var languageID = await sharedPref.getString(APP_LANGUAGE); + Map queryParams = { + 'Phone': data['MobileNumber'], + 'Email': data['EmailAddress'], + 'FileNumber': data['PatientID'].toString(), + 'Language': languageID.toString(), + 'Gender': data['Gender'].toString(), + 'FirstName': data['FirstName'], + 'LastName': data['LastName'], + 'LanguageId': languageID.toString(), + 'CountryCode': data['ZipCode'], + }; + hasError = false; + try { + await baseAppClient.get(PHARMACY_CREATE_CUSTOMER, + onSuccess: (dynamic response, int statusCode) { + if (!response['IsRegistered']) {} + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, queryParams: queryParams); + } catch (error) { + throw error; + } + } + Future getBannerListList() async { hasError = false; try { @@ -40,7 +91,10 @@ class PharmacyModuleService extends BaseService { onSuccess: (dynamic response, int statusCode) { manufacturerList.clear(); response['manufacturer'].forEach((item) { - manufacturerList.add(Manufacturer.fromJson(item)); + Manufacturer manufacturer = Manufacturer.fromJson(item); + if(manufacturer.image != null){ + manufacturerList.add(Manufacturer.fromJson(item)); + } }); }, onFailure: (String error, int statusCode) { hasError = true; @@ -81,14 +135,14 @@ class PharmacyModuleService extends BaseService { try { await baseAppClient.get("$GET_PHARMACY_PRODUCTs_BY_IDS$lastVisited", onSuccess: (dynamic response, int statusCode) { - lastVisitedProducts.clear(); - response['products'].forEach((item) { - lastVisitedProducts.add(PharmacyProduct.fromJson(item)); - }); - }, onFailure: (String error, int statusCode) { - hasError = true; - super.error = error; - }); + lastVisitedProducts.clear(); + response['products'].forEach((item) { + lastVisitedProducts.add(PharmacyProduct.fromJson(item)); + }); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }); } catch (error) { throw error; } diff --git a/lib/core/service/parmacyModule/terms-condition-service.dart b/lib/core/service/parmacyModule/terms-condition-service.dart new file mode 100644 index 00000000..68fac632 --- /dev/null +++ b/lib/core/service/parmacyModule/terms-condition-service.dart @@ -0,0 +1,33 @@ +import 'package:diplomaticquarterapp/config/config.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/ListUserAgreement.dart'; + +import '../base_service.dart'; + +class TermsConditionService extends BaseService{ + bool isFinished = true; + bool hasError = false; + String errorMsg = ''; + String successMsg = ''; + + ListUserAgreement listUserAgreement; + + Future getUserTermsAndConditionsForEPharmcy() async { + hasError = false; + super.error = ""; + + Map body = Map(); + + try { + await baseAppClient.post(LAKUM_GET_USER_TERMS_AND_CONDITIONS, + onSuccess: (response, statusCode) async { + listUserAgreement = ListUserAgreement.fromJson(response['ListUserAgreement'][0]); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body: body); + } catch (error) { + throw error; + } + } + +} \ No newline at end of file diff --git a/lib/core/service/pharmacies_service.dart b/lib/core/service/pharmacies_service.dart index f89fb425..dbd4fae1 100644 --- a/lib/core/service/pharmacies_service.dart +++ b/lib/core/service/pharmacies_service.dart @@ -2,6 +2,7 @@ import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/core/model/pharmacies/pharmacies_list_model.dart'; import 'package:diplomaticquarterapp/core/service/base_service.dart'; import 'package:diplomaticquarterapp/core/model/pharmacies/pharmacies_model.dart'; +import 'package:geolocator/geolocator.dart'; class PharmacyService extends BaseService { List _medicineItem = List(); @@ -59,10 +60,30 @@ class PharmacyService extends BaseService { projectID: 15, ); + double _latitude=0; + double _longitude=0; + + _getCurrentLocation() async { + await Geolocator.getLastKnownPosition().then((value) { + _latitude = value.latitude; + _longitude = value.longitude; + }).catchError((e) { + _longitude = 0; + _latitude = 0; + }); + } + Future getMedicineList({String drugName}) async { hasError = false; - _requestGetPharmaciesModel.pHRItemName = drugName; - try { + await _getCurrentLocation(); + Map body = Map(); + body['PHR_itemName'] = drugName.trim(); + body['isLoginForDoctorApp'] = true; + body['isDentalAllowedBackend'] = true; + body['PageSize'] = 25; + body['Latitude'] = _latitude; + body['Longitude'] = _longitude; + await baseAppClient.post(GET_PHARMCY_ITEMS, onSuccess: (dynamic response, int statusCode) { _medicineItem.clear(); @@ -72,15 +93,18 @@ class PharmacyService extends BaseService { }, onFailure: (String error, int statusCode) { hasError = true; super.error = error; - }, body: _requestGetPharmaciesModel.toJson()); - } catch (error) { - throw error; - } + }, body: body); + } Future getPharmaciesList({int itemID}) async { - _pharmaciesListModel.itemID = itemID; - try { + + await _getCurrentLocation(); + Map body = Map(); + body['ItemID'] = itemID; + body['Latitude'] = _latitude; + body['Longitude'] = _longitude; + await baseAppClient.post(GET_PHARMACY_LIST, onSuccess: (dynamic response, int statusCode) { _pharmaciesList.clear(); @@ -91,9 +115,7 @@ class PharmacyService extends BaseService { }, onFailure: (String error, int statusCode) { hasError = true; super.error = error; - }, body: _pharmaciesListModel.toJson()); - } catch (error) { - throw error; - } + }, body:body); + } } diff --git a/lib/core/service/pharmacy_categorise_service.dart b/lib/core/service/pharmacy_categorise_service.dart new file mode 100644 index 00000000..b55a755d --- /dev/null +++ b/lib/core/service/pharmacy_categorise_service.dart @@ -0,0 +1,225 @@ +import 'package:diplomaticquarterapp/config/config.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacy/brands_model.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacy/categorise_parent_model.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacy/final_products_model.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacy/parent_products_model.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacy/pharmacy_categorise.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacy/scan_qr_model.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacy/sub_categories_model.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacy/sub_products_model.dart'; +import 'package:diplomaticquarterapp/core/model/search_products_model.dart'; + +import 'base_service.dart'; + +class PharmacyCategoriseService extends BaseService { + //service one + List _categoriseList = List(); + List get categoriseList => _categoriseList; + + //service two + List _parentCategoriseList = List(); + List get parentCategoriseList => _parentCategoriseList; + + //service three + List _parentProductsList = List(); + List get parentProductsList => _parentProductsList; + + //service four + List _subCategoriseList = List(); + List get subCategoriseList => _subCategoriseList; + + //service five + List _subProductsList = List(); + List get subProductsList => _subProductsList; + + //service six + List _finalProducts = List(); + List get finalProducts => _finalProducts; + + //service 7 + + List _brandsList = List(); + List get brandsList => _brandsList; + + // service 8 + + List _searchList = List(); + List get searchList => _searchList; + + List _scanList = List(); + List get scanList => _scanList; + + clearSearchList() { + _searchList.clear(); + } + + Future getCategorise() async { + hasError = false; + _categoriseList.clear(); + await baseAppClient.get( + GET_PHARMACY_CATEGORISE, + onSuccess: (dynamic response, int statusCode) { + response['categories'].forEach((item) { + _categoriseList.add(PharmacyCategorise.fromJson(item)); + }); + }, + onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, + ); + } + + Future scanQr({String id}) async { + hasError = false; + _scanList.clear(); + String endPoint = id != null ? SCAN_QR_CODE + "$id" : SCAN_QR_CODE + ""; + await baseAppClient.get( + endPoint, + onSuccess: (dynamic response, int statusCode) { + response['products'].forEach((item) { + _scanList.add(ScanQrModel.fromJson(item)); + }); + }, + onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, + ); + } + + Future searchProducts({String productName}) async { + hasError = false; + _searchList.clear(); + String endPoint = productName != null + ? GET_SEARCH_PRODUCTS + "$productName" + '&language_id=1' + : GET_SEARCH_PRODUCTS + ""; + await baseAppClient.get( + endPoint, + onSuccess: (dynamic response, int statusCode) { + response['products'].forEach((item) { + _searchList.add(SearchProductsModel.fromJson(item)); + }); + }, + onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, + ); + } + + Future getBrands() async { + hasError = false; + _brandsList.clear(); + await baseAppClient.get( + GET_BRANDS_LIST, + onSuccess: (dynamic response, int statusCode) { + response['manufacturer'].forEach((item) { + _brandsList.add(BrandsModel.fromJson(item)); + }); + }, + onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, + ); + } + + Future getCategoriseParent({String id}) async { + hasError = false; + _parentCategoriseList.clear(); + String endPoint = + id != null ? GET_CATEGORISE_PARENT + "$id" : GET_CATEGORISE_PARENT + ""; + await baseAppClient.get( + endPoint, + onSuccess: (dynamic response, int statusCode) { + response['categories'].forEach((item) { + _parentCategoriseList.add(CategoriseParentModel.fromJson(item)); + }); + }, + onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, + ); + } + + Future getParentProducts({String id}) async { + hasError = false; + _parentProductsList.clear(); + String endPoint = id != null + ? GET_PARENT_PRODUCTS + "$id" + '&page=1&limit=50' + : GET_PARENT_PRODUCTS + ""; + await baseAppClient.get( + endPoint, + onSuccess: (dynamic response, int statusCode) { + response['products'].forEach((item) { + _parentProductsList.add(ParentProductsModel.fromJson(item)); + }); + }, + onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, + ); + } + + Future getSubCategorise({String id}) async { + hasError = false; + _subCategoriseList.clear(); + + String endPoint = + id != null ? GET_SUB_CATEGORISE + "$id" : GET_SUB_CATEGORISE + ""; + await baseAppClient.get( + endPoint, + onSuccess: (dynamic response, int statusCode) { + response['categories'].forEach((item) { + _subCategoriseList.add(SubCategoriesModel.fromJson(item)); + }); + }, + onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, + ); + } + + Future getSubProducts({String id}) async { + hasError = false; + _subProductsList.clear(); + String endPoint = id != null + ? GET_SUB_PRODUCTS + "$id" + '&page=1&limit=50' + : GET_SUB_PRODUCTS + ""; + await baseAppClient.get( + endPoint, + onSuccess: (dynamic response, int statusCode) { + response['products'].forEach((item) { + _subProductsList.add(SubProductsModel.fromJson(item)); + }); + }, + onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, + ); + } + + Future getFinalProducts({String id}) async { + hasError = false; + _finalProducts.clear(); + String endPoint = + id != null ? GET_FINAL_PRODUCTS + "$id" : GET_FINAL_PRODUCTS + ""; + await baseAppClient.get( + endPoint, + onSuccess: (dynamic response, int statusCode) { + response['products'].forEach((item) { + _finalProducts.add(FinalProductsModel.fromJson(item)); + }); + }, + onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, + ); + } +} diff --git a/lib/core/service/weather_service.dart b/lib/core/service/weather_service.dart index b2dcf0ef..10ab1adf 100644 --- a/lib/core/service/weather_service.dart +++ b/lib/core/service/weather_service.dart @@ -21,17 +21,16 @@ class WeatherService extends BaseService { await baseAppClient.post(WEATHER_INDICATOR, onSuccess: (dynamic response, int statusCode) { - - + weatherIndicatorData = []; response['GetCityInfo_List'].forEach((data) { weatherIndicatorData.add(GetCityInfoList.fromJson(data)); }); print(weatherIndicatorData); - }, onFailure: (String error, int statusCode) { hasError = true; super.error = error; }, body: body); - await this.sharedPref.setObject(WEATHER,weatherIndicatorData[0]); + await this.sharedPref.setObject(WEATHER, weatherIndicatorData[0]); + return Future.value(weatherIndicatorData[0]); } } diff --git a/lib/core/viewModels/AlHabibMedicalService/cmc_view_model.dart b/lib/core/viewModels/AlHabibMedicalService/cmc_view_model.dart index 0774e5a7..f2c81956 100644 --- a/lib/core/viewModels/AlHabibMedicalService/cmc_view_model.dart +++ b/lib/core/viewModels/AlHabibMedicalService/cmc_view_model.dart @@ -99,6 +99,7 @@ class CMCViewModel extends BaseViewModel { await _cMCService .getOrderDetailByOrderID(getOrderDetailByOrderIDRequestModel); } + //TODO check it in uat Future insertPresPresOrder({CMCInsertPresOrderRequestModel order}) async { setState(ViewState.Busy); order.createdBy = user.patientID; diff --git a/lib/core/viewModels/all_habib_medical_services/e_referral_view_model.dart b/lib/core/viewModels/all_habib_medical_services/e_referral_view_model.dart index 047e06f2..1972e08f 100644 --- a/lib/core/viewModels/all_habib_medical_services/e_referral_view_model.dart +++ b/lib/core/viewModels/all_habib_medical_services/e_referral_view_model.dart @@ -4,7 +4,6 @@ import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/EReferral/check_activation_code_for_e_referral_request_model.dart'; import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/EReferral/create_e_referral_request_model.dart'; import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/EReferral/get_all_cities_response_model.dart'; -import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/EReferral/get_all_projects_response_model.dart'; import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/EReferral/get_all_relationship_types_response_model.dart'; import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/EReferral/search_e_referral_request_model.dart'; import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/EReferral/search_e_referral_response_model.dart'; @@ -19,108 +18,74 @@ class EReferralViewModel extends BaseViewModel { List get relationTypes => _eReferralService.relationTypes; - List get allCities => _eReferralService.allCities; + List get allReferral => _eReferralService.allReferral; - List get allHospitals => - _eReferralService.allProjects; - List get allReferral => - _eReferralService.allReferral; - void getRelationTypes() async { + void getRelationTypes() async { setState(ViewState.Busy); await _eReferralService.getRelationTypes(); if (_eReferralService.hasError) { error = _eReferralService.error; setState(ViewState.Error); - } else { + } else{ setState(ViewState.Idle); } } - - void getAllCities() async { + void getAllCities() async { setState(ViewState.Busy); await _eReferralService.getAllCities(); if (_eReferralService.hasError) { error = _eReferralService.error; setState(ViewState.Error); - } else { + } else{ setState(ViewState.Idle); } } - void getAllProjects() async { - setState(ViewState.Busy); - await _eReferralService.getAllProjects(); - if (_eReferralService.hasError) { - error = _eReferralService.error; - setState(ViewState.Error); - } else { - setState(ViewState.Idle); - } - } - - void sendActivationCodeForEReferral( - SendActivationCodeForEReferralRequestModel - sendActivationCodeForEReferralRequestModel) async { + void sendActivationCodeForEReferral(SendActivationCodeForEReferralRequestModel sendActivationCodeForEReferralRequestModel) async { setState(ViewState.BusyLocal); - await _eReferralService.sendActivationCodeForEReferral( - sendActivationCodeForEReferralRequestModel); + await _eReferralService.sendActivationCodeForEReferral(sendActivationCodeForEReferralRequestModel); if (_eReferralService.hasError) { error = _eReferralService.error; setState(ViewState.ErrorLocal); - } else { + } else{ setState(ViewState.Idle); } } - checkActivationCodeForEReferral( - CheckActivationCodeForEReferralResponseModel - checkActivationCodeForEReferralRequestModel) async { + checkActivationCodeForEReferral(CheckActivationCodeForEReferralResponseModel checkActivationCodeForEReferralRequestModel) async { setState(ViewState.BusyLocal); - await _eReferralService.checkActivationCodeForEReferral( - checkActivationCodeForEReferralRequestModel); + await _eReferralService.checkActivationCodeForEReferral(checkActivationCodeForEReferralRequestModel); if (_eReferralService.hasError) { error = _eReferralService.error; setState(ViewState.ErrorLocal); - } else { + } else{ setState(ViewState.Idle); } } - Future createEReferral( + void createEReferral( CreateEReferralRequestModel createEReferralRequestModel) async { - dynamic localRes; setState(ViewState.BusyLocal); - await _eReferralService - .createEReferral(createEReferralRequestModel) - .then((response) { - localRes = response; - }); + await _eReferralService.createEReferral(createEReferralRequestModel); if (_eReferralService.hasError) { error = _eReferralService.error; setState(ViewState.ErrorLocal); } else { setState(ViewState.Idle); } - return Future.value(localRes); } - Future getEReferrals(SearchEReferralRequestModel searchEReferralRequestModel) async { + getEReferrals(SearchEReferralRequestModel searchEReferralRequestModel) async { setState(ViewState.BusyLocal); - dynamic localRes; - await _eReferralService.getEReferrals(searchEReferralRequestModel).then((response) { - localRes = response; - }); + await _eReferralService.getEReferrals(searchEReferralRequestModel); if (_eReferralService.hasError) { error = _eReferralService.error; setState(ViewState.ErrorLocal); } else { setState(ViewState.Idle); } - - return Future.value(localRes); - } } diff --git a/lib/core/viewModels/appointment_rate_view_model.dart b/lib/core/viewModels/appointment_rate_view_model.dart index 23d00366..e1bdfc9e 100644 --- a/lib/core/viewModels/appointment_rate_view_model.dart +++ b/lib/core/viewModels/appointment_rate_view_model.dart @@ -40,7 +40,7 @@ class AppointmentRateViewModel extends BaseViewModel { Future sendAppointmentRate(int rate, int appointmentNo, int projectID, int doctorID, int clinicID, String note) async { - setState(ViewState.BusyLocal); + setState(ViewState.Busy); await _appointmentRateService.sendAppointmentRate( rate, appointmentNo, projectID, doctorID, clinicID, note); if (_appointmentRateService.hasError) { diff --git a/lib/core/viewModels/base_view_model.dart b/lib/core/viewModels/base_view_model.dart index d8ea5196..aab267e9 100644 --- a/lib/core/viewModels/base_view_model.dart +++ b/lib/core/viewModels/base_view_model.dart @@ -29,11 +29,16 @@ class BaseViewModel extends ChangeNotifier { if (hasListeners) notifyListeners(); } + setUser(AuthenticatedUser user){ + this.user = user; + notifyListeners(); + } + BaseViewModel() { //authenticatedUserObject.getUser(); user = authenticatedUserObject.user; this.isLogin = authenticatedUserObject.isLogin; - _getUser(); + } _getUser() async { diff --git a/lib/core/viewModels/child_vaccines/add_new_child_view_model.dart b/lib/core/viewModels/child_vaccines/add_new_child_view_model.dart index 2559c074..eebaca02 100644 --- a/lib/core/viewModels/child_vaccines/add_new_child_view_model.dart +++ b/lib/core/viewModels/child_vaccines/add_new_child_view_model.dart @@ -13,6 +13,7 @@ class AddNewChildViewModel extends BaseViewModel { CreteNewBabyService _creteNewBabyService = locator(); ChildVaccinesService _childVaccinesService = locator(); + // DeleteBabyService _deleteBabyService = locator(); bool isAdded = false; ///create new baby createNewBabyOrders({ CreateNewBaby newChild}) async { @@ -24,7 +25,13 @@ class AddNewChildViewModel extends BaseViewModel { } else { isAdded = true; setState(ViewState.Idle); + await _childVaccinesService.getAllBabyInformationOrders(); + if (_childVaccinesService.hasError) { + error = _childVaccinesService.error; + setState(ViewState.Error); + } else{ + } } } diff --git a/lib/core/viewModels/child_vaccines/child_vaccines_view_model.dart b/lib/core/viewModels/child_vaccines/child_vaccines_view_model.dart index a713b6ec..7c4af285 100644 --- a/lib/core/viewModels/child_vaccines/child_vaccines_view_model.dart +++ b/lib/core/viewModels/child_vaccines/child_vaccines_view_model.dart @@ -16,11 +16,14 @@ class ChildVaccinesViewModel extends BaseViewModel{ List get babyInformationModelList=> _childVaccinesService.babyInformationModelList; + +//=========== CreteNewBabyService _creteNewBabyService = locator(); DeleteBabyService _deleteBabyService = locator(); bool isAdded = false; bool isDeleted = false; + //============ getNewUserOrders() async { @@ -45,15 +48,25 @@ class ChildVaccinesViewModel extends BaseViewModel{ ///delete baby - deleteBabyOrders({ List_BabyInformationModel babyInfo}) async { + deleteBabyOrders({ DeleteBaby newChild}) async { setState(ViewState.Busy); - await _deleteBabyService.getDeleteBabyOrder(babyInfo: babyInfo); - if (_deleteBabyService.hasError) { - error = _deleteBabyService.error; + //await _creteNewBabyService.getCreateNewBabyOrders(newChild: newChild, userID: _childVaccinesService.userID); + await _deleteBabyService.getDeleteBabyOrder(deleteChild: newChild,babyID: newChild.babyID); + //getDeleteBabyOrder(deleteChild: newChild,); + // getDeleteBabyOrder + if (_creteNewBabyService.hasError) { + error = _creteNewBabyService.error; setState(ViewState.Error); } else { isDeleted = true; - getBabyInformatioRequestOrders(); + setState(ViewState.Idle); + await _childVaccinesService.getAllBabyInformationOrders(); + if (_childVaccinesService.hasError) { + error = _childVaccinesService.error; + setState(ViewState.Error); + } else{ + + } } } diff --git a/lib/core/viewModels/child_vaccines/user_information_view_model.dart b/lib/core/viewModels/child_vaccines/user_information_view_model.dart index e183ee42..43269f42 100644 --- a/lib/core/viewModels/child_vaccines/user_information_view_model.dart +++ b/lib/core/viewModels/child_vaccines/user_information_view_model.dart @@ -8,7 +8,8 @@ class UserInformationViewModel extends BaseViewModel { UserInformationService _userInformationService = locator(); - List_UserInformationModel get userInformationModelList => _userInformationService.userInformationModel; + List get userInformationModelList => + _userInformationService.userInformationModelList; getUserInformationRequestOrders() async { setState(ViewState.Busy); @@ -19,15 +20,4 @@ class UserInformationViewModel extends BaseViewModel { } else setState(ViewState.Idle); } - - updateEmail(String email)async{ - setState(ViewState.Busy); - await _userInformationService.updateEmail(email); - await _userInformationService.updateUserInfo(email); - if (_userInformationService.hasError) { - error = _userInformationService.error; - setState(ViewState.Error); - } else - await getUserInformationRequestOrders(); - } } diff --git a/lib/core/viewModels/child_vaccines/vaccination_table_view_model.dart b/lib/core/viewModels/child_vaccines/vaccination_table_view_model.dart index 25559b81..3b72dd50 100644 --- a/lib/core/viewModels/child_vaccines/vaccination_table_view_model.dart +++ b/lib/core/viewModels/child_vaccines/vaccination_table_view_model.dart @@ -1,27 +1,30 @@ import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; -import 'package:diplomaticquarterapp/core/model/childvaccines/List_BabyInformationModel.dart'; +import 'package:diplomaticquarterapp/core/model/childvaccines/add_newchild_model.dart'; import 'package:diplomaticquarterapp/core/model/childvaccines/create_vaccination_table.dart'; -import 'package:diplomaticquarterapp/core/model/childvaccines/user_information_model.dart'; +import 'package:diplomaticquarterapp/core/service/childvaccines/add_new_child_service.dart'; import 'package:diplomaticquarterapp/core/service/childvaccines/vaccination_table_service.dart'; import '../../../locator.dart'; import '../base_view_model.dart'; -class VaccinationTableViewModel extends BaseViewModel { - VaccinationTableService _creteVaccinationTableService = - locator(); - List get creteVaccinationTableModelList => - _creteVaccinationTableService.createVaccinationTableModelList; +class VaccinationTableViewModel extends BaseViewModel{ - getCreateVaccinationTable({List_BabyInformationModel babyInfo, List_UserInformationModel informationModel, bool isSendEmail =false}) async { + VaccinationTableService _creteVaccinationTableService = locator(); + + // String get creteVaccinationTableContent => _creteVaccinationTableService.userAgreementContent; + //String get userAgreementContent => _creteNewBabyService.v//_reportsService.userAgreementContent; + List get creteVaccinationTableModelList=> _creteVaccinationTableService.createVaccinationTableModelList;//.createNewBabyModelList; + getCreateVaccinationTable() async { setState(ViewState.Busy); - await _creteVaccinationTableService.getCreateVaccinationTableOrders(babyInfo: babyInfo,informationModel: informationModel,isSendEmail: isSendEmail); - if (_creteVaccinationTableService.hasError) { - error = _creteVaccinationTableService.error; + await _creteVaccinationTableService.getCreateVaccinationTableOrders();//getCreateNewBabyOrders(); + + if ( _creteVaccinationTableService.hasError) { + error = _creteVaccinationTableService.error; setState(ViewState.Error); } else setState(ViewState.Idle); } + } diff --git a/lib/core/viewModels/dashboard_view_model.dart b/lib/core/viewModels/dashboard_view_model.dart index e98ca341..e085e476 100644 --- a/lib/core/viewModels/dashboard_view_model.dart +++ b/lib/core/viewModels/dashboard_view_model.dart @@ -1,7 +1,9 @@ +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; import 'package:diplomaticquarterapp/core/service/medical/vital_sign_service.dart'; import 'package:diplomaticquarterapp/core/viewModels/base_view_model.dart'; - +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; import '../../locator.dart'; class DashboardViewModel extends BaseViewModel { @@ -10,7 +12,7 @@ class DashboardViewModel extends BaseViewModel { String get weightKg => _vitalSignService.weightKg; String get heightCm => _vitalSignService.heightCm; - String bloadType = ""; + String booldType = "-"; // ToDoCountProviderModel toDoProvider = // Provider.of(AppGlobal.context); @@ -21,10 +23,11 @@ class DashboardViewModel extends BaseViewModel { await _vitalSignService.getPatientRadOrders(); if (_vitalSignService.hasError) { error = _vitalSignService.error; - setState(ViewState.Error); - } else + setState(ViewState.ErrorLocal); + } else { + booldType = await sharedPref.getString(BLOOD_TYPE) ?? "-"; setState(ViewState.Idle); - // getToDoCount(); + } } } diff --git a/lib/core/viewModels/feedback/feedback_view_model.dart b/lib/core/viewModels/feedback/feedback_view_model.dart index 4956024d..6793c786 100644 --- a/lib/core/viewModels/feedback/feedback_view_model.dart +++ b/lib/core/viewModels/feedback/feedback_view_model.dart @@ -21,59 +21,8 @@ class FeedbackViewModel extends BaseViewModel { FeedbackService _feedbackService = locator(); List get cOCItemList => _feedbackService.cOCItemList; - MessageType messageType = MessageType.NON; - MessageType messageTypeDialog = MessageType.NON; - - String getSelected(BuildContext context) { - switch (messageType) { - case MessageType.ComplaintOnAnAppointment: - return TranslationBase.of(context).complainAppo; - break; - case MessageType.ComplaintWithoutAppointment: - return TranslationBase.of(context).complainWithoutAppo; - break; - case MessageType.Question: - return TranslationBase.of(context).question; - break; - case MessageType.Compliment: - return TranslationBase.of(context).compliment; - break; - case MessageType.Suggestion: - return TranslationBase.of(context).suggestion; - break; - case MessageType.NON: - return TranslationBase.of(context).notClassified; - break; - } - return TranslationBase.of(context).notClassified; - } - - setMessageDialogType(MessageType messageType) { - messageTypeDialog = messageType; - notifyListeners(); - } - - setMessageType(MessageType messageType) { - this.messageType = messageType; - switch (messageType) { - case MessageType.ComplaintOnAnAppointment: - break; - case MessageType.ComplaintWithoutAppointment: - break; - case MessageType.Question: - break; - case MessageType.Compliment: - break; - case MessageType.Suggestion: - break; - case MessageType.NON: - break; - } - notifyListeners(); - } - List get appointHistoryList => _feedbackService.appointHistoryList; @@ -93,11 +42,9 @@ class FeedbackViewModel extends BaseViewModel { if (_feedbackService.hasError) { error = _feedbackService.error; setState(ViewState.ErrorLocal); - setMessageType(MessageType.NON); return false; } else { setState(ViewState.Idle); - setMessageType(MessageType.NON); return true; } } diff --git a/lib/core/viewModels/insurance_card_View_model.dart b/lib/core/viewModels/insurance_card_View_model.dart index 7029f082..234db5d4 100644 --- a/lib/core/viewModels/insurance_card_View_model.dart +++ b/lib/core/viewModels/insurance_card_View_model.dart @@ -1,7 +1,7 @@ import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; import 'package:diplomaticquarterapp/core/model/insurance/insurance_approval.dart'; import 'package:diplomaticquarterapp/core/model/insurance/insurance_card.dart'; -import 'package:diplomaticquarterapp/core/model/insurance/insurance_card_update.dart'; +import 'package:diplomaticquarterapp/core/model/insurance/insurance_card_update_model.dart'; import 'package:diplomaticquarterapp/core/service/insurance_service.dart'; import 'package:diplomaticquarterapp/models/FamilyFiles/GetAllSharedRecordByStatusResponse.dart'; @@ -72,5 +72,14 @@ class InsuranceViewModel extends BaseViewModel { } else setState(ViewState.Idle); } + Future uploadInsuranceCard({String patientIdentificationID, int patientID,String image =""}) async { + setState(ViewState.BusyLocal); + await _insuranceCardService.uploadInsuranceCard(patientIdentificationID: patientIdentificationID,patientID: patientID,image: image); + if (_insuranceCardService.hasError) { + error = _insuranceCardService.error; + setState(ViewState.ErrorLocal); + } else + setState(ViewState.Idle); + } } diff --git a/lib/core/viewModels/medical/labs_view_model.dart b/lib/core/viewModels/medical/labs_view_model.dart index 582ee745..9e3f09e5 100644 --- a/lib/core/viewModels/medical/labs_view_model.dart +++ b/lib/core/viewModels/medical/labs_view_model.dart @@ -1,9 +1,11 @@ import 'package:diplomaticquarterapp/core/enum/filter_type.dart'; import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; +import 'package:diplomaticquarterapp/core/model/labs/LabOrderResult.dart'; import 'package:diplomaticquarterapp/core/model/labs/lab_result.dart'; import 'package:diplomaticquarterapp/core/model/labs/patient_lab_orders.dart'; import 'package:diplomaticquarterapp/core/model/labs/patient_lab_special_result.dart'; import 'package:diplomaticquarterapp/core/service/medical/labs_service.dart'; +import 'package:diplomaticquarterapp/uitl/app_toast.dart'; import '../../../locator.dart'; import '../base_view_model.dart'; @@ -12,6 +14,9 @@ class LabsViewModel extends BaseViewModel { FilterType filterType = FilterType.Clinic; LabsService _labsService = locator(); + List get labOrdersResultsList => _labsService.labOrdersResultsList; + + List _patientLabOrdersListClinic = List(); List _patientLabOrdersListHospital = List(); @@ -105,43 +110,54 @@ class LabsViewModel extends BaseViewModel { getPatientLabResult({PatientLabOrders patientLabOrder}) async { setState(ViewState.Busy); - await _labsService.getPatientLabResult( - patientLabOrder: patientLabOrder - ); + await _labsService.getPatientLabResult(patientLabOrder: patientLabOrder); if (_labsService.hasError) { error = _labsService.error; setState(ViewState.Error); } else { _labsService.labResultList.forEach((element) { - List patientLabOrdersClinic = - labResultLists - .where((elementClinic) => - elementClinic.filterName == element.testCode) - .toList(); + List patientLabOrdersClinic = labResultLists.where((elementClinic) => elementClinic.filterName == element.testCode).toList(); if (patientLabOrdersClinic.length != 0) { - labResultLists[labResultLists.indexOf(patientLabOrdersClinic[0])] - .patientLabResultList - .add(element); + + var value= labResultLists[labResultLists.indexOf(patientLabOrdersClinic[0])].patientLabResultList + .where((e) => e.sampleCollectedOn== element.sampleCollectedOn && e.resultValue ==element.resultValue ).toList(); + if(value.isEmpty) + labResultLists[labResultLists.indexOf(patientLabOrdersClinic[0])].patientLabResultList.add(element); } else { - labResultLists.add(LabResultList( - filterName: element.testCode, - lab: element)); + labResultLists.add(LabResultList(filterName: element.testCode, lab: element)); } - }); setState(ViewState.Idle); } } - sendLabReportEmail({PatientLabOrders patientLabOrder}) async { + + getPatientLabOrdersResults({PatientLabOrders patientLabOrder,String procedure}) async { setState(ViewState.Busy); - await _labsService.sendLabReportEmail(patientLabOrder: patientLabOrder); + await _labsService.getPatientLabOrdersResults(patientLabOrder: patientLabOrder,procedure: procedure); if (_labsService.hasError) { error = _labsService.error; setState(ViewState.Error); } else { + bool isShouldClear = false; + if(_labsService.labOrdersResultsList.length==1) + { + labOrdersResultsList.forEach((element) { + if(element.resultValue.contains('/') ||element.resultValue.contains('*' )|| element.resultValue.isEmpty ) + isShouldClear = true; + });} + if(isShouldClear) + _labsService.labOrdersResultsList.clear(); setState(ViewState.Idle); } } + + sendLabReportEmail({PatientLabOrders patientLabOrder,String mes}) async { + await _labsService.sendLabReportEmail(patientLabOrder: patientLabOrder); + if (_labsService.hasError) { + error = _labsService.error; + }else + AppToast.showSuccessToast(message: mes); + } } diff --git a/lib/core/viewModels/medical/my_balance_view_model.dart b/lib/core/viewModels/medical/my_balance_view_model.dart index f9e549a4..e38a8a73 100644 --- a/lib/core/viewModels/medical/my_balance_view_model.dart +++ b/lib/core/viewModels/medical/my_balance_view_model.dart @@ -74,11 +74,10 @@ class MyBalanceViewModel extends BaseViewModel { setState(ViewState.Idle); } - //============== + Future getCities() async { setState(ViewState.Busy); await _bloodDonationService.getAllCitiesOrders(); - // getHospitals(); if (_bloodDonationService.hasError) { error = _bloodDonationService.error; setState(ViewState.Error); @@ -89,8 +88,6 @@ class MyBalanceViewModel extends BaseViewModel { Future getBlood() async { setState(ViewState.Busy); await _bloodDetailsService.getAllBloodOrders(); - ; - if (_bloodDetailsService.hasError) { error = _bloodDetailsService.error; setState(ViewState.Error); @@ -98,7 +95,6 @@ class MyBalanceViewModel extends BaseViewModel { setState(ViewState.Idle); } - //=============== Future getPatientInfoByPatientID({String id}) async { setState(ViewState.Busy); @@ -154,7 +150,7 @@ class MyBalanceViewModel extends BaseViewModel { Future getFamilyFiles() async { setState(ViewState.Busy); - await _myBalanceService.getSharedRecordByStatus(); + await _myBalanceService.getFamilyFiles(); if (_myBalanceService.hasError) { error = _myBalanceService.error; setState(ViewState.ErrorLocal); diff --git a/lib/core/viewModels/medical/prescriptions_view_model.dart b/lib/core/viewModels/medical/prescriptions_view_model.dart index 1cd934e2..2c32a081 100644 --- a/lib/core/viewModels/medical/prescriptions_view_model.dart +++ b/lib/core/viewModels/medical/prescriptions_view_model.dart @@ -119,6 +119,7 @@ class PrescriptionsViewModel extends BaseViewModel { int patientID, String clinicName, String doctorName, + String mes, int projectID}) async { setState(ViewState.BusyLocal); await _prescriptionsService.sendPrescriptionEmail( @@ -128,7 +129,7 @@ class PrescriptionsViewModel extends BaseViewModel { setState(ViewState.ErrorLocal); AppToast.showErrorToast(message: error); } else { - AppToast.showSuccessToast(message: 'A copy has been sent to the e-mail'); + AppToast.showSuccessToast(message: mes); setState(ViewState.Idle); } } diff --git a/lib/core/viewModels/medical/radiology_view_model.dart b/lib/core/viewModels/medical/radiology_view_model.dart index 26d40361..076707dc 100644 --- a/lib/core/viewModels/medical/radiology_view_model.dart +++ b/lib/core/viewModels/medical/radiology_view_model.dart @@ -80,7 +80,7 @@ class RadiologyViewModel extends BaseViewModel { } sendRadReportEmail( - {FinalRadiology finalRadiology}) async { + {FinalRadiology finalRadiology,String mes}) async { setState(ViewState.BusyLocal); await _radiologyService.sendRadReportEmail( finalRadiology: finalRadiology @@ -89,7 +89,7 @@ class RadiologyViewModel extends BaseViewModel { error = _radiologyService.error; AppToast.showErrorToast(message: error); } else { - AppToast.showSuccessToast(message: 'A copy has been sent to the email'); + AppToast.showSuccessToast(message: mes); } setState(ViewState.Idle); } diff --git a/lib/core/viewModels/medical/reports_monthly_view_model.dart b/lib/core/viewModels/medical/reports_monthly_view_model.dart index 3ae196f5..adb7223e 100644 --- a/lib/core/viewModels/medical/reports_monthly_view_model.dart +++ b/lib/core/viewModels/medical/reports_monthly_view_model.dart @@ -13,11 +13,9 @@ class ReportsMonthlyViewModel extends BaseViewModel { ReportsService _reportsService = locator(); - - String get userAgreementContent => _reportsService.userAgreementContent; - getUserTermsAndConditions() async{ + getUserTermsAndConditions() async { setState(ViewState.Busy); await _reportsService.getUserTermsAndConditions(); if (_reportsService.hasError) { @@ -28,19 +26,33 @@ class ReportsMonthlyViewModel extends BaseViewModel { } } - updatePatientHealthSummaryReport({String message, bool isSummary})async{ + updatePatientHealthSummaryReport( + {String message, + bool isSummary, + bool isUpdateEmail = false, + String email}) async { setState(ViewState.BusyLocal); - await _reportsService.updatePatientHealthSummaryReport(isSummary: isSummary); + await _reportsService.updatePatientHealthSummaryReport( + isSummary: isSummary); if (_reportsService.hasError) { error = _reportsService.error; AppToast.showErrorToast(message: error); setState(ViewState.ErrorLocal); } else { - AppToast.showSuccessToast(message: message); - setState(ViewState.Idle); + if (isUpdateEmail) { + await _reportsService.updateEmail(email: email); + if (_reportsService.hasError) { + error = _reportsService.error; + AppToast.showErrorToast(message: error); + setState(ViewState.ErrorLocal); + } else { + AppToast.showSuccessToast(message: message); + setState(ViewState.Idle); + } + } else { + AppToast.showSuccessToast(message: message); + setState(ViewState.Idle); + } } } - - - } diff --git a/lib/core/viewModels/medical/reports_view_model.dart b/lib/core/viewModels/medical/reports_view_model.dart index e0fdfaa3..271b5463 100644 --- a/lib/core/viewModels/medical/reports_view_model.dart +++ b/lib/core/viewModels/medical/reports_view_model.dart @@ -69,7 +69,7 @@ class ReportsViewModel extends BaseViewModel { } - insertRequestForMedicalReport(AppointmentHistory appointmentHistory)async{ + insertRequestForMedicalReport(AppointmentHistory appointmentHistory,String mes)async{ setState(ViewState.Busy); await _reportsService.insertRequestForMedicalReport(appointmentHistory); if (_reportsService.hasError) { @@ -77,7 +77,7 @@ class ReportsViewModel extends BaseViewModel { AppToast.showErrorToast(message: error); setState(ViewState.ErrorLocal); } else { - AppToast.showSuccessToast(message: 'The order was send '); + AppToast.showSuccessToast(message: mes); setState(ViewState.Idle); } } diff --git a/lib/core/viewModels/medical/vital_sign_view_model.dart b/lib/core/viewModels/medical/vital_sign_view_model.dart index f534140f..b2110187 100644 --- a/lib/core/viewModels/medical/vital_sign_view_model.dart +++ b/lib/core/viewModels/medical/vital_sign_view_model.dart @@ -11,7 +11,15 @@ class VitalSignViewModel extends BaseViewModel { List get vitalSignResModelList => _vitalSignService.vitalSignResModelList; - getPatientRadOrders({int appointmentNo, int projectID}) async { + String heightCm = "0"; + String weightKg = "0"; + String bodyMax = "0"; + String temperatureCelcius = "0"; + String hartRat = "0"; + String respirationBeatPerMinute = "0"; + String bloodPressure = "0 / 0"; + + getPatientVitalSign({int appointmentNo, int projectID}) async { setState(ViewState.Busy); if (appointmentNo != null && projectID != null) { @@ -23,7 +31,41 @@ class VitalSignViewModel extends BaseViewModel { if (_vitalSignService.hasError) { error = _vitalSignService.error; setState(ViewState.Error); - } else + } else { + _vitalSignService.vitalSignResModelList.forEach((element) { + if (heightCm == "0" || heightCm == null || heightCm == 'null') { + heightCm = element.heightCm.toString(); + } + if (weightKg == "0" || weightKg == null || weightKg == 'null') { + weightKg = element.weightKg.toString(); + } + if (bodyMax == "0" || + bodyMax == null || + bodyMax == 'null') { + bodyMax = element.bodyMassIndex.toString(); + } + if (temperatureCelcius == "0" || + temperatureCelcius == null || + temperatureCelcius == 'null') { + temperatureCelcius = element.temperatureCelcius.toString(); + } + if (hartRat == "0" || hartRat == null || hartRat == 'null') { + hartRat = element.pulseBeatPerMinute.toString(); + } + if (respirationBeatPerMinute == "0" || + respirationBeatPerMinute == null || + respirationBeatPerMinute == 'null') { + respirationBeatPerMinute = + element.respirationBeatPerMinute.toString(); + } + if (bloodPressure == "0 / 0" || + bloodPressure == null || + bloodPressure == 'null') { + bloodPressure = element.bloodPressure.toString(); + } + }); + setState(ViewState.Idle); + } } } diff --git a/lib/core/viewModels/offers_Categorise_view_model.dart b/lib/core/viewModels/offers_Categorise_view_model.dart new file mode 100644 index 00000000..b63dd553 --- /dev/null +++ b/lib/core/viewModels/offers_Categorise_view_model.dart @@ -0,0 +1,48 @@ +import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacy/offer_products_model.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacy/offers_model.dart'; +import 'package:diplomaticquarterapp/core/service/offers_service.dart'; +import 'package:diplomaticquarterapp/locator.dart'; + +import 'base_view_model.dart'; + +class OffersCategoriseViewModel extends BaseViewModel { + bool hasError = false; + + OffersCategoriseService _offersCategoriseService = + locator(); + List get categorise => _offersCategoriseService.offersList; + + List get products => + _offersCategoriseService.offersProducts; + + Future getOffersCategorise() async { + hasError = false; + _offersCategoriseService.clearCategorise(); + setState(ViewState.Busy); + await _offersCategoriseService.getOffersCategorise(); + if (_offersCategoriseService.hasError) { + error = _offersCategoriseService.error; + setState(ViewState.ErrorLocal); + } else + await getOffersProducts(); + } + + Future getOffersProducts({String i}) async { + hasError = false; + + setState(ViewState.Busy); + await _offersCategoriseService.getOffersProducts(id: i); + if (_offersCategoriseService.hasError) { + error = _offersCategoriseService.error; + setState(ViewState.ErrorLocal); + } else + setState(ViewState.Idle); + } +} +// await _offersCategoriseService.getOffersProducts(); +// if (_offersCategoriseService.hasError) { +// error = _offersCategoriseService.error; +// setState(ViewState.ErrorLocal); +// } else +// setState(ViewState.Idle); diff --git a/lib/core/viewModels/packages_offers/PackagesOffersViewModel.dart b/lib/core/viewModels/packages_offers/PackagesOffersViewModel.dart new file mode 100644 index 00000000..21df52bc --- /dev/null +++ b/lib/core/viewModels/packages_offers/PackagesOffersViewModel.dart @@ -0,0 +1,19 @@ +import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; +import 'package:diplomaticquarterapp/core/model/packages_offers/responses/OfferCategoriesResponseModel.dart'; +import 'package:diplomaticquarterapp/core/model/packages_offers/responses/OfferProductsResponseModel.dart'; +import 'package:diplomaticquarterapp/core/service/base_service.dart'; +import 'package:diplomaticquarterapp/core/service/client/base_app_client.dart'; +import 'package:diplomaticquarterapp/core/service/packages_offers/PackagesOffersServices.dart'; +import 'package:diplomaticquarterapp/core/viewModels/base_view_model.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:diplomaticquarterapp/locator.dart'; + +class OfferCategoriesViewModel extends BaseViewModel { + OffersAndPackagesServices service = locator(); + List get list => service.categoryList; +} + +class OfferProductsViewModel extends BaseViewModel { + OffersAndPackagesServices service = locator(); + List get list => service.productList; +} diff --git a/lib/core/viewModels/pharmacies_view_model.dart b/lib/core/viewModels/pharmacies_view_model.dart index 01ad4e72..b9e162fc 100644 --- a/lib/core/viewModels/pharmacies_view_model.dart +++ b/lib/core/viewModels/pharmacies_view_model.dart @@ -23,9 +23,11 @@ class PharmacyViewModel extends BaseViewModel { setState(ViewState.Error); } else setState(ViewState.Idle); - //_pharmacyService.clearPharmaciesList(); } + clearMedicineSearch(){ + _pharmacyService.clearMedicineList(); + } Future getMedicine({String name}) async { hasError = false; _pharmacyService.clearMedicineList(); diff --git a/lib/core/viewModels/pharmacyModule/OrderPreviewViewModel.dart b/lib/core/viewModels/pharmacyModule/OrderPreviewViewModel.dart index 00f4819b..06295188 100644 --- a/lib/core/viewModels/pharmacyModule/OrderPreviewViewModel.dart +++ b/lib/core/viewModels/pharmacyModule/OrderPreviewViewModel.dart @@ -1,3 +1,11 @@ +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/Addresses.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/LacumAccountInformation.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/ShippingOption.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/ShoppingCart.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/ShoppingCartResponse.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/payment-checkout-data.dart'; import 'package:diplomaticquarterapp/core/service/parmacyModule/order-preview-service.dart'; import '../../../locator.dart'; @@ -5,4 +13,183 @@ import '../base_view_model.dart'; class OrderPreviewViewModel extends BaseViewModel { OrderPreviewService _orderService = locator(); + + List get addresses => _orderService.addresses; + LacumAccountInformation get lacumInformation => + _orderService.lacumInformation; + ShoppingCartResponse cartResponse = ShoppingCartResponse(); + PaymentCheckoutData paymentCheckoutData = PaymentCheckoutData(); + double totalAdditionalShippingCharge = 0; + + Future getOrderPreviewData() async { + setState(ViewState.Busy); + await _orderService.getAddresses(); + if (_orderService.hasError) { + error = _orderService.error; + setState(ViewState.Error); + } else { + getShoppingCart(); + } + } + + getShoppingCart() async { + setState(ViewState.Busy); + await _orderService.getShoppingCart().then((res) { + _handleGetShoppingCartResponse(res); + }); + if (_orderService.hasError) { + error = _orderService.error; + setState(ViewState.Error); + } else { + if (paymentCheckoutData != null) { + paymentCheckoutData.cartDataVisible = true; + } + setState(ViewState.Idle); + } + } + + changeProductQuantity(ShoppingCart product) async { + setState(ViewState.Busy); + await _orderService.changeProductQuantity(product.id, product).then((res) { + _handleGetShoppingCartResponse(res); + }); + if (_orderService.hasError) { + error = _orderService.error; + setState(ViewState.Error); + } else { + setState(ViewState.Idle); + } + } + + deleteProduct(ShoppingCart product) async { + setState(ViewState.Busy); + await _orderService.deleteProduct(product.id).then((res) { + _handleGetShoppingCartResponse(res); + }); + if (_orderService.hasError) { + error = _orderService.error; + setState(ViewState.Error); + } else { + setState(ViewState.Idle); + } + } + + deleteShoppingCart() async { + setState(ViewState.Busy); + await _orderService.deleteShoppingCart().then((res) { + _handleGetShoppingCartResponse(res); + }); + if (_orderService.hasError) { + error = _orderService.error; + setState(ViewState.Error); + } else { + setState(ViewState.Idle); + } + } + + _handleGetShoppingCartResponse(Map res) { + totalAdditionalShippingCharge = 0; + if (res == null) { + error = "response is null"; + setState(ViewState.Error); + return; + } + print(res); + cartResponse.itemCount = res["item_count"]; + cartResponse.quantityCount = res["quantity_count"]; + cartResponse.subtotal = res["subtotal"]; + cartResponse.subtotalWithVat = res["subtotal_with_vat"]; + cartResponse.subtotalVatAmount = res["subtotal_vat_amount"]; + cartResponse.subtotalVatRate = res["subtotal_vat_rate"]; + cartResponse.shoppingCarts = List(); + res["shopping_carts"].forEach((item) { + ShoppingCart shoppingCart = ShoppingCart.fromJson(item); + cartResponse.shoppingCarts.add(shoppingCart); + totalAdditionalShippingCharge += shoppingCart.product.additionalShippingCharge; + }); + cartResponse.updateShoppingCard(); + } + + String getPaymentOptionImage(PaymentOption paymentOption) { + String assetFile = "assets/images/pharmacy_module/payment/"; + switch (paymentOption.index) { + case 0: + return "${assetFile}mada.png"; + break; + case 1: + return "${assetFile}sadad.png"; + break; + case 2: + return "${assetFile}visa.png"; + break; + case 3: + return "${assetFile}mastercard.png"; + break; + case 4: + return "${assetFile}installment.png"; + break; + default: + return ""; + } + } + + String getPaymentOptionName(PaymentOption paymentOption) { + return _orderService.getPaymentOptionName(paymentOption); + } + + getInformationsByAddress() async { + await getLacumAccountInformation(); + await getShippingOption(); + } + + getLacumAccountInformation() async { + setState(ViewState.Busy); + await _orderService.getLacumAccountInformation(); + if (_orderService.hasError) { + error = _orderService.error; + setState(ViewState.Error); + } else { + getLacumGroupData(); + } + } + + Future getLacumGroupData() async { + setState(ViewState.Busy); + await _orderService.getLacumGroupInformation(); + paymentCheckoutData.lacumInformation = _orderService.lacumGroupInformation; + paymentCheckoutData.usedLakumPoints = paymentCheckoutData.lacumInformation.lakumInquiryInformationObjVersion.pointsBalanceAmount; + if (_orderService.hasError) { + error = _orderService.error; + setState(ViewState.Error); + } else { + setState(ViewState.Idle); + } + } + + getShippingOption() async { + setState(ViewState.Busy); + await _orderService.getShippingOption(paymentCheckoutData.address).then((res) { + paymentCheckoutData.shippingOption = ShippingOption.fromJson(res); + paymentCheckoutData.updateData(); + }); + if (_orderService.hasError) { + error = _orderService.error; + setState(ViewState.Error); + } else { + setState(ViewState.Idle); + } + } + + Future makeOrder() async { + setState(ViewState.Busy); + await _orderService.makeOrder(paymentCheckoutData, cartResponse.shoppingCarts); + if (_orderService.hasError) { + error = _orderService.error; + setState(ViewState.Error); + } else { + setState(ViewState.Idle); + } + } } + +enum PaymentOption { meda, sadad, visa, mastercard, installments } diff --git a/lib/core/viewModels/pharmacyModule/PharmacyAddressesViewModel.dart b/lib/core/viewModels/pharmacyModule/PharmacyAddressesViewModel.dart new file mode 100644 index 00000000..485c92fb --- /dev/null +++ b/lib/core/viewModels/pharmacyModule/PharmacyAddressesViewModel.dart @@ -0,0 +1,117 @@ +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/Addresses.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/Country.dart'; +import 'package:diplomaticquarterapp/services/pharmacy_services/pharmacyAddress_service.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/PharmacyAddressesModel.dart'; +import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; +import 'package:google_maps_place_picker/google_maps_place_picker.dart'; +import '../../../locator.dart'; +import '../base_view_model.dart'; + +class PharmacyAddressesViewModel extends BaseViewModel { + PharmacyAddressService _pharmacyAddressService = + locator(); + + List get addresses => _pharmacyAddressService.addresses; + + int get selectedAddressIndex => _pharmacyAddressService.selectedAddressIndex; + + CountryData get country => _pharmacyAddressService.country; + + setSelectedAddressIndex(int index) { + _pharmacyAddressService.selectedAddressIndex = index; + } + + Future getAddressesList() async { + setState(ViewState.Busy); + await _pharmacyAddressService.getAddresses(); + if (_pharmacyAddressService.hasError) { + error = _pharmacyAddressService.error; + setState(ViewState.Error); + } else { + setState(ViewState.Idle); + } + } + +/* Future getCountries(String countryName) async { + setState(ViewState.Busy); + await _pharmacyAddressService.getCountries(countryName); + if (_pharmacyAddressService.hasError) { + error = _pharmacyAddressService.error; + // setState(ViewState.Error); + } else { + // setState(ViewState.Idle); + } + }*/ + + Future addEditAddress(PickResult value, Addresses editedAddress) async { + setState(ViewState.Busy); + + Addresses sendingAddress; + + if (editedAddress == null) { + sendingAddress = Addresses(); + sendingAddress.id = "0"; + sendingAddress.firstName = user.firstName; + sendingAddress.lastName = user.lastName; + sendingAddress.email = user.emailAddress; + sendingAddress.company = null; + } else { + sendingAddress = editedAddress; + } + value.addressComponents.forEach((element) { + if (element.types.contains("country")) { + sendingAddress.country = element.longName; + } + if (element.types.contains("administrative_area_level_1")) { + sendingAddress.city = element.longName; + } + if (element.types.contains("postal_code")) { + sendingAddress.zipPostalCode = element.longName; + } + if (element.types.contains("administrative_area_level_2")) { + sendingAddress.province = element.longName; + } + }); + sendingAddress.latLong = value.geometry.location.toString(); + + await _pharmacyAddressService.getCountries(sendingAddress.country); + sendingAddress.countryId = country.id; + sendingAddress.stateProvinceId = null; + sendingAddress.address1 = value.formattedAddress; + sendingAddress.address2 = ""; + sendingAddress.phoneNumber = user.mobileNumber; + sendingAddress.faxNumber = user.faxNumber; + sendingAddress.customerAttributes = ""; + sendingAddress.createdOnUtc = DateTime.now().toString(); + + if (editedAddress == null) { + await _pharmacyAddressService.addCustomerAddress(sendingAddress); + } else { + await _pharmacyAddressService.editCustomerAddress(sendingAddress); + } + + if (_pharmacyAddressService.hasError) { + error = _pharmacyAddressService.error; + setState(ViewState.Error); + } else { + setState(ViewState.Idle); + } + } + + Future deleteAddresses(Addresses sendingAddress) async { + setState(ViewState.Busy); + await _pharmacyAddressService.deleteCustomerAddress(sendingAddress); + if (_pharmacyAddressService.hasError) { + error = _pharmacyAddressService.error; + setState(ViewState.Error); + } else { + setState(ViewState.Idle); + } + } + + Future saveSelectedAddressLocally(Addresses selectedAddress) async { + await sharedPref.setObject(PHARMACY_SELECTED_ADDRESS, selectedAddress); + } +} diff --git a/lib/core/viewModels/pharmacyModule/brand_view_model.dart b/lib/core/viewModels/pharmacyModule/brand_view_model.dart new file mode 100644 index 00000000..c981b2b3 --- /dev/null +++ b/lib/core/viewModels/pharmacyModule/brand_view_model.dart @@ -0,0 +1,57 @@ +import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; +import 'package:diplomaticquarterapp/core/viewModels/base_view_model.dart'; +import 'package:diplomaticquarterapp/models/pharmacy/brandModel.dart'; +import 'package:diplomaticquarterapp/models/pharmacy/topBrandsModel.dart'; +import 'package:diplomaticquarterapp/services/pharmacy_services/brands_service.dart'; + + +import '../../../locator.dart'; + +class BrandsViewModel extends BaseViewModel{ + BrandsService _brandsService = locator(); + List get brandsListList => _brandsService.brandsList; + + BrandsService _topBrandsService = locator(); + List get topBrandsListList => _topBrandsService.topBrandsList; + + List get searchList => + _brandsService.searchList; + + bool hasError = false; + + + Future getBrandsData() async { + hasError = false; + setState(ViewState.Busy); + await _brandsService.getBrands(); + if (_brandsService.hasError) { + error = _brandsService.error; + setState(ViewState.ErrorLocal); + } else + setState(ViewState.Idle); + } + + Future getTopBrandsData() async { + hasError = false; + setState(ViewState.Busy); + await _topBrandsService.getTopBrands(); + if (_topBrandsService.hasError) { + error = _topBrandsService.error; + setState(ViewState.ErrorLocal); + } else + setState(ViewState.Idle); + } + + + Future searchProducts({String productName}) async { + hasError = false; + _brandsService.clearSearchList(); + setState(ViewState.Busy); + await _brandsService.searchProducts(productName: productName); + if (_brandsService.hasError) { + error = _brandsService.error; + setState(ViewState.ErrorLocal); + } else + setState(ViewState.Idle); + } +} \ No newline at end of file diff --git a/lib/core/viewModels/pharmacyModule/lacum-registration-viewModel.dart b/lib/core/viewModels/pharmacyModule/lacum-registration-viewModel.dart new file mode 100644 index 00000000..f8f5ea05 --- /dev/null +++ b/lib/core/viewModels/pharmacyModule/lacum-registration-viewModel.dart @@ -0,0 +1,55 @@ +import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/LacumAccountInformation.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/ListUserAgreement.dart'; +import 'package:diplomaticquarterapp/core/service/parmacyModule/lacum-registration-service.dart'; +import 'package:diplomaticquarterapp/core/service/parmacyModule/lacum-transfer-service.dart'; + +import '../../../locator.dart'; +import 'lacum-viewmodel.dart'; + +class LacumRegistrationViewModel extends LacumViewModel { + LacumRegistrationService _lacumService = locator(); + + ListUserAgreement get listUserAgreement => _lacumService.listUserAgreement; + + Future checkLacumAccountActivation(String patientIdentificationNo) async { + setState(ViewState.Busy); + await _lacumService.getLacumAccountInformationById(patientIdentificationNo); + if (_lacumService.hasError) { + error = _lacumService.error; + setState(ViewState.Error); + } else { + if(_lacumService.lacumInformation.yahalaAccountNo != 0){ + error = "The account has already been activated"; + setState(ViewState.Error); + } else { + setState(ViewState.Idle); + } + } + } + + Future getUserTermsAndConditionsForEPharmcy() async { + setState(ViewState.Busy); + await _lacumService.getUserTermsAndConditionsForEPharmcy(); + if (_lacumService.hasError) { + error = _lacumService.error; + setState(ViewState.Error); + } else { + setState(ViewState.Idle); + } + } + + Future createNewLakumAccount(String name, String phone, String identificationNo, int languageId) async { + setState(ViewState.Busy); + await _lacumService.createLakumAccount(name, phone, 0, identificationNo, languageId); + if (_lacumService.hasError) { + error = _lacumService.error; + setState(ViewState.Error); + return 404; + } else { + setState(ViewState.Idle); + return 200; + } + } + +} diff --git a/lib/core/viewModels/pharmacyModule/lacum-trasnfer-viewModel.dart b/lib/core/viewModels/pharmacyModule/lacum-trasnfer-viewModel.dart new file mode 100644 index 00000000..cd19a40f --- /dev/null +++ b/lib/core/viewModels/pharmacyModule/lacum-trasnfer-viewModel.dart @@ -0,0 +1,42 @@ +import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/LacumAccountInformation.dart'; +import 'package:diplomaticquarterapp/core/service/parmacyModule/lacum-transfer-service.dart'; + +import '../../../locator.dart'; +import 'lacum-viewmodel.dart'; + +class LacumTranferViewModel extends LacumViewModel { + LacumTransferService _lacumService = locator(); + + LacumAccountInformation get lacumReceiverInformation => + _lacumService.lacumReceiverInformation; + + Future getLacumGroupDataBuAccountId(String accountId) async { + setState(ViewState.Busy); + await _lacumService.getLacumGroupDataBuAccountId(accountId); + if (_lacumService.hasError) { + error = _lacumService.error; + setState(ViewState.Error); + } else { + setState(ViewState.Idle); + } + } + + Future transferYaHalaLoyaltyPoints(String points) async { + setState(ViewState.Busy); + await _lacumService.transferYaHalaLoyaltyPoints(points); + if (_lacumService.hasError) { + error = _lacumService.error; + setState(ViewState.Error); + return 404; + } else { + setState(ViewState.Idle); + return 200; + } + } + + setLakumData(LacumAccountInformation lacumInformation, LacumAccountInformation lacumGroupInformation){ + _lacumService.lacumInformation = lacumInformation; + _lacumService.lacumGroupInformation = lacumGroupInformation; + } +} diff --git a/lib/core/viewModels/pharmacyModule/lacum-viewmodel.dart b/lib/core/viewModels/pharmacyModule/lacum-viewmodel.dart new file mode 100644 index 00000000..ba8d70d9 --- /dev/null +++ b/lib/core/viewModels/pharmacyModule/lacum-viewmodel.dart @@ -0,0 +1,111 @@ +import 'dart:typed_data'; + +import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/LacumAccountInformation.dart'; +import 'package:diplomaticquarterapp/core/service/parmacyModule/lacum-service.dart'; +import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; +import 'dart:async'; +import 'dart:convert' as convert; + +import '../../../locator.dart'; +import '../base_view_model.dart'; + +class LacumViewModel extends BaseViewModel { + LacumService _lacumService = locator(); + + LacumAccountInformation get lacumInformation => + _lacumService.lacumInformation; + + LacumAccountInformation get lacumGroupInformation => + _lacumService.lacumGroupInformation; + + Future getLacumData() async { + await getLacumAccountData(); + getLacumGroupData(); + } + + Future getLacumAccountData() async { + setState(ViewState.Busy); + await _lacumService.getLacumAccountInformation(); + if (_lacumService.hasError) { + error = _lacumService.error; + setState(ViewState.Error); + } else { + setState(ViewState.Idle); + } + } + + Future getLacumGroupData() async { + setState(ViewState.Busy); + await _lacumService.getLacumGroupInformation(); + if (_lacumService.hasError) { + error = _lacumService.error; + setState(ViewState.Error); + } else { + setState(ViewState.Idle); + } + } + + Future makeAccountActivate() async { + setState(ViewState.Busy); + await _lacumService.makeAccountActivate(); + if (_lacumService.hasError) { + error = _lacumService.error; + setState(ViewState.Error); + } else { + lacumGroupInformation.lakumInquiryInformationObjVersion.accountStatus = "Active"; + getLacumAccountData(); + } + } + + Future makeAccountDeactivate() async { + setState(ViewState.Busy); + await _lacumService.makeAccountDeactivate(); + if (_lacumService.hasError) { + error = _lacumService.error; + setState(ViewState.Error); + } else { + lacumGroupInformation.lakumInquiryInformationObjVersion.accountStatus = "Cancelled"; + getLacumAccountData(); + } + } + + Future createLakumAccount(String name, String phone) async { + setState(ViewState.Busy); + await _lacumService.createLakumAccount(name, phone, lacumInformation.yahalaAccountNo, lacumInformation.identificationNo, null); + if (_lacumService.hasError) { + error = _lacumService.error; + setState(ViewState.Error); + return 404; + } else { + setState(ViewState.Idle); + return 200; + } + } + + String formatCreatedDateToString() { + DateTime createdDate = DateUtil.convertStringToDate( + lacumGroupInformation.lakumInquiryInformationObjVersion.createdDate); + return DateUtil.getFormattedDate(createdDate, "MMM dd,yyyy"); + } + + Uint8List convertBase64ToBarCodeImage() { + try { + final _byteImage = convert.base64Decode( + lacumGroupInformation.lakumInquiryInformationObjVersion.barCode); + return _byteImage; + } catch (e) { + print(e); + return null; + } + } + + setLakumData(LacumAccountInformation lacumInformation, LacumAccountInformation lacumGroupInformation){ + _lacumService.lacumInformation = lacumInformation; + _lacumService.lacumGroupInformation = lacumGroupInformation; + } + + clearLakumGroupData(){ + _lacumService.lacumGroupInformation = null; + } +} diff --git a/lib/core/viewModels/pharmacyModule/order_model_view_model.dart b/lib/core/viewModels/pharmacyModule/order_model_view_model.dart new file mode 100644 index 00000000..b7ddb528 --- /dev/null +++ b/lib/core/viewModels/pharmacyModule/order_model_view_model.dart @@ -0,0 +1,127 @@ +import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/Addresses.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/LacumAccountInformation.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/ShoppingCartResponse.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/payment-checkout-data.dart'; +import 'package:diplomaticquarterapp/core/service/parmacyModule/order-preview-service.dart'; +import 'package:diplomaticquarterapp/pages/pharmacy/order/Order.dart'; +import 'package:diplomaticquarterapp/pages/pharmacy/order/OrderDetails.dart'; +import 'package:diplomaticquarterapp/services/pharmacy_services/cancelOrder_service.dart'; +import 'package:diplomaticquarterapp/services/pharmacy_services/orderDetails_service.dart'; +import 'package:diplomaticquarterapp/services/pharmacy_services/order_service.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/order_model.dart'; +import 'package:diplomaticquarterapp/uitl/app_toast.dart'; +import 'package:flutter/material.dart'; +import '../../../locator.dart'; +import '../base_view_model.dart'; + +class OrderModelViewModel extends BaseViewModel { + OrderService _orderService = locator(); + + List get order => _orderService.orderList; + + OrderDetailsService _orderDetailsService = locator(); + + List get orderDetails => _orderDetailsService.orderDetails; + + CancelOrderService _cancelOrderService = locator(); + + List get cancelOrder => _cancelOrderService.cancelOrderList; + + + OrderPreviewService _orderServices = locator(); + List get addresses => _orderServices.addresses; + LacumAccountInformation get lacumInformation => + _orderServices.lacumInformation; + ShoppingCartResponse cartResponse = ShoppingCartResponse(); + PaymentCheckoutData paymentCheckoutData = PaymentCheckoutData(); + double totalAdditionalShippingCharge = 0; + + + + Future getOrder(customerId, pageID) async { + print("this is customer id" + customerId); + setState(ViewState.Busy); + await _orderService.getOrder(customerId, pageID); + if (_orderService.hasError) { + error = _orderService.error; + setState(ViewState.Error); + } else { + //order = _orderService.orderList; + setState(ViewState.Idle); + } + } + + Future getOrderDetails(orderId) async { + setState(ViewState.Busy); + await _orderDetailsService.getOrderDetails(orderId); + if (_orderDetailsService.hasError) { + error = _orderDetailsService.error; + setState(ViewState.Error); + } else { + setState(ViewState.Idle); + } + } + + Future getProductReview() async { + setState(ViewState.Busy); + // await _orderService.getProductReview(); + if (_orderService.hasError) { + error = _orderService.error; + setState(ViewState.Error); + } else { + //order = _orderService.orderList; + setState(ViewState.Idle); + } + } + + Future getCanceledOrder(order, context) async { + print("this is order id" + order); + setState(ViewState.Busy); + dynamic res; + await _cancelOrderService.getCanceledOrder(order).then((value) { + res = value['success']['SuccessEndUserMsg']; + print(value['success']['SuccessEndUserMsg']); + AppToast.showSuccessToast(message: "Request Sent Successfully"); +// Navigator.pop(context); + }); + if (_cancelOrderService.hasError) { + error = _cancelOrderService.error; + setState(ViewState.Error); + AppToast.showErrorToast(message: error); + } else { + setState(ViewState.Idle); +// AppToast.showSuccessToast(message: "Request Sent Successfully"); +// Navigator.push(context, +// MaterialPageRoute(builder: (context) => OrderPage())); + + } + + return res; + } + + Future makeReview(Product product, double rating, String reviewText) async { + setState(ViewState.Busy); + await _orderDetailsService.makeReview(product, rating, reviewText); + if (_orderDetailsService.hasError) { + error = _orderDetailsService.error; + setState(ViewState.Error); + AppToast.showErrorToast(message: error); + } else { + setState(ViewState.Idle); + AppToast.showSuccessToast( + message: "Your review has been Submitted successfully"); + } + } + Future makeOrder() async { + setState(ViewState.Busy); + await _orderServices.makeOrder(paymentCheckoutData, cartResponse.shoppingCarts); + if (_orderServices.hasError) { + error = _orderServices.error; + setState(ViewState.Error); + } else { + setState(ViewState.Idle); + } + } + +} diff --git a/lib/core/viewModels/pharmacyModule/pharmacy_module_view_model.dart b/lib/core/viewModels/pharmacyModule/pharmacy_module_view_model.dart index f8c574f7..4dfc6a26 100644 --- a/lib/core/viewModels/pharmacyModule/pharmacy_module_view_model.dart +++ b/lib/core/viewModels/pharmacyModule/pharmacy_module_view_model.dart @@ -1,3 +1,4 @@ +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; import 'package:diplomaticquarterapp/core/model/pharmacies/Manufacturer.dart'; import 'package:diplomaticquarterapp/core/model/pharmacies/PharmacyImageObject.dart'; @@ -21,6 +22,25 @@ class PharmacyModuleViewModel extends BaseViewModel { _pharmacyService.lastVisitedProducts; Future getPharmacyHomeData() async { + setState(ViewState.Busy); + var data = await sharedPref.getObject(USER_PROFILE); + var customerId = await sharedPref.getString(PHARMACY_CUSTOMER_ID); + + if (authenticatedUserObject.isLogin && data != null && customerId == null) { + await _pharmacyService.makeVerifyCustomer(data); + // here must call getShoppingCard() + if (_pharmacyService.hasError) { + error = _pharmacyService.error; + setState(ViewState.Error); + } else { + await getBannerList(); + } + } else { + await getBannerList(); + } + } + + Future getBannerList() async { setState(ViewState.Busy); await _pharmacyService.getBannerListList(); if (_pharmacyService.hasError) { @@ -47,6 +67,7 @@ class PharmacyModuleViewModel extends BaseViewModel { error = _pharmacyService.error; setState(ViewState.Error); } else { + setState(ViewState.Idle); _getBestSellerProducts(); } } @@ -70,4 +91,18 @@ class PharmacyModuleViewModel extends BaseViewModel { setState(ViewState.Idle); } } + + Future checkUserIsActivated() async { + if (authenticatedUserObject.isLogin) { + var customerId = await sharedPref.getString(PHARMACY_CUSTOMER_ID); + if (customerId != null) { + return true; + } else { + return false; + } + } else { + // go to login page + return false; + } + } } diff --git a/lib/core/viewModels/pharmacyModule/product_detail_view_model.dart b/lib/core/viewModels/pharmacyModule/product_detail_view_model.dart new file mode 100644 index 00000000..47a3bb11 --- /dev/null +++ b/lib/core/viewModels/pharmacyModule/product_detail_view_model.dart @@ -0,0 +1,110 @@ +import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; +import 'package:diplomaticquarterapp/core/viewModels/base_view_model.dart'; +import 'package:diplomaticquarterapp/models/pharmacy/Wishlist.dart'; +import 'package:diplomaticquarterapp/models/pharmacy/locationModel.dart'; +import 'package:diplomaticquarterapp/models/pharmacy/productDetailModel.dart'; +import 'package:diplomaticquarterapp/services/pharmacy_services/product_detail_service.dart'; +import 'package:diplomaticquarterapp/models/pharmacy/specification.dart'; + + +import '../../../locator.dart'; + +class ProductDetailViewModel extends BaseViewModel{ + ProductDetailService _productDetailService = locator(); + ProductDetailService _productLocationService = locator(); + ProductDetailService _productWishlistService = locator(); + ProductDetailService _productSpecification = locator(); + + List get productDetailService => _productDetailService.productDetailList; + + List get productLocationService => _productLocationService.productLocationList; + + List get wishListItems => _productWishlistService.wishListProducts; + + List get productSpecification => _productSpecification.productSpecification; + + bool hasError = false; + + + Future getProductReviewsData(productID) async { + print('ENAD REview'); + hasError = false; + setState(ViewState.Busy); + await _productDetailService.getProductReviews(productID); + if (_productDetailService.hasError) { + error = _productDetailService.error; + setState(ViewState.ErrorLocal); + } else + setState(ViewState.Idle); + } + + Future getProductLocationData() async { + print('ENAD in model view'); + hasError = false; + setState(ViewState.Busy); + await _productLocationService.getProductAvailabiltyDetail(); + if (_productLocationService.hasError) { + error = _productLocationService.error; + setState(ViewState.ErrorLocal); + } else + setState(ViewState.Idle); + } + + Future addToCartData(quantity, itemID) async { + hasError = false; + setState(ViewState.Busy); + await _productLocationService.addToCart(quantity, itemID); + if (_productLocationService.hasError) { + error = _productLocationService.error; + setState(ViewState.ErrorLocal); + } else + setState(ViewState.Idle); + } + + Future addToWishlistData(itemID) async { + hasError = false; + setState(ViewState.Busy); + await _productLocationService.addToWishlist(itemID); + if (_productLocationService.hasError) { + error = _productLocationService.error; + setState(ViewState.ErrorLocal); + } else + setState(ViewState.Idle); + } + + Future checkWishlistData() async { + hasError = false; + setState(ViewState.Busy); + await _productWishlistService.getWishlistItems(); + if (_productWishlistService.hasError) { + error = _productWishlistService.error; + setState(ViewState.ErrorLocal); + } else + setState(ViewState.Idle); + } + + + Future deletWishlistData(itemID) async { + hasError = false; + setState(ViewState.Busy); + await _productWishlistService.delteItemFromWishlist(itemID); + if (_productWishlistService.hasError) { + error = _productWishlistService.error; + setState(ViewState.ErrorLocal); + } else + setState(ViewState.Idle); + } + + + Future productSpecificationData(itemID) async { + hasError = false; + setState(ViewState.Busy); + await _productWishlistService.productSpecificationData(itemID); + if (_productWishlistService.hasError) { + error = _productWishlistService.error; + setState(ViewState.ErrorLocal); + } else + setState(ViewState.Idle); + } + +} \ No newline at end of file diff --git a/lib/core/viewModels/pharmacyModule/review_view_model.dart b/lib/core/viewModels/pharmacyModule/review_view_model.dart new file mode 100644 index 00000000..3661820b --- /dev/null +++ b/lib/core/viewModels/pharmacyModule/review_view_model.dart @@ -0,0 +1,26 @@ +import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; +import 'package:diplomaticquarterapp/core/viewModels/base_view_model.dart'; +import 'package:diplomaticquarterapp/models/pharmacy/reviewModel.dart'; +import 'package:diplomaticquarterapp/services/pharmacy_services/review_service.dart'; + +import '../../../locator.dart'; + +class ReviewViewModel extends BaseViewModel{ + ReviewService _reviewService = locator(); + + List get reviewListList => _reviewService.reviewList; + + bool hasError = false; + + + Future getReviewData() async { + hasError = false; + setState(ViewState.Busy); + await _reviewService.getReview(); + if (_reviewService.hasError) { + error = _reviewService.error; + setState(ViewState.ErrorLocal); + } else + setState(ViewState.Idle); + } +} \ No newline at end of file diff --git a/lib/core/viewModels/pharmacyModule/tems-condition-viewmodel.dart b/lib/core/viewModels/pharmacyModule/tems-condition-viewmodel.dart new file mode 100644 index 00000000..6a5bd476 --- /dev/null +++ b/lib/core/viewModels/pharmacyModule/tems-condition-viewmodel.dart @@ -0,0 +1,24 @@ +import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/ListUserAgreement.dart'; +import 'package:diplomaticquarterapp/core/service/parmacyModule/terms-condition-service.dart'; +import 'dart:async'; + +import '../../../locator.dart'; +import '../base_view_model.dart'; + +class TermsConditionViewModel extends BaseViewModel { + TermsConditionService _termsConditionService = locator(); + + ListUserAgreement get listUserAgreement => _termsConditionService.listUserAgreement; + + Future getUserTermsAndConditionsForEPharmcy() async { + setState(ViewState.Busy); + await _termsConditionService.getUserTermsAndConditionsForEPharmcy(); + if (_termsConditionService.hasError) { + error = _termsConditionService.error; + setState(ViewState.Error); + } else { + setState(ViewState.Idle); + } + } +} diff --git a/lib/core/viewModels/pharmacyModule/wishlist_view_model.dart b/lib/core/viewModels/pharmacyModule/wishlist_view_model.dart new file mode 100644 index 00000000..788b7f3c --- /dev/null +++ b/lib/core/viewModels/pharmacyModule/wishlist_view_model.dart @@ -0,0 +1,36 @@ +import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; +import 'package:diplomaticquarterapp/core/viewModels/base_view_model.dart'; +import 'package:diplomaticquarterapp/models/pharmacy/Wishlist.dart'; +import 'package:diplomaticquarterapp/services/pharmacy_services/wishList_service.dart'; + +import '../../../locator.dart'; + +class WishListViewModel extends BaseViewModel{ + WishListService _wishlistService = locator(); + + List get wishListList => _wishlistService.wishListProducts; + bool hasError = false; + + +// Future getWishlistData() async { +// setState(ViewState.Busy); +// await _wishlistService.getWishlist(); +// if (_wishlistService.hasError) { +// error = _wishlistService.error; +// setState(ViewState.Error); +// } else { +// setState(ViewState.Idle); +// } +// } + + Future getWishlistData() async { + hasError = false; + setState(ViewState.Busy); + await _wishlistService.getWishlist(); + if (_wishlistService.hasError) { + error = _wishlistService.error; + setState(ViewState.ErrorLocal); + } else + setState(ViewState.Idle); + } +} \ No newline at end of file diff --git a/lib/core/viewModels/pharmacy_categorise_view_model.dart b/lib/core/viewModels/pharmacy_categorise_view_model.dart new file mode 100644 index 00000000..5e1f4f9f --- /dev/null +++ b/lib/core/viewModels/pharmacy_categorise_view_model.dart @@ -0,0 +1,158 @@ +import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacy/brands_model.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacy/categorise_parent_model.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacy/final_products_model.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacy/parent_products_model.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacy/pharmacy_categorise.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacy/scan_qr_model.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacy/sub_categories_model.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacy/sub_products_model.dart'; +import 'package:diplomaticquarterapp/core/model/search_products_model.dart'; + +import 'package:diplomaticquarterapp/core/service/pharmacy_categorise_service.dart'; +import 'package:diplomaticquarterapp/locator.dart'; + +import 'base_view_model.dart'; + +class PharmacyCategoriseViewModel extends BaseViewModel { + bool hasError = false; + PharmacyCategoriseService _pharmacyCategoriseService = + locator(); + + List get categorise => + _pharmacyCategoriseService.categoriseList; + + List get categoriseParent => + _pharmacyCategoriseService.parentCategoriseList; + + List get parentProducts => + _pharmacyCategoriseService.parentProductsList; + + List get subCategorise => + _pharmacyCategoriseService.subCategoriseList; + + List get subProducts => + _pharmacyCategoriseService.subProductsList; + + List get finalProducts => + _pharmacyCategoriseService.finalProducts; + List get brandsList => _pharmacyCategoriseService.brandsList; + + List get searchList => + _pharmacyCategoriseService.searchList; + + List get scanList => _pharmacyCategoriseService.scanList; + + Future getCategorise() async { + hasError = false; + // _insuranceCardService.clearInsuranceCard(); + setState(ViewState.Busy); + await _pharmacyCategoriseService.getCategorise(); + if (_pharmacyCategoriseService.hasError) { + error = _pharmacyCategoriseService.error; + setState(ViewState.ErrorLocal); + } else + setState(ViewState.Idle); + } + + Future getBrands() async { + hasError = false; + // _insuranceCardService.clearInsuranceCard(); + setState(ViewState.Busy); + await _pharmacyCategoriseService.getBrands(); + if (_pharmacyCategoriseService.hasError) { + error = _pharmacyCategoriseService.error; + setState(ViewState.ErrorLocal); + } else + setState(ViewState.Idle); + } + + Future scanQr({String id}) async { + hasError = false; + // _insuranceCardService.clearInsuranceCard(); + setState(ViewState.Busy); + await _pharmacyCategoriseService.scanQr(id: id); + if (_pharmacyCategoriseService.hasError) { + error = _pharmacyCategoriseService.error; + setState(ViewState.ErrorLocal); + } else + setState(ViewState.Idle); + } + + clearSearchList() { + _pharmacyCategoriseService.clearSearchList(); + } + + Future searchProducts({String productName}) async { + hasError = false; + _pharmacyCategoriseService.clearSearchList(); + setState(ViewState.Busy); + await _pharmacyCategoriseService.searchProducts(productName: productName); + if (_pharmacyCategoriseService.hasError) { + error = _pharmacyCategoriseService.error; + setState(ViewState.ErrorLocal); + } else + setState(ViewState.Idle); + } + + Future getCategoriseParent({String i}) async { + hasError = false; + // _insuranceCardService.clearInsuranceCard(); + setState(ViewState.Busy); + await _pharmacyCategoriseService.getCategoriseParent(id: i); + if (_pharmacyCategoriseService.hasError) { + error = _pharmacyCategoriseService.error; + setState(ViewState.ErrorLocal); + } else + await getParentProducts(i: i); + await getBrands(); + } + + Future getParentProducts({String i}) async { + hasError = false; + // _insuranceCardService.clearInsuranceCard(); + setState(ViewState.Busy); + await _pharmacyCategoriseService.getParentProducts(id: i); + if (_pharmacyCategoriseService.hasError) { + error = _pharmacyCategoriseService.error; + setState(ViewState.ErrorLocal); + } else + setState(ViewState.Idle); + } + + Future getSubCategorise({String i}) async { + hasError = false; + // _insuranceCardService.clearInsuranceCard(); + setState(ViewState.Busy); + await _pharmacyCategoriseService.getSubCategorise(id: i); + if (_pharmacyCategoriseService.hasError) { + error = _pharmacyCategoriseService.error; + setState(ViewState.ErrorLocal); + } else + getSubProducts(i: i); + } + + Future getSubProducts({String i}) async { + hasError = false; + // _insuranceCardService.clearInsuranceCard(); + setState(ViewState.Busy); + await _pharmacyCategoriseService.getSubProducts(id: i); + if (_pharmacyCategoriseService.hasError) { + error = _pharmacyCategoriseService.error; + setState(ViewState.ErrorLocal); + } else + setState(ViewState.Idle); + } + + Future getFinalProducts({String i}) async { + hasError = false; + // _insuranceCardService.clearInsuranceCard(); + setState(ViewState.Busy); + await _pharmacyCategoriseService.getFinalProducts(id: i); + if (_pharmacyCategoriseService.hasError) { + error = _pharmacyCategoriseService.error; + setState(ViewState.ErrorLocal); + } else + setState(ViewState.Idle); + } +} diff --git a/lib/core/viewModels/project_view_model.dart b/lib/core/viewModels/project_view_model.dart index 700ab2a4..baaf6b5b 100644 --- a/lib/core/viewModels/project_view_model.dart +++ b/lib/core/viewModels/project_view_model.dart @@ -6,11 +6,17 @@ import 'package:diplomaticquarterapp/core/model/privilege/PrivilegeModel.dart'; import 'package:diplomaticquarterapp/core/service/privilege_service.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'; import 'package:flutter_datetime_picker/flutter_datetime_picker.dart'; class ProjectViewModel extends BaseViewModel { + // Platform Bridge + PlatformBridge platformBridge() { + return PlatformBridge.shared(); + } + AppSharedPreferences sharedPref = AppSharedPreferences(); Locale _appLocale = Locale('ar'); String currentLanguage = 'ar'; @@ -60,9 +66,8 @@ class ProjectViewModel extends BaseViewModel { }); } - void loadSharedPrefLanguage() async { - currentLanguage = - await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar'); + Future loadSharedPrefLanguage() async { + currentLanguage = await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar'); _appLocale = Locale(currentLanguage); _isArabic = currentLanguage == 'ar'; notifyListeners(); diff --git a/lib/generated/json/GeoZonesResponseModel_helper.dart b/lib/generated/json/GeoZonesResponseModel_helper.dart new file mode 100644 index 00000000..7cf3cc5f --- /dev/null +++ b/lib/generated/json/GeoZonesResponseModel_helper.dart @@ -0,0 +1,50 @@ +import 'package:diplomaticquarterapp/core/model/geofencing/responses/GeoZonesResponseModel.dart'; + +geoZonesResponseModelEntityFromJson(GeoZonesResponseModel data, Map json) { + if (json['GEOF_ID'] != null) { + data.geofId = json['GEOF_ID']?.toInt(); + } + if (json['Description'] != null) { + data.description = json['Description']?.toString(); + } + if (json['DescriptionN'] != null) { + data.descriptionN = json['DescriptionN']?.toString(); + } + if (json['Latitude'] != null) { + data.latitude = json['Latitude']?.toString(); + } + if (json['Longitude'] != null) { + data.longitude = json['Longitude']?.toString(); + } + if (json['Radius'] != null) { + data.radius = json['Radius']?.toInt(); + } + if (json['Type'] != null) { + data.type = json['Type']?.toInt(); + } + if (json['ProjectID'] != null) { + data.projectID = json['ProjectID']?.toInt(); + } + if (json['ImageURL'] != null) { + data.imageURL = json['ImageURL']?.toString(); + } + if (json['IsCity'] != null) { + data.isCity = json['IsCity']; + } + return data; +} + +Map geoZonesResponseModelEntityToJson(GeoZonesResponseModel entity) { + final Map data = new Map(); + data['GEOF_ID'] = entity.geofId; + data['Description'] = entity.description; + data['DescriptionN'] = entity.descriptionN; + data['Latitude'] = entity.latitude; + data['Longitude'] = entity.longitude; + data['Radius'] = entity.radius; + data['Type'] = entity.type; + data['ProjectID'] = entity.projectID; + data['ImageURL'] = entity.imageURL; + data['IsCity'] = entity.isCity; + return data; +} diff --git a/lib/generated/json/OfferCategoriesResponseModel_helper.dart b/lib/generated/json/OfferCategoriesResponseModel_helper.dart new file mode 100644 index 00000000..e5ebc914 --- /dev/null +++ b/lib/generated/json/OfferCategoriesResponseModel_helper.dart @@ -0,0 +1,172 @@ +import 'package:diplomaticquarterapp/core/model/packages_offers/responses/OfferCategoriesResponseModel.dart'; + +offerCategoriesResponseModelFromJson(OfferCategoriesResponseModel data, Map json) { + if (json['id'] != null) { + data.id = json['id']?.toString(); + } + if (json['name'] != null) { + data.name = json['name']?.toString(); + } + if (json['namen'] != null) { + data.namen = json['namen']?.toString(); + } + if (json['localized_names'] != null) { + data.localizedNames = new List(); + (json['localized_names'] as List).forEach((v) { + data.localizedNames.add(new OfferCategoriesResponseModelLocalizedName().fromJson(v)); + }); + } + if (json['description'] != null) { + data.description = json['description']; + } + if (json['category_template_id'] != null) { + data.categoryTemplateId = json['category_template_id']?.toInt(); + } + if (json['meta_keywords'] != null) { + data.metaKeywords = json['meta_keywords']?.toString(); + } + if (json['meta_description'] != null) { + data.metaDescription = json['meta_description']?.toString(); + } + if (json['meta_title'] != null) { + data.metaTitle = json['meta_title']?.toString(); + } + if (json['parent_category_id'] != null) { + data.parentCategoryId = json['parent_category_id']?.toInt(); + } + if (json['page_size'] != null) { + data.pageSize = json['page_size']?.toInt(); + } + if (json['page_size_options'] != null) { + data.pageSizeOptions = json['page_size_options']?.toString(); + } + if (json['price_ranges'] != null) { + data.priceRanges = json['price_ranges']; + } + if (json['show_on_home_page'] != null) { + data.showOnHomePage = json['show_on_home_page']; + } + if (json['include_in_top_menu'] != null) { + data.includeInTopMenu = json['include_in_top_menu']; + } + if (json['has_discounts_applied'] != null) { + data.hasDiscountsApplied = json['has_discounts_applied']; + } + if (json['published'] != null) { + data.published = json['published']; + } + if (json['deleted'] != null) { + data.deleted = json['deleted']; + } + if (json['display_order'] != null) { + data.displayOrder = json['display_order']?.toInt(); + } + if (json['created_on_utc'] != null) { + data.createdOnUtc = json['created_on_utc']?.toString(); + } + if (json['updated_on_utc'] != null) { + data.updatedOnUtc = json['updated_on_utc']?.toString(); + } + if (json['role_ids'] != null) { + data.roleIds = new List(); + data.roleIds.addAll(json['role_ids']); + } + if (json['discount_ids'] != null) { + data.discountIds = new List(); + data.discountIds.addAll(json['discount_ids']); + } + if (json['store_ids'] != null) { + data.storeIds = new List(); + data.storeIds.addAll(json['store_ids']); + } + if (json['image'] != null) { + data.image = new OfferCategoriesResponseModelImage().fromJson(json['image']); + } + if (json['se_name'] != null) { + data.seName = json['se_name']?.toString(); + } + if (json['is_leaf'] != null) { + data.isLeaf = json['is_leaf']; + } + return data; +} + +Map offerCategoriesResponseModelToJson(OfferCategoriesResponseModel entity) { + final Map data = new Map(); + data['id'] = entity.id; + data['name'] = entity.name; + data['namen'] = entity.namen; + if (entity.localizedNames != null) { + data['localized_names'] = entity.localizedNames.map((v) => v.toJson()).toList(); + } + data['description'] = entity.description; + data['category_template_id'] = entity.categoryTemplateId; + data['meta_keywords'] = entity.metaKeywords; + data['meta_description'] = entity.metaDescription; + data['meta_title'] = entity.metaTitle; + data['parent_category_id'] = entity.parentCategoryId; + data['page_size'] = entity.pageSize; + data['page_size_options'] = entity.pageSizeOptions; + data['price_ranges'] = entity.priceRanges; + data['show_on_home_page'] = entity.showOnHomePage; + data['include_in_top_menu'] = entity.includeInTopMenu; + data['has_discounts_applied'] = entity.hasDiscountsApplied; + data['published'] = entity.published; + data['deleted'] = entity.deleted; + data['display_order'] = entity.displayOrder; + data['created_on_utc'] = entity.createdOnUtc; + data['updated_on_utc'] = entity.updatedOnUtc; + if (entity.roleIds != null) { + data['role_ids'] = []; + } + if (entity.discountIds != null) { + data['discount_ids'] = []; + } + if (entity.storeIds != null) { + data['store_ids'] = []; + } + if (entity.image != null) { + data['image'] = entity.image.toJson(); + } + data['se_name'] = entity.seName; + data['is_leaf'] = entity.isLeaf; + return data; +} + +offerCategoriesResponseModelLocalizedNameFromJson(OfferCategoriesResponseModelLocalizedName data, Map json) { + if (json['language_id'] != null) { + data.languageId = json['language_id']?.toInt(); + } + if (json['localized_name'] != null) { + data.localizedName = json['localized_name']?.toString(); + } + return data; +} + +Map offerCategoriesResponseModelLocalizedNameToJson(OfferCategoriesResponseModelLocalizedName entity) { + final Map data = new Map(); + data['language_id'] = entity.languageId; + data['localized_name'] = entity.localizedName; + return data; +} + +offerCategoriesResponseModelImageFromJson(OfferCategoriesResponseModelImage data, Map json) { + if (json['src'] != null) { + data.src = json['src']?.toString(); + } + if (json['thumb'] != null) { + data.thumb = json['thumb']; + } + if (json['attachment'] != null) { + data.attachment = json['attachment']; + } + return data; +} + +Map offerCategoriesResponseModelImageToJson(OfferCategoriesResponseModelImage entity) { + final Map data = new Map(); + data['src'] = entity.src; + data['thumb'] = entity.thumb; + data['attachment'] = entity.attachment; + return data; +} diff --git a/lib/generated/json/OfferProductsResponseModel_helper.dart b/lib/generated/json/OfferProductsResponseModel_helper.dart new file mode 100644 index 00000000..dc0edeca --- /dev/null +++ b/lib/generated/json/OfferProductsResponseModel_helper.dart @@ -0,0 +1,569 @@ +import 'package:diplomaticquarterapp/core/model/packages_offers/responses/OfferProductsResponseModel.dart'; + +offerProductsResponseModelFromJson(OfferProductsResponseModel data, Map json) { + if (json['id'] != null) { + data.id = json['id']?.toString(); + } + if (json['visible_individually'] != null) { + data.visibleIndividually = json['visible_individually']; + } + if (json['name'] != null) { + data.name = json['name']?.toString(); + } + if (json['namen'] != null) { + data.namen = json['namen']?.toString(); + } + if (json['localized_names'] != null) { + data.localizedNames = new List(); + (json['localized_names'] as List).forEach((v) { + data.localizedNames.add(new OfferProductsResponseModelLocalizedName().fromJson(v)); + }); + } + if (json['short_description'] != null) { + data.shortDescription = json['short_description']?.toString(); + } + if (json['short_descriptionn'] != null) { + data.shortDescriptionn = json['short_descriptionn']?.toString(); + } + if (json['full_description'] != null) { + data.fullDescription = json['full_description']?.toString(); + } + if (json['full_descriptionn'] != null) { + data.fullDescriptionn = json['full_descriptionn']?.toString(); + } + if (json['markas_new'] != null) { + data.markasNew = json['markas_new']; + } + if (json['show_on_home_page'] != null) { + data.showOnHomePage = json['show_on_home_page']; + } + if (json['meta_keywords'] != null) { + data.metaKeywords = json['meta_keywords']; + } + if (json['meta_description'] != null) { + data.metaDescription = json['meta_description']; + } + if (json['meta_title'] != null) { + data.metaTitle = json['meta_title']; + } + if (json['allow_customer_reviews'] != null) { + data.allowCustomerReviews = json['allow_customer_reviews']; + } + if (json['approved_rating_sum'] != null) { + data.approvedRatingSum = json['approved_rating_sum']?.toInt(); + } + if (json['not_approved_rating_sum'] != null) { + data.notApprovedRatingSum = json['not_approved_rating_sum']?.toInt(); + } + if (json['approved_total_reviews'] != null) { + data.approvedTotalReviews = json['approved_total_reviews']?.toInt(); + } + if (json['not_approved_total_reviews'] != null) { + data.notApprovedTotalReviews = json['not_approved_total_reviews']?.toInt(); + } + if (json['sku'] != null) { + data.sku = json['sku']?.toString(); + } + if (json['is_rx'] != null) { + data.isRx = json['is_rx']; + } + if (json['prescription_required'] != null) { + data.prescriptionRequired = json['prescription_required']; + } + if (json['rx_message'] != null) { + data.rxMessage = json['rx_message']; + } + if (json['rx_messagen'] != null) { + data.rxMessagen = json['rx_messagen']; + } + if (json['manufacturer_part_number'] != null) { + data.manufacturerPartNumber = json['manufacturer_part_number']; + } + if (json['gtin'] != null) { + data.gtin = json['gtin']; + } + if (json['is_gift_card'] != null) { + data.isGiftCard = json['is_gift_card']; + } + if (json['require_other_products'] != null) { + data.requireOtherProducts = json['require_other_products']; + } + if (json['automatically_add_required_products'] != null) { + data.automaticallyAddRequiredProducts = json['automatically_add_required_products']; + } + if (json['is_download'] != null) { + data.isDownload = json['is_download']; + } + if (json['unlimited_downloads'] != null) { + data.unlimitedDownloads = json['unlimited_downloads']; + } + if (json['max_number_of_downloads'] != null) { + data.maxNumberOfDownloads = json['max_number_of_downloads']?.toInt(); + } + if (json['download_expiration_days'] != null) { + data.downloadExpirationDays = json['download_expiration_days']; + } + if (json['has_sample_download'] != null) { + data.hasSampleDownload = json['has_sample_download']; + } + if (json['has_user_agreement'] != null) { + data.hasUserAgreement = json['has_user_agreement']; + } + if (json['is_recurring'] != null) { + data.isRecurring = json['is_recurring']; + } + if (json['recurring_cycle_length'] != null) { + data.recurringCycleLength = json['recurring_cycle_length']?.toInt(); + } + if (json['recurring_total_cycles'] != null) { + data.recurringTotalCycles = json['recurring_total_cycles']?.toInt(); + } + if (json['is_rental'] != null) { + data.isRental = json['is_rental']; + } + if (json['rental_price_length'] != null) { + data.rentalPriceLength = json['rental_price_length']?.toInt(); + } + if (json['is_ship_enabled'] != null) { + data.isShipEnabled = json['is_ship_enabled']; + } + if (json['is_free_shipping'] != null) { + data.isFreeShipping = json['is_free_shipping']; + } + if (json['ship_separately'] != null) { + data.shipSeparately = json['ship_separately']; + } + if (json['additional_shipping_charge'] != null) { + data.additionalShippingCharge = json['additional_shipping_charge']?.toDouble(); + } + if (json['is_tax_exempt'] != null) { + data.isTaxExempt = json['is_tax_exempt']; + } + if (json['is_telecommunications_or_broadcasting_or_electronic_services'] != null) { + data.isTelecommunicationsOrBroadcastingOrElectronicServices = json['is_telecommunications_or_broadcasting_or_electronic_services']; + } + if (json['use_multiple_warehouses'] != null) { + data.useMultipleWarehouses = json['use_multiple_warehouses']; + } + if (json['manage_inventory_method_id'] != null) { + data.manageInventoryMethodId = json['manage_inventory_method_id']?.toInt(); + } + if (json['stock_quantity'] != null) { + data.stockQuantity = json['stock_quantity']?.toInt(); + } + if (json['stock_availability'] != null) { + data.stockAvailability = json['stock_availability']?.toString(); + } + if (json['stock_availabilityn'] != null) { + data.stockAvailabilityn = json['stock_availabilityn']?.toString(); + } + if (json['display_stock_availability'] != null) { + data.displayStockAvailability = json['display_stock_availability']; + } + if (json['display_stock_quantity'] != null) { + data.displayStockQuantity = json['display_stock_quantity']; + } + if (json['min_stock_quantity'] != null) { + data.minStockQuantity = json['min_stock_quantity']?.toInt(); + } + if (json['notify_admin_for_quantity_below'] != null) { + data.notifyAdminForQuantityBelow = json['notify_admin_for_quantity_below']?.toInt(); + } + if (json['allow_back_in_stock_subscriptions'] != null) { + data.allowBackInStockSubscriptions = json['allow_back_in_stock_subscriptions']; + } + if (json['order_minimum_quantity'] != null) { + data.orderMinimumQuantity = json['order_minimum_quantity']?.toInt(); + } + if (json['order_maximum_quantity'] != null) { + data.orderMaximumQuantity = json['order_maximum_quantity']?.toInt(); + } + if (json['allowed_quantities'] != null) { + data.allowedQuantities = json['allowed_quantities']; + } + if (json['allow_adding_only_existing_attribute_combinations'] != null) { + data.allowAddingOnlyExistingAttributeCombinations = json['allow_adding_only_existing_attribute_combinations']; + } + if (json['disable_buy_button'] != null) { + data.disableBuyButton = json['disable_buy_button']; + } + if (json['disable_wishlist_button'] != null) { + data.disableWishlistButton = json['disable_wishlist_button']; + } + if (json['available_for_pre_order'] != null) { + data.availableForPreOrder = json['available_for_pre_order']; + } + if (json['pre_order_availability_start_date_time_utc'] != null) { + data.preOrderAvailabilityStartDateTimeUtc = json['pre_order_availability_start_date_time_utc']; + } + if (json['call_for_price'] != null) { + data.callForPrice = json['call_for_price']; + } + if (json['price'] != null) { + data.price = json['price']?.toDouble(); + } + if (json['old_price'] != null) { + data.oldPrice = json['old_price']?.toDouble(); + } + if (json['product_cost'] != null) { + data.productCost = json['product_cost']?.toDouble(); + } + if (json['special_price'] != null) { + data.specialPrice = json['special_price']; + } + if (json['special_price_start_date_time_utc'] != null) { + data.specialPriceStartDateTimeUtc = json['special_price_start_date_time_utc']; + } + if (json['special_price_end_date_time_utc'] != null) { + data.specialPriceEndDateTimeUtc = json['special_price_end_date_time_utc']; + } + if (json['customer_enters_price'] != null) { + data.customerEntersPrice = json['customer_enters_price']; + } + if (json['minimum_customer_entered_price'] != null) { + data.minimumCustomerEnteredPrice = json['minimum_customer_entered_price']?.toDouble(); + } + if (json['maximum_customer_entered_price'] != null) { + data.maximumCustomerEnteredPrice = json['maximum_customer_entered_price']?.toDouble(); + } + if (json['baseprice_enabled'] != null) { + data.basepriceEnabled = json['baseprice_enabled']; + } + if (json['baseprice_amount'] != null) { + data.basepriceAmount = json['baseprice_amount']?.toDouble(); + } + if (json['baseprice_base_amount'] != null) { + data.basepriceBaseAmount = json['baseprice_base_amount']?.toDouble(); + } + if (json['has_tier_prices'] != null) { + data.hasTierPrices = json['has_tier_prices']; + } + if (json['has_discounts_applied'] != null) { + data.hasDiscountsApplied = json['has_discounts_applied']; + } + if (json['discount_name'] != null) { + data.discountName = json['discount_name']; + } + if (json['discount_namen'] != null) { + data.discountNamen = json['discount_namen']; + } + if (json['discount_description'] != null) { + data.discountDescription = json['discount_description']; + } + if (json['discount_Descriptionn'] != null) { + data.discountDescriptionn = json['discount_Descriptionn']; + } + if (json['discount_percentage'] != null) { + data.discountPercentage = json['discount_percentage']; + } + if (json['currency'] != null) { + data.currency = json['currency']?.toString(); + } + if (json['currencyn'] != null) { + data.currencyn = json['currencyn']?.toString(); + } + if (json['weight'] != null) { + data.weight = json['weight']?.toDouble(); + } + if (json['length'] != null) { + data.length = json['length']?.toDouble(); + } + if (json['width'] != null) { + data.width = json['width']?.toDouble(); + } + if (json['height'] != null) { + data.height = json['height']?.toDouble(); + } + if (json['available_start_date_time_utc'] != null) { + data.availableStartDateTimeUtc = json['available_start_date_time_utc']; + } + if (json['available_end_date_time_utc'] != null) { + data.availableEndDateTimeUtc = json['available_end_date_time_utc']; + } + if (json['display_order'] != null) { + data.displayOrder = json['display_order']?.toInt(); + } + if (json['published'] != null) { + data.published = json['published']; + } + if (json['deleted'] != null) { + data.deleted = json['deleted']; + } + if (json['created_on_utc'] != null) { + data.createdOnUtc = json['created_on_utc']?.toString(); + } + if (json['updated_on_utc'] != null) { + data.updatedOnUtc = json['updated_on_utc']?.toString(); + } + if (json['product_type'] != null) { + data.productType = json['product_type']?.toString(); + } + if (json['parent_grouped_product_id'] != null) { + data.parentGroupedProductId = json['parent_grouped_product_id']?.toInt(); + } + if (json['role_ids'] != null) { + data.roleIds = new List(); + data.roleIds.addAll(json['role_ids']); + } + if (json['discount_ids'] != null) { + data.discountIds = new List(); + data.discountIds.addAll(json['discount_ids']); + } + if (json['store_ids'] != null) { + data.storeIds = new List(); + data.storeIds.addAll(json['store_ids']); + } + if (json['manufacturer_ids'] != null) { + data.manufacturerIds = json['manufacturer_ids']?.map((v) => v?.toInt())?.toList()?.cast(); + } + if (json['reviews'] != null) { + data.reviews = new List(); + data.reviews.addAll(json['reviews']); + } + if (json['images'] != null) { + data.images = new List(); + (json['images'] as List).forEach((v) { + data.images.add(new OfferProductsResponseModelImage().fromJson(v)); + }); + } + if (json['attributes'] != null) { + data.attributes = new List(); + data.attributes.addAll(json['attributes']); + } + if (json['specifications'] != null) { + data.specifications = new List(); + (json['specifications'] as List).forEach((v) { + data.specifications.add(new OfferProductsResponseModelSpecification().fromJson(v)); + }); + } + if (json['associated_product_ids'] != null) { + data.associatedProductIds = new List(); + data.associatedProductIds.addAll(json['associated_product_ids']); + } + if (json['tags'] != null) { + data.tags = new List(); + data.tags.addAll(json['tags']); + } + if (json['vendor_id'] != null) { + data.vendorId = json['vendor_id']?.toInt(); + } + if (json['se_name'] != null) { + data.seName = json['se_name']?.toString(); + } + return data; +} + +Map offerProductsResponseModelToJson(OfferProductsResponseModel entity) { + final Map data = new Map(); + data['id'] = entity.id; + data['visible_individually'] = entity.visibleIndividually; + data['name'] = entity.name; + data['namen'] = entity.namen; + if (entity.localizedNames != null) { + data['localized_names'] = entity.localizedNames.map((v) => v.toJson()).toList(); + } + data['short_description'] = entity.shortDescription; + data['short_descriptionn'] = entity.shortDescriptionn; + data['full_description'] = entity.fullDescription; + data['full_descriptionn'] = entity.fullDescriptionn; + data['markas_new'] = entity.markasNew; + data['show_on_home_page'] = entity.showOnHomePage; + data['meta_keywords'] = entity.metaKeywords; + data['meta_description'] = entity.metaDescription; + data['meta_title'] = entity.metaTitle; + data['allow_customer_reviews'] = entity.allowCustomerReviews; + data['approved_rating_sum'] = entity.approvedRatingSum; + data['not_approved_rating_sum'] = entity.notApprovedRatingSum; + data['approved_total_reviews'] = entity.approvedTotalReviews; + data['not_approved_total_reviews'] = entity.notApprovedTotalReviews; + data['sku'] = entity.sku; + data['is_rx'] = entity.isRx; + data['prescription_required'] = entity.prescriptionRequired; + data['rx_message'] = entity.rxMessage; + data['rx_messagen'] = entity.rxMessagen; + data['manufacturer_part_number'] = entity.manufacturerPartNumber; + data['gtin'] = entity.gtin; + data['is_gift_card'] = entity.isGiftCard; + data['require_other_products'] = entity.requireOtherProducts; + data['automatically_add_required_products'] = entity.automaticallyAddRequiredProducts; + data['is_download'] = entity.isDownload; + data['unlimited_downloads'] = entity.unlimitedDownloads; + data['max_number_of_downloads'] = entity.maxNumberOfDownloads; + data['download_expiration_days'] = entity.downloadExpirationDays; + data['has_sample_download'] = entity.hasSampleDownload; + data['has_user_agreement'] = entity.hasUserAgreement; + data['is_recurring'] = entity.isRecurring; + data['recurring_cycle_length'] = entity.recurringCycleLength; + data['recurring_total_cycles'] = entity.recurringTotalCycles; + data['is_rental'] = entity.isRental; + data['rental_price_length'] = entity.rentalPriceLength; + data['is_ship_enabled'] = entity.isShipEnabled; + data['is_free_shipping'] = entity.isFreeShipping; + data['ship_separately'] = entity.shipSeparately; + data['additional_shipping_charge'] = entity.additionalShippingCharge; + data['is_tax_exempt'] = entity.isTaxExempt; + data['is_telecommunications_or_broadcasting_or_electronic_services'] = entity.isTelecommunicationsOrBroadcastingOrElectronicServices; + data['use_multiple_warehouses'] = entity.useMultipleWarehouses; + data['manage_inventory_method_id'] = entity.manageInventoryMethodId; + data['stock_quantity'] = entity.stockQuantity; + data['stock_availability'] = entity.stockAvailability; + data['stock_availabilityn'] = entity.stockAvailabilityn; + data['display_stock_availability'] = entity.displayStockAvailability; + data['display_stock_quantity'] = entity.displayStockQuantity; + data['min_stock_quantity'] = entity.minStockQuantity; + data['notify_admin_for_quantity_below'] = entity.notifyAdminForQuantityBelow; + data['allow_back_in_stock_subscriptions'] = entity.allowBackInStockSubscriptions; + data['order_minimum_quantity'] = entity.orderMinimumQuantity; + data['order_maximum_quantity'] = entity.orderMaximumQuantity; + data['allowed_quantities'] = entity.allowedQuantities; + data['allow_adding_only_existing_attribute_combinations'] = entity.allowAddingOnlyExistingAttributeCombinations; + data['disable_buy_button'] = entity.disableBuyButton; + data['disable_wishlist_button'] = entity.disableWishlistButton; + data['available_for_pre_order'] = entity.availableForPreOrder; + data['pre_order_availability_start_date_time_utc'] = entity.preOrderAvailabilityStartDateTimeUtc; + data['call_for_price'] = entity.callForPrice; + data['price'] = entity.price; + data['old_price'] = entity.oldPrice; + data['product_cost'] = entity.productCost; + data['special_price'] = entity.specialPrice; + data['special_price_start_date_time_utc'] = entity.specialPriceStartDateTimeUtc; + data['special_price_end_date_time_utc'] = entity.specialPriceEndDateTimeUtc; + data['customer_enters_price'] = entity.customerEntersPrice; + data['minimum_customer_entered_price'] = entity.minimumCustomerEnteredPrice; + data['maximum_customer_entered_price'] = entity.maximumCustomerEnteredPrice; + data['baseprice_enabled'] = entity.basepriceEnabled; + data['baseprice_amount'] = entity.basepriceAmount; + data['baseprice_base_amount'] = entity.basepriceBaseAmount; + data['has_tier_prices'] = entity.hasTierPrices; + data['has_discounts_applied'] = entity.hasDiscountsApplied; + data['discount_name'] = entity.discountName; + data['discount_namen'] = entity.discountNamen; + data['discount_description'] = entity.discountDescription; + data['discount_Descriptionn'] = entity.discountDescriptionn; + data['discount_percentage'] = entity.discountPercentage; + data['currency'] = entity.currency; + data['currencyn'] = entity.currencyn; + data['weight'] = entity.weight; + data['length'] = entity.length; + data['width'] = entity.width; + data['height'] = entity.height; + data['available_start_date_time_utc'] = entity.availableStartDateTimeUtc; + data['available_end_date_time_utc'] = entity.availableEndDateTimeUtc; + data['display_order'] = entity.displayOrder; + data['published'] = entity.published; + data['deleted'] = entity.deleted; + data['created_on_utc'] = entity.createdOnUtc; + data['updated_on_utc'] = entity.updatedOnUtc; + data['product_type'] = entity.productType; + data['parent_grouped_product_id'] = entity.parentGroupedProductId; + if (entity.roleIds != null) { + data['role_ids'] = []; + } + if (entity.discountIds != null) { + data['discount_ids'] = []; + } + if (entity.storeIds != null) { + data['store_ids'] = []; + } + data['manufacturer_ids'] = entity.manufacturerIds; + if (entity.reviews != null) { + data['reviews'] = []; + } + if (entity.images != null) { + data['images'] = entity.images.map((v) => v.toJson()).toList(); + } + if (entity.attributes != null) { + data['attributes'] = []; + } + if (entity.specifications != null) { + data['specifications'] = entity.specifications.map((v) => v.toJson()).toList(); + } + if (entity.associatedProductIds != null) { + data['associated_product_ids'] = []; + } + if (entity.tags != null) { + data['tags'] = []; + } + data['vendor_id'] = entity.vendorId; + data['se_name'] = entity.seName; + return data; +} + +offerProductsResponseModelLocalizedNameFromJson(OfferProductsResponseModelLocalizedName data, Map json) { + if (json['language_id'] != null) { + data.languageId = json['language_id']?.toInt(); + } + if (json['localized_name'] != null) { + data.localizedName = json['localized_name']?.toString(); + } + return data; +} + +Map offerProductsResponseModelLocalizedNameToJson(OfferProductsResponseModelLocalizedName entity) { + final Map data = new Map(); + data['language_id'] = entity.languageId; + data['localized_name'] = entity.localizedName; + return data; +} + +offerProductsResponseModelImageFromJson(OfferProductsResponseModelImage data, Map json) { + if (json['id'] != null) { + data.id = json['id']?.toInt(); + } + if (json['position'] != null) { + data.position = json['position']?.toInt(); + } + if (json['src'] != null) { + data.src = json['src']?.toString(); + } + if (json['thumb'] != null) { + data.thumb = json['thumb']?.toString(); + } + if (json['attachment'] != null) { + data.attachment = json['attachment']?.toString(); + } + return data; +} + +Map offerProductsResponseModelImageToJson(OfferProductsResponseModelImage entity) { + final Map data = new Map(); + data['id'] = entity.id; + data['position'] = entity.position; + data['src'] = entity.src; + data['thumb'] = entity.thumb; + data['attachment'] = entity.attachment; + return data; +} + +offerProductsResponseModelSpecificationFromJson(OfferProductsResponseModelSpecification data, Map json) { + if (json['id'] != null) { + data.id = json['id']?.toInt(); + } + if (json['display_order'] != null) { + data.displayOrder = json['display_order']?.toInt(); + } + if (json['default_value'] != null) { + data.defaultValue = json['default_value']?.toString(); + } + if (json['default_valuen'] != null) { + data.defaultValuen = json['default_valuen']?.toString(); + } + if (json['name'] != null) { + data.name = json['name']?.toString(); + } + if (json['nameN'] != null) { + data.nameN = json['nameN']?.toString(); + } + return data; +} + +Map offerProductsResponseModelSpecificationToJson(OfferProductsResponseModelSpecification entity) { + final Map data = new Map(); + data['id'] = entity.id; + data['display_order'] = entity.displayOrder; + data['default_value'] = entity.defaultValue; + data['default_valuen'] = entity.defaultValuen; + data['name'] = entity.name; + data['nameN'] = entity.nameN; + return data; +} diff --git a/lib/generated/json/base/json_convert_content.dart b/lib/generated/json/base/json_convert_content.dart new file mode 100644 index 00000000..9fab946e --- /dev/null +++ b/lib/generated/json/base/json_convert_content.dart @@ -0,0 +1,128 @@ +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: camel_case_types +// ignore_for_file: prefer_single_quotes + +// This file is automatically generated. DO NOT EDIT, all your changes would be lost. +import 'package:diplomaticquarterapp/core/model/packages_offers/responses/OfferCategoriesResponseModel.dart'; +import 'package:diplomaticquarterapp/generated/json/OfferCategoriesResponseModel_helper.dart'; +import 'package:diplomaticquarterapp/core/model/geofencing/responses/LogGeoZoneResponseModel.dart'; +import 'package:diplomaticquarterapp/generated/json/log_geo_zone_response_model_entity_helper.dart'; +import 'package:diplomaticquarterapp/core/model/packages_offers/responses/OfferProductsResponseModel.dart'; +import 'package:diplomaticquarterapp/generated/json/OfferProductsResponseModel_helper.dart'; +import 'package:diplomaticquarterapp/core/model/geofencing/responses/GeoZonesResponseModel.dart'; +import 'package:diplomaticquarterapp/generated/json/GeoZonesResponseModel_helper.dart'; + +class JsonConvert { + T fromJson(Map json) { + return _getFromJson(runtimeType, this, json); + } + + Map toJson() { + return _getToJson(runtimeType, this); + } + + static _getFromJson(Type type, data, json) { + switch (type) { + case OfferCategoriesResponseModel: + return offerCategoriesResponseModelFromJson(data as OfferCategoriesResponseModel, json) as T; + case OfferCategoriesResponseModelLocalizedName: + return offerCategoriesResponseModelLocalizedNameFromJson(data as OfferCategoriesResponseModelLocalizedName, json) as T; + case OfferCategoriesResponseModelImage: + return offerCategoriesResponseModelImageFromJson(data as OfferCategoriesResponseModelImage, json) as T; + case LogGeoZoneResponseModel: + return logGeoZoneResponseModelEntityFromJson(data as LogGeoZoneResponseModel, json) as T; + case OfferProductsResponseModel: + return offerProductsResponseModelFromJson(data as OfferProductsResponseModel, json) as T; + case OfferProductsResponseModelLocalizedName: + return offerProductsResponseModelLocalizedNameFromJson(data as OfferProductsResponseModelLocalizedName, json) as T; + case OfferProductsResponseModelImage: + return offerProductsResponseModelImageFromJson(data as OfferProductsResponseModelImage, json) as T; + case OfferProductsResponseModelSpecification: + return offerProductsResponseModelSpecificationFromJson(data as OfferProductsResponseModelSpecification, json) as T; + case GeoZonesResponseModel: + return geoZonesResponseModelEntityFromJson(data as GeoZonesResponseModel, json) as T; + } + return data as T; + } + + static _getToJson(Type type, data) { + switch (type) { + case OfferCategoriesResponseModel: + return offerCategoriesResponseModelToJson(data as OfferCategoriesResponseModel); + case OfferCategoriesResponseModelLocalizedName: + return offerCategoriesResponseModelLocalizedNameToJson(data as OfferCategoriesResponseModelLocalizedName); + case OfferCategoriesResponseModelImage: + return offerCategoriesResponseModelImageToJson(data as OfferCategoriesResponseModelImage); + case LogGeoZoneResponseModel: + return logGeoZoneResponseModelEntityToJson(data as LogGeoZoneResponseModel); + case OfferProductsResponseModel: + return offerProductsResponseModelToJson(data as OfferProductsResponseModel); + case OfferProductsResponseModelLocalizedName: + return offerProductsResponseModelLocalizedNameToJson(data as OfferProductsResponseModelLocalizedName); + case OfferProductsResponseModelImage: + return offerProductsResponseModelImageToJson(data as OfferProductsResponseModelImage); + case OfferProductsResponseModelSpecification: + return offerProductsResponseModelSpecificationToJson(data as OfferProductsResponseModelSpecification); + case GeoZonesResponseModel: + return geoZonesResponseModelEntityToJson(data as GeoZonesResponseModel); + } + return data as T; + } + + //Go back to a single instance by type + static _fromJsonSingle(json) { + String type = M.toString(); + if (type == (OfferCategoriesResponseModel).toString()) { + return OfferCategoriesResponseModel().fromJson(json); + } else if (type == (OfferCategoriesResponseModelLocalizedName).toString()) { + return OfferCategoriesResponseModelLocalizedName().fromJson(json); + } else if (type == (OfferCategoriesResponseModelImage).toString()) { + return OfferCategoriesResponseModelImage().fromJson(json); + } else if (type == (LogGeoZoneResponseModel).toString()) { + return LogGeoZoneResponseModel().fromJson(json); + } else if (type == (OfferProductsResponseModel).toString()) { + return OfferProductsResponseModel().fromJson(json); + } else if (type == (OfferProductsResponseModelLocalizedName).toString()) { + return OfferProductsResponseModelLocalizedName().fromJson(json); + } else if (type == (OfferProductsResponseModelImage).toString()) { + return OfferProductsResponseModelImage().fromJson(json); + } else if (type == (OfferProductsResponseModelSpecification).toString()) { + return OfferProductsResponseModelSpecification().fromJson(json); + } else if (type == (GeoZonesResponseModel).toString()) { + return GeoZonesResponseModel().fromJson(json); + } + return null; + } + + //list is returned by type + static M _getListChildType(List data) { + if (List() is M) { + return data.map((e) => OfferCategoriesResponseModel().fromJson(e)).toList() as M; + } else if (List() is M) { + return data.map((e) => OfferCategoriesResponseModelLocalizedName().fromJson(e)).toList() as M; + } else if (List() is M) { + return data.map((e) => OfferCategoriesResponseModelImage().fromJson(e)).toList() as M; + } else if (List() is M) { + return data.map((e) => LogGeoZoneResponseModel().fromJson(e)).toList() as M; + } else if (List() is M) { + return data.map((e) => OfferProductsResponseModel().fromJson(e)).toList() as M; + } else if (List() is M) { + return data.map((e) => OfferProductsResponseModelLocalizedName().fromJson(e)).toList() as M; + } else if (List() is M) { + return data.map((e) => OfferProductsResponseModelImage().fromJson(e)).toList() as M; + } else if (List() is M) { + return data.map((e) => OfferProductsResponseModelSpecification().fromJson(e)).toList() as M; + } else if (List() is M) { + return data.map((e) => GeoZonesResponseModel().fromJson(e)).toList() as M; + } + return null; + } + + static M fromJsonAsT(json) { + if (json is List) { + return _getListChildType(json); + } else { + return _fromJsonSingle(json) as M; + } + } +} diff --git a/lib/generated/json/base/json_field.dart b/lib/generated/json/base/json_field.dart new file mode 100644 index 00000000..bc92972b --- /dev/null +++ b/lib/generated/json/base/json_field.dart @@ -0,0 +1,21 @@ +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: camel_case_types +// ignore_for_file: prefer_single_quotes + +// This file is automatically generated. DO NOT EDIT, all your changes would be lost. + +class JSONField { + //Specify the parse field name + final String name; + + //Specify the time resolution format + final String format; + + //Whether to participate in toJson + final bool serialize; + + //Whether to participate in fromMap + final bool deserialize; + + const JSONField({this.name, this.format, this.serialize, this.deserialize}); +} diff --git a/lib/generated/json/log_geo_zone_response_model_entity_helper.dart b/lib/generated/json/log_geo_zone_response_model_entity_helper.dart new file mode 100644 index 00000000..28b8c996 --- /dev/null +++ b/lib/generated/json/log_geo_zone_response_model_entity_helper.dart @@ -0,0 +1,54 @@ +import 'package:diplomaticquarterapp/core/model/geofencing/responses/LogGeoZoneResponseModel.dart'; + +logGeoZoneResponseModelEntityFromJson(LogGeoZoneResponseModel data, Map json) { + if (json['LanguageID'] != null) { + data.languageID = json['LanguageID']?.toInt(); + } + if (json['ErrorCode'] != null) { + data.errorCode = json['ErrorCode']; + } + if (json['ErrorEndUserMessage'] != null) { + data.errorEndUserMessage = json['ErrorEndUserMessage']?.toString(); + } + if (json['ErrorEndUserMessageN'] != null) { + data.errorEndUserMessageN = json['ErrorEndUserMessageN']; + } + if (json['ErrorMessage'] != null) { + data.errorMessage = json['ErrorMessage']; + } + if (json['ErrorType'] != null) { + data.errorType = json['ErrorType']?.toInt(); + } + if (json['IsAuthenticated'] != null) { + data.isAuthenticated = json['IsAuthenticated']; + } + if (json['SuccessMsg'] != null) { + data.successMsg = json['SuccessMsg']; + } + if (json['SuccessMsgN'] != null) { + data.successMsgN = json['SuccessMsgN']; + } + if (json['statusCode'] != null) { + data.statusCode = json['statusCode']?.toInt(); + } + if (json['MessageStatus'] != null) { + data.messageStatus = json['MessageStatus']?.toInt(); + } + return data; +} + +Map logGeoZoneResponseModelEntityToJson(LogGeoZoneResponseModel entity) { + final Map data = new Map(); + data['LanguageID'] = entity.languageID; + data['ErrorCode'] = entity.errorCode; + data['ErrorEndUserMessage'] = entity.errorEndUserMessage; + data['ErrorEndUserMessageN'] = entity.errorEndUserMessageN; + data['ErrorMessage'] = entity.errorMessage; + data['ErrorType'] = entity.errorType; + data['IsAuthenticated'] = entity.isAuthenticated; + data['SuccessMsg'] = entity.successMsg; + data['SuccessMsgN'] = entity.successMsgN; + data['statusCode'] = entity.statusCode; + data['MessageStatus'] = entity.messageStatus; + return data; +} diff --git a/lib/locator.dart b/lib/locator.dart index 68557d01..7830e395 100644 --- a/lib/locator.dart +++ b/lib/locator.dart @@ -1,6 +1,5 @@ import 'package:diplomaticquarterapp/core/service/AlHabibMedicalService/H2O_service.dart'; import 'package:diplomaticquarterapp/core/service/qr_service.dart'; -import 'package:diplomaticquarterapp/core/service/weather_service.dart'; import 'package:diplomaticquarterapp/core/viewModels/AlHabibMedicalService/H2O_view_model.dart'; import 'package:diplomaticquarterapp/core/viewModels/child_vaccines/user_information_view_model.dart'; import 'package:diplomaticquarterapp/core/viewModels/AlHabibMedicalService/home_health_care_view_model.dart'; @@ -9,7 +8,14 @@ import 'package:diplomaticquarterapp/core/viewModels/weather/weather_view_model. // import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/PharmacyAddressesViewModel.dart'; // import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/order_model_view_model.dart'; // import 'package:diplomaticquarterapp/services/pharmacy_services/order_service.dart'; +import 'package:diplomaticquarterapp/services/pharmacy_services/review_service.dart'; +import 'package:diplomaticquarterapp/services/pharmacy_services/wishList_service.dart'; +import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/PharmacyAddressesViewModel.dart'; +import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/order_model_view_model.dart'; +import 'package:diplomaticquarterapp/services/pharmacy_services/cancelOrder_service.dart'; +import 'package:diplomaticquarterapp/services/pharmacy_services/order_service.dart'; import 'package:diplomaticquarterapp/uitl/navigation_service.dart'; +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:get_it/get_it.dart'; import 'core/service/AlHabibMedicalService/cmc_service.dart'; @@ -31,6 +37,7 @@ import 'core/service/dashboard_service.dart'; import 'core/service/er/am_service.dart'; import 'core/service/er/er_service.dart'; import 'core/service/feedback/feedback_service.dart'; +import 'core/service/geofencing/GeofencingServices.dart'; import 'core/service/hospital_service.dart'; import 'core/service/medical/ActiveMedicationsService.dart'; import 'core/service/medical/AllergiesService.dart'; @@ -48,12 +55,20 @@ import 'core/service/medical/prescriptions_service.dart'; import 'core/service/medical/radiology_service.dart'; import 'core/service/medical/reports_monthly_service.dart'; import 'core/service/medical/vital_sign_service.dart'; +import 'core/service/packages_offers/PackagesOffersServices.dart'; +import 'core/service/parmacyModule/lacum-registration-service.dart'; +import 'core/service/parmacyModule/lacum-service.dart'; +import 'core/service/parmacyModule/lacum-transfer-service.dart'; import 'core/service/parmacyModule/order-preview-service.dart'; import 'core/service/notifications_service.dart'; +import 'core/service/parmacyModule/terms-condition-service.dart'; import 'core/service/privilege_service.dart'; +import 'core/service/weather_service.dart'; import 'core/viewModels/AlHabibMedicalService/cmc_view_model.dart'; import 'core/service/parmacyModule/parmacy_module_service.dart'; +import 'core/service/offers_service.dart'; +import 'core/service/pharmacy_categorise_service.dart'; import 'core/viewModels/all_habib_medical_services/e_referral_view_model.dart'; import 'core/viewModels/appointment_rate_view_model.dart'; import 'core/viewModels/blooddonation/blood_details_view_model.dart'; @@ -86,20 +101,43 @@ import 'core/viewModels/medical/vital_sign_view_model.dart'; import 'core/viewModels/medical/reports_view_model.dart'; import 'core/viewModels/medical/weight_pressure_view_model.dart'; import 'core/viewModels/notifications_view_model.dart'; +import 'core/viewModels/offers_Categorise_view_model.dart'; +import 'core/viewModels/packages_offers/PackagesOffersViewModel.dart'; import 'core/viewModels/pharmacies_view_model.dart'; import 'core/service/pharmacies_service.dart'; import 'core/service/insurance_service.dart'; import 'core/viewModels/insurance_card_View_model.dart'; +import 'core/viewModels/pharmacyModule/brand_view_model.dart'; +import 'core/viewModels/pharmacyModule/pharmacy_module_view_model.dart'; +import 'core/viewModels/pharmacyModule/product_detail_view_model.dart'; +import 'core/viewModels/pharmacyModule/review_view_model.dart'; +import 'core/viewModels/pharmacyModule/wishlist_view_model.dart'; +import 'core/viewModels/qr_view_model.dart'; +import 'core/viewModels/vaccine_view_model.dart'; +import 'core/service/vaccine_service.dart'; +import 'core/viewModels/weather/weather_view_model.dart'; +import 'services/pharmacy_services/brands_service.dart'; +import 'services/pharmacy_services/product_detail_service.dart'; import 'core/viewModels/pharmacyModule/OrderPreviewViewModel.dart'; +import 'core/viewModels/pharmacyModule/lacum-registration-viewModel.dart'; +import 'core/viewModels/pharmacyModule/lacum-trasnfer-viewModel.dart'; +import 'core/viewModels/pharmacyModule/lacum-viewmodel.dart'; import 'core/viewModels/pharmacyModule/pharmacy_module_view_model.dart'; +import 'core/viewModels/pharmacyModule/tems-condition-viewmodel.dart'; +import 'core/viewModels/pharmacy_categorise_view_model.dart'; import 'core/viewModels/qr_view_model.dart'; import 'core/viewModels/vaccine_view_model.dart'; import 'core/service/vaccine_service.dart'; +import 'services/pharmacy_services/orderDetails_service.dart'; +import 'services/pharmacy_services/pharmacyAddress_service.dart'; GetIt locator = GetIt.instance; ///di void setupLocator() { + /// Others + locator.registerLazySingleton(() => FlutterLocalNotificationsPlugin()); + /// Services locator.registerLazySingleton(() => AuthenticatedUserObject()); locator.registerLazySingleton(() => HospitalService()); @@ -124,6 +162,7 @@ void setupLocator() { locator.registerLazySingleton(() => EReferralService()); locator.registerLazySingleton(() => HomeHealthCareService()); locator.registerLazySingleton(() => CMCService()); + locator.registerLazySingleton(() => PatientSickLeaveService()); locator.registerLazySingleton(() => MyBalanceService()); locator.registerLazySingleton(() => BloodSugarService()); @@ -136,25 +175,43 @@ void setupLocator() { locator.registerLazySingleton(() => FindusService()); locator.registerLazySingleton(() => LiveChatService()); locator.registerLazySingleton(() => H2OService()); + locator.registerLazySingleton(() => BloodDonationService()); locator.registerLazySingleton(() => BloodDetailsService()); locator.registerLazySingleton(() => ChildVaccinesService()); locator.registerLazySingleton(() => UserInformationService()); locator.registerLazySingleton(() => CreteNewBabyService()); locator.registerLazySingleton(() => DeleteBabyService()); + locator.registerLazySingleton(() => VaccinationTableService()); //pharmacy // locator.registerLazySingleton(() => PharmacyCategoriseService()); // locator.registerLazySingleton(() => OffersCategoriseService()); + locator.registerLazySingleton(() => PharmacyCategoriseService()); + locator.registerLazySingleton(() => OffersCategoriseService()); locator.registerLazySingleton(() => NotificationService()); - locator.registerLazySingleton(() => WeatherService()); locator.registerLazySingleton(() => PharmacyModuleService()); + locator.registerLazySingleton(() => WishListService()); + locator.registerLazySingleton(() => ReviewService()); + locator.registerLazySingleton(() => BrandsService()); + locator.registerLazySingleton(() => ProductDetailService()); + locator.registerLazySingleton(() => OrderPreviewService()); + locator.registerLazySingleton(() => LacumService()); + locator.registerLazySingleton(() => LacumTransferService()); + locator.registerLazySingleton(() => LacumRegistrationService()); + locator.registerLazySingleton(() => OrderService()); + locator.registerLazySingleton(() => PharmacyAddressService()); + locator.registerLazySingleton(() => OrderDetailsService()); locator.registerLazySingleton(() => CustomerAddressesService()); // locator.registerLazySingleton(() => TermsConditionService()); locator.registerLazySingleton(() => PrivilegeService()); + locator.registerLazySingleton(() => TermsConditionService()); + locator.registerLazySingleton(() => CancelOrderService()); + locator.registerLazySingleton(() => PrivilegeService()); + locator.registerLazySingleton(() => WeatherService()); /// View Model locator.registerFactory(() => HospitalViewModel()); @@ -174,7 +231,6 @@ void setupLocator() { locator.registerFactory(() => QrViewModel()); locator.registerFactory(() => ReportsMonthlyViewModel()); locator.registerFactory(() => NearHospitalViewModel()); - locator.registerFactory(() => WeatherViewModel()); locator.registerFactory(() => AmRequestViewModel()); locator.registerFactory(() => PatientSickLeaveViewMode()); locator.registerFactory(() => MyBalanceViewModel()); @@ -186,6 +242,10 @@ void setupLocator() { locator.registerFactory(() => ChildVaccinesViewModel()); locator.registerFactory(() => UserInformationViewModel()); locator.registerFactory(() => VaccinationTableViewModel()); + locator.registerFactory(() => OrderModelViewModel()); + locator.registerFactory(() => PharmacyAddressesViewModel()); + locator.registerFactory(() => TermsConditionViewModel()); + locator.registerFactory(() => AddNewChildViewModel()); locator.registerFactory(() => H2OViewModel()); locator.registerFactory(() => BloodSugarViewMode()); @@ -201,9 +261,35 @@ void setupLocator() { locator.registerFactory(() => NotificationViewModel()); locator.registerFactory(() => PharmacyModuleViewModel()); + locator.registerFactory(() => WishListViewModel()); + locator.registerFactory(() => ReviewViewModel()); + locator.registerFactory(() => BrandsViewModel()); + locator.registerFactory(() => ProductDetailViewModel()); + locator.registerFactory(() => WeatherViewModel()); + locator.registerFactory(() => OrderPreviewViewModel()); + locator.registerFactory(() => LacumViewModel()); + locator.registerFactory(() => LacumTranferViewModel()); + locator.registerFactory(() => LacumRegistrationViewModel()); + + //pharmacy + locator.registerFactory(() => PharmacyCategoriseViewModel()); + locator.registerFactory(() => OffersCategoriseViewModel()); + + // Offer And Packages + //---------------------- + locator.registerLazySingleton( + () => OffersAndPackagesServices()); // offerPackagesServices Service + locator.registerFactory( + () => OfferCategoriesViewModel()); // Categories View Model + locator + .registerFactory(() => OfferProductsViewModel()); // Products View Model //pharmacy // locator.registerFactory(() => PharmacyCategoriseViewModel()); // locator.registerFactory(() => OffersCategoriseViewModel()); + // Geofencing + // --------------------- + locator.registerLazySingleton( + () => GeofencingServices()); // Geofencing Services } diff --git a/lib/main.dart b/lib/main.dart index 218fbf07..e0444a32 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -4,27 +4,38 @@ import 'package:diplomaticquarterapp/routes.dart'; import 'package:diplomaticquarterapp/services/robo_search/event_provider.dart'; import 'package:diplomaticquarterapp/services/robo_search/search_provider.dart'; import 'package:diplomaticquarterapp/theme/theme_value.dart'; +import 'package:diplomaticquarterapp/uitl/HMG_Geofence.dart'; +import 'package:diplomaticquarterapp/uitl/LocalNotification.dart'; +import 'package:diplomaticquarterapp/uitl/PlatformBridge.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:flutter/material.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:hexcolor/hexcolor.dart'; import 'package:provider/provider.dart'; +import 'Constants.dart'; import 'config/size_config.dart'; +import 'core/model/geofencing/requests/GeoZonesRequestModel.dart'; +import 'core/service/geofencing/GeofencingServices.dart'; import 'core/viewModels/project_view_model.dart'; import 'locator.dart'; +import 'pages/pharmacies/compare-list.dart'; void main() async { setupLocator(); - runApp(ChangeNotifierProvider( - create: (context) => ThemeNotifier(defaultTheme), child: MyApp() )); + runApp(ChangeNotifierProvider(create: (context) => ThemeNotifier(defaultTheme), child: MyApp())); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { - final themeNotifier = Provider.of(context); + PlatformBridge.init(context); + LocalNotification.init(onNotificationClick: (payload){ + LocalNotification.getInstance().showNow(title: "Payload", subtitle: payload, payload: payload); + }); + final themeNotifier = Provider.of(context); + precacheImage(AssetImage('assets/images/powerd-by.jpg'), context); return LayoutBuilder( builder: (context, constraints) { return OrientationBuilder( @@ -35,17 +46,17 @@ class MyApp extends StatelessWidget { ChangeNotifierProvider( create: (context) => ProjectViewModel(), ), - ChangeNotifierProvider( - create: (context) => ToDoCountProviderModel()), - ChangeNotifierProvider( - create: (context) => SearchProvider()), + ChangeNotifierProvider(create: (context) => ToDoCountProviderModel()), + ChangeNotifierProvider(create: (context) => SearchProvider()), ChangeNotifierProvider.value( value: SearchProvider(), ), StreamProvider.value( value: RobotProvider().intStream(), initialData: RobotProvider().setValue({}), - ) + ), + ChangeNotifierProvider( + create: (context) => CompareList()), ], child: Consumer( builder: (context, projectProvider, child) => MaterialApp( @@ -63,9 +74,8 @@ class MyApp extends StatelessWidget { const Locale('ar', ''), // Arabic const Locale('en', ''), // English ], - // theme: themeNotifier.getTheme(), - theme:ThemeData( - fontFamily:projectProvider.isArabic ? 'Cairo' : 'WorkSans', + theme: ThemeData( + fontFamily: projectProvider.isArabic ? 'Cairo' : 'WorkSans', primarySwatch: Colors.blue, visualDensity: VisualDensity.adaptivePlatformDensity, brightness: Brightness.light, @@ -90,13 +100,14 @@ class MyApp extends StatelessWidget { backgroundColor: Color.fromRGBO(255, 255, 255, 1), highlightColor: Colors.grey[100].withOpacity(0.4), splashColor: Colors.transparent, - primaryColor: Colors.grey, - bottomSheetTheme: BottomSheetThemeData( - backgroundColor: HexColor('#E0E0E0')), + primaryColor: Color(0xff515A5D), + toggleableActiveColor: secondaryColor, + indicatorColor: secondaryColor, + bottomSheetTheme: BottomSheetThemeData(backgroundColor: HexColor('#E0E0E0')), cursorColor: Colors.grey, iconTheme: IconThemeData(), appBarTheme: AppBarTheme( - color: Colors.grey[700], + color: Color(0xff515A5D), brightness: Brightness.light, elevation: 0.0, actionsIconTheme: IconThemeData( diff --git a/lib/models/Appointments/AppoimentAllHistoryResultList.dart b/lib/models/Appointments/AppoimentAllHistoryResultList.dart index 20eace25..045f759e 100644 --- a/lib/models/Appointments/AppoimentAllHistoryResultList.dart +++ b/lib/models/Appointments/AppoimentAllHistoryResultList.dart @@ -50,6 +50,7 @@ class AppoitmentAllHistoryResultList { bool isExecludeDoctor; int isFollowup; bool isLiveCareAppointment; + bool isInOutPatient; bool isMedicalReportRequested; bool isOnlineCheckedIN; String latitude; @@ -188,6 +189,7 @@ class AppoitmentAllHistoryResultList { isExecludeDoctor = json['IsExecludeDoctor']; isFollowup = json['IsFollowup']; isLiveCareAppointment = json['IsLiveCareAppointment']; + isInOutPatient = json['IsInOutPatient']; isMedicalReportRequested = json['IsMedicalReportRequested']; isOnlineCheckedIN = json['IsOnlineCheckedIN']; latitude = json['Latitude']; @@ -259,6 +261,7 @@ class AppoitmentAllHistoryResultList { data['IsExecludeDoctor'] = this.isExecludeDoctor; data['IsFollowup'] = this.isFollowup; data['IsLiveCareAppointment'] = this.isLiveCareAppointment; + data['IsInOutPatient'] = this.isInOutPatient; data['IsMedicalReportRequested'] = this.isMedicalReportRequested; data['IsOnlineCheckedIN'] = this.isOnlineCheckedIN; data['Latitude'] = this.latitude; diff --git a/lib/models/Appointments/toDoCountProviderModel.dart b/lib/models/Appointments/toDoCountProviderModel.dart index 0fd83491..e44a0ebb 100644 --- a/lib/models/Appointments/toDoCountProviderModel.dart +++ b/lib/models/Appointments/toDoCountProviderModel.dart @@ -2,11 +2,15 @@ import 'package:flutter/cupertino.dart'; class ToDoCountProviderModel with ChangeNotifier { int _count; + bool _isShowBadge = false; int get count => _count == null ? 0 : _count; - void setState(int count) { + bool get isShowBadge => _isShowBadge; + + void setState(int count, bool isShowBadge) { _count = count; + _isShowBadge = isShowBadge; notifyListeners(); } } diff --git a/lib/models/Authentication/check_activation_code_response.dart b/lib/models/Authentication/check_activation_code_response.dart index 55ba6559..3a0aed65 100644 --- a/lib/models/Authentication/check_activation_code_response.dart +++ b/lib/models/Authentication/check_activation_code_response.dart @@ -270,7 +270,7 @@ class CheckActivationCode { } } -class Lists { +class List { String setupID; int patientType; int patientID; @@ -330,7 +330,7 @@ class Lists { dynamic tempAddress; dynamic zipCode; - Lists({ + List({ this.setupID, this.patientType, this.patientID, @@ -391,7 +391,7 @@ class Lists { this.zipCode, }); - Lists.fromJson(Map json) { + List.fromJson(Map json) { setupID = json['SetupID']; patientType = json['PatientType']; patientID = json['PatientID']; diff --git a/lib/models/FamilyFiles/GetAllSharedRecordByStatusResponse.dart b/lib/models/FamilyFiles/GetAllSharedRecordByStatusResponse.dart index b21d940f..750cf0be 100644 --- a/lib/models/FamilyFiles/GetAllSharedRecordByStatusResponse.dart +++ b/lib/models/FamilyFiles/GetAllSharedRecordByStatusResponse.dart @@ -25,7 +25,7 @@ class GetAllSharedRecordsByStatusResponse { dynamic successMsgN; dynamic doctorInformationList; List getAllPendingRecordsList; - List getAllSharedRecordsByStatusList; + List getAllSharedRecordsByStatusList = List(); List getResponseFileList; bool isHMGPatient; bool isLoginSuccessfully; @@ -92,7 +92,7 @@ class GetAllSharedRecordsByStatusResponse { this.successMsgN, this.doctorInformationList, this.getAllPendingRecordsList, - this.getAllSharedRecordsByStatusList, + this.getAllSharedRecordsByStatusList , this.getResponseFileList, this.isHMGPatient, this.isLoginSuccessfully, diff --git a/lib/models/id-name-pair.dart b/lib/models/id-name-pair.dart new file mode 100644 index 00000000..00336572 --- /dev/null +++ b/lib/models/id-name-pair.dart @@ -0,0 +1,12 @@ +import 'package:flutter/material.dart'; + +class IdNamePair with ChangeNotifier{ + var id; + var name; + + IdNamePair(this.id, this.name); + + void updateData() { + notifyListeners(); + } +} \ No newline at end of file diff --git a/lib/models/pharmacy/Wishlist.dart b/lib/models/pharmacy/Wishlist.dart new file mode 100644 index 00000000..41704ede --- /dev/null +++ b/lib/models/pharmacy/Wishlist.dart @@ -0,0 +1,881 @@ +// To parse this JSON data, do +// +// final wishlist = wishlistFromJson(jsonString); + +import 'dart:convert'; + +List wishlistFromJson(String str) => List.from(json.decode(str).map((x) => Wishlist.fromJson(x))); + +String wishlistToJson(List data) => json.encode(List.from(data.map((x) => x.toJson()))); + +class Wishlist { + Wishlist({ + this.languageId, + this.id, + this.productAttributes, + this.customerEnteredPrice, + this.quantity, + this.discountAmountInclTax, + this.subtotal, + this.subtotalWithVat, + this.subtotalVatAmount, + this.subtotalVatRate, + this.currency, + this.currencyn, + this.rentalStartDateUtc, + this.rentalEndDateUtc, + this.createdOnUtc, + this.updatedOnUtc, + this.shoppingCartType, + this.productId, + this.product, + this.customerId, + this.customer, + }); + + dynamic languageId; + dynamic id; + List productAttributes; + dynamic customerEnteredPrice; + dynamic quantity; + dynamic discountAmountInclTax; + dynamic subtotal; + dynamic subtotalWithVat; + dynamic subtotalVatAmount; + dynamic subtotalVatRate; + dynamic currency; + dynamic currencyn; + dynamic rentalStartDateUtc; + dynamic rentalEndDateUtc; + dynamic createdOnUtc; + dynamic updatedOnUtc; + dynamic shoppingCartType; + dynamic productId; + dynamic product; + dynamic customerId; + Customer customer; + + factory Wishlist.fromJson(Map json) => Wishlist( + languageId: json["language_id"], + id: json["id"], + productAttributes: List.from(json["product_attributes"].map((x) => x)), + customerEnteredPrice: json["customer_entered_price"], + quantity: json["quantity"], + discountAmountInclTax: json["discount_amount_incl_tax"], + subtotal: json["subtotal"], + subtotalWithVat: json["subtotal_with_vat"], + subtotalVatAmount: json["subtotal_vat_amount"], + subtotalVatRate: json["subtotal_vat_rate"], + currency: json["currency"], + currencyn: json["currencyn"], + rentalStartDateUtc: json["rental_start_date_utc"], + rentalEndDateUtc: json["rental_end_date_utc"], + createdOnUtc: DateTime.parse(json["created_on_utc"]), + updatedOnUtc: DateTime.parse(json["updated_on_utc"]), + shoppingCartType: json["shopping_cart_type"], + productId: json["product_id"], + product: Product.fromJson(json["product"]), + customerId: json["customer_id"], + customer: Customer.fromJson(json["customer"]), + ); + + Map toJson() => { + "language_id": languageId, + "id": id, + "product_attributes": List.from(productAttributes.map((x) => x)), + "customer_entered_price": customerEnteredPrice, + "quantity": quantity, + "discount_amount_incl_tax": discountAmountInclTax, + "subtotal": subtotal, + "subtotal_with_vat": subtotalWithVat, + "subtotal_vat_amount": subtotalVatAmount, + "subtotal_vat_rate": subtotalVatRate, + "currency": currency, + "currencyn": currencyn, + "rental_start_date_utc": rentalStartDateUtc, + "rental_end_date_utc": rentalEndDateUtc, + "created_on_utc": createdOnUtc.toIso8601String(), + "updated_on_utc": updatedOnUtc.toIso8601String(), + "shopping_cart_type": shoppingCartType, + "product_id": productId, + "product": product.toJson(), + "customer_id": customerId, + "customer": customer.toJson(), + }; +} + +class Customer { + Customer({ + this.billingAddress, + this.shippingAddress, + this.addresses, + this.id, + this.username, + this.email, + this.firstName, + this.lastName, + this.languageId, + this.adminComment, + this.isTaxExempt, + this.hasShoppingCartItems, + this.active, + this.deleted, + this.isSystemAccount, + this.systemName, + this.lastIpAddress, + this.createdOnUtc, + this.lastLoginDateUtc, + this.lastActivityDateUtc, + this.registeredInStoreId, + this.roleIds, + }); + + Address billingAddress; + Address shippingAddress; + List
addresses; + String id; + String username; + String email; + dynamic firstName; + dynamic lastName; + dynamic languageId; + dynamic adminComment; + bool isTaxExempt; + bool hasShoppingCartItems; + bool active; + bool deleted; + bool isSystemAccount; + dynamic systemName; + String lastIpAddress; + DateTime createdOnUtc; + DateTime lastLoginDateUtc; + DateTime lastActivityDateUtc; + dynamic registeredInStoreId; + List roleIds; + + factory Customer.fromJson(Map json) => Customer( + billingAddress: Address.fromJson(json["billing_address"]), + shippingAddress: Address.fromJson(json["shipping_address"]), + addresses: List
.from(json["addresses"].map((x) => Address.fromJson(x))), + id: json["id"], + username: json["username"], + email: json["email"], + firstName: json["first_name"], + lastName: json["last_name"], + languageId: json["language_id"], + adminComment: json["admin_comment"], + isTaxExempt: json["is_tax_exempt"], + hasShoppingCartItems: json["has_shopping_cart_items"], + active: json["active"], + deleted: json["deleted"], + isSystemAccount: json["is_system_account"], + systemName: json["system_name"], + lastIpAddress: json["last_ip_address"], + createdOnUtc: DateTime.parse(json["created_on_utc"]), + lastLoginDateUtc: DateTime.parse(json["last_login_date_utc"]), + lastActivityDateUtc: DateTime.parse(json["last_activity_date_utc"]), + registeredInStoreId: json["registered_in_store_id"], + roleIds: List.from(json["role_ids"].map((x) => x)), + ); + + Map toJson() => { + "billing_address": billingAddress.toJson(), + "shipping_address": shippingAddress.toJson(), + "addresses": List.from(addresses.map((x) => x.toJson())), + "id": id, + "username": username, + "email": email, + "first_name": firstName, + "last_name": lastName, + "language_id": languageId, + "admin_comment": adminComment, + "is_tax_exempt": isTaxExempt, + "has_shopping_cart_items": hasShoppingCartItems, + "active": active, + "deleted": deleted, + "is_system_account": isSystemAccount, + "system_name": systemName, + "last_ip_address": lastIpAddress, + "created_on_utc": createdOnUtc.toIso8601String(), + "last_login_date_utc": lastLoginDateUtc.toIso8601String(), + "last_activity_date_utc": lastActivityDateUtc.toIso8601String(), + "registered_in_store_id": registeredInStoreId, + "role_ids": List.from(roleIds.map((x) => x)), + }; +} + +class Address { + Address({ + this.id, + this.firstName, + this.lastName, + this.email, + this.company, + this.countryId, + this.country, + this.stateProvinceId, + this.city, + this.address1, + this.address2, + this.zipPostalCode, + this.phoneNumber, + this.faxNumber, + this.customerAttributes, + this.createdOnUtc, + this.province, + this.latLong, + }); + + String id; + FirstName firstName; + LastName lastName; + Email email; + dynamic company; + dynamic countryId; + Country country; + dynamic stateProvinceId; + City city; + String address1; + String address2; + String zipPostalCode; + String phoneNumber; + dynamic faxNumber; + String customerAttributes; + DateTime createdOnUtc; + dynamic province; + String latLong; + + factory Address.fromJson(Map json) => Address( + id: json["id"], + firstName: firstNameValues.map[json["first_name"]], + lastName: lastNameValues.map[json["last_name"]], + email: emailValues.map[json["email"]], + company: json["company"], + countryId: json["country_id"], + country: countryValues.map[json["country"]], + stateProvinceId: json["state_province_id"], + city: cityValues.map[json["city"]], + address1: json["address1"], + address2: json["address2"], + zipPostalCode: json["zip_postal_code"], + phoneNumber: json["phone_number"], + faxNumber: json["fax_number"], + customerAttributes: json["customer_attributes"], + createdOnUtc: DateTime.parse(json["created_on_utc"]), + province: json["province"], + latLong: json["lat_long"], + ); + + Map toJson() => { + "id": id, + "first_name": firstNameValues.reverse[firstName], + "last_name": lastNameValues.reverse[lastName], + "email": emailValues.reverse[email], + "company": company, + "country_id": countryId, + "country": countryValues.reverse[country], + "state_province_id": stateProvinceId, + "city": cityValues.reverse[city], + "address1": address1, + "address2": address2, + "zip_postal_code": zipPostalCode, + "phone_number": phoneNumber, + "fax_number": faxNumber, + "customer_attributes": customerAttributes, + "created_on_utc": createdOnUtc.toIso8601String(), + "province": province, + "lat_long": latLong, + }; +} + +enum City { RIYADH, AL_OYUN } + +final cityValues = EnumValues({ + "Al Oyun": City.AL_OYUN, + "Riyadh": City.RIYADH +}); + +enum Country { SAUDI_ARABIA } + +final countryValues = EnumValues({ + "Saudi Arabia": Country.SAUDI_ARABIA +}); + +enum Email { TAMER_FANASHEH_GMAIL_COM, TAMER_DASDASDAS_GMAIL_COM } + +final emailValues = EnumValues({ + "Tamer.dasdasdas@gmail.com": Email.TAMER_DASDASDAS_GMAIL_COM, + "Tamer.fanasheh@gmail.com": Email.TAMER_FANASHEH_GMAIL_COM +}); + +enum FirstName { TAMER, TAMER_FANASHEH } + +final firstNameValues = EnumValues({ + "TAMER": FirstName.TAMER, + "TAMER FANASHEH": FirstName.TAMER_FANASHEH +}); + +enum LastName { FANASHEH, MUSA } + +final lastNameValues = EnumValues({ + "FANASHEH": LastName.FANASHEH, + "MUSA": LastName.MUSA +}); + +class Product { + Product({ + this.id, + this.visibleIndividually, + this.name, + this.namen, + this.localizedNames, + this.shortDescription, + this.shortDescriptionn, + this.fullDescription, + this.fullDescriptionn, + this.markasNew, + this.showOnHomePage, + this.metaKeywords, + this.metaDescription, + this.metaTitle, + this.allowCustomerReviews, + this.approvedRatingSum, + this.notApprovedRatingSum, + this.approvedTotalReviews, + this.notApprovedTotalReviews, + this.sku, + this.isRx, + this.prescriptionRequired, + this.rxMessage, + this.rxMessagen, + this.manufacturerPartNumber, + this.gtin, + this.isGiftCard, + this.requireOtherProducts, + this.automaticallyAddRequiredProducts, + this.isDownload, + this.unlimitedDownloads, + this.maxNumberOfDownloads, + this.downloadExpirationDays, + this.hasSampleDownload, + this.hasUserAgreement, + this.isRecurring, + this.recurringCycleLength, + this.recurringTotalCycles, + this.isRental, + this.rentalPriceLength, + this.isShipEnabled, + this.isFreeShipping, + this.shipSeparately, + this.additionalShippingCharge, + this.isTaxExempt, + this.isTelecommunicationsOrBroadcastingOrElectronicServices, + this.useMultipleWarehouses, + this.manageInventoryMethodId, + this.stockQuantity, + this.stockAvailability, + this.stockAvailabilityn, + this.displayStockAvailability, + this.displayStockQuantity, + this.minStockQuantity, + this.notifyAdminForQuantityBelow, + this.allowBackInStockSubscriptions, + this.orderMinimumQuantity, + this.orderMaximumQuantity, + this.allowedQuantities, + this.allowAddingOnlyExistingAttributeCombinations, + this.disableBuyButton, + this.disableWishlistButton, + this.availableForPreOrder, + this.preOrderAvailabilityStartDateTimeUtc, + this.callForPrice, + this.price, + this.oldPrice, + this.productCost, + this.specialPrice, + this.specialPriceStartDateTimeUtc, + this.specialPriceEndDateTimeUtc, + this.customerEntersPrice, + this.minimumCustomerEnteredPrice, + this.maximumCustomerEnteredPrice, + this.basepriceEnabled, + this.basepriceAmount, + this.basepriceBaseAmount, + this.hasTierPrices, + this.hasDiscountsApplied, + this.discountName, + this.discountNamen, + this.discountDescription, + this.discountDescriptionn, + this.discountPercentage, + this.currency, + this.currencyn, + this.weight, + this.length, + this.width, + this.height, + this.availableStartDateTimeUtc, + this.availableEndDateTimeUtc, + this.displayOrder, + this.published, + this.deleted, + this.createdOnUtc, + this.updatedOnUtc, + this.productType, + this.parentGroupedProductId, + this.roleIds, + this.discountIds, + this.storeIds, + this.manufacturerIds, + this.reviews, + this.images, + this.attributes, + this.specifications, + this.associatedProductIds, + this.tags, + this.vendorId, + this.seName, + }); + + String id; + bool visibleIndividually; + String name; + String namen; + List localizedNames; + String shortDescription; + String shortDescriptionn; + String fullDescription; + String fullDescriptionn; + bool markasNew; + bool showOnHomePage; + dynamic metaKeywords; + dynamic metaDescription; + dynamic metaTitle; + bool allowCustomerReviews; + dynamic approvedRatingSum; + dynamic notApprovedRatingSum; + dynamic approvedTotalReviews; + dynamic notApprovedTotalReviews; + String sku; + bool isRx; + bool prescriptionRequired; + dynamic rxMessage; + dynamic rxMessagen; + dynamic manufacturerPartNumber; + dynamic gtin; + bool isGiftCard; + bool requireOtherProducts; + bool automaticallyAddRequiredProducts; + bool isDownload; + bool unlimitedDownloads; + dynamic maxNumberOfDownloads; + dynamic downloadExpirationDays; + bool hasSampleDownload; + bool hasUserAgreement; + bool isRecurring; + dynamic recurringCycleLength; + dynamic recurringTotalCycles; + bool isRental; + dynamic rentalPriceLength; + bool isShipEnabled; + bool isFreeShipping; + bool shipSeparately; + dynamic additionalShippingCharge; + bool isTaxExempt; + bool isTelecommunicationsOrBroadcastingOrElectronicServices; + bool useMultipleWarehouses; + dynamic manageInventoryMethodId; + dynamic stockQuantity; + String stockAvailability; + String stockAvailabilityn; + bool displayStockAvailability; + bool displayStockQuantity; + dynamic minStockQuantity; + dynamic notifyAdminForQuantityBelow; + bool allowBackInStockSubscriptions; + dynamic orderMinimumQuantity; + dynamic orderMaximumQuantity; + dynamic allowedQuantities; + bool allowAddingOnlyExistingAttributeCombinations; + bool disableBuyButton; + bool disableWishlistButton; + bool availableForPreOrder; + dynamic preOrderAvailabilityStartDateTimeUtc; + bool callForPrice; + double price; + dynamic oldPrice; + double productCost; + dynamic specialPrice; + dynamic specialPriceStartDateTimeUtc; + dynamic specialPriceEndDateTimeUtc; + bool customerEntersPrice; + dynamic minimumCustomerEnteredPrice; + dynamic maximumCustomerEnteredPrice; + bool basepriceEnabled; + dynamic basepriceAmount; + dynamic basepriceBaseAmount; + bool hasTierPrices; + bool hasDiscountsApplied; + dynamic discountName; + dynamic discountNamen; + dynamic discountDescription; + dynamic discountDescriptionn; + dynamic discountPercentage; + String currency; + String currencyn; + double weight; + dynamic length; + dynamic width; + dynamic height; + dynamic availableStartDateTimeUtc; + dynamic availableEndDateTimeUtc; + dynamic displayOrder; + bool published; + bool deleted; + DateTime createdOnUtc; + DateTime updatedOnUtc; + String productType; + dynamic parentGroupedProductId; + List roleIds; + List discountIds; + List storeIds; + List manufacturerIds; + List reviews; + List images; + List attributes; + List specifications; + List associatedProductIds; + List tags; + dynamic vendorId; + String seName; + + factory Product.fromJson(Map json) => Product( + id: json["id"], + visibleIndividually: json["visible_individually"], + name: json["name"], + namen: json["namen"], + localizedNames: List.from(json["localized_names"].map((x) => LocalizedName.fromJson(x))), + shortDescription: json["short_description"], + shortDescriptionn: json["short_descriptionn"], + fullDescription: json["full_description"], + fullDescriptionn: json["full_descriptionn"], + markasNew: json["markas_new"], + showOnHomePage: json["show_on_home_page"], + metaKeywords: json["meta_keywords"], + metaDescription: json["meta_description"], + metaTitle: json["meta_title"], + allowCustomerReviews: json["allow_customer_reviews"], + approvedRatingSum: json["approved_rating_sum"], + notApprovedRatingSum: json["not_approved_rating_sum"], + approvedTotalReviews: json["approved_total_reviews"], + notApprovedTotalReviews: json["not_approved_total_reviews"], + sku: json["sku"], + isRx: json["is_rx"], + prescriptionRequired: json["prescription_required"], + rxMessage: json["rx_message"], + rxMessagen: json["rx_messagen"], + manufacturerPartNumber: json["manufacturer_part_number"], + gtin: json["gtin"], + isGiftCard: json["is_gift_card"], + requireOtherProducts: json["require_other_products"], + automaticallyAddRequiredProducts: json["automatically_add_required_products"], + isDownload: json["is_download"], + unlimitedDownloads: json["unlimited_downloads"], + maxNumberOfDownloads: json["max_number_of_downloads"], + downloadExpirationDays: json["download_expiration_days"], + hasSampleDownload: json["has_sample_download"], + hasUserAgreement: json["has_user_agreement"], + isRecurring: json["is_recurring"], + recurringCycleLength: json["recurring_cycle_length"], + recurringTotalCycles: json["recurring_total_cycles"], + isRental: json["is_rental"], + rentalPriceLength: json["rental_price_length"], + isShipEnabled: json["is_ship_enabled"], + isFreeShipping: json["is_free_shipping"], + shipSeparately: json["ship_separately"], + additionalShippingCharge: json["additional_shipping_charge"], + isTaxExempt: json["is_tax_exempt"], + isTelecommunicationsOrBroadcastingOrElectronicServices: json["is_telecommunications_or_broadcasting_or_electronic_services"], + useMultipleWarehouses: json["use_multiple_warehouses"], + manageInventoryMethodId: json["manage_inventory_method_id"], + stockQuantity: json["stock_quantity"], + stockAvailability: json["stock_availability"], + stockAvailabilityn: json["stock_availabilityn"], + displayStockAvailability: json["display_stock_availability"], + displayStockQuantity: json["display_stock_quantity"], + minStockQuantity: json["min_stock_quantity"], + notifyAdminForQuantityBelow: json["notify_admin_for_quantity_below"], + allowBackInStockSubscriptions: json["allow_back_in_stock_subscriptions"], + orderMinimumQuantity: json["order_minimum_quantity"], + orderMaximumQuantity: json["order_maximum_quantity"], + allowedQuantities: json["allowed_quantities"], + allowAddingOnlyExistingAttributeCombinations: json["allow_adding_only_existing_attribute_combinations"], + disableBuyButton: json["disable_buy_button"], + disableWishlistButton: json["disable_wishlist_button"], + availableForPreOrder: json["available_for_pre_order"], + preOrderAvailabilityStartDateTimeUtc: json["pre_order_availability_start_date_time_utc"], + callForPrice: json["call_for_price"], + price: json["price"].toDouble(), + oldPrice: json["old_price"], + productCost: json["product_cost"].toDouble(), + specialPrice: json["special_price"], + specialPriceStartDateTimeUtc: json["special_price_start_date_time_utc"], + specialPriceEndDateTimeUtc: json["special_price_end_date_time_utc"], + customerEntersPrice: json["customer_enters_price"], + minimumCustomerEnteredPrice: json["minimum_customer_entered_price"], + maximumCustomerEnteredPrice: json["maximum_customer_entered_price"], + basepriceEnabled: json["baseprice_enabled"], + basepriceAmount: json["baseprice_amount"], + basepriceBaseAmount: json["baseprice_base_amount"], + hasTierPrices: json["has_tier_prices"], + hasDiscountsApplied: json["has_discounts_applied"], + discountName: json["discount_name"], + discountNamen: json["discount_namen"], + discountDescription: json["discount_description"], + discountDescriptionn: json["discount_Descriptionn"], + discountPercentage: json["discount_percentage"], + currency: json["currency"], + currencyn: json["currencyn"], + weight: json["weight"].toDouble(), + length: json["length"], + width: json["width"], + height: json["height"], + availableStartDateTimeUtc: json["available_start_date_time_utc"], + availableEndDateTimeUtc: json["available_end_date_time_utc"], + displayOrder: json["display_order"], + published: json["published"], + deleted: json["deleted"], + createdOnUtc: DateTime.parse(json["created_on_utc"]), + updatedOnUtc: DateTime.parse(json["updated_on_utc"]), + productType: json["product_type"], + parentGroupedProductId: json["parent_grouped_product_id"], + roleIds: List.from(json["role_ids"].map((x) => x)), + discountIds: List.from(json["discount_ids"].map((x) => x)), + storeIds: List.from(json["store_ids"].map((x) => x)), + manufacturerIds: List.from(json["manufacturer_ids"].map((x) => x)), + reviews: List.from(json["reviews"].map((x) => x)), + images: List.from(json["images"].map((x) => Image.fromJson(x))), + attributes: List.from(json["attributes"].map((x) => x)), + specifications: List.from(json["specifications"].map((x) => Specification.fromJson(x))), + associatedProductIds: List.from(json["associated_product_ids"].map((x) => x)), + tags: List.from(json["tags"].map((x) => x)), + vendorId: json["vendor_id"], + seName: json["se_name"], + ); + + Map toJson() => { + "id": id, + "visible_individually": visibleIndividually, + "name": name, + "namen": namen, + "localized_names": List.from(localizedNames.map((x) => x.toJson())), + "short_description": shortDescription, + "short_descriptionn": shortDescriptionn, + "full_description": fullDescription, + "full_descriptionn": fullDescriptionn, + "markas_new": markasNew, + "show_on_home_page": showOnHomePage, + "meta_keywords": metaKeywords, + "meta_description": metaDescription, + "meta_title": metaTitle, + "allow_customer_reviews": allowCustomerReviews, + "approved_rating_sum": approvedRatingSum, + "not_approved_rating_sum": notApprovedRatingSum, + "approved_total_reviews": approvedTotalReviews, + "not_approved_total_reviews": notApprovedTotalReviews, + "sku": sku, + "is_rx": isRx, + "prescription_required": prescriptionRequired, + "rx_message": rxMessage, + "rx_messagen": rxMessagen, + "manufacturer_part_number": manufacturerPartNumber, + "gtin": gtin, + "is_gift_card": isGiftCard, + "require_other_products": requireOtherProducts, + "automatically_add_required_products": automaticallyAddRequiredProducts, + "is_download": isDownload, + "unlimited_downloads": unlimitedDownloads, + "max_number_of_downloads": maxNumberOfDownloads, + "download_expiration_days": downloadExpirationDays, + "has_sample_download": hasSampleDownload, + "has_user_agreement": hasUserAgreement, + "is_recurring": isRecurring, + "recurring_cycle_length": recurringCycleLength, + "recurring_total_cycles": recurringTotalCycles, + "is_rental": isRental, + "rental_price_length": rentalPriceLength, + "is_ship_enabled": isShipEnabled, + "is_free_shipping": isFreeShipping, + "ship_separately": shipSeparately, + "additional_shipping_charge": additionalShippingCharge, + "is_tax_exempt": isTaxExempt, + "is_telecommunications_or_broadcasting_or_electronic_services": isTelecommunicationsOrBroadcastingOrElectronicServices, + "use_multiple_warehouses": useMultipleWarehouses, + "manage_inventory_method_id": manageInventoryMethodId, + "stock_quantity": stockQuantity, + "stock_availability": stockAvailability, + "stock_availabilityn": stockAvailabilityn, + "display_stock_availability": displayStockAvailability, + "display_stock_quantity": displayStockQuantity, + "min_stock_quantity": minStockQuantity, + "notify_admin_for_quantity_below": notifyAdminForQuantityBelow, + "allow_back_in_stock_subscriptions": allowBackInStockSubscriptions, + "order_minimum_quantity": orderMinimumQuantity, + "order_maximum_quantity": orderMaximumQuantity, + "allowed_quantities": allowedQuantities, + "allow_adding_only_existing_attribute_combinations": allowAddingOnlyExistingAttributeCombinations, + "disable_buy_button": disableBuyButton, + "disable_wishlist_button": disableWishlistButton, + "available_for_pre_order": availableForPreOrder, + "pre_order_availability_start_date_time_utc": preOrderAvailabilityStartDateTimeUtc, + "call_for_price": callForPrice, + "price": price, + "old_price": oldPrice, + "product_cost": productCost, + "special_price": specialPrice, + "special_price_start_date_time_utc": specialPriceStartDateTimeUtc, + "special_price_end_date_time_utc": specialPriceEndDateTimeUtc, + "customer_enters_price": customerEntersPrice, + "minimum_customer_entered_price": minimumCustomerEnteredPrice, + "maximum_customer_entered_price": maximumCustomerEnteredPrice, + "baseprice_enabled": basepriceEnabled, + "baseprice_amount": basepriceAmount, + "baseprice_base_amount": basepriceBaseAmount, + "has_tier_prices": hasTierPrices, + "has_discounts_applied": hasDiscountsApplied, + "discount_name": discountName, + "discount_namen": discountNamen, + "discount_description": discountDescription, + "discount_Descriptionn": discountDescriptionn, + "discount_percentage": discountPercentage, + "currency": currency, + "currencyn": currencyn, + "weight": weight, + "length": length, + "width": width, + "height": height, + "available_start_date_time_utc": availableStartDateTimeUtc, + "available_end_date_time_utc": availableEndDateTimeUtc, + "display_order": displayOrder, + "published": published, + "deleted": deleted, + "created_on_utc": createdOnUtc.toIso8601String(), + "updated_on_utc": updatedOnUtc.toIso8601String(), + "product_type": productType, + "parent_grouped_product_id": parentGroupedProductId, + "role_ids": List.from(roleIds.map((x) => x)), + "discount_ids": List.from(discountIds.map((x) => x)), + "store_ids": List.from(storeIds.map((x) => x)), + "manufacturer_ids": List.from(manufacturerIds.map((x) => x)), + "reviews": List.from(reviews.map((x) => x)), + "images": List.from(images.map((x) => x.toJson())), + "attributes": List.from(attributes.map((x) => x)), + "specifications": List.from(specifications.map((x) => x.toJson())), + "associated_product_ids": List.from(associatedProductIds.map((x) => x)), + "tags": List.from(tags.map((x) => x)), + "vendor_id": vendorId, + "se_name": seName, + }; +} + +class Image { + Image({ + this.id, + this.position, + this.src, + this.thumb, + this.attachment, + }); + + dynamic id; + dynamic position; + String src; + String thumb; + String attachment; + + factory Image.fromJson(Map json) => Image( + id: json["id"], + position: json["position"], + src: json["src"], + thumb: json["thumb"], + attachment: json["attachment"], + ); + + Map toJson() => { + "id": id, + "position": position, + "src": src, + "thumb": thumb, + "attachment": attachment, + }; +} + +class LocalizedName { + LocalizedName({ + this.languageId, + this.localizedName, + }); + + dynamic languageId; + String localizedName; + + factory LocalizedName.fromJson(Map json) => LocalizedName( + languageId: json["language_id"], + localizedName: json["localized_name"], + ); + + Map toJson() => { + "language_id": languageId, + "localized_name": localizedName, + }; +} + +class Specification { + Specification({ + this.id, + this.displayOrder, + this.defaultValue, + this.defaultValuen, + this.name, + this.nameN, + }); + + dynamic id; + dynamic displayOrder; + String defaultValue; + String defaultValuen; + String name; + String nameN; + + factory Specification.fromJson(Map json) => Specification( + id: json["id"], + displayOrder: json["display_order"], + defaultValue: json["default_value"], + defaultValuen: json["default_valuen"], + name: json["name"], + nameN: json["nameN"], + ); + + Map toJson() => { + "id": id, + "display_order": displayOrder, + "default_value": defaultValue, + "default_valuen": defaultValuen, + "name": name, + "nameN": nameN, + }; +} + +class EnumValues { + Map map; + Map reverseMap; + + EnumValues(this.map); + + Map get reverse { + if (reverseMap == null) { + reverseMap = map.map((k, v) => new MapEntry(v, k)); + } + return reverseMap; + } +} diff --git a/lib/models/pharmacy/addToCartModel.dart b/lib/models/pharmacy/addToCartModel.dart new file mode 100644 index 00000000..3253e6f7 --- /dev/null +++ b/lib/models/pharmacy/addToCartModel.dart @@ -0,0 +1,924 @@ +// To parse this JSON data, do +// +// final shoppingCart = shoppingCartFromJson(jsonString); + +import 'dart:convert'; + +ShoppingCart shoppingCartFromJson(String str) => ShoppingCart.fromJson(json.decode(str)); + +String shoppingCartToJson(ShoppingCart data) => json.encode(data.toJson()); + +class ShoppingCart { + ShoppingCart({ + this.itemCount, + this.quantityCount, + this.subtotal, + this.subtotalWithVat, + this.subtotalVatAmount, + this.subtotalVatRate, + this.shoppingCarts, + }); + + int itemCount; + int quantityCount; + double subtotal; + double subtotalWithVat; + double subtotalVatAmount; + int subtotalVatRate; + List shoppingCarts; + + factory ShoppingCart.fromJson(Map json) => ShoppingCart( + itemCount: json["item_count"], + quantityCount: json["quantity_count"], + subtotal: json["subtotal"].toDouble(), + subtotalWithVat: json["subtotal_with_vat"].toDouble(), + subtotalVatAmount: json["subtotal_vat_amount"].toDouble(), + subtotalVatRate: json["subtotal_vat_rate"], + shoppingCarts: List.from(json["shopping_carts"].map((x) => ShoppingCartElement.fromJson(x))), + ); + + Map toJson() => { + "item_count": itemCount, + "quantity_count": quantityCount, + "subtotal": subtotal, + "subtotal_with_vat": subtotalWithVat, + "subtotal_vat_amount": subtotalVatAmount, + "subtotal_vat_rate": subtotalVatRate, + "shopping_carts": List.from(shoppingCarts.map((x) => x.toJson())), + }; +} + +class ShoppingCartElement { + ShoppingCartElement({ + this.languageId, + this.id, + this.productAttributes, + this.customerEnteredPrice, + this.quantity, + this.discountAmountInclTax, + this.subtotal, + this.subtotalWithVat, + this.subtotalVatAmount, + this.subtotalVatRate, + this.currency, + this.currencyn, + this.rentalStartDateUtc, + this.rentalEndDateUtc, + this.createdOnUtc, + this.updatedOnUtc, + this.shoppingCartType, + this.productId, + this.product, + this.customerId, + this.customer, + }); + + int languageId; + String id; + List productAttributes; + int customerEnteredPrice; + int quantity; + dynamic discountAmountInclTax; + String subtotal; + String subtotalWithVat; + String subtotalVatAmount; + String subtotalVatRate; + String currency; + String currencyn; + dynamic rentalStartDateUtc; + dynamic rentalEndDateUtc; + DateTime createdOnUtc; + DateTime updatedOnUtc; + String shoppingCartType; + int productId; + Product product; + int customerId; + Customer customer; + + factory ShoppingCartElement.fromJson(Map json) => ShoppingCartElement( + languageId: json["language_id"], + id: json["id"], + productAttributes: List.from(json["product_attributes"].map((x) => x)), + customerEnteredPrice: json["customer_entered_price"], + quantity: json["quantity"], + discountAmountInclTax: json["discount_amount_incl_tax"], + subtotal: json["subtotal"], + subtotalWithVat: json["subtotal_with_vat"], + subtotalVatAmount: json["subtotal_vat_amount"], + subtotalVatRate: json["subtotal_vat_rate"], + currency: json["currency"], + currencyn: json["currencyn"], + rentalStartDateUtc: json["rental_start_date_utc"], + rentalEndDateUtc: json["rental_end_date_utc"], + createdOnUtc: DateTime.parse(json["created_on_utc"]), + updatedOnUtc: DateTime.parse(json["updated_on_utc"]), + shoppingCartType: json["shopping_cart_type"], + productId: json["product_id"], + product: Product.fromJson(json["product"]), + customerId: json["customer_id"], + customer: Customer.fromJson(json["customer"]), + ); + + Map toJson() => { + "language_id": languageId, + "id": id, + "product_attributes": List.from(productAttributes.map((x) => x)), + "customer_entered_price": customerEnteredPrice, + "quantity": quantity, + "discount_amount_incl_tax": discountAmountInclTax, + "subtotal": subtotal, + "subtotal_with_vat": subtotalWithVat, + "subtotal_vat_amount": subtotalVatAmount, + "subtotal_vat_rate": subtotalVatRate, + "currency": currency, + "currencyn": currencyn, + "rental_start_date_utc": rentalStartDateUtc, + "rental_end_date_utc": rentalEndDateUtc, + "created_on_utc": createdOnUtc.toIso8601String(), + "updated_on_utc": updatedOnUtc.toIso8601String(), + "shopping_cart_type": shoppingCartType, + "product_id": productId, + "product": product.toJson(), + "customer_id": customerId, + "customer": customer.toJson(), + }; +} + +class Customer { + Customer({ + this.billingAddress, + this.shippingAddress, + this.addresses, + this.id, + this.username, + this.email, + this.firstName, + this.lastName, + this.languageId, + this.adminComment, + this.isTaxExempt, + this.hasShoppingCartItems, + this.active, + this.deleted, + this.isSystemAccount, + this.systemName, + this.lastIpAddress, + this.createdOnUtc, + this.lastLoginDateUtc, + this.lastActivityDateUtc, + this.registeredInStoreId, + this.roleIds, + }); + + Address billingAddress; + Address shippingAddress; + List
addresses; + String id; + String username; + String email; + dynamic firstName; + dynamic lastName; + dynamic languageId; + dynamic adminComment; + bool isTaxExempt; + bool hasShoppingCartItems; + bool active; + bool deleted; + bool isSystemAccount; + dynamic systemName; + String lastIpAddress; + DateTime createdOnUtc; + DateTime lastLoginDateUtc; + DateTime lastActivityDateUtc; + int registeredInStoreId; + List roleIds; + + factory Customer.fromJson(Map json) => Customer( + billingAddress: Address.fromJson(json["billing_address"]), + shippingAddress: Address.fromJson(json["shipping_address"]), + addresses: List
.from(json["addresses"].map((x) => Address.fromJson(x))), + id: json["id"], + username: json["username"], + email: json["email"], + firstName: json["first_name"], + lastName: json["last_name"], + languageId: json["language_id"], + adminComment: json["admin_comment"], + isTaxExempt: json["is_tax_exempt"], + hasShoppingCartItems: json["has_shopping_cart_items"], + active: json["active"], + deleted: json["deleted"], + isSystemAccount: json["is_system_account"], + systemName: json["system_name"], + lastIpAddress: json["last_ip_address"], + createdOnUtc: DateTime.parse(json["created_on_utc"]), + lastLoginDateUtc: DateTime.parse(json["last_login_date_utc"]), + lastActivityDateUtc: DateTime.parse(json["last_activity_date_utc"]), + registeredInStoreId: json["registered_in_store_id"], + roleIds: List.from(json["role_ids"].map((x) => x)), + ); + + Map toJson() => { + "billing_address": billingAddress.toJson(), + "shipping_address": shippingAddress.toJson(), + "addresses": List.from(addresses.map((x) => x.toJson())), + "id": id, + "username": username, + "email": email, + "first_name": firstName, + "last_name": lastName, + "language_id": languageId, + "admin_comment": adminComment, + "is_tax_exempt": isTaxExempt, + "has_shopping_cart_items": hasShoppingCartItems, + "active": active, + "deleted": deleted, + "is_system_account": isSystemAccount, + "system_name": systemName, + "last_ip_address": lastIpAddress, + "created_on_utc": createdOnUtc.toIso8601String(), + "last_login_date_utc": lastLoginDateUtc.toIso8601String(), + "last_activity_date_utc": lastActivityDateUtc.toIso8601String(), + "registered_in_store_id": registeredInStoreId, + "role_ids": List.from(roleIds.map((x) => x)), + }; +} + +class Address { + Address({ + this.id, + this.firstName, + this.lastName, + this.email, + this.company, + this.countryId, + this.country, + this.stateProvinceId, + this.city, + this.address1, + this.address2, + this.zipPostalCode, + this.phoneNumber, + this.faxNumber, + this.customerAttributes, + this.createdOnUtc, + this.province, + this.latLong, + }); + + String id; + FirstName firstName; + LastName lastName; + Email email; + dynamic company; + int countryId; + Country country; + dynamic stateProvinceId; + City city; + String address1; + String address2; + String zipPostalCode; + String phoneNumber; + dynamic faxNumber; + String customerAttributes; + DateTime createdOnUtc; + dynamic province; + String latLong; + + factory Address.fromJson(Map json) => Address( + id: json["id"], + firstName: firstNameValues.map[json["first_name"]], + lastName: lastNameValues.map[json["last_name"]], + email: emailValues.map[json["email"]], + company: json["company"], + countryId: json["country_id"], + country: countryValues.map[json["country"]], + stateProvinceId: json["state_province_id"], + city: cityValues.map[json["city"]], + address1: json["address1"], + address2: json["address2"], + zipPostalCode: json["zip_postal_code"], + phoneNumber: json["phone_number"], + faxNumber: json["fax_number"], + customerAttributes: json["customer_attributes"], + createdOnUtc: DateTime.parse(json["created_on_utc"]), + province: json["province"], + latLong: json["lat_long"], + ); + + Map toJson() => { + "id": id, + "first_name": firstNameValues.reverse[firstName], + "last_name": lastNameValues.reverse[lastName], + "email": emailValues.reverse[email], + "company": company, + "country_id": countryId, + "country": countryValues.reverse[country], + "state_province_id": stateProvinceId, + "city": cityValues.reverse[city], + "address1": address1, + "address2": address2, + "zip_postal_code": zipPostalCode, + "phone_number": phoneNumber, + "fax_number": faxNumber, + "customer_attributes": customerAttributes, + "created_on_utc": createdOnUtc.toIso8601String(), + "province": province, + "lat_long": latLong, + }; +} + +enum City { CALIFORNIA, RIYADH, AL_OYUN } + +final cityValues = EnumValues({ + "Al Oyun": City.AL_OYUN, + "California": City.CALIFORNIA, + "Riyadh": City.RIYADH +}); + +enum Country { UNITED_STATES, SAUDI_ARABIA } + +final countryValues = EnumValues({ + "Saudi Arabia": Country.SAUDI_ARABIA, + "United States": Country.UNITED_STATES +}); + +enum Email { TAMER_FANASHEH_GMAIL_COM, TAMER_DASDASDAS_GMAIL_COM, TAMER_F_CLOUDSOLUTION_SA_COM } + +final emailValues = EnumValues({ + "Tamer.dasdasdas@gmail.com": Email.TAMER_DASDASDAS_GMAIL_COM, + "Tamer.fanasheh@gmail.com": Email.TAMER_FANASHEH_GMAIL_COM, + "Tamer.F@cloudsolution-sa.com": Email.TAMER_F_CLOUDSOLUTION_SA_COM +}); + +enum FirstName { TAMER, TAMER_FANASHEH } + +final firstNameValues = EnumValues({ + "TAMER": FirstName.TAMER, + "TAMER FANASHEH": FirstName.TAMER_FANASHEH +}); + +enum LastName { FANASHEH, MUSA } + +final lastNameValues = EnumValues({ + "FANASHEH": LastName.FANASHEH, + "MUSA": LastName.MUSA +}); + +class Product { + Product({ + this.id, + this.visibleIndividually, + this.name, + this.namen, + this.localizedNames, + this.shortDescription, + this.shortDescriptionn, + this.fullDescription, + this.fullDescriptionn, + this.markasNew, + this.showOnHomePage, + this.metaKeywords, + this.metaDescription, + this.metaTitle, + this.allowCustomerReviews, + this.approvedRatingSum, + this.notApprovedRatingSum, + this.approvedTotalReviews, + this.notApprovedTotalReviews, + this.sku, + this.isRx, + this.prescriptionRequired, + this.rxMessage, + this.rxMessagen, + this.manufacturerPartNumber, + this.gtin, + this.isGiftCard, + this.requireOtherProducts, + this.automaticallyAddRequiredProducts, + this.isDownload, + this.unlimitedDownloads, + this.maxNumberOfDownloads, + this.downloadExpirationDays, + this.hasSampleDownload, + this.hasUserAgreement, + this.isRecurring, + this.recurringCycleLength, + this.recurringTotalCycles, + this.isRental, + this.rentalPriceLength, + this.isShipEnabled, + this.isFreeShipping, + this.shipSeparately, + this.additionalShippingCharge, + this.isTaxExempt, + this.isTelecommunicationsOrBroadcastingOrElectronicServices, + this.useMultipleWarehouses, + this.manageInventoryMethodId, + this.stockQuantity, + this.stockAvailability, + this.stockAvailabilityn, + this.displayStockAvailability, + this.displayStockQuantity, + this.minStockQuantity, + this.notifyAdminForQuantityBelow, + this.allowBackInStockSubscriptions, + this.orderMinimumQuantity, + this.orderMaximumQuantity, + this.allowedQuantities, + this.allowAddingOnlyExistingAttributeCombinations, + this.disableBuyButton, + this.disableWishlistButton, + this.availableForPreOrder, + this.preOrderAvailabilityStartDateTimeUtc, + this.callForPrice, + this.price, + this.oldPrice, + this.productCost, + this.specialPrice, + this.specialPriceStartDateTimeUtc, + this.specialPriceEndDateTimeUtc, + this.customerEntersPrice, + this.minimumCustomerEnteredPrice, + this.maximumCustomerEnteredPrice, + this.basepriceEnabled, + this.basepriceAmount, + this.basepriceBaseAmount, + this.hasTierPrices, + this.hasDiscountsApplied, + this.discountName, + this.discountNamen, + this.discountDescription, + this.discountDescriptionn, + this.discountPercentage, + this.currency, + this.currencyn, + this.weight, + this.length, + this.width, + this.height, + this.availableStartDateTimeUtc, + this.availableEndDateTimeUtc, + this.displayOrder, + this.published, + this.deleted, + this.createdOnUtc, + this.updatedOnUtc, + this.productType, + this.parentGroupedProductId, + this.roleIds, + this.discountIds, + this.storeIds, + this.manufacturerIds, + this.reviews, + this.images, + this.attributes, + this.specifications, + this.associatedProductIds, + this.tags, + this.vendorId, + this.seName, + }); + + String id; + bool visibleIndividually; + String name; + String namen; + List localizedNames; + String shortDescription; + String shortDescriptionn; + String fullDescription; + String fullDescriptionn; + bool markasNew; + bool showOnHomePage; + String metaKeywords; + String metaDescription; + String metaTitle; + bool allowCustomerReviews; + int approvedRatingSum; + int notApprovedRatingSum; + int approvedTotalReviews; + int notApprovedTotalReviews; + String sku; + bool isRx; + bool prescriptionRequired; + dynamic rxMessage; + dynamic rxMessagen; + dynamic manufacturerPartNumber; + dynamic gtin; + bool isGiftCard; + bool requireOtherProducts; + bool automaticallyAddRequiredProducts; + bool isDownload; + bool unlimitedDownloads; + int maxNumberOfDownloads; + dynamic downloadExpirationDays; + bool hasSampleDownload; + bool hasUserAgreement; + bool isRecurring; + int recurringCycleLength; + int recurringTotalCycles; + bool isRental; + int rentalPriceLength; + bool isShipEnabled; + bool isFreeShipping; + bool shipSeparately; + int additionalShippingCharge; + bool isTaxExempt; + bool isTelecommunicationsOrBroadcastingOrElectronicServices; + bool useMultipleWarehouses; + int manageInventoryMethodId; + int stockQuantity; + String stockAvailability; + String stockAvailabilityn; + bool displayStockAvailability; + bool displayStockQuantity; + int minStockQuantity; + int notifyAdminForQuantityBelow; + bool allowBackInStockSubscriptions; + int orderMinimumQuantity; + int orderMaximumQuantity; + dynamic allowedQuantities; + bool allowAddingOnlyExistingAttributeCombinations; + bool disableBuyButton; + bool disableWishlistButton; + bool availableForPreOrder; + dynamic preOrderAvailabilityStartDateTimeUtc; + bool callForPrice; + double price; + int oldPrice; + double productCost; + dynamic specialPrice; + dynamic specialPriceStartDateTimeUtc; + dynamic specialPriceEndDateTimeUtc; + bool customerEntersPrice; + int minimumCustomerEnteredPrice; + int maximumCustomerEnteredPrice; + bool basepriceEnabled; + int basepriceAmount; + int basepriceBaseAmount; + bool hasTierPrices; + bool hasDiscountsApplied; + dynamic discountName; + dynamic discountNamen; + dynamic discountDescription; + dynamic discountDescriptionn; + dynamic discountPercentage; + String currency; + String currencyn; + double weight; + int length; + int width; + int height; + dynamic availableStartDateTimeUtc; + dynamic availableEndDateTimeUtc; + int displayOrder; + bool published; + bool deleted; + DateTime createdOnUtc; + DateTime updatedOnUtc; + String productType; + int parentGroupedProductId; + List roleIds; + List discountIds; + List storeIds; + List manufacturerIds; + List reviews; + List images; + List attributes; + List specifications; + List associatedProductIds; + List tags; + int vendorId; + String seName; + + factory Product.fromJson(Map json) => Product( + id: json["id"], + visibleIndividually: json["visible_individually"], + name: json["name"], + namen: json["namen"], + localizedNames: List.from(json["localized_names"].map((x) => LocalizedName.fromJson(x))), + shortDescription: json["short_description"], + shortDescriptionn: json["short_descriptionn"], + fullDescription: json["full_description"], + fullDescriptionn: json["full_descriptionn"], + markasNew: json["markas_new"], + showOnHomePage: json["show_on_home_page"], + metaKeywords: json["meta_keywords"] == null ? null : json["meta_keywords"], + metaDescription: json["meta_description"] == null ? null : json["meta_description"], + metaTitle: json["meta_title"] == null ? null : json["meta_title"], + allowCustomerReviews: json["allow_customer_reviews"], + approvedRatingSum: json["approved_rating_sum"], + notApprovedRatingSum: json["not_approved_rating_sum"], + approvedTotalReviews: json["approved_total_reviews"], + notApprovedTotalReviews: json["not_approved_total_reviews"], + sku: json["sku"], + isRx: json["is_rx"], + prescriptionRequired: json["prescription_required"], + rxMessage: json["rx_message"], + rxMessagen: json["rx_messagen"], + manufacturerPartNumber: json["manufacturer_part_number"], + gtin: json["gtin"], + isGiftCard: json["is_gift_card"], + requireOtherProducts: json["require_other_products"], + automaticallyAddRequiredProducts: json["automatically_add_required_products"], + isDownload: json["is_download"], + unlimitedDownloads: json["unlimited_downloads"], + maxNumberOfDownloads: json["max_number_of_downloads"], + downloadExpirationDays: json["download_expiration_days"], + hasSampleDownload: json["has_sample_download"], + hasUserAgreement: json["has_user_agreement"], + isRecurring: json["is_recurring"], + recurringCycleLength: json["recurring_cycle_length"], + recurringTotalCycles: json["recurring_total_cycles"], + isRental: json["is_rental"], + rentalPriceLength: json["rental_price_length"], + isShipEnabled: json["is_ship_enabled"], + isFreeShipping: json["is_free_shipping"], + shipSeparately: json["ship_separately"], + additionalShippingCharge: json["additional_shipping_charge"], + isTaxExempt: json["is_tax_exempt"], + isTelecommunicationsOrBroadcastingOrElectronicServices: json["is_telecommunications_or_broadcasting_or_electronic_services"], + useMultipleWarehouses: json["use_multiple_warehouses"], + manageInventoryMethodId: json["manage_inventory_method_id"], + stockQuantity: json["stock_quantity"], + stockAvailability: json["stock_availability"], + stockAvailabilityn: json["stock_availabilityn"], + displayStockAvailability: json["display_stock_availability"], + displayStockQuantity: json["display_stock_quantity"], + minStockQuantity: json["min_stock_quantity"], + notifyAdminForQuantityBelow: json["notify_admin_for_quantity_below"], + allowBackInStockSubscriptions: json["allow_back_in_stock_subscriptions"], + orderMinimumQuantity: json["order_minimum_quantity"], + orderMaximumQuantity: json["order_maximum_quantity"], + allowedQuantities: json["allowed_quantities"], + allowAddingOnlyExistingAttributeCombinations: json["allow_adding_only_existing_attribute_combinations"], + disableBuyButton: json["disable_buy_button"], + disableWishlistButton: json["disable_wishlist_button"], + availableForPreOrder: json["available_for_pre_order"], + preOrderAvailabilityStartDateTimeUtc: json["pre_order_availability_start_date_time_utc"], + callForPrice: json["call_for_price"], + price: json["price"].toDouble(), + oldPrice: json["old_price"], + productCost: json["product_cost"].toDouble(), + specialPrice: json["special_price"], + specialPriceStartDateTimeUtc: json["special_price_start_date_time_utc"], + specialPriceEndDateTimeUtc: json["special_price_end_date_time_utc"], + customerEntersPrice: json["customer_enters_price"], + minimumCustomerEnteredPrice: json["minimum_customer_entered_price"], + maximumCustomerEnteredPrice: json["maximum_customer_entered_price"], + basepriceEnabled: json["baseprice_enabled"], + basepriceAmount: json["baseprice_amount"], + basepriceBaseAmount: json["baseprice_base_amount"], + hasTierPrices: json["has_tier_prices"], + hasDiscountsApplied: json["has_discounts_applied"], + discountName: json["discount_name"], + discountNamen: json["discount_namen"], + discountDescription: json["discount_description"], + discountDescriptionn: json["discount_Descriptionn"], + discountPercentage: json["discount_percentage"], + currency: json["currency"], + currencyn: json["currencyn"], + weight: json["weight"].toDouble(), + length: json["length"], + width: json["width"], + height: json["height"], + availableStartDateTimeUtc: json["available_start_date_time_utc"], + availableEndDateTimeUtc: json["available_end_date_time_utc"], + displayOrder: json["display_order"], + published: json["published"], + deleted: json["deleted"], + createdOnUtc: DateTime.parse(json["created_on_utc"]), + updatedOnUtc: DateTime.parse(json["updated_on_utc"]), + productType: json["product_type"], + parentGroupedProductId: json["parent_grouped_product_id"], + roleIds: List.from(json["role_ids"].map((x) => x)), + discountIds: List.from(json["discount_ids"].map((x) => x)), + storeIds: List.from(json["store_ids"].map((x) => x)), + manufacturerIds: List.from(json["manufacturer_ids"].map((x) => x)), + reviews: List.from(json["reviews"].map((x) => x)), + images: List.from(json["images"].map((x) => Image.fromJson(x))), + attributes: List.from(json["attributes"].map((x) => x)), + specifications: List.from(json["specifications"].map((x) => Specification.fromJson(x))), + associatedProductIds: List.from(json["associated_product_ids"].map((x) => x)), + tags: List.from(json["tags"].map((x) => x)), + vendorId: json["vendor_id"], + seName: json["se_name"], + ); + + Map toJson() => { + "id": id, + "visible_individually": visibleIndividually, + "name": name, + "namen": namen, + "localized_names": List.from(localizedNames.map((x) => x.toJson())), + "short_description": shortDescription, + "short_descriptionn": shortDescriptionn, + "full_description": fullDescription, + "full_descriptionn": fullDescriptionn, + "markas_new": markasNew, + "show_on_home_page": showOnHomePage, + "meta_keywords": metaKeywords == null ? null : metaKeywords, + "meta_description": metaDescription == null ? null : metaDescription, + "meta_title": metaTitle == null ? null : metaTitle, + "allow_customer_reviews": allowCustomerReviews, + "approved_rating_sum": approvedRatingSum, + "not_approved_rating_sum": notApprovedRatingSum, + "approved_total_reviews": approvedTotalReviews, + "not_approved_total_reviews": notApprovedTotalReviews, + "sku": sku, + "is_rx": isRx, + "prescription_required": prescriptionRequired, + "rx_message": rxMessage, + "rx_messagen": rxMessagen, + "manufacturer_part_number": manufacturerPartNumber, + "gtin": gtin, + "is_gift_card": isGiftCard, + "require_other_products": requireOtherProducts, + "automatically_add_required_products": automaticallyAddRequiredProducts, + "is_download": isDownload, + "unlimited_downloads": unlimitedDownloads, + "max_number_of_downloads": maxNumberOfDownloads, + "download_expiration_days": downloadExpirationDays, + "has_sample_download": hasSampleDownload, + "has_user_agreement": hasUserAgreement, + "is_recurring": isRecurring, + "recurring_cycle_length": recurringCycleLength, + "recurring_total_cycles": recurringTotalCycles, + "is_rental": isRental, + "rental_price_length": rentalPriceLength, + "is_ship_enabled": isShipEnabled, + "is_free_shipping": isFreeShipping, + "ship_separately": shipSeparately, + "additional_shipping_charge": additionalShippingCharge, + "is_tax_exempt": isTaxExempt, + "is_telecommunications_or_broadcasting_or_electronic_services": isTelecommunicationsOrBroadcastingOrElectronicServices, + "use_multiple_warehouses": useMultipleWarehouses, + "manage_inventory_method_id": manageInventoryMethodId, + "stock_quantity": stockQuantity, + "stock_availability": stockAvailability, + "stock_availabilityn": stockAvailabilityn, + "display_stock_availability": displayStockAvailability, + "display_stock_quantity": displayStockQuantity, + "min_stock_quantity": minStockQuantity, + "notify_admin_for_quantity_below": notifyAdminForQuantityBelow, + "allow_back_in_stock_subscriptions": allowBackInStockSubscriptions, + "order_minimum_quantity": orderMinimumQuantity, + "order_maximum_quantity": orderMaximumQuantity, + "allowed_quantities": allowedQuantities, + "allow_adding_only_existing_attribute_combinations": allowAddingOnlyExistingAttributeCombinations, + "disable_buy_button": disableBuyButton, + "disable_wishlist_button": disableWishlistButton, + "available_for_pre_order": availableForPreOrder, + "pre_order_availability_start_date_time_utc": preOrderAvailabilityStartDateTimeUtc, + "call_for_price": callForPrice, + "price": price, + "old_price": oldPrice, + "product_cost": productCost, + "special_price": specialPrice, + "special_price_start_date_time_utc": specialPriceStartDateTimeUtc, + "special_price_end_date_time_utc": specialPriceEndDateTimeUtc, + "customer_enters_price": customerEntersPrice, + "minimum_customer_entered_price": minimumCustomerEnteredPrice, + "maximum_customer_entered_price": maximumCustomerEnteredPrice, + "baseprice_enabled": basepriceEnabled, + "baseprice_amount": basepriceAmount, + "baseprice_base_amount": basepriceBaseAmount, + "has_tier_prices": hasTierPrices, + "has_discounts_applied": hasDiscountsApplied, + "discount_name": discountName, + "discount_namen": discountNamen, + "discount_description": discountDescription, + "discount_Descriptionn": discountDescriptionn, + "discount_percentage": discountPercentage, + "currency": currency, + "currencyn": currencyn, + "weight": weight, + "length": length, + "width": width, + "height": height, + "available_start_date_time_utc": availableStartDateTimeUtc, + "available_end_date_time_utc": availableEndDateTimeUtc, + "display_order": displayOrder, + "published": published, + "deleted": deleted, + "created_on_utc": createdOnUtc.toIso8601String(), + "updated_on_utc": updatedOnUtc.toIso8601String(), + "product_type": productType, + "parent_grouped_product_id": parentGroupedProductId, + "role_ids": List.from(roleIds.map((x) => x)), + "discount_ids": List.from(discountIds.map((x) => x)), + "store_ids": List.from(storeIds.map((x) => x)), + "manufacturer_ids": List.from(manufacturerIds.map((x) => x)), + "reviews": List.from(reviews.map((x) => x)), + "images": List.from(images.map((x) => x.toJson())), + "attributes": List.from(attributes.map((x) => x)), + "specifications": List.from(specifications.map((x) => x.toJson())), + "associated_product_ids": List.from(associatedProductIds.map((x) => x)), + "tags": List.from(tags.map((x) => x)), + "vendor_id": vendorId, + "se_name": seName, + }; +} + +class Image { + Image({ + this.id, + this.position, + this.src, + this.thumb, + this.attachment, + }); + + int id; + int position; + String src; + String thumb; + String attachment; + + factory Image.fromJson(Map json) => Image( + id: json["id"], + position: json["position"], + src: json["src"], + thumb: json["thumb"], + attachment: json["attachment"], + ); + + Map toJson() => { + "id": id, + "position": position, + "src": src, + "thumb": thumb, + "attachment": attachment, + }; +} + +class LocalizedName { + LocalizedName({ + this.languageId, + this.localizedName, + }); + + int languageId; + String localizedName; + + factory LocalizedName.fromJson(Map json) => LocalizedName( + languageId: json["language_id"], + localizedName: json["localized_name"], + ); + + Map toJson() => { + "language_id": languageId, + "localized_name": localizedName, + }; +} + +class Specification { + Specification({ + this.id, + this.displayOrder, + this.defaultValue, + this.defaultValuen, + this.name, + this.nameN, + }); + + int id; + int displayOrder; + String defaultValue; + String defaultValuen; + String name; + String nameN; + + factory Specification.fromJson(Map json) => Specification( + id: json["id"], + displayOrder: json["display_order"], + defaultValue: json["default_value"], + defaultValuen: json["default_valuen"], + name: json["name"], + nameN: json["nameN"], + ); + + Map toJson() => { + "id": id, + "display_order": displayOrder, + "default_value": defaultValue, + "default_valuen": defaultValuen, + "name": name, + "nameN": nameN, + }; +} + +class EnumValues { + Map map; + Map reverseMap; + + EnumValues(this.map); + + Map get reverse { + if (reverseMap == null) { + reverseMap = map.map((k, v) => new MapEntry(v, k)); + } + return reverseMap; + } +} diff --git a/lib/models/pharmacy/brandModel.dart b/lib/models/pharmacy/brandModel.dart new file mode 100644 index 00000000..2855d492 --- /dev/null +++ b/lib/models/pharmacy/brandModel.dart @@ -0,0 +1,137 @@ +// To parse this JSON data, do +// +// final brand = brandFromJson(jsonString); + +import 'dart:convert'; + +List brandFromJson(String str) => List.from(json.decode(str).map((x) => Brand.fromJson(x))); + +String brandToJson(List data) => json.encode(List.from(data.map((x) => x.toJson()))); + +class Brand { + Brand({ + this.id, + this.name, + this.namen, + this.localizedNames, + this.description, + this.manufacturerTemplateId, + this.metaKeywords, + this.metaDescription, + this.metaTitle, + this.pageSize, + this.pageSizeOptions, + this.priceRanges, + this.published, + this.deleted, + this.displayOrder, + this.createdOnUtc, + this.updatedOnUtc, + this.image, + }); + + String id; + String name; + String namen; + List localizedNames; + String description; + int manufacturerTemplateId; + String metaKeywords; + dynamic metaDescription; + dynamic metaTitle; + int pageSize; + String pageSizeOptions; + dynamic priceRanges; + bool published; + bool deleted; + int displayOrder; + DateTime createdOnUtc; + DateTime updatedOnUtc; + Image image; + + factory Brand.fromJson(Map json) => Brand( + id: json["id"], + name: json["name"], + namen: json["namen"], + localizedNames: List.from(json["localized_names"].map((x) => LocalizedName.fromJson(x))), + description: json["description"] == null ? null : json["description"], + manufacturerTemplateId: json["manufacturer_template_id"], + metaKeywords: json["meta_keywords"], + metaDescription: json["meta_description"], + metaTitle: json["meta_title"], + pageSize: json["page_size"], + pageSizeOptions: json["page_size_options"], + priceRanges: json["price_ranges"], + published: json["published"], + deleted: json["deleted"], + displayOrder: json["display_order"], + createdOnUtc: DateTime.parse(json["created_on_utc"]), + updatedOnUtc: DateTime.parse(json["updated_on_utc"]), + image: json["image"] == null ? null : Image.fromJson(json["image"]), + ); + + Map toJson() => { + "id": id, + "name": name, + "namen": namen, + "localized_names": List.from(localizedNames.map((x) => x.toJson())), + "description": description == null ? null : description, + "manufacturer_template_id": manufacturerTemplateId, + "meta_keywords": metaKeywords, + "meta_description": metaDescription, + "meta_title": metaTitle, + "page_size": pageSize, + "page_size_options": pageSizeOptions, + "price_ranges": priceRanges, + "published": published, + "deleted": deleted, + "display_order": displayOrder, + "created_on_utc": createdOnUtc.toIso8601String(), + "updated_on_utc": updatedOnUtc.toIso8601String(), + "image": image == null ? null : image.toJson(), + }; +} + +class Image { + Image({ + this.src, + this.thumb, + this.attachment, + }); + + String src; + dynamic thumb; + dynamic attachment; + + factory Image.fromJson(Map json) => Image( + src: json["src"], + thumb: json["thumb"], + attachment: json["attachment"], + ); + + Map toJson() => { + "src": src, + "thumb": thumb, + "attachment": attachment, + }; +} + +class LocalizedName { + LocalizedName({ + this.languageId, + this.localizedName, + }); + + int languageId; + String localizedName; + + factory LocalizedName.fromJson(Map json) => LocalizedName( + languageId: json["language_id"], + localizedName: json["localized_name"], + ); + + Map toJson() => { + "language_id": languageId, + "localized_name": localizedName, + }; +} diff --git a/lib/models/pharmacy/locationModel.dart b/lib/models/pharmacy/locationModel.dart new file mode 100644 index 00000000..36ee7350 --- /dev/null +++ b/lib/models/pharmacy/locationModel.dart @@ -0,0 +1,159 @@ +// To parse this JSON data, do +// +// final locationModel = locationModelFromJson(jsonString); + +import 'dart:convert'; + +List locationModelFromJson(String str) => List.from(json.decode(str).map((x) => LocationModel.fromJson(x))); + +String locationModelToJson(List data) => json.encode(List.from(data.map((x) => x.toJson()))); + +class LocationModel { + LocationModel({ + this.expiryDate, + this.sellingPrice, + this.quantity, + this.itemId, + this.locationId, + this.projectId, + this.setupId, + this.locationDescription, + this.locationDescriptionN, + this.itemDescription, + this.itemDescriptionN, + this.alias, + this.locationTypeId, + this.barcode, + this.companybarcode, + this.cityId, + this.cityName, + this.distanceInKilometers, + this.latitude, + this.locationType, + this.longitude, + this.phoneNumber, + this.projectImageUrl, + this.sortOrder, + }); + + ExpiryDate expiryDate; + double sellingPrice; + int quantity; + int itemId; + int locationId; + int projectId; + String setupId; + String locationDescription; + dynamic locationDescriptionN; + ItemDescription itemDescription; + dynamic itemDescriptionN; + Alias alias; + int locationTypeId; + int barcode; + dynamic companybarcode; + int cityId; + CityName cityName; + int distanceInKilometers; + String latitude; + int locationType; + String longitude; + String phoneNumber; + String projectImageUrl; + int sortOrder; + + factory LocationModel.fromJson(Map json) => LocationModel( + expiryDate: expiryDateValues.map[json["ExpiryDate"]], + sellingPrice: json["SellingPrice"].toDouble(), + quantity: json["Quantity"], + itemId: json["ItemID"], + locationId: json["LocationID"], + projectId: json["ProjectID"], + setupId: json["SetupID"], + locationDescription: json["LocationDescription"], + locationDescriptionN: json["LocationDescriptionN"], + itemDescription: itemDescriptionValues.map[json["ItemDescription"]], + itemDescriptionN: json["ItemDescriptionN"], + alias: aliasValues.map[json["Alias"]], + locationTypeId: json["LocationTypeID"], + barcode: json["Barcode"], + companybarcode: json["Companybarcode"], + cityId: json["CityID"], + cityName: cityNameValues.map[json["CityName"]], + distanceInKilometers: json["DistanceInKilometers"], + latitude: json["Latitude"], + locationType: json["LocationType"], + longitude: json["Longitude"], + phoneNumber: json["PhoneNumber"], + projectImageUrl: json["ProjectImageURL"], + sortOrder: json["SortOrder"], + ); + + Map toJson() => { + "ExpiryDate": expiryDateValues.reverse[expiryDate], + "SellingPrice": sellingPrice, + "Quantity": quantity, + "ItemID": itemId, + "LocationID": locationId, + "ProjectID": projectId, + "SetupID": setupId, + "LocationDescription": locationDescription, + "LocationDescriptionN": locationDescriptionN, + "ItemDescription": itemDescriptionValues.reverse[itemDescription], + "ItemDescriptionN": itemDescriptionN, + "Alias": aliasValues.reverse[alias], + "LocationTypeID": locationTypeId, + "Barcode": barcode, + "Companybarcode": companybarcode, + "CityID": cityId, + "CityName": cityNameValues.reverse[cityName], + "DistanceInKilometers": distanceInKilometers, + "Latitude": latitude, + "LocationType": locationType, + "Longitude": longitude, + "PhoneNumber": phoneNumber, + "ProjectImageURL": projectImageUrl, + "SortOrder": sortOrder, + }; +} + +enum Alias { CAPSULE } + +final aliasValues = EnumValues({ + "CAPSULE": Alias.CAPSULE +}); + +enum CityName { RIYADH, KHOBAR, QASSIM } + +final cityNameValues = EnumValues({ + "Khobar": CityName.KHOBAR, + "Qassim": CityName.QASSIM, + "Riyadh": CityName.RIYADH +}); + +enum ExpiryDate { DATE_16223220000000300, DATE_16250004000000300, DATE_16538580000000300 } + +final expiryDateValues = EnumValues({ + "/Date(1622322000000+0300)/": ExpiryDate.DATE_16223220000000300, + "/Date(1625000400000+0300)/": ExpiryDate.DATE_16250004000000300, + "/Date(1653858000000+0300)/": ExpiryDate.DATE_16538580000000300 +}); + +enum ItemDescription { XERACTAN_20_MG_CAP_30_S } + +final itemDescriptionValues = EnumValues({ + "XERACTAN 20 MG CAP 30'S": ItemDescription.XERACTAN_20_MG_CAP_30_S +}); + +class EnumValues { + Map map; + Map reverseMap; + + EnumValues(this.map); + + Map get reverse { + if (reverseMap == null) { + reverseMap = map.map((k, v) => new MapEntry(v, k)); + } + return reverseMap; + } +} diff --git a/lib/models/pharmacy/productDetailModel.dart b/lib/models/pharmacy/productDetailModel.dart new file mode 100644 index 00000000..d2e8f010 --- /dev/null +++ b/lib/models/pharmacy/productDetailModel.dart @@ -0,0 +1,249 @@ +// To parse this JSON data, do +// +// final productDetail = productDetailFromJson(jsonString); + +import 'dart:convert'; + +List productDetailFromJson(String str) => List.from(json.decode(str).map((x) => ProductDetail.fromJson(x))); + +String productDetailToJson(List data) => json.encode(List.from(data.map((x) => x.toJson()))); + +class ProductDetail { + ProductDetail({ + this.reviews, + }); + + List reviews; + + factory ProductDetail.fromJson(Map json) => ProductDetail( + reviews: List.from(json["reviews"].map((x) => Review.fromJson(x))), + ); + + Map toJson() => { + "reviews": List.from(reviews.map((x) => x.toJson())), + }; +} + +class Review { + Review({ + this.id, + this.position, + this.reviewId, + this.customerId, + this.productId, + this.storeId, + this.isApproved, + this.title, + this.reviewText, + this.replyText, + this.rating, + this.helpfulYesTotal, + this.helpfulNoTotal, + this.createdOnUtc, + this.customer, + this.product, + }); + + int id; + int position; + int reviewId; + int customerId; + int productId; + int storeId; + bool isApproved; + String title; + String reviewText; + dynamic replyText; + int rating; + int helpfulYesTotal; + int helpfulNoTotal; + DateTime createdOnUtc; + Customer customer; + dynamic product; + + factory Review.fromJson(Map json) => Review( + id: json["id"], + position: json["position"], + reviewId: json["review_id"], + customerId: json["customer_id"], + productId: json["product_id"], + storeId: json["store_id"], + isApproved: json["is_approved"], + title: json["title"], + reviewText: json["review_text"], + replyText: json["reply_text"], + rating: json["rating"], + helpfulYesTotal: json["helpful_yes_total"], + helpfulNoTotal: json["helpful_no_total"], + createdOnUtc: DateTime.parse(json["created_on_utc"]), + customer: Customer.fromJson(json["customer"]), + product: json["product"], + ); + + Map toJson() => { + "id": id, + "position": position, + "review_id": reviewId, + "customer_id": customerId, + "product_id": productId, + "store_id": storeId, + "is_approved": isApproved, + "title": title, + "review_text": reviewText, + "reply_text": replyText, + "rating": rating, + "helpful_yes_total": helpfulYesTotal, + "helpful_no_total": helpfulNoTotal, + "created_on_utc": createdOnUtc.toIso8601String(), + "customer": customer.toJson(), + "product": product, + }; +} + +class Customer { + Customer({ + this.fileNumber, + this.iqamaNumber, + this.isOutSa, + this.patientType, + this.gender, + this.birthDate, + this.phone, + this.countryCode, + this.yahalaAccountno, + this.billingAddress, + this.shippingAddress, + this.id, + this.username, + this.email, + this.firstName, + this.lastName, + this.languageId, + this.adminComment, + this.isTaxExempt, + this.hasShoppingCartItems, + this.active, + this.deleted, + this.isSystemAccount, + this.systemName, + this.lastIpAddress, + this.createdOnUtc, + this.lastLoginDateUtc, + this.lastActivityDateUtc, + this.registeredInStoreId, + }); + + dynamic fileNumber; + dynamic iqamaNumber; + int isOutSa; + int patientType; + dynamic gender; + DateTime birthDate; + dynamic phone; + dynamic countryCode; + dynamic yahalaAccountno; + dynamic billingAddress; + dynamic shippingAddress; + String id; + Email username; + Email email; + dynamic firstName; + dynamic lastName; + dynamic languageId; + dynamic adminComment; + dynamic isTaxExempt; + dynamic hasShoppingCartItems; + dynamic active; + dynamic deleted; + dynamic isSystemAccount; + dynamic systemName; + dynamic lastIpAddress; + dynamic createdOnUtc; + dynamic lastLoginDateUtc; + dynamic lastActivityDateUtc; + dynamic registeredInStoreId; + + factory Customer.fromJson(Map json) => Customer( + fileNumber: json["file_number"], + iqamaNumber: json["iqama_number"], + isOutSa: json["is_out_sa"], + patientType: json["patient_type"], + gender: json["gender"], + birthDate: DateTime.parse(json["birth_date"]), + phone: json["phone"], + countryCode: json["country_code"], + yahalaAccountno: json["yahala_accountno"], + billingAddress: json["billing_address"], + shippingAddress: json["shipping_address"], + id: json["id"], + username: emailValues.map[json["username"]], + email: emailValues.map[json["email"]], + firstName: json["first_name"], + lastName: json["last_name"], + languageId: json["language_id"], + adminComment: json["admin_comment"], + isTaxExempt: json["is_tax_exempt"], + hasShoppingCartItems: json["has_shopping_cart_items"], + active: json["active"], + deleted: json["deleted"], + isSystemAccount: json["is_system_account"], + systemName: json["system_name"], + lastIpAddress: json["last_ip_address"], + createdOnUtc: json["created_on_utc"], + lastLoginDateUtc: json["last_login_date_utc"], + lastActivityDateUtc: json["last_activity_date_utc"], + registeredInStoreId: json["registered_in_store_id"], + ); + + Map toJson() => { + "file_number": fileNumber, + "iqama_number": iqamaNumber, + "is_out_sa": isOutSa, + "patient_type": patientType, + "gender": gender, + "birth_date": birthDate.toIso8601String(), + "phone": phone, + "country_code": countryCode, + "yahala_accountno": yahalaAccountno, + "billing_address": billingAddress, + "shipping_address": shippingAddress, + "id": id, + "username": emailValues.reverse[username], + "email": emailValues.reverse[email], + "first_name": firstName, + "last_name": lastName, + "language_id": languageId, + "admin_comment": adminComment, + "is_tax_exempt": isTaxExempt, + "has_shopping_cart_items": hasShoppingCartItems, + "active": active, + "deleted": deleted, + "is_system_account": isSystemAccount, + "system_name": systemName, + "last_ip_address": lastIpAddress, + "created_on_utc": createdOnUtc, + "last_login_date_utc": lastLoginDateUtc, + "last_activity_date_utc": lastActivityDateUtc, + "registered_in_store_id": registeredInStoreId, + }; +} + +enum Email { STEVE_GATES_NOP_COMMERCE_COM } + +final emailValues = EnumValues({ + "steve_gates@nopCommerce.com": Email.STEVE_GATES_NOP_COMMERCE_COM +}); + +class EnumValues { + Map map; + Map reverseMap; + + EnumValues(this.map); + + Map get reverse { + if (reverseMap == null) { + reverseMap = map.map((k, v) => new MapEntry(v, k)); + } + return reverseMap; + } +} diff --git a/lib/models/pharmacy/products.dart b/lib/models/pharmacy/products.dart new file mode 100644 index 00000000..b4833c64 --- /dev/null +++ b/lib/models/pharmacy/products.dart @@ -0,0 +1,835 @@ +// To parse this JSON data, do +// +// final products = productsFromJson(jsonString); + +import 'dart:convert'; + +Products productsFromJson(String str) => Products.fromJson(json.decode(str)); + +String productsToJson(Products data) => json.encode(data.toJson()); + +class Products { + Products({ + this.messageStatus, + this.products, + }); + + dynamic messageStatus; + List products; + + factory Products.fromJson(Map json) => Products( + messageStatus: json["MessageStatus"], + products: List.from(json["products"].map((x) => Product.fromJson(x))), + ); + + Map toJson() => { + "MessageStatus": messageStatus, + "products": List.from(products.map((x) => x.toJson())), + }; +} + +class Product { + Product({ + this.id, + this.visibleIndividually, + this.name, + this.namen, + this.localizedNames, + this.shortDescription, + this.shortDescriptionn, + this.fullDescription, + this.fullDescriptionn, + this.markasNew, + this.showOnHomePage, + this.metaKeywords, + this.metaDescription, + this.metaTitle, + this.allowCustomerReviews, + this.approvedRatingSum, + this.notApprovedRatingSum, + this.approvedTotalReviews, + this.notApprovedTotalReviews, + this.sku, + this.isRx, + this.prescriptionRequired, + this.rxMessage, + this.rxMessagen, + this.manufacturerPartNumber, + this.gtin, + this.isGiftCard, + this.requireOtherProducts, + this.automaticallyAddRequiredProducts, + this.isDownload, + this.unlimitedDownloads, + this.maxNumberOfDownloads, + this.downloadExpirationDays, + this.hasSampleDownload, + this.hasUserAgreement, + this.isRecurring, + this.recurringCycleLength, + this.recurringTotalCycles, + this.isRental, + this.rentalPriceLength, + this.isShipEnabled, + this.isFreeShipping, + this.shipSeparately, + this.additionalShippingCharge, + this.isTaxExempt, + this.isTelecommunicationsOrBroadcastingOrElectronicServices, + this.useMultipleWarehouses, + this.manageInventoryMethodId, + this.stockQuantity, + this.stockAvailability, + this.stockAvailabilityn, + this.displayStockAvailability, + this.displayStockQuantity, + this.minStockQuantity, + this.notifyAdminForQuantityBelow, + this.allowBackInStockSubscriptions, + this.orderMinimumQuantity, + this.orderMaximumQuantity, + this.allowedQuantities, + this.allowAddingOnlyExistingAttributeCombinations, + this.disableBuyButton, + this.disableWishlistButton, + this.availableForPreOrder, + this.preOrderAvailabilityStartDateTimeUtc, + this.callForPrice, + this.price, + this.oldPrice, + this.productCost, + this.specialPrice, + this.specialPriceStartDateTimeUtc, + this.specialPriceEndDateTimeUtc, + this.customerEntersPrice, + this.minimumCustomerEnteredPrice, + this.maximumCustomerEnteredPrice, + this.basepriceEnabled, + this.basepriceAmount, + this.basepriceBaseAmount, + this.hasTierPrices, + this.hasDiscountsApplied, + this.discountName, + this.discountNamen, + this.discountDescription, + this.discountDescriptionn, + this.discountPercentage, + this.currency, + this.currencyn, + this.weight, + this.length, + this.width, + this.height, + this.availableStartDateTimeUtc, + this.availableEndDateTimeUtc, + this.displayOrder, + this.published, + this.deleted, + this.createdOnUtc, + this.updatedOnUtc, + this.productType, + this.parentGroupedProductId, + this.roleIds, + this.discountIds, + this.storeIds, + this.manufacturerIds, + this.reviews, + this.images, + this.attributes, + this.specifications, + this.associatedProductIds, + this.tags, + this.vendorId, + this.seName, + }); + + String id; + bool visibleIndividually; + String name; + String namen; + List localizedNames; + String shortDescription; + String shortDescriptionn; + String fullDescription; + String fullDescriptionn; + bool markasNew; + bool showOnHomePage; + String metaKeywords; + String metaDescription; + String metaTitle; + bool allowCustomerReviews; + int approvedRatingSum; + int notApprovedRatingSum; + int approvedTotalReviews; + int notApprovedTotalReviews; + String sku; + bool isRx; + bool prescriptionRequired; + String rxMessage; + String rxMessagen; + dynamic manufacturerPartNumber; + dynamic gtin; + bool isGiftCard; + bool requireOtherProducts; + bool automaticallyAddRequiredProducts; + bool isDownload; + bool unlimitedDownloads; + int maxNumberOfDownloads; + dynamic downloadExpirationDays; + bool hasSampleDownload; + bool hasUserAgreement; + bool isRecurring; + int recurringCycleLength; + int recurringTotalCycles; + bool isRental; + int rentalPriceLength; + bool isShipEnabled; + bool isFreeShipping; + bool shipSeparately; + int additionalShippingCharge; + bool isTaxExempt; + bool isTelecommunicationsOrBroadcastingOrElectronicServices; + bool useMultipleWarehouses; + int manageInventoryMethodId; + int stockQuantity; + String stockAvailability; + String stockAvailabilityn; + bool displayStockAvailability; + bool displayStockQuantity; + int minStockQuantity; + int notifyAdminForQuantityBelow; + bool allowBackInStockSubscriptions; + int orderMinimumQuantity; + int orderMaximumQuantity; + dynamic allowedQuantities; + bool allowAddingOnlyExistingAttributeCombinations; + bool disableBuyButton; + bool disableWishlistButton; + bool availableForPreOrder; + dynamic preOrderAvailabilityStartDateTimeUtc; + bool callForPrice; + double price; + int oldPrice; + double productCost; + dynamic specialPrice; + dynamic specialPriceStartDateTimeUtc; + dynamic specialPriceEndDateTimeUtc; + bool customerEntersPrice; + int minimumCustomerEnteredPrice; + int maximumCustomerEnteredPrice; + bool basepriceEnabled; + int basepriceAmount; + int basepriceBaseAmount; + bool hasTierPrices; + bool hasDiscountsApplied; + String discountName; + String discountNamen; + String discountDescription; + String discountDescriptionn; + String discountPercentage; + String currency; + String currencyn; + double weight; + int length; + int width; + int height; + dynamic availableStartDateTimeUtc; + dynamic availableEndDateTimeUtc; + int displayOrder; + bool published; + bool deleted; + DateTime createdOnUtc; + DateTime updatedOnUtc; + String productType; + int parentGroupedProductId; + List roleIds; + List discountIds; + List storeIds; + List manufacturerIds; + List reviews; + List images; + List attributes; + List specifications; + List associatedProductIds; + List tags; + int vendorId; + String seName; + + factory Product.fromJson(Map json) => Product( + id: json["id"], + visibleIndividually: json["visible_individually"], + name: json["name"], + namen: json["namen"], + localizedNames: List.from(json["localized_names"].map((x) => LocalizedName.fromJson(x))), + shortDescription: json["short_description"] == null ? null : json["short_description"], + shortDescriptionn: json["short_descriptionn"] == null ? null : json["short_descriptionn"], + fullDescription: json["full_description"], + fullDescriptionn: json["full_descriptionn"], + markasNew: json["markas_new"], + showOnHomePage: json["show_on_home_page"], + metaKeywords: json["meta_keywords"] == null ? null : json["meta_keywords"], + metaDescription: json["meta_description"] == null ? null : json["meta_description"], + metaTitle: json["meta_title"] == null ? null : json["meta_title"], + allowCustomerReviews: json["allow_customer_reviews"], + approvedRatingSum: json["approved_rating_sum"], + notApprovedRatingSum: json["not_approved_rating_sum"], + approvedTotalReviews: json["approved_total_reviews"], + notApprovedTotalReviews: json["not_approved_total_reviews"], + sku: json["sku"], + isRx: json["is_rx"], + prescriptionRequired: json["prescription_required"], + rxMessage: json["rx_message"] == null ? null : json["rx_message"], + rxMessagen: json["rx_messagen"] == null ? null : json["rx_messagen"], + manufacturerPartNumber: json["manufacturer_part_number"], + gtin: json["gtin"], + isGiftCard: json["is_gift_card"], + requireOtherProducts: json["require_other_products"], + automaticallyAddRequiredProducts: json["automatically_add_required_products"], + isDownload: json["is_download"], + unlimitedDownloads: json["unlimited_downloads"], + maxNumberOfDownloads: json["max_number_of_downloads"], + downloadExpirationDays: json["download_expiration_days"], + hasSampleDownload: json["has_sample_download"], + hasUserAgreement: json["has_user_agreement"], + isRecurring: json["is_recurring"], + recurringCycleLength: json["recurring_cycle_length"], + recurringTotalCycles: json["recurring_total_cycles"], + isRental: json["is_rental"], + rentalPriceLength: json["rental_price_length"], + isShipEnabled: json["is_ship_enabled"], + isFreeShipping: json["is_free_shipping"], + shipSeparately: json["ship_separately"], + additionalShippingCharge: json["additional_shipping_charge"], + isTaxExempt: json["is_tax_exempt"], + isTelecommunicationsOrBroadcastingOrElectronicServices: json["is_telecommunications_or_broadcasting_or_electronic_services"], + useMultipleWarehouses: json["use_multiple_warehouses"], + manageInventoryMethodId: json["manage_inventory_method_id"], + stockQuantity: json["stock_quantity"], + stockAvailability: json["stock_availability"], + stockAvailabilityn: json["stock_availabilityn"], + displayStockAvailability: json["display_stock_availability"], + displayStockQuantity: json["display_stock_quantity"], + minStockQuantity: json["min_stock_quantity"], + notifyAdminForQuantityBelow: json["notify_admin_for_quantity_below"], + allowBackInStockSubscriptions: json["allow_back_in_stock_subscriptions"], + orderMinimumQuantity: json["order_minimum_quantity"], + orderMaximumQuantity: json["order_maximum_quantity"], + allowedQuantities: json["allowed_quantities"], + allowAddingOnlyExistingAttributeCombinations: json["allow_adding_only_existing_attribute_combinations"], + disableBuyButton: json["disable_buy_button"], + disableWishlistButton: json["disable_wishlist_button"], + availableForPreOrder: json["available_for_pre_order"], + preOrderAvailabilityStartDateTimeUtc: json["pre_order_availability_start_date_time_utc"], + callForPrice: json["call_for_price"], + price: json["price"].toDouble(), + oldPrice: json["old_price"], + productCost: json["product_cost"].toDouble(), + specialPrice: json["special_price"], + specialPriceStartDateTimeUtc: json["special_price_start_date_time_utc"], + specialPriceEndDateTimeUtc: json["special_price_end_date_time_utc"], + customerEntersPrice: json["customer_enters_price"], + minimumCustomerEnteredPrice: json["minimum_customer_entered_price"], + maximumCustomerEnteredPrice: json["maximum_customer_entered_price"], + basepriceEnabled: json["baseprice_enabled"], + basepriceAmount: json["baseprice_amount"], + basepriceBaseAmount: json["baseprice_base_amount"], + hasTierPrices: json["has_tier_prices"], + hasDiscountsApplied: json["has_discounts_applied"], + discountName: json["discount_name"] == null ? null : json["discount_name"], + discountNamen: json["discount_namen"] == null ? null : json["discount_namen"], + discountDescription: json["discount_description"] == null ? null : json["discount_description"], + discountDescriptionn: json["discount_Descriptionn"] == null ? null : json["discount_Descriptionn"], + discountPercentage: json["discount_percentage"] == null ? null : json["discount_percentage"], + currency: json["currency"], + currencyn: json["currencyn"], + weight: json["weight"].toDouble(), + length: json["length"], + width: json["width"], + height: json["height"], + availableStartDateTimeUtc: json["available_start_date_time_utc"], + availableEndDateTimeUtc: json["available_end_date_time_utc"], + displayOrder: json["display_order"], + published: json["published"], + deleted: json["deleted"], + createdOnUtc: DateTime.parse(json["created_on_utc"]), + updatedOnUtc: DateTime.parse(json["updated_on_utc"]), + productType: json["product_type"], + parentGroupedProductId: json["parent_grouped_product_id"], + roleIds: List.from(json["role_ids"].map((x) => x)), + discountIds: List.from(json["discount_ids"].map((x) => x)), + storeIds: List.from(json["store_ids"].map((x) => x)), + manufacturerIds: List.from(json["manufacturer_ids"].map((x) => x)), + reviews: List.from(json["reviews"].map((x) => Review.fromJson(x))), + images: List.from(json["images"].map((x) => Image.fromJson(x))), + attributes: List.from(json["attributes"].map((x) => x)), + specifications: List.from(json["specifications"].map((x) => Specification.fromJson(x))), + associatedProductIds: List.from(json["associated_product_ids"].map((x) => x)), + tags: List.from(json["tags"].map((x) => x)), + vendorId: json["vendor_id"], + seName: json["se_name"], + ); + + Map toJson() => { + "id": id, + "visible_individually": visibleIndividually, + "name": name, + "namen": namen, + "localized_names": List.from(localizedNames.map((x) => x.toJson())), + "short_description": shortDescription == null ? null : shortDescription, + "short_descriptionn": shortDescriptionn == null ? null : shortDescriptionn, + "full_description": fullDescription, + "full_descriptionn": fullDescriptionn, + "markas_new": markasNew, + "show_on_home_page": showOnHomePage, + "meta_keywords": metaKeywords == null ? null : metaKeywords, + "meta_description": metaDescription == null ? null : metaDescription, + "meta_title": metaTitle == null ? null : metaTitle, + "allow_customer_reviews": allowCustomerReviews, + "approved_rating_sum": approvedRatingSum, + "not_approved_rating_sum": notApprovedRatingSum, + "approved_total_reviews": approvedTotalReviews, + "not_approved_total_reviews": notApprovedTotalReviews, + "sku": sku, + "is_rx": isRx, + "prescription_required": prescriptionRequired, + "rx_message": rxMessage == null ? null : rxMessage, + "rx_messagen": rxMessagen == null ? null : rxMessagen, + "manufacturer_part_number": manufacturerPartNumber, + "gtin": gtin, + "is_gift_card": isGiftCard, + "require_other_products": requireOtherProducts, + "automatically_add_required_products": automaticallyAddRequiredProducts, + "is_download": isDownload, + "unlimited_downloads": unlimitedDownloads, + "max_number_of_downloads": maxNumberOfDownloads, + "download_expiration_days": downloadExpirationDays, + "has_sample_download": hasSampleDownload, + "has_user_agreement": hasUserAgreement, + "is_recurring": isRecurring, + "recurring_cycle_length": recurringCycleLength, + "recurring_total_cycles": recurringTotalCycles, + "is_rental": isRental, + "rental_price_length": rentalPriceLength, + "is_ship_enabled": isShipEnabled, + "is_free_shipping": isFreeShipping, + "ship_separately": shipSeparately, + "additional_shipping_charge": additionalShippingCharge, + "is_tax_exempt": isTaxExempt, + "is_telecommunications_or_broadcasting_or_electronic_services": isTelecommunicationsOrBroadcastingOrElectronicServices, + "use_multiple_warehouses": useMultipleWarehouses, + "manage_inventory_method_id": manageInventoryMethodId, + "stock_quantity": stockQuantity, + "stock_availability": stockAvailability, + "stock_availabilityn": stockAvailabilityn, + "display_stock_availability": displayStockAvailability, + "display_stock_quantity": displayStockQuantity, + "min_stock_quantity": minStockQuantity, + "notify_admin_for_quantity_below": notifyAdminForQuantityBelow, + "allow_back_in_stock_subscriptions": allowBackInStockSubscriptions, + "order_minimum_quantity": orderMinimumQuantity, + "order_maximum_quantity": orderMaximumQuantity, + "allowed_quantities": allowedQuantities, + "allow_adding_only_existing_attribute_combinations": allowAddingOnlyExistingAttributeCombinations, + "disable_buy_button": disableBuyButton, + "disable_wishlist_button": disableWishlistButton, + "available_for_pre_order": availableForPreOrder, + "pre_order_availability_start_date_time_utc": preOrderAvailabilityStartDateTimeUtc, + "call_for_price": callForPrice, + "price": price, + "old_price": oldPrice, + "product_cost": productCost, + "special_price": specialPrice, + "special_price_start_date_time_utc": specialPriceStartDateTimeUtc, + "special_price_end_date_time_utc": specialPriceEndDateTimeUtc, + "customer_enters_price": customerEntersPrice, + "minimum_customer_entered_price": minimumCustomerEnteredPrice, + "maximum_customer_entered_price": maximumCustomerEnteredPrice, + "baseprice_enabled": basepriceEnabled, + "baseprice_amount": basepriceAmount, + "baseprice_base_amount": basepriceBaseAmount, + "has_tier_prices": hasTierPrices, + "has_discounts_applied": hasDiscountsApplied, + "discount_name": discountName == null ? null : discountName, + "discount_namen": discountNamen == null ? null : discountNamen, + "discount_description": discountDescription == null ? null : discountDescription, + "discount_Descriptionn": discountDescriptionn == null ? null : discountDescriptionn, + "discount_percentage": discountPercentage == null ? null : discountPercentage, + "currency": currency, + "currencyn": currencyn, + "weight": weight, + "length": length, + "width": width, + "height": height, + "available_start_date_time_utc": availableStartDateTimeUtc, + "available_end_date_time_utc": availableEndDateTimeUtc, + "display_order": displayOrder, + "published": published, + "deleted": deleted, + "created_on_utc": createdOnUtc.toIso8601String(), + "updated_on_utc": updatedOnUtc.toIso8601String(), + "product_type": productType, + "parent_grouped_product_id": parentGroupedProductId, + "role_ids": List.from(roleIds.map((x) => x)), + "discount_ids": List.from(discountIds.map((x) => x)), + "store_ids": List.from(storeIds.map((x) => x)), + "manufacturer_ids": List.from(manufacturerIds.map((x) => x)), + "reviews": List.from(reviews.map((x) => x.toJson())), + "images": List.from(images.map((x) => x.toJson())), + "attributes": List.from(attributes.map((x) => x)), + "specifications": List.from(specifications.map((x) => x.toJson())), + "associated_product_ids": List.from(associatedProductIds.map((x) => x)), + "tags": List.from(tags.map((x) => x)), + "vendor_id": vendorId, + "se_name": seName, + }; +} + +class Image { + Image({ + this.id, + this.position, + this.src, + this.thumb, + this.attachment, + }); + + int id; + int position; + String src; + String thumb; + String attachment; + + factory Image.fromJson(Map json) => Image( + id: json["id"], + position: json["position"], + src: json["src"], + thumb: json["thumb"], + attachment: json["attachment"], + ); + + Map toJson() => { + "id": id, + "position": position, + "src": src, + "thumb": thumb, + "attachment": attachment, + }; +} + +class LocalizedName { + LocalizedName({ + this.languageId, + this.localizedName, + }); + + int languageId; + String localizedName; + + factory LocalizedName.fromJson(Map json) => LocalizedName( + languageId: json["language_id"], + localizedName: json["localized_name"], + ); + + Map toJson() => { + "language_id": languageId, + "localized_name": localizedName, + }; +} + +class Review { + Review({ + this.id, + this.position, + this.reviewId, + this.customerId, + this.productId, + this.storeId, + this.isApproved, + this.title, + this.reviewText, + this.replyText, + this.rating, + this.helpfulYesTotal, + this.helpfulNoTotal, + this.createdOnUtc, + this.customer, + this.product, + }); + + int id; + int position; + int reviewId; + int customerId; + int productId; + int storeId; + bool isApproved; + String title; + String reviewText; + dynamic replyText; + int rating; + int helpfulYesTotal; + int helpfulNoTotal; + DateTime createdOnUtc; + Customer customer; + dynamic product; + + factory Review.fromJson(Map json) => Review( + id: json["id"], + position: json["position"], + reviewId: json["review_id"], + customerId: json["customer_id"], + productId: json["product_id"], + storeId: json["store_id"], + isApproved: json["is_approved"], + title: json["title"], + reviewText: json["review_text"], + replyText: json["reply_text"], + rating: json["rating"], + helpfulYesTotal: json["helpful_yes_total"], + helpfulNoTotal: json["helpful_no_total"], + createdOnUtc: DateTime.parse(json["created_on_utc"]), + customer: Customer.fromJson(json["customer"]), + product: json["product"], + ); + + Map toJson() => { + "id": id, + "position": position, + "review_id": reviewId, + "customer_id": customerId, + "product_id": productId, + "store_id": storeId, + "is_approved": isApproved, + "title": title, + "review_text": reviewText, + "reply_text": replyText, + "rating": rating, + "helpful_yes_total": helpfulYesTotal, + "helpful_no_total": helpfulNoTotal, + "created_on_utc": createdOnUtc.toIso8601String(), + "customer": customer.toJson(), + "product": product, + }; +} + +class Customer { + Customer({ + this.fileNumber, + this.iqamaNumber, + this.isOutSa, + this.patientType, + this.gender, + this.birthDate, + this.phone, + this.countryCode, + this.yahalaAccountno, + this.billingAddress, + this.shippingAddress, + this.addresses, + this.id, + this.username, + this.email, + this.firstName, + this.lastName, + this.languageId, + this.adminComment, + this.isTaxExempt, + this.hasShoppingCartItems, + this.active, + this.deleted, + this.isSystemAccount, + this.systemName, + this.lastIpAddress, + this.createdOnUtc, + this.lastLoginDateUtc, + this.lastActivityDateUtc, + this.registeredInStoreId, + this.roleIds, + }); + + dynamic fileNumber; + dynamic iqamaNumber; + int isOutSa; + int patientType; + dynamic gender; + DateTime birthDate; + dynamic phone; + dynamic countryCode; + dynamic yahalaAccountno; + dynamic billingAddress; + dynamic shippingAddress; + List addresses; + String id; + Username username; + Email email; + dynamic firstName; + dynamic lastName; + dynamic languageId; + dynamic adminComment; + dynamic isTaxExempt; + dynamic hasShoppingCartItems; + dynamic active; + dynamic deleted; + dynamic isSystemAccount; + dynamic systemName; + dynamic lastIpAddress; + dynamic createdOnUtc; + dynamic lastLoginDateUtc; + dynamic lastActivityDateUtc; + dynamic registeredInStoreId; + List roleIds; + + factory Customer.fromJson(Map json) => Customer( + fileNumber: json["file_number"], + iqamaNumber: json["iqama_number"], + isOutSa: json["is_out_sa"], + patientType: json["patient_type"], + gender: json["gender"], + birthDate: DateTime.parse(json["birth_date"]), + phone: json["phone"], + countryCode: json["country_code"], + yahalaAccountno: json["yahala_accountno"], + billingAddress: json["billing_address"], + shippingAddress: json["shipping_address"], + addresses: List.from(json["addresses"].map((x) => x)), + id: json["id"], + username: usernameValues.map[json["username"]], + email: emailValues.map[json["email"]], + firstName: json["first_name"], + lastName: json["last_name"], + languageId: json["language_id"], + adminComment: json["admin_comment"], + isTaxExempt: json["is_tax_exempt"], + hasShoppingCartItems: json["has_shopping_cart_items"], + active: json["active"], + deleted: json["deleted"], + isSystemAccount: json["is_system_account"], + systemName: json["system_name"], + lastIpAddress: json["last_ip_address"], + createdOnUtc: json["created_on_utc"], + lastLoginDateUtc: json["last_login_date_utc"], + lastActivityDateUtc: json["last_activity_date_utc"], + registeredInStoreId: json["registered_in_store_id"], + roleIds: List.from(json["role_ids"].map((x) => x)), + ); + + Map toJson() => { + "file_number": fileNumber, + "iqama_number": iqamaNumber, + "is_out_sa": isOutSa, + "patient_type": patientType, + "gender": gender, + "birth_date": birthDate.toIso8601String(), + "phone": phone, + "country_code": countryCode, + "yahala_accountno": yahalaAccountno, + "billing_address": billingAddress, + "shipping_address": shippingAddress, + "addresses": List.from(addresses.map((x) => x)), + "id": id, + "username": usernameValues.reverse[username], + "email": emailValues.reverse[email], + "first_name": firstName, + "last_name": lastName, + "language_id": languageId, + "admin_comment": adminComment, + "is_tax_exempt": isTaxExempt, + "has_shopping_cart_items": hasShoppingCartItems, + "active": active, + "deleted": deleted, + "is_system_account": isSystemAccount, + "system_name": systemName, + "last_ip_address": lastIpAddress, + "created_on_utc": createdOnUtc, + "last_login_date_utc": lastLoginDateUtc, + "last_activity_date_utc": lastActivityDateUtc, + "registered_in_store_id": registeredInStoreId, + "role_ids": List.from(roleIds.map((x) => x)), + }; +} + +enum Email { MEMO17299_GMAIL_COM, STEVE_GATES_NOP_COMMERCE_COM } + +final emailValues = EnumValues({ + "Memo17299@gmail.com": Email.MEMO17299_GMAIL_COM, + "steve_gates@nopCommerce.com": Email.STEVE_GATES_NOP_COMMERCE_COM +}); + +enum Username { AMAL_26, STEVE_GATES_NOP_COMMERCE_COM } + +final usernameValues = EnumValues({ + "amal_26": Username.AMAL_26, + "steve_gates@nopCommerce.com": Username.STEVE_GATES_NOP_COMMERCE_COM +}); + +class Specification { + Specification({ + this.id, + this.displayOrder, + this.defaultValue, + this.defaultValuen, + this.name, + this.nameN, + }); + + int id; + int displayOrder; + String defaultValue; + String defaultValuen; + Name name; + NameN nameN; + + factory Specification.fromJson(Map json) => Specification( + id: json["id"], + displayOrder: json["display_order"], + defaultValue: json["default_value"], + defaultValuen: json["default_valuen"], + name: nameValues.map[json["name"]], + nameN: nameNValues.map[json["nameN"]], + ); + + Map toJson() => { + "id": id, + "display_order": displayOrder, + "default_value": defaultValue, + "default_valuen": defaultValuen, + "name": nameValues.reverse[name], + "nameN": nameNValues.reverse[nameN], + }; +} + +enum Name { PRIMARY_UNIT_OF_MEASURE, BRAND, MANUFACTURER_COUNTRY_NAME, STORAGE, COMPOSITION, SPF } + +final nameValues = EnumValues({ + "BRAND": Name.BRAND, + "COMPOSITION": Name.COMPOSITION, + "MANUFACTURER COUNTRY NAME": Name.MANUFACTURER_COUNTRY_NAME, + "Primary Unit Of Measure": Name.PRIMARY_UNIT_OF_MEASURE, + "SPF": Name.SPF, + "STORAGE": Name.STORAGE +}); + +enum NameN { EMPTY, NAME_N, PURPLE, FLUFFY, TENTACLED, SPF } + +final nameNValues = EnumValues({ + "وحدة القياس الأولية": NameN.EMPTY, + "تخزين": NameN.FLUFFY, + "علامة تجارية": NameN.NAME_N, + "اسم البلد المصنع": NameN.PURPLE, + "SPF": NameN.SPF, + "المكونات": NameN.TENTACLED +}); + +class EnumValues { + Map map; + Map reverseMap; + + EnumValues(this.map); + + Map get reverse { + if (reverseMap == null) { + reverseMap = map.map((k, v) => new MapEntry(v, k)); + } + return reverseMap; + } +} diff --git a/lib/models/pharmacy/reviewModel.dart b/lib/models/pharmacy/reviewModel.dart new file mode 100644 index 00000000..da30212c --- /dev/null +++ b/lib/models/pharmacy/reviewModel.dart @@ -0,0 +1,803 @@ +// To parse this JSON data, do +// +// final review = reviewFromJson(jsonString); + +import 'dart:convert'; + +List reviewFromJson(String str) => List.from(json.decode(str).map((x) => Review.fromJson(x))); + +String reviewToJson(List data) => json.encode(List.from(data.map((x) => x.toJson()))); + +class Product { + Product({ + this.id, + this.visibleIndividually, + this.name, + this.namen, + this.localizedNames, + this.shortDescription, + this.shortDescriptionn, + this.fullDescription, + this.fullDescriptionn, + this.markasNew, + this.showOnHomePage, + this.metaKeywords, + this.metaDescription, + this.metaTitle, + this.allowCustomerReviews, + this.approvedRatingSum, + this.notApprovedRatingSum, + this.approvedTotalReviews, + this.notApprovedTotalReviews, + this.sku, + this.isRx, + this.prescriptionRequired, + this.rxMessage, + this.rxMessagen, + this.manufacturerPartNumber, + this.gtin, + this.isGiftCard, + this.requireOtherProducts, + this.automaticallyAddRequiredProducts, + this.isDownload, + this.unlimitedDownloads, + this.maxNumberOfDownloads, + this.downloadExpirationDays, + this.hasSampleDownload, + this.hasUserAgreement, + this.isRecurring, + this.recurringCycleLength, + this.recurringTotalCycles, + this.isRental, + this.rentalPriceLength, + this.isShipEnabled, + this.isFreeShipping, + this.shipSeparately, + this.additionalShippingCharge, + this.isTaxExempt, + this.isTelecommunicationsOrBroadcastingOrElectronicServices, + this.useMultipleWarehouses, + this.manageInventoryMethodId, + this.stockQuantity, + this.stockAvailability, + this.stockAvailabilityn, + this.displayStockAvailability, + this.displayStockQuantity, + this.minStockQuantity, + this.notifyAdminForQuantityBelow, + this.allowBackInStockSubscriptions, + this.orderMinimumQuantity, + this.orderMaximumQuantity, + this.allowedQuantities, + this.allowAddingOnlyExistingAttributeCombinations, + this.disableBuyButton, + this.disableWishlistButton, + this.availableForPreOrder, + this.preOrderAvailabilityStartDateTimeUtc, + this.callForPrice, + this.price, + this.oldPrice, + this.productCost, + this.specialPrice, + this.specialPriceStartDateTimeUtc, + this.specialPriceEndDateTimeUtc, + this.customerEntersPrice, + this.minimumCustomerEnteredPrice, + this.maximumCustomerEnteredPrice, + this.basepriceEnabled, + this.basepriceAmount, + this.basepriceBaseAmount, + this.hasTierPrices, + this.hasDiscountsApplied, + this.discountName, + this.discountNamen, + this.discountDescription, + this.discountDescriptionn, + this.discountPercentage, + this.currency, + this.currencyn, + this.weight, + this.length, + this.width, + this.height, + this.availableStartDateTimeUtc, + this.availableEndDateTimeUtc, + this.displayOrder, + this.published, + this.deleted, + this.createdOnUtc, + this.updatedOnUtc, + this.productType, + this.parentGroupedProductId, + this.roleIds, + this.discountIds, + this.storeIds, + this.manufacturerIds, + this.reviews, + this.images, + this.attributes, + this.specifications, + this.associatedProductIds, + this.tags, + this.vendorId, + this.seName, + }); + + String id; + bool visibleIndividually; + String name; + String namen; + List localizedNames; + String shortDescription; + String shortDescriptionn; + String fullDescription; + String fullDescriptionn; + bool markasNew; + bool showOnHomePage; + String metaKeywords; + String metaDescription; + String metaTitle; + bool allowCustomerReviews; + dynamic approvedRatingSum; + dynamic notApprovedRatingSum; + dynamic approvedTotalReviews; + dynamic notApprovedTotalReviews; + String sku; + bool isRx; + bool prescriptionRequired; + dynamic rxMessage; + dynamic rxMessagen; + dynamic manufacturerPartNumber; + dynamic gtin; + bool isGiftCard; + bool requireOtherProducts; + bool automaticallyAddRequiredProducts; + bool isDownload; + bool unlimitedDownloads; + dynamic maxNumberOfDownloads; + dynamic downloadExpirationDays; + bool hasSampleDownload; + bool hasUserAgreement; + bool isRecurring; + dynamic recurringCycleLength; + dynamic recurringTotalCycles; + bool isRental; + dynamic rentalPriceLength; + bool isShipEnabled; + bool isFreeShipping; + bool shipSeparately; + dynamic additionalShippingCharge; + bool isTaxExempt; + bool isTelecommunicationsOrBroadcastingOrElectronicServices; + bool useMultipleWarehouses; + dynamic manageInventoryMethodId; + dynamic stockQuantity; + String stockAvailability; + String stockAvailabilityn; + bool displayStockAvailability; + bool displayStockQuantity; + dynamic minStockQuantity; + dynamic notifyAdminForQuantityBelow; + bool allowBackInStockSubscriptions; + dynamic orderMinimumQuantity; + dynamic orderMaximumQuantity; + dynamic allowedQuantities; + bool allowAddingOnlyExistingAttributeCombinations; + bool disableBuyButton; + bool disableWishlistButton; + bool availableForPreOrder; + dynamic preOrderAvailabilityStartDateTimeUtc; + bool callForPrice; + dynamic price; + dynamic oldPrice; + dynamic productCost; + dynamic specialPrice; + dynamic specialPriceStartDateTimeUtc; + dynamic specialPriceEndDateTimeUtc; + bool customerEntersPrice; + dynamic minimumCustomerEnteredPrice; + dynamic maximumCustomerEnteredPrice; + bool basepriceEnabled; + dynamic basepriceAmount; + dynamic basepriceBaseAmount; + bool hasTierPrices; + bool hasDiscountsApplied; + dynamic discountName; + dynamic discountNamen; + dynamic discountDescription; + dynamic discountDescriptionn; + dynamic discountPercentage; + String currency; + String currencyn; + double weight; + dynamic length; + dynamic width; + dynamic height; + dynamic availableStartDateTimeUtc; + dynamic availableEndDateTimeUtc; + dynamic displayOrder; + bool published; + bool deleted; + DateTime createdOnUtc; + DateTime updatedOnUtc; + String productType; + dynamic parentGroupedProductId; + List roleIds; + List discountIds; + List storeIds; + List manufacturerIds; + List reviews; + List images; + List attributes; + List specifications; + List associatedProductIds; + List tags; + dynamic vendorId; + String seName; + + factory Product.fromJson(Map json) => Product( + id: json["id"], + visibleIndividually: json["visible_individually"], + name: json["name"], + namen: json["namen"], + localizedNames: List.from(json["localized_names"].map((x) => LocalizedName.fromJson(x))), + shortDescription: json["short_description"], + shortDescriptionn: json["short_descriptionn"], + fullDescription: json["full_description"], + fullDescriptionn: json["full_descriptionn"], + markasNew: json["markas_new"], + showOnHomePage: json["show_on_home_page"], + metaKeywords: json["meta_keywords"], + metaDescription: json["meta_description"], + metaTitle: json["meta_title"], + allowCustomerReviews: json["allow_customer_reviews"], + approvedRatingSum: json["approved_rating_sum"], + notApprovedRatingSum: json["not_approved_rating_sum"], + approvedTotalReviews: json["approved_total_reviews"], + notApprovedTotalReviews: json["not_approved_total_reviews"], + sku: json["sku"], + isRx: json["is_rx"], + prescriptionRequired: json["prescription_required"], + rxMessage: json["rx_message"], + rxMessagen: json["rx_messagen"], + manufacturerPartNumber: json["manufacturer_part_number"], + gtin: json["gtin"], + isGiftCard: json["is_gift_card"], + requireOtherProducts: json["require_other_products"], + automaticallyAddRequiredProducts: json["automatically_add_required_products"], + isDownload: json["is_download"], + unlimitedDownloads: json["unlimited_downloads"], + maxNumberOfDownloads: json["max_number_of_downloads"], + downloadExpirationDays: json["download_expiration_days"], + hasSampleDownload: json["has_sample_download"], + hasUserAgreement: json["has_user_agreement"], + isRecurring: json["is_recurring"], + recurringCycleLength: json["recurring_cycle_length"], + recurringTotalCycles: json["recurring_total_cycles"], + isRental: json["is_rental"], + rentalPriceLength: json["rental_price_length"], + isShipEnabled: json["is_ship_enabled"], + isFreeShipping: json["is_free_shipping"], + shipSeparately: json["ship_separately"], + additionalShippingCharge: json["additional_shipping_charge"], + isTaxExempt: json["is_tax_exempt"], + isTelecommunicationsOrBroadcastingOrElectronicServices: json["is_telecommunications_or_broadcasting_or_electronic_services"], + useMultipleWarehouses: json["use_multiple_warehouses"], + manageInventoryMethodId: json["manage_inventory_method_id"], + stockQuantity: json["stock_quantity"], + stockAvailability: json["stock_availability"], + stockAvailabilityn: json["stock_availabilityn"], + displayStockAvailability: json["display_stock_availability"], + displayStockQuantity: json["display_stock_quantity"], + minStockQuantity: json["min_stock_quantity"], + notifyAdminForQuantityBelow: json["notify_admin_for_quantity_below"], + allowBackInStockSubscriptions: json["allow_back_in_stock_subscriptions"], + orderMinimumQuantity: json["order_minimum_quantity"], + orderMaximumQuantity: json["order_maximum_quantity"], + allowedQuantities: json["allowed_quantities"], + allowAddingOnlyExistingAttributeCombinations: json["allow_adding_only_existing_attribute_combinations"], + disableBuyButton: json["disable_buy_button"], + disableWishlistButton: json["disable_wishlist_button"], + availableForPreOrder: json["available_for_pre_order"], + preOrderAvailabilityStartDateTimeUtc: json["pre_order_availability_start_date_time_utc"], + callForPrice: json["call_for_price"], + price: json["price"], + oldPrice: json["old_price"], + productCost: json["product_cost"], + specialPrice: json["special_price"], + specialPriceStartDateTimeUtc: json["special_price_start_date_time_utc"], + specialPriceEndDateTimeUtc: json["special_price_end_date_time_utc"], + customerEntersPrice: json["customer_enters_price"], + minimumCustomerEnteredPrice: json["minimum_customer_entered_price"], + maximumCustomerEnteredPrice: json["maximum_customer_entered_price"], + basepriceEnabled: json["baseprice_enabled"], + basepriceAmount: json["baseprice_amount"], + basepriceBaseAmount: json["baseprice_base_amount"], + hasTierPrices: json["has_tier_prices"], + hasDiscountsApplied: json["has_discounts_applied"], + discountName: json["discount_name"], + discountNamen: json["discount_namen"], + discountDescription: json["discount_description"], + discountDescriptionn: json["discount_Descriptionn"], + discountPercentage: json["discount_percentage"], + currency: json["currency"], + currencyn: json["currencyn"], + weight: json["weight"].toDouble(), + length: json["length"], + width: json["width"], + height: json["height"], + availableStartDateTimeUtc: json["available_start_date_time_utc"], + availableEndDateTimeUtc: json["available_end_date_time_utc"], + displayOrder: json["display_order"], + published: json["published"], + deleted: json["deleted"], + createdOnUtc: DateTime.parse(json["created_on_utc"]), + updatedOnUtc: DateTime.parse(json["updated_on_utc"]), + productType: json["product_type"], + parentGroupedProductId: json["parent_grouped_product_id"], + roleIds: List.from(json["role_ids"].map((x) => x)), + discountIds: List.from(json["discount_ids"].map((x) => x)), + storeIds: List.from(json["store_ids"].map((x) => x)), + manufacturerIds: List.from(json["manufacturer_ids"].map((x) => x)), + reviews: List.from(json["reviews"].map((x) => Review.fromJson(x))), + images: List.from(json["images"].map((x) => Image.fromJson(x))), + attributes: List.from(json["attributes"].map((x) => x)), + specifications: List.from(json["specifications"].map((x) => Specification.fromJson(x))), + associatedProductIds: List.from(json["associated_product_ids"].map((x) => x)), + tags: List.from(json["tags"].map((x) => x)), + vendorId: json["vendor_id"], + seName: json["se_name"], + ); + + Map toJson() => { + "id": id, + "visible_individually": visibleIndividually, + "name": name, + "namen": namen, + "localized_names": List.from(localizedNames.map((x) => x.toJson())), + "short_description": shortDescription, + "short_descriptionn": shortDescriptionn, + "full_description": fullDescription, + "full_descriptionn": fullDescriptionn, + "markas_new": markasNew, + "show_on_home_page": showOnHomePage, + "meta_keywords": metaKeywords, + "meta_description": metaDescription, + "meta_title": metaTitle, + "allow_customer_reviews": allowCustomerReviews, + "approved_rating_sum": approvedRatingSum, + "not_approved_rating_sum": notApprovedRatingSum, + "approved_total_reviews": approvedTotalReviews, + "not_approved_total_reviews": notApprovedTotalReviews, + "sku": sku, + "is_rx": isRx, + "prescription_required": prescriptionRequired, + "rx_message": rxMessage, + "rx_messagen": rxMessagen, + "manufacturer_part_number": manufacturerPartNumber, + "gtin": gtin, + "is_gift_card": isGiftCard, + "require_other_products": requireOtherProducts, + "automatically_add_required_products": automaticallyAddRequiredProducts, + "is_download": isDownload, + "unlimited_downloads": unlimitedDownloads, + "max_number_of_downloads": maxNumberOfDownloads, + "download_expiration_days": downloadExpirationDays, + "has_sample_download": hasSampleDownload, + "has_user_agreement": hasUserAgreement, + "is_recurring": isRecurring, + "recurring_cycle_length": recurringCycleLength, + "recurring_total_cycles": recurringTotalCycles, + "is_rental": isRental, + "rental_price_length": rentalPriceLength, + "is_ship_enabled": isShipEnabled, + "is_free_shipping": isFreeShipping, + "ship_separately": shipSeparately, + "additional_shipping_charge": additionalShippingCharge, + "is_tax_exempt": isTaxExempt, + "is_telecommunications_or_broadcasting_or_electronic_services": isTelecommunicationsOrBroadcastingOrElectronicServices, + "use_multiple_warehouses": useMultipleWarehouses, + "manage_inventory_method_id": manageInventoryMethodId, + "stock_quantity": stockQuantity, + "stock_availability": stockAvailability, + "stock_availabilityn": stockAvailabilityn, + "display_stock_availability": displayStockAvailability, + "display_stock_quantity": displayStockQuantity, + "min_stock_quantity": minStockQuantity, + "notify_admin_for_quantity_below": notifyAdminForQuantityBelow, + "allow_back_in_stock_subscriptions": allowBackInStockSubscriptions, + "order_minimum_quantity": orderMinimumQuantity, + "order_maximum_quantity": orderMaximumQuantity, + "allowed_quantities": allowedQuantities, + "allow_adding_only_existing_attribute_combinations": allowAddingOnlyExistingAttributeCombinations, + "disable_buy_button": disableBuyButton, + "disable_wishlist_button": disableWishlistButton, + "available_for_pre_order": availableForPreOrder, + "pre_order_availability_start_date_time_utc": preOrderAvailabilityStartDateTimeUtc, + "call_for_price": callForPrice, + "price": price, + "old_price": oldPrice, + "product_cost": productCost, + "special_price": specialPrice, + "special_price_start_date_time_utc": specialPriceStartDateTimeUtc, + "special_price_end_date_time_utc": specialPriceEndDateTimeUtc, + "customer_enters_price": customerEntersPrice, + "minimum_customer_entered_price": minimumCustomerEnteredPrice, + "maximum_customer_entered_price": maximumCustomerEnteredPrice, + "baseprice_enabled": basepriceEnabled, + "baseprice_amount": basepriceAmount, + "baseprice_base_amount": basepriceBaseAmount, + "has_tier_prices": hasTierPrices, + "has_discounts_applied": hasDiscountsApplied, + "discount_name": discountName, + "discount_namen": discountNamen, + "discount_description": discountDescription, + "discount_Descriptionn": discountDescriptionn, + "discount_percentage": discountPercentage, + "currency": currency, + "currencyn": currencyn, + "weight": weight, + "length": length, + "width": width, + "height": height, + "available_start_date_time_utc": availableStartDateTimeUtc, + "available_end_date_time_utc": availableEndDateTimeUtc, + "display_order": displayOrder, + "published": published, + "deleted": deleted, + "created_on_utc": createdOnUtc.toIso8601String(), + "updated_on_utc": updatedOnUtc.toIso8601String(), + "product_type": productType, + "parent_grouped_product_id": parentGroupedProductId, + "role_ids": List.from(roleIds.map((x) => x)), + "discount_ids": List.from(discountIds.map((x) => x)), + "store_ids": List.from(storeIds.map((x) => x)), + "manufacturer_ids": List.from(manufacturerIds.map((x) => x)), + "reviews": List.from(reviews.map((x) => x.toJson())), + "images": List.from(images.map((x) => x.toJson())), + "attributes": List.from(attributes.map((x) => x)), + "specifications": List.from(specifications.map((x) => x.toJson())), + "associated_product_ids": List.from(associatedProductIds.map((x) => x)), + "tags": List.from(tags.map((x) => x)), + "vendor_id": vendorId, + "se_name": seName, + }; +} + +class Review { + Review({ + this.id, + this.position, + this.reviewId, + this.customerId, + this.productId, + this.storeId, + this.isApproved, + this.title, + this.reviewText, + this.replyText, + this.rating, + this.helpfulYesTotal, + this.helpfulNoTotal, + this.createdOnUtc, + this.customer, + this.product, + }); + + dynamic id; + dynamic position; + dynamic reviewId; + dynamic customerId; + dynamic productId; + dynamic storeId; + bool isApproved; + String title; + ReviewText reviewText; + dynamic replyText; + dynamic rating; + dynamic helpfulYesTotal; + dynamic helpfulNoTotal; + DateTime createdOnUtc; + Customer customer; + Product product; + + factory Review.fromJson(Map json) => Review( + id: json["id"], + position: json["position"], + reviewId: json["review_id"], + customerId: json["customer_id"], + productId: json["product_id"], + storeId: json["store_id"], + isApproved: json["is_approved"], + title: json["title"], + reviewText: reviewTextValues.map[json["review_text"]], + replyText: json["reply_text"], + rating: json["rating"], + helpfulYesTotal: json["helpful_yes_total"], + helpfulNoTotal: json["helpful_no_total"], + createdOnUtc: DateTime.parse(json["created_on_utc"]), + customer: Customer.fromJson(json["customer"]), + product: json["product"] == null ? null : Product.fromJson(json["product"]), + ); + + Map toJson() => { + "id": id, + "position": position, + "review_id": reviewId, + "customer_id": customerId, + "product_id": productId, + "store_id": storeId, + "is_approved": isApproved, + "title": title, + "review_text": reviewText, + "reply_text": replyText, + "rating": rating, + "helpful_yes_total": helpfulYesTotal, + "helpful_no_total": helpfulNoTotal, + "created_on_utc": createdOnUtc.toIso8601String(), + "customer": customer.toJson(), + "product": product == null ? null : product.toJson(), + }; +} + +class Image { + Image({ + this.id, + this.position, + this.src, + this.thumb, + this.attachment, + }); + + dynamic id; + dynamic position; + String src; + String thumb; + String attachment; + + factory Image.fromJson(Map json) => Image( + id: json["id"], + position: json["position"], + src: json["src"], + thumb: json["thumb"], + attachment: json["attachment"], + ); + + Map toJson() => { + "id": id, + "position": position, + "src": src, + "thumb": thumb, + "attachment": attachment, + }; +} + +class LocalizedName { + LocalizedName({ + this.languageId, + this.localizedName, + }); + + dynamic languageId; + String localizedName; + + factory LocalizedName.fromJson(Map json) => LocalizedName( + languageId: json["language_id"], + localizedName: json["localized_name"], + ); + + Map toJson() => { + "language_id": languageId, + "localized_name": localizedName, + }; +} + +class Specification { + Specification({ + this.id, + this.displayOrder, + this.defaultValue, + this.defaultValuen, + this.name, + this.nameN, + }); + + dynamic id; + dynamic displayOrder; + String defaultValue; + String defaultValuen; + String name; + String nameN; + + factory Specification.fromJson(Map json) => Specification( + id: json["id"], + displayOrder: json["display_order"], + defaultValue: json["default_value"], + defaultValuen: json["default_valuen"], + name: json["name"], + nameN: json["nameN"], + ); + + Map toJson() => { + "id": id, + "display_order": displayOrder, + "default_value": defaultValue, + "default_valuen": defaultValuen, + "name": name, + "nameN": nameN, + }; +} + +class Customer { + Customer({ + this.fileNumber, + this.iqamaNumber, + this.isOutSa, + this.patientType, + this.gender, + this.birthDate, + this.phone, + this.countryCode, + this.yahalaAccountno, + this.billingAddress, + this.shippingAddress, + this.addresses, + this.id, + this.username, + this.email, + this.firstName, + this.lastName, + this.languageId, + this.adminComment, + this.isTaxExempt, + this.hasShoppingCartItems, + this.active, + this.deleted, + this.isSystemAccount, + this.systemName, + this.lastIpAddress, + this.createdOnUtc, + this.lastLoginDateUtc, + this.lastActivityDateUtc, + this.registeredInStoreId, + this.roleIds, + }); + + dynamic fileNumber; + dynamic iqamaNumber; + dynamic isOutSa; + dynamic patientType; + dynamic gender; + DateTime birthDate; + dynamic phone; + dynamic countryCode; + dynamic yahalaAccountno; + dynamic billingAddress; + dynamic shippingAddress; + List addresses; + String id; + Username username; + Email email; + dynamic firstName; + dynamic lastName; + dynamic languageId; + dynamic adminComment; + dynamic isTaxExempt; + dynamic hasShoppingCartItems; + dynamic active; + dynamic deleted; + dynamic isSystemAccount; + dynamic systemName; + dynamic lastIpAddress; + dynamic createdOnUtc; + dynamic lastLoginDateUtc; + dynamic lastActivityDateUtc; + dynamic registeredInStoreId; + List roleIds; + + factory Customer.fromJson(Map json) => Customer( + fileNumber: json["file_number"], + iqamaNumber: json["iqama_number"], + isOutSa: json["is_out_sa"], + patientType: json["patient_type"], + gender: json["gender"], + birthDate: DateTime.parse(json["birth_date"]), + phone: json["phone"], + countryCode: json["country_code"], + yahalaAccountno: json["yahala_accountno"], + billingAddress: json["billing_address"], + shippingAddress: json["shipping_address"], + addresses: List.from(json["addresses"].map((x) => x)), + id: json["id"], + username: usernameValues.map[json["username"]], + email: emailValues.map[json["email"]], + firstName: json["first_name"], + lastName: json["last_name"], + languageId: json["language_id"], + adminComment: json["admin_comment"], + isTaxExempt: json["is_tax_exempt"], + hasShoppingCartItems: json["has_shopping_cart_items"], + active: json["active"], + deleted: json["deleted"], + isSystemAccount: json["is_system_account"], + systemName: json["system_name"], + lastIpAddress: json["last_ip_address"], + createdOnUtc: json["created_on_utc"], + lastLoginDateUtc: json["last_login_date_utc"], + lastActivityDateUtc: json["last_activity_date_utc"], + registeredInStoreId: json["registered_in_store_id"], + roleIds: List.from(json["role_ids"].map((x) => x)), + ); + + Map toJson() => { + "file_number": fileNumber, + "iqama_number": iqamaNumber, + "is_out_sa": isOutSa, + "patient_type": patientType, + "gender": gender, + "birth_date": birthDate.toIso8601String(), + "phone": phone, + "country_code": countryCode, + "yahala_accountno": yahalaAccountno, + "billing_address": billingAddress, + "shipping_address": shippingAddress, + "addresses": List.from(addresses.map((x) => x)), + "id": id, + "username": usernameValues.reverse[username], + "email": emailValues.reverse[email], + "first_name": firstName, + "last_name": lastName, + "language_id": languageId, + "admin_comment": adminComment, + "is_tax_exempt": isTaxExempt, + "has_shopping_cart_items": hasShoppingCartItems, + "active": active, + "deleted": deleted, + "is_system_account": isSystemAccount, + "system_name": systemName, + "last_ip_address": lastIpAddress, + "created_on_utc": createdOnUtc, + "last_login_date_utc": lastLoginDateUtc, + "last_activity_date_utc": lastActivityDateUtc, + "registered_in_store_id": registeredInStoreId, + "role_ids": List.from(roleIds.map((x) => x)), + }; +} + +enum Email { TAMER_FANASHEH_DRSULAIMANALHABIB_COM, STEVE_GATES_NOP_COMMERCE_COM } + +final emailValues = EnumValues({ + "steve_gates@nopCommerce.com": Email.STEVE_GATES_NOP_COMMERCE_COM, + "tamer.fanasheh@drsulaimanalhabib.com": Email.TAMER_FANASHEH_DRSULAIMANALHABIB_COM +}); + +enum Username { TAMERF, STEVE_GATES_NOP_COMMERCE_COM } + +final usernameValues = EnumValues({ + "steve_gates@nopCommerce.com": Username.STEVE_GATES_NOP_COMMERCE_COM, + "tamerf": Username.TAMERF +}); + +enum ReviewText { ENADDD, ENAD_TEST_0001, GOOD, ENAD_TEST_REVIEW_001, ENAD } + +final reviewTextValues = EnumValues({ + "ENAD ": ReviewText.ENAD, + "enaddd": ReviewText.ENADDD, + "ENAD TEST 0001": ReviewText.ENAD_TEST_0001, + "Enad Test Review 001": ReviewText.ENAD_TEST_REVIEW_001, + "good": ReviewText.GOOD +}); + +class EnumValues { + Map map; + Map reverseMap; + + EnumValues(this.map); + + Map get reverse { + if (reverseMap == null) { + reverseMap = map.map((k, v) => new MapEntry(v, k)); + } + return reverseMap; + } +} diff --git a/lib/models/pharmacy/specification.dart b/lib/models/pharmacy/specification.dart new file mode 100644 index 00000000..6ef69191 --- /dev/null +++ b/lib/models/pharmacy/specification.dart @@ -0,0 +1,61 @@ +// To parse this JSON data, do +// +// final specificationModel = specificationModelFromJson(jsonString); + +import 'dart:convert'; + +SpecificationModel specificationModelFromJson(String str) => SpecificationModel.fromJson(json.decode(str)); + +String specificationModelToJson(SpecificationModel data) => json.encode(data.toJson()); + +class SpecificationModel { + SpecificationModel({ + this.specification, + }); + + List specification; + + factory SpecificationModel.fromJson(Map json) => SpecificationModel( + specification: List.from(json["specification"].map((x) => Specification.fromJson(x))), + ); + + Map toJson() => { + "specification": List.from(specification.map((x) => x.toJson())), + }; +} + +class Specification { + Specification({ + this.id, + this.displayOrder, + this.defaultValue, + this.defaultValuen, + this.name, + this.nameN, + }); + + int id; + int displayOrder; + String defaultValue; + String defaultValuen; + String name; + String nameN; + + factory Specification.fromJson(Map json) => Specification( + id: json["id"], + displayOrder: json["display_order"], + defaultValue: json["default_value"], + defaultValuen: json["default_valuen"], + name: json["name"], + nameN: json["nameN"], + ); + + Map toJson() => { + "id": id, + "display_order": displayOrder, + "default_value": defaultValue, + "default_valuen": defaultValuen, + "name": name, + "nameN": nameN, + }; +} diff --git a/lib/models/pharmacy/topBrandsModel.dart b/lib/models/pharmacy/topBrandsModel.dart new file mode 100644 index 00000000..0cd833b7 --- /dev/null +++ b/lib/models/pharmacy/topBrandsModel.dart @@ -0,0 +1,137 @@ +// To parse this JSON data, do +// +// final topBrand = topBrandFromJson(jsonString); + +import 'dart:convert'; + +List topBrandFromJson(String str) => List.from(json.decode(str).map((x) => TopBrand.fromJson(x))); + +String topBrandToJson(List data) => json.encode(List.from(data.map((x) => x.toJson()))); + +class TopBrand { + TopBrand({ + this.id, + this.name, + this.namen, + this.localizedNames, + this.description, + this.manufacturerTemplateId, + this.metaKeywords, + this.metaDescription, + this.metaTitle, + this.pageSize, + this.pageSizeOptions, + this.priceRanges, + this.published, + this.deleted, + this.displayOrder, + this.createdOnUtc, + this.updatedOnUtc, + this.image, + }); + + String id; + String name; + String namen; + List localizedNames; + String description; + int manufacturerTemplateId; + String metaKeywords; + dynamic metaDescription; + dynamic metaTitle; + int pageSize; + String pageSizeOptions; + dynamic priceRanges; + bool published; + bool deleted; + int displayOrder; + DateTime createdOnUtc; + DateTime updatedOnUtc; + Image image; + + factory TopBrand.fromJson(Map json) => TopBrand( + id: json["id"], + name: json["name"], + namen: json["namen"], + localizedNames: List.from(json["localized_names"].map((x) => LocalizedName.fromJson(x))), + description: json["description"] == null ? null : json["description"], + manufacturerTemplateId: json["manufacturer_template_id"], + metaKeywords: json["meta_keywords"], + metaDescription: json["meta_description"], + metaTitle: json["meta_title"], + pageSize: json["page_size"], + pageSizeOptions: json["page_size_options"], + priceRanges: json["price_ranges"], + published: json["published"], + deleted: json["deleted"], + displayOrder: json["display_order"], + createdOnUtc: DateTime.parse(json["created_on_utc"]), + updatedOnUtc: DateTime.parse(json["updated_on_utc"]), + image: json["image"] == null ? null : Image.fromJson(json["image"]), + ); + + Map toJson() => { + "id": id, + "name": name, + "namen": namen, + "localized_names": List.from(localizedNames.map((x) => x.toJson())), + "description": description == null ? null : description, + "manufacturer_template_id": manufacturerTemplateId, + "meta_keywords": metaKeywords, + "meta_description": metaDescription, + "meta_title": metaTitle, + "page_size": pageSize, + "page_size_options": pageSizeOptions, + "price_ranges": priceRanges, + "published": published, + "deleted": deleted, + "display_order": displayOrder, + "created_on_utc": createdOnUtc.toIso8601String(), + "updated_on_utc": updatedOnUtc.toIso8601String(), + "image": image == null ? null : image.toJson(), + }; +} + +class Image { + Image({ + this.src, + this.thumb, + this.attachment, + }); + + String src; + dynamic thumb; + dynamic attachment; + + factory Image.fromJson(Map json) => Image( + src: json["src"], + thumb: json["thumb"], + attachment: json["attachment"], + ); + + Map toJson() => { + "src": src, + "thumb": thumb, + "attachment": attachment, + }; +} + +class LocalizedName { + LocalizedName({ + this.languageId, + this.localizedName, + }); + + int languageId; + String localizedName; + + factory LocalizedName.fromJson(Map json) => LocalizedName( + languageId: json["language_id"], + localizedName: json["localized_name"], + ); + + Map toJson() => { + "language_id": languageId, + "localized_name": localizedName, + }; +} diff --git a/lib/pages/AlHabibMedicalService/ComprehensiveMedicalCheckup/NewCMC/cmc_location_page.dart b/lib/pages/AlHabibMedicalService/ComprehensiveMedicalCheckup/NewCMC/cmc_location_page.dart index c584a21e..4e396427 100644 --- a/lib/pages/AlHabibMedicalService/ComprehensiveMedicalCheckup/NewCMC/cmc_location_page.dart +++ b/lib/pages/AlHabibMedicalService/ComprehensiveMedicalCheckup/NewCMC/cmc_location_page.dart @@ -50,99 +50,99 @@ class _CMCLocationPageState return BaseView( onModelReady: (model) {}, builder: (_, model, widget) => AppScaffold( - isShowDecPage: false, - isShowAppBar: true, - baseViewModel: model, - body: PlacePicker( - apiKey: GOOGLE_API_KEY, - enableMyLocationButton: true, - automaticallyImplyAppBarLeading: false, - autocompleteOnTrailingWhitespace: true, - selectInitialPosition: true, - autocompleteLanguage: projectViewModel.currentLanguage, - enableMapTypeButton: true, - searchForInitialValue: false, - onPlacePicked: (PickResult result) { - print(result.adrAddress); + isShowDecPage: false, + isShowAppBar: true, + baseViewModel: model, + body: PlacePicker( + apiKey: GOOGLE_API_KEY, + enableMyLocationButton: true, + automaticallyImplyAppBarLeading: false, + autocompleteOnTrailingWhitespace: true, + selectInitialPosition: true, + autocompleteLanguage: projectViewModel.currentLanguage, + enableMapTypeButton: true, + searchForInitialValue: false, + onPlacePicked: (PickResult result) { + print(result.adrAddress); - }, - selectedPlaceWidgetBuilder: - (_, selectedPlace, state, isSearchBarFocused) { - print("state: $state, isSearchBarFocused: $isSearchBarFocused"); - return isSearchBarFocused - ? Container() - : FloatingCard( - bottomPosition: 0.0, - leftPosition: 0.0, - rightPosition: 0.0, - width: 500, - borderRadius: BorderRadius.circular(12.0), - child: state == SearchingState.Searching - ? Center(child: CircularProgressIndicator()) - : Container( - margin: EdgeInsets.all(12), - child: Column( - children: [ - SecondaryButton( - color: Colors.grey[800], - textColor: Colors.white, - onTap: () async { - print(selectedPlace); - AddNewAddressRequestModel - addNewAddressRequestModel = - new AddNewAddressRequestModel( - customer: Customer(addresses: [ - Addresses( - address1: - selectedPlace.formattedAddress, - address2: selectedPlace - .formattedAddress, - customerAttributes: "", - city: "", - createdOnUtc: "", - id: 0, - latLong: "$latitude,$longitude", - email: "") - ]), - ); + }, + selectedPlaceWidgetBuilder: + (_, selectedPlace, state, isSearchBarFocused) { + print("state: $state, isSearchBarFocused: $isSearchBarFocused"); + return isSearchBarFocused + ? Container() + : FloatingCard( + bottomPosition: 0.0, + leftPosition: 0.0, + rightPosition: 0.0, + width: 500, + borderRadius: BorderRadius.circular(12.0), + child: state == SearchingState.Searching + ? Center(child: CircularProgressIndicator()) + : Container( + margin: EdgeInsets.all(12), + child: Column( + children: [ + SecondaryButton( + color: Colors.grey[800], + textColor: Colors.white, + onTap: () async { + print(selectedPlace); + AddNewAddressRequestModel + addNewAddressRequestModel = + new AddNewAddressRequestModel( + customer: Customer(addresses: [ + Addresses( + address1: + selectedPlace.formattedAddress, + address2: selectedPlace + .formattedAddress, + customerAttributes: "", + city: "", + createdOnUtc: "", + id: 0, + latLong: "$latitude,$longitude", + email: "") + ]), + ); - selectedPlace.addressComponents.forEach((e) { - if (e.types.contains("country")) { - addNewAddressRequestModel.customer - .addresses[0].country = e.longName; - } - if (e.types.contains("postal_code")) { - addNewAddressRequestModel.customer - .addresses[0].zipPostalCode = - e.longName; - } - if (e.types.contains("locality")) { - addNewAddressRequestModel.customer - .addresses[0].city = - e.longName; - } - }); + selectedPlace.addressComponents.forEach((e) { + if (e.types.contains("country")) { + addNewAddressRequestModel.customer + .addresses[0].country = e.longName; + } + if (e.types.contains("postal_code")) { + addNewAddressRequestModel.customer + .addresses[0].zipPostalCode = + e.longName; + } + if (e.types.contains("locality")) { + addNewAddressRequestModel.customer + .addresses[0].city = + e.longName; + } + }); - await model.addAddressInfo( - addNewAddressRequestModel: addNewAddressRequestModel); - if (model.state == ViewState.ErrorLocal) { - Utils.showErrorToast(model.error); - } else { - AppToast.showSuccessToast( - message: "Address Added Successfully"); - } - Navigator.of(context).pop(); - }, - label: TranslationBase.of(context).addNewAddress, - ), - ], - ), + await model.addAddressInfo( + addNewAddressRequestModel: addNewAddressRequestModel); + if (model.state == ViewState.ErrorLocal) { + Utils.showErrorToast(model.error); + } else { + AppToast.showSuccessToast( + message: "Address Added Successfully"); + } + Navigator.of(context).pop(); + }, + label: TranslationBase.of(context).addNewAddress, + ), + ], ), - ); - }, - initialPosition: LatLng(latitude, longitude), - useCurrentLocation: false, - ), - )); + ), + ); + }, + initialPosition: LatLng(latitude, longitude), + useCurrentLocation: false, + ), + )); } } diff --git a/lib/pages/AlHabibMedicalService/ComprehensiveMedicalCheckup/NewCMC/new_cmc_page.dart b/lib/pages/AlHabibMedicalService/ComprehensiveMedicalCheckup/NewCMC/new_cmc_page.dart index ecfe31fb..2a7696b7 100644 --- a/lib/pages/AlHabibMedicalService/ComprehensiveMedicalCheckup/NewCMC/new_cmc_page.dart +++ b/lib/pages/AlHabibMedicalService/ComprehensiveMedicalCheckup/NewCMC/new_cmc_page.dart @@ -119,13 +119,16 @@ class _NewCMCPageState extends State height: MediaQuery.of(context).size.height * 0.8, child: Column( children: [ - Container( - margin: EdgeInsets.only(left: MediaQuery.of(context).size.width*0.05, right: MediaQuery.of(context).size.width*0.05), - child: StepsWidget( - index: _currentIndex, - changeCurrentTab: changePageViewIndex, + if (widget.model.cmcAllOrderDetail.length == 0) + Container( + margin: EdgeInsets.only( + left: MediaQuery.of(context).size.width * 0.05, + right: MediaQuery.of(context).size.width * 0.05), + child: StepsWidget( + index: _currentIndex, + changeCurrentTab: changePageViewIndex, + ), ), - ), Expanded( child: PageView( physics: NeverScrollableScrollPhysics(), diff --git a/lib/pages/AlHabibMedicalService/ComprehensiveMedicalCheckup/cmc_page.dart b/lib/pages/AlHabibMedicalService/ComprehensiveMedicalCheckup/cmc_page.dart index 06a83cc1..b745e0c9 100644 --- a/lib/pages/AlHabibMedicalService/ComprehensiveMedicalCheckup/cmc_page.dart +++ b/lib/pages/AlHabibMedicalService/ComprehensiveMedicalCheckup/cmc_page.dart @@ -1,5 +1,6 @@ import 'dart:ui'; +import 'package:diplomaticquarterapp/core/model/ImagesInfo.dart'; import 'package:diplomaticquarterapp/core/viewModels/AlHabibMedicalService/cmc_view_model.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; @@ -35,12 +36,14 @@ class _CMCPageState extends State @override Widget build(BuildContext context) { return BaseView( - onModelReady: (model){ - model.getCmcAllPresOrders(); + onModelReady: (model) async{ + await model.getCmcAllPresOrders(); + }, builder: (_, model, widget) => AppScaffold( isShowAppBar: true, - description: TranslationBase.of(context).HHCNotAuthMsg, + description:TranslationBase.of(context).infoCMC, + imagesInfo: [ImagesInfo(imageAr: 'assets/images/AlHabibMedicalService/Wifi-AR.png',imageEn: 'assets/images/AlHabibMedicalService/Wifi-EN.png', isAsset: true)], appBarTitle: TranslationBase.of(context).comprehensiveMedicalCheckup, body: Scaffold( extendBodyBehindAppBar: true, @@ -79,7 +82,7 @@ class _CMCPageState extends State isScrollable: true, controller: _tabController, indicatorWeight: 5.0, - indicatorSize: TabBarIndicatorSize.label, + indicatorSize: TabBarIndicatorSize.tab, indicatorColor: Colors.red[800], labelColor: Theme.of(context).primaryColor, labelPadding: diff --git a/lib/pages/AlHabibMedicalService/E-Referral/New_E_Referral/new_e_referral_index_page.dart b/lib/pages/AlHabibMedicalService/E-Referral/New_E_Referral/new_e_referral_index_page.dart index 2cb179b8..fb2b94c6 100644 --- a/lib/pages/AlHabibMedicalService/E-Referral/New_E_Referral/new_e_referral_index_page.dart +++ b/lib/pages/AlHabibMedicalService/E-Referral/New_E_Referral/new_e_referral_index_page.dart @@ -40,32 +40,34 @@ class _StartIndexForNewEReferralState extends State @override Widget build(BuildContext context) { return Scaffold( - body: SingleChildScrollView( - child: Container( - height: MediaQuery.of(context).size.height * 0.9, - child: PageView( - physics: NeverScrollableScrollPhysics(), - controller: _controller, - onPageChanged: (index) { - setState(() { - _currentIndex = index; - }); - }, - scrollDirection: Axis.horizontal, - children: [ - NewEReferralStepOnePage( - changePageViewIndex: changePageViewIndex, - createEReferralRequestModel: createEReferralRequestModel, - ), - NewEReferralStepTowPage( - changePageViewIndex: changePageViewIndex, - createEReferralRequestModel: createEReferralRequestModel, - ), - NewEReferralStepThreePage( - changePageViewIndex: changePageViewIndex, - createEReferralRequestModel: createEReferralRequestModel, - ), - ], + body: SafeArea( + child: SingleChildScrollView( + child: Container( + height: MediaQuery.of(context).size.height * 0.9, + child: PageView( + physics: NeverScrollableScrollPhysics(), + controller: _controller, + onPageChanged: (index) { + setState(() { + _currentIndex = index; + }); + }, + scrollDirection: Axis.horizontal, + children: [ + NewEReferralStepOnePage( + changePageViewIndex: changePageViewIndex, + createEReferralRequestModel: createEReferralRequestModel, + ), + NewEReferralStepTowPage( + changePageViewIndex: changePageViewIndex, + createEReferralRequestModel: createEReferralRequestModel, + ), + NewEReferralStepThreePage( + changePageViewIndex: changePageViewIndex, + createEReferralRequestModel: createEReferralRequestModel, + ), + ], + ), ), ), ), diff --git a/lib/pages/AlHabibMedicalService/E-Referral/New_E_Referral/new_e_referral_step_one_page.dart b/lib/pages/AlHabibMedicalService/E-Referral/New_E_Referral/new_e_referral_step_one_page.dart index e486d9aa..62799c6d 100644 --- a/lib/pages/AlHabibMedicalService/E-Referral/New_E_Referral/new_e_referral_step_one_page.dart +++ b/lib/pages/AlHabibMedicalService/E-Referral/New_E_Referral/new_e_referral_step_one_page.dart @@ -6,9 +6,9 @@ import 'package:diplomaticquarterapp/core/model/my_balance/AdvanceModel.dart'; import 'package:diplomaticquarterapp/core/viewModels/all_habib_medical_services/e_referral_view_model.dart'; import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; import 'package:diplomaticquarterapp/models/FamilyFiles/GetAllSharedRecordByStatusResponse.dart'; +import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/E-Referral/e_referral_confirm_sms_dialog.dart'; import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/E-Referral/dialogs/select_country_ingo_Dialog.dart'; import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/E-Referral/dialogs/select_relation_type_dialog.dart'; -import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/E-Referral/e_referral_confirm_sms_dialog.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; import 'package:diplomaticquarterapp/pages/medical/balance/new_text_Field.dart'; import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; @@ -19,17 +19,15 @@ import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; + class NewEReferralStepOnePage extends StatefulWidget { final CreateEReferralRequestModel createEReferralRequestModel; final Function changePageViewIndex; - const NewEReferralStepOnePage( - {Key key, this.createEReferralRequestModel, this.changePageViewIndex}) - : super(key: key); + const NewEReferralStepOnePage({Key key, this.createEReferralRequestModel, this.changePageViewIndex}) : super(key: key); @override - _NewEReferralStepOnePageState createState() => - _NewEReferralStepOnePageState(); + _NewEReferralStepOnePageState createState() => _NewEReferralStepOnePageState(); } class _NewEReferralStepOnePageState extends State { @@ -66,25 +64,27 @@ class _NewEReferralStepOnePageState extends State { context: context, barrierDismissible: false, child: EReferralConfirmSMSDialog( - phoneNumber: _selectedCountry['code'] + _mobileTextController.text, - onSucces: () { - Navigator.of(context).pop(); - widget.changePageViewIndex(1); - widget.createEReferralRequestModel.requesterName = - _nameTextController.text; - widget.createEReferralRequestModel.requesterContactNo = - _selectedCountry['code'].toString().substring(1) + - _mobileTextController.text; - widget.createEReferralRequestModel.requesterRelationship = - _selectedRelation.iD; - }), + phoneNumber: _selectedCountry['code']+_mobileTextController.text, + onSucces: (){ + Navigator.of(context).pop(); + widget.changePageViewIndex(1); + widget.createEReferralRequestModel.requesterName=_nameTextController.text; + widget.createEReferralRequestModel.requesterContactNo = _selectedCountry['code'].toString().substring(1)+_mobileTextController.text; + widget.createEReferralRequestModel.requesterRelationship=_selectedRelation.iD; + + + } + + + ), ).then((value) { print("dialog dismissed"); print(value); - if (value != null && value) {} + if (value != null && value) { + + } }); } - return BaseView( onModelReady: (model) => model.getRelationTypes(), builder: (_, model, widget) => AppScaffold( @@ -92,7 +92,7 @@ class _NewEReferralStepOnePageState extends State { body: SingleChildScrollView( physics: ScrollPhysics(), child: Container( - margin: EdgeInsets.all(10), + margin: EdgeInsets.all(12), child: Center( child: FractionallySizedBox( widthFactor: 0.9, @@ -100,10 +100,11 @@ class _NewEReferralStepOnePageState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( - height: 80, + height: 20, ), Center( child: Texts( +// TranslationBase.of(context).advancePaymentLabel, "Referral requester information", textAlign: TextAlign.center, ), @@ -184,30 +185,34 @@ class _NewEReferralStepOnePageState extends State { ), ), bottomSheet: Container( - height: MediaQuery.of(context).size.height * 0.1, + height: MediaQuery + .of(context) + .size + .height * 0.1, width: double.infinity, padding: EdgeInsets.all(9), child: SecondaryButton( textColor: Colors.white, - label: TranslationBase.of(context).next, - onTap: () async { - SendActivationCodeForEReferralRequestModel - sendActivationCodeForEReferralRequestModel = - SendActivationCodeForEReferralRequestModel( + label: "Next", + onTap: () async { + SendActivationCodeForEReferralRequestModel sendActivationCodeForEReferralRequestModel = + SendActivationCodeForEReferralRequestModel( zipCode: _selectedCountry['code'], - patientMobileNumber: int.parse(_mobileTextController.text), - ); - await model.sendActivationCodeForEReferral( - sendActivationCodeForEReferralRequestModel); + patientMobileNumber: int.parse( + _mobileTextController.text),); + await model.sendActivationCodeForEReferral(sendActivationCodeForEReferralRequestModel); showSMSDialog(); }, loading: model.state == ViewState.BusyLocal, - disabled: _nameTextController.text.isEmpty || + disabled: + _nameTextController.text.isEmpty || _selectedRelation == null || _mobileTextController.text.isEmpty, ), ))); + + } void confirmSelectRelationTypeDialog( @@ -256,8 +261,12 @@ class _NewEReferralStepOnePageState extends State { } class MobileNumberTextFiled extends StatelessWidget { - const MobileNumberTextFiled({Key key, this.controller, this.code}) - : super(key: key); + const MobileNumberTextFiled({ + Key key, + this.controller, + this.code + }) : super(key: key); + final TextEditingController controller; final String code; diff --git a/lib/pages/AlHabibMedicalService/E-Referral/New_E_Referral/new_e_referral_step_three_page.dart b/lib/pages/AlHabibMedicalService/E-Referral/New_E_Referral/new_e_referral_step_three_page.dart index cb9f03df..a823c154 100644 --- a/lib/pages/AlHabibMedicalService/E-Referral/New_E_Referral/new_e_referral_step_three_page.dart +++ b/lib/pages/AlHabibMedicalService/E-Referral/New_E_Referral/new_e_referral_step_three_page.dart @@ -1,23 +1,21 @@ import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/EReferral/create_e_referral_request_model.dart'; -import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/EReferral/get_all_projects_response_model.dart'; +import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/EReferral/get_all_cities_response_model.dart'; import 'package:diplomaticquarterapp/core/viewModels/all_habib_medical_services/e_referral_view_model.dart'; import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; import 'package:diplomaticquarterapp/models/FamilyFiles/GetAllSharedRecordByStatusResponse.dart'; -import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/E-Referral/dialogs/select_project_dialog.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; -import 'package:diplomaticquarterapp/routes.dart'; import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; -import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/bottom_options/BottomSheet.dart'; import 'package:diplomaticquarterapp/widgets/buttons/secondary_button.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; -import 'package:diplomaticquarterapp/widgets/dialogs/alert_dialog.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import '../dialogs/select_city_dialog.dart'; +import 'dart:io'; class NewEReferralStepThreePage extends StatefulWidget { final CreateEReferralRequestModel createEReferralRequestModel; final Function changePageViewIndex; @@ -34,8 +32,7 @@ class NewEReferralStepThreePage extends StatefulWidget { class _NewEReferralStepThreePageState extends State { TextEditingController _nameTextController = TextEditingController(); TextEditingController _mobileTextController = TextEditingController(); - - GetAllProjectsResponseModel _selectedHospital; + GetAllCitiesResponseModel _selectedCity; GetAllSharedRecordsByStatusList selectedPatientFamily; List medicalReportImages = []; @@ -53,7 +50,6 @@ class _NewEReferralStepThreePageState extends State { @override Widget build(BuildContext context) { return BaseView( - onModelReady: (model) => model.getAllProjects(), builder: (_, model, widget) => AppScaffold( isShowAppBar: false, body: SingleChildScrollView( @@ -68,7 +64,7 @@ class _NewEReferralStepThreePageState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( - height: 80, + height: 20, ), Center( child: Texts( @@ -105,7 +101,7 @@ class _NewEReferralStepThreePageState extends State { InkWell( onTap: () { ImageOptions.showImageOptions(context, - (String image) { + (String image,File file) { setState(() { EReferralAttachment eReferralAttachment = new EReferralAttachment( @@ -115,7 +111,7 @@ class _NewEReferralStepThreePageState extends State { medicalReportImages .add(eReferralAttachment); }); - }); + }, ); }, child: Container( margin: EdgeInsets.only( @@ -216,7 +212,7 @@ class _NewEReferralStepThreePageState extends State { ), InkWell( onTap: () => - confirmSelectHospital(model.allHospitals), + confirmSelectCityDialog(model.allCities), child: Container( padding: EdgeInsets.all(12), width: double.infinity, @@ -290,7 +286,7 @@ class _NewEReferralStepThreePageState extends State { InkWell( onTap: () { ImageOptions.showImageOptions(context, - (String image) { + (String image,File file) { setState(() { EReferralAttachment eReferralAttachment = @@ -410,27 +406,19 @@ class _NewEReferralStepThreePageState extends State { isPatientInsured; // ToDo make the preferred Branch info dynamic this.widget.createEReferralRequestModel.preferredBranchCode = - _selectedHospital.iD; + 15; this.widget.createEReferralRequestModel.preferredBranchName = - _selectedHospital.desciption; + "Arryan Hospital"; + // this.widget.createEReferralRequestModel.fullName= ""; this.widget.createEReferralRequestModel.otherRelationship = ""; + // this.widget.createEReferralRequestModel.; + // this.widget.createEReferralRequestModel. preferredBranchName= "Arryan Hospital"; + // this.widget.createEReferralRequestModel. preferredBranchName= "Arryan Hospital"; await model - .createEReferral(this.widget.createEReferralRequestModel) - .then((value) { - AlertDialogBox( - context: context, - confirmMessage: - TranslationBase.of(context).ereferralSaveSuccess + - value['ReferralNumber'].toString(), - okText: TranslationBase.of(context).ok, - okFunction: () { - AlertDialogBox.closeAlertDialog(context); - navigateToHome(context); - }).showAlertDialog(context); - }); + .createEReferral(this.widget.createEReferralRequestModel); }, loading: model.state == ViewState.BusyLocal, disabled: medicalReportImages.length == 0, @@ -438,19 +426,15 @@ class _NewEReferralStepThreePageState extends State { ))); } - Future navigateToHome(context) async { - Navigator.of(context).popAndPushNamed(HOME); - } - - void confirmSelectHospital(List projects) { + void confirmSelectCityDialog(List cities) { showDialog( context: context, - child: SelectHospitalDialog( - hospitals: projects, - selectedHospital: _selectedHospital, + child: SelectCityDialog( + cities: cities, + selectedCity: _selectedCity, onValueSelected: (value) { setState(() { - _selectedHospital = value; + _selectedCity = value; }); }, ), @@ -458,9 +442,9 @@ class _NewEReferralStepThreePageState extends State { } String getRelationName() { - if (_selectedHospital != null) - return _selectedHospital.desciption; + if (_selectedCity != null) + return _selectedCity.description; else - return "Select Hospital*" /*TranslationBase.of(context).selectHospital*/; + return "Select Relationship" /*TranslationBase.of(context).selectHospital*/; } } diff --git a/lib/pages/AlHabibMedicalService/E-Referral/New_E_Referral/new_e_referral_step_two_page.dart b/lib/pages/AlHabibMedicalService/E-Referral/New_E_Referral/new_e_referral_step_two_page.dart index 1ecd2e07..5f85fe12 100644 --- a/lib/pages/AlHabibMedicalService/E-Referral/New_E_Referral/new_e_referral_step_two_page.dart +++ b/lib/pages/AlHabibMedicalService/E-Referral/New_E_Referral/new_e_referral_step_two_page.dart @@ -8,7 +8,6 @@ import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/E-Referral/dial import 'package:diplomaticquarterapp/pages/base/base_view.dart'; import 'package:diplomaticquarterapp/pages/medical/balance/new_text_Field.dart'; import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; -import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/bottom_options/BottomSheet.dart'; import 'package:diplomaticquarterapp/widgets/buttons/secondary_button.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; @@ -72,7 +71,7 @@ class _NewEReferralStepTowPageState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( - height: 80, + height: 30, ), Center( child: Texts( @@ -180,7 +179,7 @@ class _NewEReferralStepTowPageState extends State { padding: EdgeInsets.all(9), child: SecondaryButton( textColor: Colors.white, - label: TranslationBase.of(context).next, + label: "Next", onTap: () async { this.widget.changePageViewIndex(2); this.widget.createEReferralRequestModel.identificationNo = int.parse( _patientIdentificationTextController.text); diff --git a/lib/pages/AlHabibMedicalService/E-Referral/dialogs/select_project_dialog.dart b/lib/pages/AlHabibMedicalService/E-Referral/dialogs/select_project_dialog.dart deleted file mode 100644 index 3a3cc083..00000000 --- a/lib/pages/AlHabibMedicalService/E-Referral/dialogs/select_project_dialog.dart +++ /dev/null @@ -1,129 +0,0 @@ -import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/EReferral/get_all_projects_response_model.dart'; -import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; -import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; -import 'package:flutter/material.dart'; - -class SelectHospitalDialog extends StatefulWidget { - - final List hospitals; - final Function(GetAllProjectsResponseModel) onValueSelected; - GetAllProjectsResponseModel selectedHospital; - - SelectHospitalDialog( - {Key key, this.hospitals, this.onValueSelected, this.selectedHospital}); - - @override - _SelectHospitalDialogState createState() => _SelectHospitalDialogState(); -} - -class _SelectHospitalDialogState extends State { - - @override - void initState() { - super.initState(); - widget.selectedHospital = widget.selectedHospital ?? widget.hospitals[0]; - } - - @override - Widget build(BuildContext context) { - return SimpleDialog( - children: [ - Column( - children: [ - Divider(), - ...List.generate( - widget.hospitals.length, - (index) => Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - height: 2, - ), - Row( - children: [ - Expanded( - flex: 1, - child: InkWell( - onTap: () { - setState(() { - widget.selectedHospital = widget.hospitals[index]; - }); - }, - child: ListTile( - title: Text(widget.hospitals[index].desciption), - leading: Radio( - value: widget.hospitals[index], - groupValue: widget.selectedHospital, - activeColor: Colors.red[800], - onChanged: (value) { - setState(() { - widget.selectedHospital = value; - }); - }, - ), - ), - ), - ) - ], - ), - SizedBox( - height: 5.0, - ), - ], - ), - ), - SizedBox( - height: 5.0, - ), - Row( - // mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - flex: 1, - child: InkWell( - onTap: () { - Navigator.pop(context); - }, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Container( - child: Center( - child: Texts( - TranslationBase.of(context).cancel.toUpperCase(), - color: Colors.red, - ), - ), - ), - ), - ), - ), - Container( - width: 1, - height: 30, - color: Colors.grey[500], - ), - Expanded( - flex: 1, - child: InkWell( - onTap: () { - widget.onValueSelected(widget.selectedHospital); - Navigator.pop(context); - }, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Center( - child: Texts( - TranslationBase.of(context).ok, - fontWeight: FontWeight.w400, - )), - ), - ), - ), - ], - ) - ], - ) - ], - ); - } -} diff --git a/lib/pages/AlHabibMedicalService/E-Referral/e_referral_page.dart b/lib/pages/AlHabibMedicalService/E-Referral/e_referral_page.dart index f50e67fa..a0583434 100644 --- a/lib/pages/AlHabibMedicalService/E-Referral/e_referral_page.dart +++ b/lib/pages/AlHabibMedicalService/E-Referral/e_referral_page.dart @@ -78,7 +78,7 @@ class _EReferralPageState extends State isScrollable: true, controller: _tabController, indicatorWeight: 5.0, - indicatorSize: TabBarIndicatorSize.label, + indicatorSize: TabBarIndicatorSize.tab, indicatorColor: Colors.red[800], labelColor: Theme.of(context).primaryColor, labelPadding: @@ -88,13 +88,13 @@ class _EReferralPageState extends State Container( width: MediaQuery.of(context).size.width * 0.37, child: Center( - child: Texts("New Referral", fontSize: 14.0), + child: Texts("New Referral"), ), ), Container( width: MediaQuery.of(context).size.width * 0.37, child: Center( - child: Texts("Search for Referrals", fontSize: 14.0), + child: Texts("Search for Referrals"), ), ), ], diff --git a/lib/pages/AlHabibMedicalService/E-Referral/referral_details.dart b/lib/pages/AlHabibMedicalService/E-Referral/referral_details.dart deleted file mode 100644 index 925d20cd..00000000 --- a/lib/pages/AlHabibMedicalService/E-Referral/referral_details.dart +++ /dev/null @@ -1,100 +0,0 @@ -import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/EReferral/get_ereferral_response_model.dart'; -import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; -import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; -import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; -import 'package:flutter/material.dart'; - -class ReferralDetails extends StatefulWidget { - GetEReferralResponseModel getEReferralResponseModel; - - ReferralDetails({@required this.getEReferralResponseModel}); - - @override - _ReferralDetailsState createState() => _ReferralDetailsState(); -} - -class _ReferralDetailsState extends State { - @override - Widget build(BuildContext context) { - return AppScaffold( - isShowDecPage: false, - isShowAppBar: true, - appBarTitle: "Referral Details", - body: Container( - margin: EdgeInsets.only(top: 20.0, left: 20.0, right: 20.0), - child: Table( - border: TableBorder.all(color: Colors.grey[600]), - children: [ - TableRow(children: [ - TableCell( - child: _getNormalText( - TranslationBase.of(context).referralStatus)), - TableCell( - child: - _getNormalText(widget.getEReferralResponseModel.status)), - ]), - TableRow(children: [ - TableCell( - child: - _getNormalText(TranslationBase.of(context).patientName)), - TableCell( - child: _getNormalText( - widget.getEReferralResponseModel.patientName)), - ]), - TableRow(children: [ - TableCell( - child: _getNormalText( - TranslationBase.of(context).referralNumber)), - TableCell( - child: _getNormalText(widget - .getEReferralResponseModel.referralNumber - .toString())), - ]), - TableRow(children: [ - TableCell( - child: _getNormalText( - TranslationBase.of(context).referralDate)), - TableCell( - child: _getNormalText(DateUtil.getMonthDayYearDateFormatted( - DateUtil.convertStringToDateNoTimeZone( - widget.getEReferralResponseModel.referralDate)))), - ]), - TableRow(children: [ - TableCell( - child: _getNormalText(TranslationBase.of(context).hospital)), - TableCell( - child: _getNormalText( - widget.getEReferralResponseModel.preferredBranchName)), - ]), - ], - ), - ), - ); - } - - _getNormalText(text) { - return Container( - color: Colors.white, - padding: EdgeInsets.only(top: 12.0, bottom: 12.0), - child: Text(text, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 14, - fontFamily: 'Open-Sans', - letterSpacing: 0.5, - color: Colors.grey[800])), - ); - } - - _getHeadingText(text) { - return Container( - padding: EdgeInsets.only(bottom: 10.0), - child: Text(text, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 26.0, - fontFamily: 'Open-Sans', - letterSpacing: 0.5, - color: Colors.white))); - } -} diff --git a/lib/pages/AlHabibMedicalService/E-Referral/search_for_referrals_page.dart b/lib/pages/AlHabibMedicalService/E-Referral/search_for_referrals_page.dart index 49c5dd60..0b75705d 100644 --- a/lib/pages/AlHabibMedicalService/E-Referral/search_for_referrals_page.dart +++ b/lib/pages/AlHabibMedicalService/E-Referral/search_for_referrals_page.dart @@ -1,25 +1,17 @@ -import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; -import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/EReferral/get_ereferral_response_model.dart'; import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/EReferral/search_criteria_model.dart'; import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/EReferral/search_e_referral_request_model.dart'; -import 'package:diplomaticquarterapp/core/service/AlHabibMedicalService/e_referral_service.dart'; import 'package:diplomaticquarterapp/core/viewModels/all_habib_medical_services/e_referral_view_model.dart'; -import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; -import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/E-Referral/referral_details.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; import 'package:diplomaticquarterapp/pages/medical/balance/new_text_Field.dart'; -import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; -import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; -import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; import 'package:diplomaticquarterapp/widgets/buttons/secondary_button.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; +import 'package:diplomaticquarterapp/widgets/errors/app_embedded_error.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; -import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; +import 'package:diplomaticquarterapp/widgets/others/network_base_view.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import '../../../locator.dart'; import 'New_E_Referral/new_e_referral_step_one_page.dart'; import 'dialogs/select_country_ingo_Dialog.dart'; import 'dialogs/select_search_criteria_dialog.dart'; @@ -36,9 +28,6 @@ class _SearchForReferralsPageState extends State { TextEditingController _mobileTextController = TextEditingController(); bool _isSubmitted = false; - AuthenticatedUser authUser; - - List allReferrals = List(); dynamic _selectedCountry = { "name": "Saudi Arabia", @@ -52,13 +41,6 @@ class _SearchForReferralsPageState extends State { SearchCriteriaModel selectedCriteria = SearchCriteriaModel( name: "Identification Number", nameAr: "رقم المحول", value: 1); - @override - void initState() { - authUser = new AuthenticatedUser(); - WidgetsBinding.instance.addPostFrameCallback((_) => getPatientData()); - super.initState(); - } - @override Widget build(BuildContext context) { return BaseView( @@ -135,102 +117,35 @@ class _SearchForReferralsPageState extends State { ? "11" : _selectedCountry["code"], ), - allReferrals.length != 0 - ? Container( - transform: - Matrix4.translationValues(0.0, -40.0, 0.0), - child: ListView.builder( - shrinkWrap: true, - scrollDirection: Axis.vertical, - physics: ScrollPhysics(), - itemCount: allReferrals.length, - itemBuilder: - (BuildContext context, int index) { - return Container( - child: InkWell( - onTap: () { - navigateToReferralDetails( - allReferrals[index]); - }, - child: Card( - margin: EdgeInsets.only(bottom: 10.0), - color: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(10), - ), - child: Container( - margin: EdgeInsets.only( - left: 10.0, right: 10.0), - padding: EdgeInsets.all(5.0), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Container( - margin: - EdgeInsets.all(5.0), - child: Text( - allReferrals[index] - .status, - style: TextStyle( - fontSize: 16.0))), - Container( - margin: - EdgeInsets.all(5.0), - child: Text( - allReferrals[index] - .patientName, - style: TextStyle( - fontSize: 16.0, - color: Colors - .grey[600]))), - Container( - margin: - EdgeInsets.all(5.0), - child: Text( - allReferrals[index] - .preferredBranchName, - style: TextStyle( - fontSize: 16.0, - color: Colors - .grey[600]))), - Container( - margin: - EdgeInsets.all(5.0), - child: Text( - DateUtil.getMonthDayYearDateFormatted( - DateUtil.convertStringToDateNoTimeZone( - allReferrals[ - index] - .referralDate)), - style: TextStyle( - fontSize: 16.0, - color: Colors - .grey[600]))), - ], - ), - Container( - child: Icon(Icons.arrow_forward, - size: 20.0, - color: Colors.grey[700]), - ), - ], - ), - ), - ), - )); - }, - ), - ) - : Container(), SizedBox( - height: 70.0, - ) + height: 12, + ), + if ((model.state == ViewState.Idle && + model.allReferral.length == 0)) + Text("There's No Referral To deliver"), + if (( + model.state == ViewState.ErrorLocal)) + AppEmbeddedError( error:model.error), + NetworkBaseView( + baseViewModel: model, + child: ListView.builder( + shrinkWrap: true, + scrollDirection: Axis.vertical, + itemCount: model.allReferral == null + ? 0 + : model.allReferral.length < 3 + ? model.allReferral.length + : 3, + itemBuilder: (BuildContext context, int index) { + return Padding( + padding: EdgeInsets.symmetric(horizontal: 0.2), + child: Container( + child: Texts("TODO add referral info"), + ), + ); + }, + ), + ), ], ), ), @@ -245,13 +160,10 @@ class _SearchForReferralsPageState extends State { textColor: Colors.white, label: "Search", onTap: () async { - GifLoaderDialogUtils.showMyDialog(context); SearchEReferralRequestModel searchEReferralRequestModel = new SearchEReferralRequestModel( - patientMobileNumber: _selectedCountry['code'] - .toString() - .replaceFirst("+", "") + - _mobileTextController.text, + patientMobileNumber: + _selectedCountry['code'] + _mobileTextController.text, ); if (selectedCriteria.value == 1) { searchEReferralRequestModel.identificationNo = @@ -262,19 +174,9 @@ class _SearchForReferralsPageState extends State { int.parse(_searchTextController.text); searchEReferralRequestModel.identificationNo = ''; } - await model - .getEReferrals(searchEReferralRequestModel) - .then((response) { - GifLoaderDialogUtils.hideDialog(context); - print(response['List_EReferrals']); - allReferrals.clear(); - setState(() { - response['List_EReferrals'].forEach((data) { - allReferrals - .add(GetEReferralResponseModel.fromJson(data)); - _isSubmitted = true; - }); - }); + await model.getEReferrals(searchEReferralRequestModel); + setState(() { + _isSubmitted = true; }); }, loading: model.state == ViewState.BusyLocal, @@ -284,49 +186,6 @@ class _SearchForReferralsPageState extends State { ))); } - void getEreferralsIsLogin() { - EReferralService _eReferralService = locator(); - - String mobileNumber; - String zipCode; - - if (authUser.mobileNumber.length > 9) { - mobileNumber = - authUser.mobileNumber.substring(1, authUser.mobileNumber.length); - } else { - mobileNumber = authUser.mobileNumber; - } - - if (authUser.outSA == 0) { - zipCode = "966"; - } else { - zipCode = "971"; - } - - _eReferralService - .getEReferralsIfLogin(zipCode + mobileNumber) - .then((response) { - allReferrals.clear(); - setState(() { - response['List_EReferrals'].forEach((data) { - allReferrals.add(GetEReferralResponseModel.fromJson(data)); - }); - }); - }).catchError(() {}); - } - - getPatientData() async { - AppSharedPreferences sharedPref = AppSharedPreferences(); - if (await sharedPref.getObject(USER_PROFILE) != null) { - var data = - AuthenticatedUser.fromJson(await sharedPref.getObject(USER_PROFILE)); - setState(() { - authUser = data; - getEreferralsIsLogin(); - }); - } - } - void confirmSelectCountryTypeDialog() { showDialog( context: context, @@ -341,15 +200,6 @@ class _SearchForReferralsPageState extends State { ); } - navigateToReferralDetails( - GetEReferralResponseModel getEReferralResponseModel) { - Navigator.push( - context, - FadePage( - page: ReferralDetails( - getEReferralResponseModel: getEReferralResponseModel))); - } - String getCountryName() { if (_selectedCountry != null) return _selectedCountry["name"]; diff --git a/lib/pages/AlHabibMedicalService/HomeHealthCare/NewHomeHealthCare/location_page.dart b/lib/pages/AlHabibMedicalService/HomeHealthCare/NewHomeHealthCare/location_page.dart index d7434b97..4bf3a762 100644 --- a/lib/pages/AlHabibMedicalService/HomeHealthCare/NewHomeHealthCare/location_page.dart +++ b/lib/pages/AlHabibMedicalService/HomeHealthCare/NewHomeHealthCare/location_page.dart @@ -49,98 +49,98 @@ class _LocationPageState return BaseView( onModelReady: (model) {}, builder: (_, model, widget) => AppScaffold( - isShowDecPage: false, - isShowAppBar: true, - baseViewModel: model, - body: PlacePicker( - apiKey: GOOGLE_API_KEY, - enableMyLocationButton: true, - automaticallyImplyAppBarLeading: false, - autocompleteOnTrailingWhitespace: true, - selectInitialPosition: true, - autocompleteLanguage: projectViewModel.currentLanguage, - enableMapTypeButton: true, - searchForInitialValue: false, - onPlacePicked: (PickResult result) { - print(result.adrAddress); + isShowDecPage: false, + isShowAppBar: true, + baseViewModel: model, + body: PlacePicker( + apiKey: GOOGLE_API_KEY, + enableMyLocationButton: true, + automaticallyImplyAppBarLeading: false, + autocompleteOnTrailingWhitespace: true, + selectInitialPosition: true, + autocompleteLanguage: projectViewModel.currentLanguage, + enableMapTypeButton: true, + searchForInitialValue: false, + onPlacePicked: (PickResult result) { + print(result.adrAddress); - }, - selectedPlaceWidgetBuilder: - (_, selectedPlace, state, isSearchBarFocused) { - print("state: $state, isSearchBarFocused: $isSearchBarFocused"); - return isSearchBarFocused - ? Container() - : FloatingCard( - bottomPosition: 0.0, - leftPosition: 0.0, - rightPosition: 0.0, - width: 500, - borderRadius: BorderRadius.circular(12.0), - child: state == SearchingState.Searching - ? Center(child: CircularProgressIndicator()) - : Container( - margin: EdgeInsets.all(12), - child: Column( - children: [ - SecondaryButton( - color: Colors.grey[800], - textColor: Colors.white, - onTap: () async { - AddNewAddressRequestModel - addNewAddressRequestModel = - new AddNewAddressRequestModel( - customer: Customer(addresses: [ - Addresses( - address1: - selectedPlace.formattedAddress, - address2: selectedPlace - .formattedAddress, - customerAttributes: "", - city: "", - createdOnUtc: "", - id: 0, - latLong: "$latitude,$longitude", - email: "") - ]), - ); + }, + selectedPlaceWidgetBuilder: + (_, selectedPlace, state, isSearchBarFocused) { + print("state: $state, isSearchBarFocused: $isSearchBarFocused"); + return isSearchBarFocused + ? Container() + : FloatingCard( + bottomPosition: 0.0, + leftPosition: 0.0, + rightPosition: 0.0, + width: 500, + borderRadius: BorderRadius.circular(12.0), + child: state == SearchingState.Searching + ? Center(child: CircularProgressIndicator()) + : Container( + margin: EdgeInsets.all(12), + child: Column( + children: [ + SecondaryButton( + color: Colors.grey[800], + textColor: Colors.white, + onTap: () async { + AddNewAddressRequestModel + addNewAddressRequestModel = + new AddNewAddressRequestModel( + customer: Customer(addresses: [ + Addresses( + address1: + selectedPlace.formattedAddress, + address2: selectedPlace + .formattedAddress, + customerAttributes: "", + city: "", + createdOnUtc: "", + id: 0, + latLong: "$latitude,$longitude", + email: "") + ]), + ); - selectedPlace.addressComponents.forEach((e) { - if (e.types.contains("country")) { - addNewAddressRequestModel.customer - .addresses[0].country = e.longName; - } - if (e.types.contains("postal_code")) { - addNewAddressRequestModel.customer - .addresses[0].zipPostalCode = - e.longName; - } - if (e.types.contains("locality")) { - addNewAddressRequestModel.customer - .addresses[0].city = - e.longName; - } - }); + selectedPlace.addressComponents.forEach((e) { + if (e.types.contains("country")) { + addNewAddressRequestModel.customer + .addresses[0].country = e.longName; + } + if (e.types.contains("postal_code")) { + addNewAddressRequestModel.customer + .addresses[0].zipPostalCode = + e.longName; + } + if (e.types.contains("locality")) { + addNewAddressRequestModel.customer + .addresses[0].city = + e.longName; + } + }); - await model.addAddressInfo( - addNewAddressRequestModel: addNewAddressRequestModel); - if (model.state == ViewState.ErrorLocal) { - Utils.showErrorToast(model.error); - } else { - AppToast.showSuccessToast( - message: "Address Added Successfully"); - } - Navigator.of(context).pop(); - }, - label: TranslationBase.of(context).addNewAddress, - ), - ], - ), + await model.addAddressInfo( + addNewAddressRequestModel: addNewAddressRequestModel); + if (model.state == ViewState.ErrorLocal) { + Utils.showErrorToast(model.error); + } else { + AppToast.showSuccessToast( + message: "Address Added Successfully"); + } + Navigator.of(context).pop(); + }, + label: TranslationBase.of(context).addNewAddress, + ), + ], ), - ); - }, - initialPosition: LatLng(latitude, longitude), - useCurrentLocation: false, - ), - )); + ), + ); + }, + initialPosition: LatLng(latitude, longitude), + useCurrentLocation: false, + ), + )); } } diff --git a/lib/pages/AlHabibMedicalService/HomeHealthCare/home_health_care_index_page.dart b/lib/pages/AlHabibMedicalService/HomeHealthCare/home_health_care_index_page.dart new file mode 100644 index 00000000..fa0799f9 --- /dev/null +++ b/lib/pages/AlHabibMedicalService/HomeHealthCare/home_health_care_index_page.dart @@ -0,0 +1,69 @@ +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/secondary_button.dart'; +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/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:hexcolor/hexcolor.dart'; + +import 'home_health_care_page.dart'; + +class HomeHealthCareIndexPage extends StatelessWidget { + @override + Widget build(BuildContext context) { + return AppScaffold( + isShowAppBar: true, + appBarTitle: TranslationBase.of(context).serviceInformation, + body: SingleChildScrollView( + padding: EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Texts( + TranslationBase.of(context).homeHealthCare, + fontWeight: FontWeight.normal, + fontSize: 25, + color: Color(0xff60686b), + ), + SizedBox( + height: 12, + ), + Texts( + TranslationBase.of(context).homeHealthCareText, + fontWeight: FontWeight.normal, + fontSize: 17, + ), + SizedBox( + height: 22, + ), + Center( + child: Image.asset( + 'assets/images/AlHabibMedicalService/Wifi-AR.png')), + SizedBox( + height: 77, + ), + ], + )), + bottomSheet: Container( + height: MediaQuery.of(context).size.height * 0.10, + width: double.infinity, + child: Column( + children: [ + Container( + width: MediaQuery.of(context).size.width * 0.9, + child: SecondaryButton( + onTap: () => Navigator.push( + context, + FadePage( + page: HomeHealthCarePage(), + ), + ), + label: TranslationBase.of(context).loginRegister, + textColor: Theme.of(context).backgroundColor), + ), + ], + ), + )); + } +} diff --git a/lib/pages/AlHabibMedicalService/HomeHealthCare/home_health_care_page.dart b/lib/pages/AlHabibMedicalService/HomeHealthCare/home_health_care_page.dart index fcdc144a..3180cf18 100644 --- a/lib/pages/AlHabibMedicalService/HomeHealthCare/home_health_care_page.dart +++ b/lib/pages/AlHabibMedicalService/HomeHealthCare/home_health_care_page.dart @@ -81,7 +81,7 @@ class _HomeHealthCarePageState extends State isScrollable: true, controller: _tabController, indicatorWeight: 5.0, - indicatorSize: TabBarIndicatorSize.label, + indicatorSize: TabBarIndicatorSize.tab, indicatorColor: Colors.red[800], labelColor: Theme.of(context).primaryColor, labelPadding: diff --git a/lib/pages/AlHabibMedicalService/all_habib_medical_service_page.dart b/lib/pages/AlHabibMedicalService/all_habib_medical_service_page.dart index f40e32cc..e1720258 100644 --- a/lib/pages/AlHabibMedicalService/all_habib_medical_service_page.dart +++ b/lib/pages/AlHabibMedicalService/all_habib_medical_service_page.dart @@ -1,4 +1,5 @@ import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/core/service/weather_service.dart'; import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/%E2%80%8B%20health_calculators.dart'; @@ -32,6 +33,7 @@ import 'package:diplomaticquarterapp/widgets/text/app_texts_widget.dart'; import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:geolocator/geolocator.dart'; import 'package:provider/provider.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -182,7 +184,6 @@ class _AllHabibMedicalServiceState extends State { 'assets/images/new-design/booking_icon_active.png', title: TranslationBase.of(context).bookAppo, ), - if(projectViewModel.havePrivilege(58)) ServicesContainer( onTap: () => Navigator.push( context, @@ -257,46 +258,46 @@ class _AllHabibMedicalServiceState extends State { ), imageLocation: 'assets/images/new-design/family_menu_icon_red.png', - title: TranslationBase.of(context).family, + title: 'My Family', ), - if(projectViewModel.havePrivilege(35)) - ServicesContainer( - onTap: () => Navigator.push( - context, - FadePage(page: ChildVaccinesPage()), + if (projectViewModel.havePrivilege(35)) + ServicesContainer( + onTap: () => Navigator.push( + context, + FadePage(page: ChildVaccinesPage()), + ), + imageLocation: + 'assets/images/new-design/children_vaccines_icon.png', + title: 'Child Vaccines', ), - imageLocation: - 'assets/images/new-design/children_vaccines_icon.png', - title: 'Child Vaccines', - ), ServicesContainer( onTap: () => Navigator.push( context, FadePage( - page: ToDo(), + page: ToDo(isShowAppBar: true), ), ), imageLocation: 'assets/images/new-design/upcoming_icon_bottom_bar.png', title: TranslationBase.of(context).todoList, ), - if(projectViewModel.havePrivilege(42)) - ServicesContainer( - onTap: () => Navigator.push( - context, - FadePage(page: SymptomInfo()), - ), - imageLocation: 'assets/images/new-design/body_icon.png', - title: 'Symptom Checker'), - if(projectViewModel.havePrivilege(36)) + if (projectViewModel.havePrivilege(42)) ServicesContainer( - onTap: () => Navigator.push( - context, - FadePage(page: BloodDonationPage()), + onTap: () => Navigator.push( + context, + FadePage(page: SymptomInfo()), + ), + imageLocation: 'assets/images/new-design/body_icon.png', + title: 'Symptom Checker'), + if (projectViewModel.havePrivilege(36)) + ServicesContainer( + onTap: () => Navigator.push( + context, + FadePage(page: BloodDonationPage()), + ), + imageLocation: 'assets/images/new-design/blood_icon.png', + title: 'Blood Donation', ), - imageLocation: 'assets/images/new-design/blood_icon.png', - title: 'Blood Donation', - ), ServicesContainer( onTap: () => Navigator.push( context, @@ -319,26 +320,27 @@ class _AllHabibMedicalServiceState extends State { 'assets/images/new-design/health_convertor_icon.png', title: 'Health Converter', ), - if(projectViewModel.havePrivilege(38)) - ServicesContainer( - onTap: () => Navigator.push( - context, - FadePage( - page: H2OPageIndexPage(), + if (projectViewModel.havePrivilege(38)) + ServicesContainer( + onTap: () => Navigator.push( + context, + FadePage( + page: H2OPageIndexPage(), + ), ), + imageLocation: 'assets/images/new-design/water_icon.png', + title: 'H2O', ), - imageLocation: 'assets/images/new-design/water_icon.png', - title: 'H2O', - ), - if(projectViewModel.havePrivilege(41)) - ServicesContainer( - onTap: () => Navigator.push( - context, - FadePage(), + if (projectViewModel.havePrivilege(41)) + ServicesContainer( + onTap: () => Navigator.push( + context, + FadePage(), + ), + imageLocation: + 'assets/images/new-design/smartwatch_icon.png', + title: TranslationBase.of(context).smartWatches, ), - imageLocation: 'assets/images/new-design/smartwatch_icon.png', - title: TranslationBase.of(context).smartWatches, - ), ServicesContainer( onTap: () => Navigator.push( context, @@ -359,19 +361,16 @@ class _AllHabibMedicalServiceState extends State { ), ServicesContainer( onTap: () { - Navigator.of(context).push( - MaterialPageRoute( + Navigator.of(context).push(MaterialPageRoute( builder: (BuildContext context) => MyWebView( - title: TranslationBase.of(context).hmgNews, - selectedUrl: - "https://twitter.com/hashtag/مجموعة_د_سليمان_الحبيب_الطبية?src=hashtag_click&f=live", - ), - ), - ); + title: "HMG News", + selectedUrl: + "https://twitter.com/hashtag/مجموعة_د_سليمان_الحبيب_الطبية?src=hashtag_click&f=live", + ))); }, imageLocation: 'assets/images/new-design/twitter_dashboard_icon.png', - title: TranslationBase.of(context).latestNews, + title: 'Latest News', ), ServicesContainer( onTap: () => Navigator.push( @@ -398,7 +397,6 @@ class _AllHabibMedicalServiceState extends State { setState(() { authUser = data; }); - print(authUser.patientID); } var data = await this.sharedPref.getObject(WEATHER); weather = data != null ? data['Temperature'].toString() + '\u2103' : '--'; diff --git a/lib/pages/AlHabibMedicalService/h2o/h2o_page.dart b/lib/pages/AlHabibMedicalService/h2o/h2o_page.dart index ad2c6ece..8ac7b437 100644 --- a/lib/pages/AlHabibMedicalService/h2o/h2o_page.dart +++ b/lib/pages/AlHabibMedicalService/h2o/h2o_page.dart @@ -68,7 +68,7 @@ class _H2OPageState extends State isScrollable: false, controller: _tabController, indicatorWeight: 5.0, - indicatorSize: TabBarIndicatorSize.label, + indicatorSize: TabBarIndicatorSize.tab, indicatorColor: Colors.red[800], labelColor: Theme.of(context).primaryColor, labelPadding: diff --git a/lib/pages/AlHabibMedicalService/health-weather/health-weather-indicator.dart b/lib/pages/AlHabibMedicalService/health-weather/health-weather-indicator.dart index a63125d0..bc1de1f6 100644 --- a/lib/pages/AlHabibMedicalService/health-weather/health-weather-indicator.dart +++ b/lib/pages/AlHabibMedicalService/health-weather/health-weather-indicator.dart @@ -98,8 +98,11 @@ class _HospitalsPageState extends State { width: 60, height: 60, ), - AppText(weather, - fontSize: 22, color: Colors.white) + Directionality( + textDirection: TextDirection.ltr, + child: AppText(weather, + fontSize: 22, + color: Colors.white)) ], ), ], diff --git a/lib/pages/AlHabibMedicalService/parking_page.dart b/lib/pages/AlHabibMedicalService/parking_page.dart index a49a4b20..82c390ea 100644 --- a/lib/pages/AlHabibMedicalService/parking_page.dart +++ b/lib/pages/AlHabibMedicalService/parking_page.dart @@ -18,7 +18,6 @@ class ParkingPage extends StatelessWidget { onModelReady: (model) => model.getIsSaveParking(), builder: (_, model, widget) => AppScaffold( isShowAppBar: true, - isShowDecPage: false, appBarTitle: TranslationBase.of(context).parking, body: SingleChildScrollView( padding: EdgeInsets.all(12), diff --git a/lib/pages/Blood/blood_donation.dart b/lib/pages/Blood/blood_donation.dart index bb91a79e..1eaa02da 100644 --- a/lib/pages/Blood/blood_donation.dart +++ b/lib/pages/Blood/blood_donation.dart @@ -32,6 +32,7 @@ import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:giffy_dialog/giffy_dialog.dart'; +import 'package:smart_progress_bar/smart_progress_bar.dart'; //import '../../../core/model/my_balance/AdvanceModel.dart'; import 'confirm_payment_page.dart'; diff --git a/lib/pages/Blood/dialogs/ConfirmSMSDialog.dart b/lib/pages/Blood/dialogs/ConfirmSMSDialog.dart index e08d2f28..d165a895 100644 --- a/lib/pages/Blood/dialogs/ConfirmSMSDialog.dart +++ b/lib/pages/Blood/dialogs/ConfirmSMSDialog.dart @@ -8,13 +8,13 @@ import 'package:diplomaticquarterapp/core/model/my_balance/patient_info_and_mobi 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/uitl/gif_loader_dialog_utils.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/buttons/secondary_button.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:smart_progress_bar/smart_progress_bar.dart'; class ConfirmSMSDialog extends StatefulWidget { final String phoneNumber; @@ -112,31 +112,32 @@ class _ConfirmSMSDialogState extends State { height: 40, color: Theme.of(context).primaryColor, child: Stack( + children: [ Center( - child: Texts( - 'SMS', - color: Colors.white, - textAlign: TextAlign.center, - ), - ), - Positioned( - child: Container( - child: InkWell( - onTap: () => Navigator.pop(context), - child: Container( - decoration: BoxDecoration( - shape: BoxShape.circle, color: Colors.white), - child: Icon( - Icons.clear, - color: Colors.grey[900], - )), + child: Texts( + 'SMS', + color: Colors.white, + textAlign: TextAlign.center, ), + ), + Positioned(child: Container( + child: InkWell( + onTap: () => Navigator.pop(context), + child: Container( + decoration: BoxDecoration( + shape: BoxShape.circle, color: Colors.white), + child: Icon( + Icons.clear, + color: Colors.grey[900], + )), ), - left: projectViewModel.isArabic ? 2 : 0, - right: projectViewModel.isArabic ? 0 : 2, + ), + left: projectViewModel.isArabic? 2:0, + right: projectViewModel.isArabic? 0:2, ) ], + ), ), Image.asset( @@ -333,14 +334,15 @@ class _ConfirmSMSDialogState extends State { } void submit(MyBalanceViewModel model) { - GifLoaderDialogUtils.showMyDialog(context); if (verifyAccountForm.currentState.validate()) { final activationCode = digit1.text + digit2.text + digit3.text + digit4.text; model .checkActivationCodeForAdvancePayment(activationCode: activationCode) + .then((value) {}) + .showProgressBar( + text: "Loading", backgroundColor: Colors.blue.withOpacity(0.6)) .then((value) { - GifLoaderDialogUtils.hideDialog(context); Navigator.pop(context, true); }); } diff --git a/lib/pages/BookAppointment/BookConfirm.dart b/lib/pages/BookAppointment/BookConfirm.dart index 7a247b78..d7e08a66 100644 --- a/lib/pages/BookAppointment/BookConfirm.dart +++ b/lib/pages/BookAppointment/BookConfirm.dart @@ -241,7 +241,7 @@ class _BookConfirmState extends State { ), ), Container( - margin: EdgeInsets.fromLTRB(20.0, 5.0, 10.0, 5.0), + margin: EdgeInsets.fromLTRB(20.0, 5.0, 20.0, 5.0), child: Text( TranslationBase.of(context).date + ": " + @@ -325,7 +325,7 @@ class _BookConfirmState extends State { Container( margin: EdgeInsets.only(top: 5.0), child: Text( - "Gender: " + + TranslationBase.of(context).gender + ": " + widget.authUser.genderDescription, style: TextStyle( fontSize: 12.0, @@ -335,7 +335,7 @@ class _BookConfirmState extends State { Container( margin: EdgeInsets.only(top: 5.0, bottom: 3.0), child: Text( - "Age: " + widget.authUser.age.toString(), + TranslationBase.of(context).age + ": " + widget.authUser.age.toString(), style: TextStyle( fontSize: 12.0, color: Colors.grey[600], @@ -423,7 +423,7 @@ class _BookConfirmState extends State { context) .then((res) { if (res['MessageStatus'] == 1) { - AppToast.showSuccessToast(message: "Appointment Booked Successfully"); + AppToast.showSuccessToast(message: TranslationBase.of(context).bookedSuccess); print(res['AppointmentNo']); Future.delayed(new Duration(milliseconds: 500), () { @@ -513,12 +513,12 @@ class _BookConfirmState extends State { } getToDoCount() { - toDoProvider.setState(0); + toDoProvider.setState(0, true); ClinicListService service = new ClinicListService(); service.getActiveAppointmentNo(context).then((res) { print(res['AppointmentActiveNumber']); if (res['MessageStatus'] == 1) { - toDoProvider.setState(res['AppointmentActiveNumber']); + toDoProvider.setState(res['AppointmentActiveNumber'], true); } else {} }).catchError((err) { print(err); diff --git a/lib/pages/BookAppointment/BookSuccess.dart b/lib/pages/BookAppointment/BookSuccess.dart index 70a5b1fb..f513c434 100644 --- a/lib/pages/BookAppointment/BookSuccess.dart +++ b/lib/pages/BookAppointment/BookSuccess.dart @@ -165,6 +165,173 @@ class _BookSuccessState extends State { ], ), ), + bottomNavigationBar: getBottomContainer(), + ); + } + + Widget getBottomContainer() { + switch (widget.patientShareResponse.nextAction) { + case 0: + return Container(); + break; + case 10: + return _getConfirmAppoButtons(); + break; + case 15: + return _getPaymentPendingAppo(); + break; + case 20: + return _getPayNowButtons(); + break; + case 30: + return _getQRButtons(); + break; + case 50: + return _getConfirmAppoButtons(); + break; + } + } + + Widget _getQRButtons() { + return Container( + alignment: Alignment.bottomCenter, + height: MediaQuery.of(context).size.height * 0.18, + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + ButtonTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10.0), + ), + minWidth: MediaQuery.of(context).size.width * 0.7, + height: 45.0, + child: RaisedButton( + color: new Color(0xFF60686b), + textColor: Colors.white, + disabledTextColor: Colors.white, + disabledColor: new Color(0xFFbcc2c4), + onPressed: () { +// navigateToQR(context); + getAppoQR(context); + }, + child: Text(TranslationBase.of(context).viewQR.toUpperCase(), + style: TextStyle(fontSize: 18.0)), + ), + ), + ], + ), + ); + } + + Widget _getPayNowButtons() { + return Container( + alignment: Alignment.bottomCenter, + height: MediaQuery.of(context).size.height * 0.2, + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + ButtonTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10.0), + ), + minWidth: MediaQuery.of(context).size.width * 0.7, + height: 45.0, + child: RaisedButton( + color: new Color(0xFF60686b), + textColor: Colors.white, + disabledTextColor: Colors.white, + disabledColor: new Color(0xFFbcc2c4), + onPressed: () { + startPaymentProcess(); + }, + child: Text(TranslationBase.of(context).payNow.toUpperCase(), + style: TextStyle(fontSize: 18.0)), + ), + ), + ButtonTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10.0), + ), + minWidth: MediaQuery.of(context).size.width * 0.7, + height: 45.0, + child: RaisedButton( + color: new Color(0xFF40ACC9), + textColor: Colors.white, + disabledTextColor: Colors.white, + disabledColor: new Color(0xFFbcc2c4), + onPressed: () { + navigateToHome(context); + }, + child: Text(TranslationBase.of(context).payLater.toUpperCase(), + style: TextStyle(fontSize: 18.0)), + ), + ), + ], + ), + ); + } + + Widget _getConfirmAppoButtons() { + return Container( + alignment: Alignment.bottomCenter, + margin: EdgeInsets.only(bottom: 5.0), + height: MediaQuery.of(context).size.height * 0.15, + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + ButtonTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10.0), + ), + minWidth: MediaQuery.of(context).size.width * 0.7, + height: 45.0, + child: RaisedButton( + color: new Color(0xFF60686b), + textColor: Colors.white, + disabledTextColor: Colors.white, + disabledColor: new Color(0xFFbcc2c4), + onPressed: () { + AppoitmentAllHistoryResultList appo = + new AppoitmentAllHistoryResultList(); + appo.clinicID = widget.docObject.clinicID; + appo.projectID = widget.docObject.projectID; + appo.appointmentNo = widget.patientShareResponse.appointmentNo; + appo.serviceID = widget.patientShareResponse.serviceID; + appo.isLiveCareAppointment = + widget.patientShareResponse.isLiveCareAppointment; + appo.doctorID = widget.patientShareResponse.doctorID; + confirmAppointment(appo); + }, + child: Text( + widget.patientShareResponse.isLiveCareAppointment + ? TranslationBase.of(context) + .confirmLiveCare + .toUpperCase() + : TranslationBase.of(context).confirm.toUpperCase(), + style: TextStyle(fontSize: 18.0)), + ), + ), + ButtonTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10.0), + ), + minWidth: MediaQuery.of(context).size.width * 0.7, + height: 45.0, + child: RaisedButton( + color: new Color(0xFF40ACC9), + textColor: Colors.white, + disabledTextColor: Colors.white, + disabledColor: new Color(0xFFbcc2c4), + onPressed: () { + navigateToHome(context); + }, + child: Text( + TranslationBase.of(context).confirmLater.toUpperCase(), + style: TextStyle(fontSize: 18.0)), + ), + ), + ], + ), ); } @@ -238,8 +405,7 @@ class _BookSuccessState extends State { _getBulletPoint("1"), Container( width: MediaQuery.of(context).size.width * 0.8, - child: Text( - "Please confirm the appointment to avoid the cancellation", + child: Text(TranslationBase.of(context).upcomingConfirm, overflow: TextOverflow.clip, style: TextStyle(fontSize: 13.0)), ), @@ -263,7 +429,7 @@ class _BookSuccessState extends State { Container( width: MediaQuery.of(context).size.width * 0.8, child: Text( - "The online payment process will be available 24 hours before the appointment.", + TranslationBase.of(context).upcomingConfirmMore, overflow: TextOverflow.clip, style: TextStyle(fontSize: 13.0)), ), @@ -277,67 +443,6 @@ class _BookSuccessState extends State { margin: EdgeInsets.fromLTRB(50.0, 20.0, 50.0, 20.0), child: Image.asset("assets/images/new-design/payment-method.png"), ), - Container( - alignment: Alignment.bottomCenter, - height: MediaQuery.of(context).size.height * 0.32, - child: Column( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - ButtonTheme( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10.0), - ), - minWidth: MediaQuery.of(context).size.width * 0.7, - height: 45.0, - child: RaisedButton( - color: new Color(0xFF60686b), - textColor: Colors.white, - disabledTextColor: Colors.white, - disabledColor: new Color(0xFFbcc2c4), - onPressed: () { - AppoitmentAllHistoryResultList appo = - new AppoitmentAllHistoryResultList(); - appo.clinicID = widget.docObject.clinicID; - appo.projectID = widget.docObject.projectID; - appo.appointmentNo = - widget.patientShareResponse.appointmentNo; - appo.serviceID = widget.patientShareResponse.serviceID; - appo.isLiveCareAppointment = - widget.patientShareResponse.isLiveCareAppointment; - appo.doctorID = widget.patientShareResponse.doctorID; - confirmAppointment(appo); - }, - child: Text( - widget.patientShareResponse.isLiveCareAppointment - ? TranslationBase.of(context) - .confirmLiveCare - .toUpperCase() - : TranslationBase.of(context).confirm.toUpperCase(), - style: TextStyle(fontSize: 18.0)), - ), - ), - ButtonTheme( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10.0), - ), - minWidth: MediaQuery.of(context).size.width * 0.7, - height: 45.0, - child: RaisedButton( - color: new Color(0xFF40ACC9), - textColor: Colors.white, - disabledTextColor: Colors.white, - disabledColor: new Color(0xFFbcc2c4), - onPressed: () { - navigateToHome(context); - }, - child: Text( - TranslationBase.of(context).confirmLater.toUpperCase(), - style: TextStyle(fontSize: 18.0)), - ), - ), - ], - ), - ), ], ); } @@ -463,52 +568,6 @@ class _BookSuccessState extends State { ), ], ), - Container( - alignment: Alignment.bottomCenter, - height: MediaQuery.of(context).size.height * 0.2, - child: Column( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - ButtonTheme( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10.0), - ), - minWidth: MediaQuery.of(context).size.width * 0.7, - height: 45.0, - child: RaisedButton( - color: new Color(0xFF60686b), - textColor: Colors.white, - disabledTextColor: Colors.white, - disabledColor: new Color(0xFFbcc2c4), - onPressed: () { - startPaymentProcess(); - }, - child: Text(TranslationBase.of(context).payNow.toUpperCase(), - style: TextStyle(fontSize: 18.0)), - ), - ), - ButtonTheme( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10.0), - ), - minWidth: MediaQuery.of(context).size.width * 0.7, - height: 45.0, - child: RaisedButton( - color: new Color(0xFF40ACC9), - textColor: Colors.white, - disabledTextColor: Colors.white, - disabledColor: new Color(0xFFbcc2c4), - onPressed: () { - navigateToHome(context); - }, - child: Text( - TranslationBase.of(context).payLater.toUpperCase(), - style: TextStyle(fontSize: 18.0)), - ), - ), - ], - ), - ), ], ); } @@ -770,34 +829,34 @@ class _BookSuccessState extends State { ), ], ), - Container( - alignment: Alignment.bottomCenter, - height: MediaQuery.of(context).size.height * 0.18, - child: Column( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - ButtonTheme( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10.0), - ), - minWidth: MediaQuery.of(context).size.width * 0.7, - height: 45.0, - child: RaisedButton( - color: new Color(0xFF60686b), - textColor: Colors.white, - disabledTextColor: Colors.white, - disabledColor: new Color(0xFFbcc2c4), - onPressed: () { -// navigateToQR(context); - getAppoQR(context); - }, - child: Text(TranslationBase.of(context).viewQR.toUpperCase(), - style: TextStyle(fontSize: 18.0)), - ), - ), - ], - ), - ), +// Container( +// alignment: Alignment.bottomCenter, +// height: MediaQuery.of(context).size.height * 0.18, +// child: Column( +// mainAxisAlignment: MainAxisAlignment.end, +// children: [ +// ButtonTheme( +// shape: RoundedRectangleBorder( +// borderRadius: BorderRadius.circular(10.0), +// ), +// minWidth: MediaQuery.of(context).size.width * 0.7, +// height: 45.0, +// child: RaisedButton( +// color: new Color(0xFF60686b), +// textColor: Colors.white, +// disabledTextColor: Colors.white, +// disabledColor: new Color(0xFFbcc2c4), +// onPressed: () { +// // navigateToQR(context); +// getAppoQR(context); +// }, +// child: Text(TranslationBase.of(context).viewQR.toUpperCase(), +// style: TextStyle(fontSize: 18.0)), +// ), +// ), +// ], +// ), +// ), ], ); } diff --git a/lib/pages/BookAppointment/BookingOptions.dart b/lib/pages/BookAppointment/BookingOptions.dart index b90c3b34..83af454f 100644 --- a/lib/pages/BookAppointment/BookingOptions.dart +++ b/lib/pages/BookAppointment/BookingOptions.dart @@ -52,10 +52,11 @@ class _BookingOptionsState extends State { children: [ Expanded( child: CardCommon( - image: 'assets/images/new-design/search_by_clinic.png', - text: TranslationBase.of(context).clinic, - subText: TranslationBase.of(context).name, - type: 0), + image: 'assets/images/new-design/search_by_clinic.png', + text: TranslationBase.of(context).clinic, + subText: TranslationBase.of(context).name, + type: 0, + ), ), Expanded( child: CardCommon( diff --git a/lib/pages/BookAppointment/DentalComplaints.dart b/lib/pages/BookAppointment/DentalComplaints.dart index 043eaff1..34a7e1e1 100644 --- a/lib/pages/BookAppointment/DentalComplaints.dart +++ b/lib/pages/BookAppointment/DentalComplaints.dart @@ -2,13 +2,12 @@ import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/models/Appointments/DentalChiefComplaintsModel.dart'; import 'package:diplomaticquarterapp/models/Appointments/SearchInfoModel.dart'; import 'package:diplomaticquarterapp/pages/BookAppointment/widgets/DentalComplaintCard.dart'; +import 'package:diplomaticquarterapp/pages/livecare/widgets/clinic_card.dart'; import 'package:diplomaticquarterapp/services/clinic_services/get_clinic_service.dart'; import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; -import 'package:diplomaticquarterapp/uitl/app_toast.dart'; -import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.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:smart_progress_bar/smart_progress_bar.dart'; class DentalComplaints extends StatefulWidget { SearchInfo searchInfo; @@ -36,8 +35,7 @@ class _DentalComplaintsState extends State { Widget build(BuildContext context) { return AppScaffold( isShowAppBar: true, - appBarTitle: TranslationBase.of(context).dentalComplaints, - isShowDecPage: false, + appBarTitle: "Symptoms", body: Container( margin: EdgeInsets.fromLTRB(10.0, 10.0, 10.0, 0.0), child: ListView.builder( @@ -61,14 +59,12 @@ class _DentalComplaintsState extends State { } getChiefComplaintsList() { - GifLoaderDialogUtils.showMyDialog(context); getLanguageID(); ClinicListService service = new ClinicListService(); service .getChiefComplaintsList( widget.searchInfo.ClinicID, widget.searchInfo.ProjectID, context) .then((res) { - GifLoaderDialogUtils.hideDialog(context); if (res['MessageStatus'] == 1) { print(res['List_DentalChiefComplain']); setState(() { @@ -77,13 +73,10 @@ class _DentalComplaintsState extends State { }); print(complaintsList.length); }); - } else { - - } + } else {} }).catchError((err) { - GifLoaderDialogUtils.hideDialog(context); - AppToast.showErrorToast(message: err); print(err); - }); + }).showProgressBar( + text: "Loading", backgroundColor: Colors.blue.withOpacity(0.6)); } } diff --git a/lib/pages/BookAppointment/DoctorProfile.dart b/lib/pages/BookAppointment/DoctorProfile.dart index 20e4ae09..392eb24c 100644 --- a/lib/pages/BookAppointment/DoctorProfile.dart +++ b/lib/pages/BookAppointment/DoctorProfile.dart @@ -53,17 +53,6 @@ class _DoctorProfileState extends State length: 2, vsync: this, initialIndex: widget.isOpenAppt == true ? 1 : 0); - - // event.controller.stream.listen((p) { - // if (p['clinic_id'] != null && - // p['doctor_id'] != null && - // p['project_id'] != null) { - // setState(() { - // // need to take the data from here - // // dropdownValue = p['clinic_id']; - // }); - // } - // }); _tabController = new TabController(length: 2, vsync: this); widget.authUser = new AuthenticatedUser(); widget.doctor.speciality = widget.docProfileList.specialty; @@ -164,7 +153,7 @@ class _DoctorProfileState extends State alignment: Alignment.center, child: Text( "(" + - widget.doctor.noOfPatientsRate.toString() + + widget.docProfileList.noOfPatientsRate.toString() + " " + TranslationBase.of(context).reviews + ")", @@ -496,7 +485,7 @@ class _DoctorProfileState extends State } double getRatingWidth(int patientNumber) { - var width = (patientNumber / this.widget.doctor.noOfPatientsRate) * 100; + var width = (patientNumber / this.widget.docProfileList.noOfPatientsRate) * 100; return width; } diff --git a/lib/pages/BookAppointment/QRCode.dart b/lib/pages/BookAppointment/QRCode.dart index 487d1be7..e92c2348 100644 --- a/lib/pages/BookAppointment/QRCode.dart +++ b/lib/pages/BookAppointment/QRCode.dart @@ -10,11 +10,11 @@ import 'package:diplomaticquarterapp/services/appointment_services/GetDoctorsLis 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/dialogs/confirm_dialog.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:flutter/material.dart'; +import 'package:smart_progress_bar/smart_progress_bar.dart'; class QRCode extends StatefulWidget { PatientShareResponse patientShareResponse; @@ -235,7 +235,6 @@ class _QRCodeState extends State { okText: TranslationBase.of(context).confirm, cancelText: TranslationBase.of(context).cancel_nocaps, okFunction: () { - GifLoaderDialogUtils.showMyDialog(context); service .sendAppointmentQREmail( widget.authUser.emailAddress, @@ -248,15 +247,15 @@ class _QRCodeState extends State { widget.patientShareResponse.doctorSpeciality), context) .then((res) { - GifLoaderDialogUtils.hideDialog(context); print(res); ConfirmDialog.closeAlertDialog(context); }).catchError((err) { - GifLoaderDialogUtils.hideDialog(context); ConfirmDialog.closeAlertDialog(context); AppToast.showErrorToast(message: err); print(err); - }); + }).showProgressBar( + text: "Loading", + backgroundColor: Colors.blue.withOpacity(0.6)); }, cancelFunction: () => {}); dialog.showAlertDialog(context); diff --git a/lib/pages/BookAppointment/Search.dart b/lib/pages/BookAppointment/Search.dart index 44cf46c3..94308c1c 100644 --- a/lib/pages/BookAppointment/Search.dart +++ b/lib/pages/BookAppointment/Search.dart @@ -1,16 +1,21 @@ import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/pages/BookAppointment/components/SearchByClinic.dart'; import 'package:diplomaticquarterapp/pages/BookAppointment/components/SearchByDoctor.dart'; +import 'package:diplomaticquarterapp/uitl/location_util.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/dialogs/confirm_dialog.dart'; import 'package:diplomaticquarterapp/widgets/others/arrow_back.dart'; +import 'package:diplomaticquarterapp/widgets/others/bottom_bar.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:flutter/material.dart'; +import 'package:geolocator/geolocator.dart'; + +import 'components/SearchByClinic.dart'; class Search extends StatefulWidget { final int type; final List clnicIds; - Search({this.type = 0, this.clnicIds}); - @override _SearchState createState() => _SearchState(); } @@ -29,34 +34,40 @@ class _SearchState extends State with TickerProviderStateMixin { @override Widget build(BuildContext context) { AppGlobal.context = context; - return Scaffold( - appBar: AppBar( - bottom: TabBar( - tabs: [ - Tab(text: TranslationBase.of(context).clinicName), - Tab( - text: TranslationBase.of(context).doctorName, - ) - ], - controller: _tabController, - ), - title: Text(TranslationBase.of(context).bookAppo, - style: TextStyle(color: Colors.white)), - leading: Builder( - builder: (BuildContext context) { - return ArrowBack(); - }, - ), - ), - body: TabBarView( - physics: NeverScrollableScrollPhysics(), - children: [ - SearchByClinic( - clnicIds: widget.clnicIds, - ), - SearchByDoctor() - ], - controller: _tabController), - ); + return AppScaffold( + isShowAppBar: true, + isShowDecPage: false, + appBarTitle: TranslationBase.of(context).bookAppo, + body: Container( + child: Column( + children: [ + TabBar( + tabs: [ + Tab(text: TranslationBase.of(context).clinicName), + Tab( + text: TranslationBase.of(context).doctorName, + ) + ], + controller: _tabController, + ), + Divider( + color: Colors.grey[600], + thickness: 0.5, + ), + Expanded( + child: new TabBarView( + physics: NeverScrollableScrollPhysics(), + children: [ + SearchByClinic( + clnicIds: widget.clnicIds, + ), + SearchByDoctor() + ], + controller: _tabController, + ), + ) + ], + ), + )); } } diff --git a/lib/pages/BookAppointment/SearchResults.dart b/lib/pages/BookAppointment/SearchResults.dart index 72226c2e..0c65a789 100644 --- a/lib/pages/BookAppointment/SearchResults.dart +++ b/lib/pages/BookAppointment/SearchResults.dart @@ -27,7 +27,6 @@ class _SearchResultsState extends State { return AppScaffold( appBarTitle: TranslationBase.of(context).bookAppo, isShowAppBar: true, - isShowDecPage: false, body: Container( margin: EdgeInsets.all(10.0), child: SingleChildScrollView( @@ -37,7 +36,7 @@ class _SearchResultsState extends State { ...List.generate( widget.patientDoctorAppointmentListHospital.length, (index) => AppExpandableNotifier( - isExpand: index == 1 ? true : false, + // isExpand: index == 0 ? true : false, title: widget.patientDoctorAppointmentListHospital[index] .filterName + " - " + diff --git a/lib/pages/BookAppointment/components/DocAvailableAppointments.dart b/lib/pages/BookAppointment/components/DocAvailableAppointments.dart index 70b6aaa0..7caf1977 100644 --- a/lib/pages/BookAppointment/components/DocAvailableAppointments.dart +++ b/lib/pages/BookAppointment/components/DocAvailableAppointments.dart @@ -178,7 +178,8 @@ class _DocAvailableAppointmentsState extends State holidayStyle: TextStyle().copyWith(color: Colors.blue[800]), ), daysOfWeekStyle: DaysOfWeekStyle( - weekendStyle: TextStyle().copyWith(color: Colors.blue[600]), + weekendStyle: TextStyle().copyWith(color: Colors.black, fontSize: 14.0), + weekdayStyle: TextStyle().copyWith(color: Colors.black, fontSize: 14.0), ), headerStyle: HeaderStyle( centerHeaderTitle: true, @@ -190,7 +191,7 @@ class _DocAvailableAppointmentsState extends State opacity: Tween(begin: 0.0, end: 1.0).animate(_animationController), child: Container( margin: const EdgeInsets.all(4.0), - padding: const EdgeInsets.only(top: 5.0, left: 6.0), + padding: const EdgeInsets.only(top: 5.0, left: 5.0), color: Colors.transparent, width: 0, height: 0, @@ -380,6 +381,7 @@ class _DocAvailableAppointmentsState extends State AppToast.showErrorToast(message: res['ErrorEndUserMessage']); } }).catchError((err) { + GifLoaderDialogUtils.hideDialog(context); print(err); }); } diff --git a/lib/pages/BookAppointment/components/DocInfo.dart b/lib/pages/BookAppointment/components/DocInfo.dart index aa6e3b9f..89b9e4d0 100644 --- a/lib/pages/BookAppointment/components/DocInfo.dart +++ b/lib/pages/BookAppointment/components/DocInfo.dart @@ -1,5 +1,6 @@ import 'package:diplomaticquarterapp/models/Appointments/DoctorProfile.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_expandable_notifier.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; @@ -13,31 +14,29 @@ class DoctorInformation extends StatelessWidget { return Container( margin: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0), child: Column( + mainAxisSize: MainAxisSize.min, children: [ - Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10), + AppExpandableNotifier( + isExpand: true, + headerWidget: Container( + margin: EdgeInsets.all(10.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + SvgPicture.asset( + "assets/images/DQ/doctor_information_icon.svg"), + Container( + margin: EdgeInsets.fromLTRB(15.0, 5.0, 15.0, 0.0), + child: Text(TranslationBase.of(context).docInfo, + style: TextStyle(fontSize: 16.0, letterSpacing: 0.8)), + ), + ], + ), ), - child: Column( + bodyWidget: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.max, children: [ - Container( - margin: EdgeInsets.all(15.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - SvgPicture.asset( - "assets/images/DQ/doctor_information_icon.svg"), - Container( - margin: EdgeInsets.fromLTRB(15.0, 5.0, 15.0, 0.0), - child: Text(TranslationBase.of(context).docInfo, - style: - TextStyle(fontSize: 16.0, letterSpacing: 0.8)), - ), - ], - ), - ), Container( padding: EdgeInsets.fromLTRB(10.0, 5.0, 10.0, 10.0), child: Table( @@ -78,34 +77,32 @@ class DoctorInformation extends StatelessWidget { ], ), ), - Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10), + // ), + AppExpandableNotifier( + isExpand: true, + headerWidget: Container( + margin: EdgeInsets.all(10.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + SvgPicture.asset( + "assets/images/DQ/doctor_qualification_icon.svg"), + Container( + margin: EdgeInsets.fromLTRB(15.0, 5.0, 15.0, 0.0), + child: Text(TranslationBase.of(context).docQualifications, + style: TextStyle(fontSize: 16.0, letterSpacing: 0.8)), + ), + ], + ), ), - child: Column( + bodyWidget: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.max, children: [ - Container( - margin: EdgeInsets.all(15.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - SvgPicture.asset( - "assets/images/DQ/doctor_qualification_icon.svg"), - Container( - margin: EdgeInsets.fromLTRB(15.0, 5.0, 15.0, 0.0), - child: Text( - TranslationBase.of(context).docQualifications, - style: - TextStyle(fontSize: 16.0, letterSpacing: 0.8)), - ), - ], - ), - ), Container( margin: EdgeInsets.fromLTRB(20.0, 0.0, 10.0, 5.0), child: Column( + mainAxisSize: MainAxisSize.min, children: [ _getNormalText(docProfileList.doctorProfileInfo) ], @@ -123,7 +120,6 @@ class DoctorInformation extends StatelessWidget { return Text(text, style: TextStyle( fontSize: 13, - fontFamily: 'Open-Sans', fontWeight: FontWeight.bold, letterSpacing: 0.5, color: Colors.grey[800])); @@ -133,11 +129,9 @@ class DoctorInformation extends StatelessWidget { return Container( margin: EdgeInsets.only(top: 5.0), child: Text(text, + maxLines: 16, style: TextStyle( - fontSize: 13, - fontFamily: 'Open-Sans', - letterSpacing: 0.5, - color: Colors.grey[700])), + fontSize: 13, letterSpacing: 0.5, color: Colors.grey[700])), ); } @@ -150,10 +144,7 @@ class DoctorInformation extends StatelessWidget { children: [ Text(text.trim(), style: TextStyle( - fontSize: 13, - fontFamily: 'Open-Sans', - letterSpacing: 0.5, - color: Colors.grey[700])), + fontSize: 13, letterSpacing: 0.5, color: Colors.grey[700])), Container( margin: EdgeInsets.only(left: 5.0, right: 5.0), child: Image.network(icon, width: 18.0, height: 18.0), diff --git a/lib/pages/BookAppointment/components/SearchByClinic.dart b/lib/pages/BookAppointment/components/SearchByClinic.dart index 355bb52b..01c9ee92 100644 --- a/lib/pages/BookAppointment/components/SearchByClinic.dart +++ b/lib/pages/BookAppointment/components/SearchByClinic.dart @@ -5,7 +5,7 @@ import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart import 'package:diplomaticquarterapp/models/Appointments/SearchInfoModel.dart'; import 'package:diplomaticquarterapp/models/Clinics/ClinicListResponse.dart'; import 'package:diplomaticquarterapp/pages/BookAppointment/DentalComplaints.dart'; -import 'package:diplomaticquarterapp/pages/BookAppointment/widgets/BranchView.dart'; +import 'package:diplomaticquarterapp/pages/BookAppointment/SearchResults.dart'; import 'package:diplomaticquarterapp/services/appointment_services/GetDoctorsList.dart'; import 'package:diplomaticquarterapp/services/clinic_services/get_clinic_service.dart'; import 'package:diplomaticquarterapp/uitl/app_toast.dart'; @@ -13,6 +13,7 @@ import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/card/rounded_container.dart'; import 'package:flutter/material.dart'; +import 'package:smart_progress_bar/smart_progress_bar.dart'; class SearchByClinic extends StatefulWidget { final List clnicIds; @@ -33,6 +34,7 @@ class _SearchByClinicState extends State { List projectsList = []; bool isMobileAppDentalAllow = false; bool isLoaded = false; + bool isProjectLoaded = false; @override void initState() { @@ -55,6 +57,11 @@ class _SearchByClinicState extends State { onChanged: (bool value) { setState(() { nearestAppo = value; + print(nearestAppo); + if (nearestAppo) + getProjectsList(); + else + isProjectLoaded = false; }); }, ), @@ -120,7 +127,8 @@ class _SearchByClinicState extends State { }, ), )), - isDentalSelectedAndSupported() == true || nearestAppo + isDentalSelectedAndSupported() == true || + (nearestAppo && isProjectLoaded) ? Container( height: 60.0, decoration: BoxDecoration( @@ -136,8 +144,7 @@ class _SearchByClinicState extends State { margin: EdgeInsets.only(top: 15.0), child: DropdownButtonHideUnderline( child: DropdownButton( - hint: - new Text(TranslationBase.of(context).selectHospital), + hint: new Text("Select Project"), value: projectDropdownValue, items: projectsList.map((item) { return new DropdownMenuItem( @@ -177,24 +184,30 @@ class _SearchByClinicState extends State { }); }); getProjectsList(); + GifLoaderDialogUtils.hideDialog(context); } else {} }).catchError((err) { print(err); + GifLoaderDialogUtils.hideDialog(context); }); } getProjectsList() { ClinicListService service = new ClinicListService(); + List projectsListLocal = []; service.getProjectsList(context).then((res) { if (res['MessageStatus'] == 1) { setState(() { res['ListProject'].forEach((v) { - projectsList.add(new HospitalsModel.fromJson(v)); + projectsListLocal.add(new HospitalsModel.fromJson(v)); }); + projectsList = projectsListLocal; }); - GifLoaderDialogUtils.hideDialog(context); filterClinic(); - } else {} + isProjectLoaded = true; + } else { + isProjectLoaded = false; + } }).catchError((err) { print(err); }); @@ -216,6 +229,9 @@ class _SearchByClinicState extends State { List arrDistance = []; List result; int numAll; + List _patientDoctorAppointmentListHospital = + List(); + DoctorsListService service = new DoctorsListService(); service .getDoctorsList( @@ -228,15 +244,34 @@ class _SearchByClinicState extends State { if (res['MessageStatus'] == 1) { setState(() { if (res['DoctorList'].length != 0) { - print(res['DoctorList']); + // print(res['DoctorList']); doctorsList.clear(); res['DoctorList'].forEach((v) { doctorsList.add(new DoctorList.fromJson(v)); + }); + doctorsList.forEach((element) { + List doctorByHospital = + _patientDoctorAppointmentListHospital + .where( + (elementClinic) => + elementClinic.filterName == element.projectName, + ) + .toList(); - arr.add(new DoctorList.fromJson(v).projectName); - arrDistance.add(new DoctorList.fromJson(v) - .projectDistanceInKiloMeters - .toString()); + 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)); + } }); } else {} }); @@ -244,7 +279,7 @@ class _SearchByClinicState extends State { result = LinkedHashSet.from(arr).toList(); numAll = result.length; navigateToSearchResults( - context, doctorsList, result, numAll, arrDistance); + context, doctorsList, _patientDoctorAppointmentListHospital); } else { AppToast.showErrorToast(message: res['ErrorEndUserMessage']); } @@ -267,24 +302,26 @@ class _SearchByClinicState extends State { } Future navigateToSearchResults( - context, docList, result, numAll, resultDistance) async { - Navigator.push( context, - MaterialPageRoute( - builder: (context) => BranchView( - doctorsList: docList, - result: result, - num: numAll, - resultDistance: resultDistance), - ), - ).then((value) { + List docList, + List + patientDoctorAppointmentListHospital) async { + isProjectLoaded = false; + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => SearchResults( + isLiveCareAppointment: false, + doctorsList: docList, + patientDoctorAppointmentListHospital: + patientDoctorAppointmentListHospital))).then((value) { getProjectsList(); }); } filterClinic() { setState(() { - if (widget.clnicIds.length > 0) { + if (widget.clnicIds != null && widget.clnicIds.length > 0) { clinicsList = clinicsList .where((i) => widget.clnicIds.indexOf(i.clinicID) > -1) .toList(); diff --git a/lib/pages/BookAppointment/components/SearchByDoctor.dart b/lib/pages/BookAppointment/components/SearchByDoctor.dart index 8d2b9387..1e1945b5 100644 --- a/lib/pages/BookAppointment/components/SearchByDoctor.dart +++ b/lib/pages/BookAppointment/components/SearchByDoctor.dart @@ -4,6 +4,7 @@ import 'package:diplomaticquarterapp/uitl/app_toast.dart'; import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:flutter/material.dart'; +import 'package:smart_progress_bar/smart_progress_bar.dart'; import '../SearchResults.dart'; @@ -128,12 +129,9 @@ class _SearchByDoctorState extends State { navigateToSearchResults( context, doctorsList, _patientDoctorAppointmentListHospital); } else { - GifLoaderDialogUtils.hideDialog(context); AppToast.showErrorToast(message: res['ErrorEndUserMessage']); } }).catchError((err) { - GifLoaderDialogUtils.hideDialog(context); - AppToast.showErrorToast(message: err); print(err); }); } diff --git a/lib/pages/BookAppointment/widgets/CardCommon.dart b/lib/pages/BookAppointment/widgets/CardCommon.dart index 6a7e2bdd..b03e9b24 100644 --- a/lib/pages/BookAppointment/widgets/CardCommon.dart +++ b/lib/pages/BookAppointment/widgets/CardCommon.dart @@ -1,16 +1,14 @@ -import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/pages/BookAppointment/Search.dart'; import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; + +import '../../../Constants.dart'; class CardCommon extends StatelessWidget { - var languageID; final image; final text; final subText; final type; - - CardCommon( + const CardCommon( {@required this.image, @required this.text, @required this.subText, @@ -18,7 +16,6 @@ class CardCommon extends StatelessWidget { @override Widget build(BuildContext context) { - ProjectViewModel projectViewModel = Provider.of(context); return GestureDetector( onTap: () { navigateToSearch(context, this.type); @@ -36,7 +33,7 @@ class CardCommon extends StatelessWidget { child: Text(this.text, overflow: TextOverflow.clip, style: TextStyle( - color: new Color(0xFF40ACC9), + color: secondaryColor, letterSpacing: 1.0, fontSize: 20.0)), ), @@ -48,12 +45,8 @@ class CardCommon extends StatelessWidget { color: Colors.black, letterSpacing: 1.0, fontSize: 15.0)), ), Container( - alignment: projectViewModel.isArabic - ? Alignment.bottomLeft - : Alignment.bottomRight, - margin: projectViewModel.isArabic - ? EdgeInsets.fromLTRB(10.0, 0.0, 00.0, 8.0) - : EdgeInsets.fromLTRB(0.0, 0.0, 10.0, 8.0), + alignment: Alignment.bottomRight, + margin: EdgeInsets.fromLTRB(0.0, 0.0, 10.0, 8.0), child: Image.asset(this.image, width: 60.0, height: 60.0), ), ], diff --git a/lib/pages/BookAppointment/widgets/DentalComplaintCard.dart b/lib/pages/BookAppointment/widgets/DentalComplaintCard.dart index eb434cad..27f37d0a 100644 --- a/lib/pages/BookAppointment/widgets/DentalComplaintCard.dart +++ b/lib/pages/BookAppointment/widgets/DentalComplaintCard.dart @@ -3,9 +3,8 @@ import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart import 'package:diplomaticquarterapp/pages/BookAppointment/SearchResults.dart'; import 'package:diplomaticquarterapp/services/clinic_services/get_clinic_service.dart'; import 'package:diplomaticquarterapp/uitl/app_toast.dart'; -import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; -import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:flutter/material.dart'; +import 'package:smart_progress_bar/smart_progress_bar.dart'; // ignore: must_be_immutable class DentalComplaintCard extends StatefulWidget { @@ -70,15 +69,14 @@ class _DentalComplaintCardState extends State { List doctorsList = []; List _patientDoctorAppointmentListHospital = List(); - GifLoaderDialogUtils.showMyDialog(context); + ClinicListService service = new ClinicListService(); service .getChiefComplaintDoctorList(widget.listDentalChiefComplain.iD, widget.listDentalChiefComplain.projectID, context) .then((res) { - GifLoaderDialogUtils.hideDialog(context); if (res['MessageStatus'] == 1) { - print(res['ErrorEndUserMessage']); + print(res['List_DentalDoctorChiefComplaintMapping']); setState(() { doctorsList.clear(); res['List_DentalDoctorChiefComplaintMapping'].forEach((v) { @@ -109,21 +107,16 @@ class _DentalComplaintCardState extends State { patientDoctorAppointment: element)); } }); - if (doctorsList.length != 0) { - navigateToSearchResults( - context, doctorsList, _patientDoctorAppointmentListHospital); - } else { - AppToast.showErrorToast(message: TranslationBase.of(context).emptyResult); - } + navigateToSearchResults( + context, doctorsList, _patientDoctorAppointmentListHospital); }); } else { AppToast.showErrorToast(message: res['ErrorEndUserMessage']); } }).catchError((err) { - GifLoaderDialogUtils.hideDialog(context); - AppToast.showErrorToast(message: err); print(err); - }); + }).showProgressBar( + text: "Loading", backgroundColor: Colors.blue.withOpacity(0.6)); } Future navigateToSearchResults( diff --git a/lib/pages/BookAppointment/widgets/DoctorView.dart b/lib/pages/BookAppointment/widgets/DoctorView.dart index bd4fb429..d419e4af 100644 --- a/lib/pages/BookAppointment/widgets/DoctorView.dart +++ b/lib/pages/BookAppointment/widgets/DoctorView.dart @@ -6,6 +6,7 @@ import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; import 'package:flutter/material.dart'; import 'package:rating_bar/rating_bar.dart'; +import 'package:smart_progress_bar/smart_progress_bar.dart'; import '../DoctorProfile.dart'; diff --git a/lib/pages/ChildVaccines/ChidDetailsWidget.dart b/lib/pages/ChildVaccines/ChidDetailsWidget.dart deleted file mode 100644 index c06c5422..00000000 --- a/lib/pages/ChildVaccines/ChidDetailsWidget.dart +++ /dev/null @@ -1,120 +0,0 @@ -import 'package:diplomaticquarterapp/core/model/childvaccines/List_BabyInformationModel.dart'; -import 'package:diplomaticquarterapp/core/model/childvaccines/delete_baby_model.dart'; -import 'package:diplomaticquarterapp/core/model/childvaccines/user_information_model.dart'; -import 'package:diplomaticquarterapp/core/viewModels/child_vaccines/child_vaccines_view_model.dart'; -import 'package:diplomaticquarterapp/pages/ChildVaccines/vaccinationtable_page.dart'; -import 'package:diplomaticquarterapp/uitl/app_toast.dart'; -import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; -import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; -import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; -import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_flexible_toast/flutter_flexible_toast.dart'; - -import 'dialogs/delete_child.dart'; - -class ChildDetailsWidget extends StatelessWidget { - final ChildVaccinesViewModel model; - final List_BabyInformationModel babyInfo; - final List_UserInformationModel informationModel; - final Function onTapDelete; - - ChildDetailsWidget({this.model, this.babyInfo, this.informationModel, this.onTapDelete}); - - @override - Widget build(BuildContext context) { - return InkWell( - onTap: (){ - Navigator.push( - context, - FadePage( - page: VaccinationTablePage( - babyInfo: babyInfo, - informationModel: informationModel, - ), - ), - ); - }, - child: Container( - margin: EdgeInsets.only(left: 5, right: 5, bottom: 10), - decoration: BoxDecoration( - shape: BoxShape.rectangle, - border: Border.all(color: Colors.white, width: 0.5), - borderRadius: BorderRadius.all(Radius.circular(5)), - color: Colors.white, - ), - padding: EdgeInsets.all(12), - width: 200, - //double.infinity, - child: Column( - children: [ - Row(children: [ - Texts(TranslationBase.of(context).childName), - ]), - Row(children: [ - Texts(babyInfo.babyName.trim()), - ]), - Row(children: [ - IconButton( - icon: Image.asset(babyInfo.gender == 1 - ? 'assets/images/new-design/male.png' - : 'assets/images/new-design/female.png'), - tooltip: '', - onPressed: () { - }, - ), - Texts(babyInfo.genderDescription), - IconButton( - icon: Icon( - Icons.remove_red_eye, - color: Colors.red, - ), - tooltip: '', - onPressed: () { - Navigator.push( - context, - FadePage( - page: VaccinationTablePage( - babyInfo: babyInfo, - informationModel: informationModel, - ), - ), - ); - }, - ) - ]), - Row(children: [ - Texts(TranslationBase.of(context).childDob), - ]), - Row( - children: [ - IconButton( - icon: new Image.asset( - 'assets/images/new-design/calender-secondary.png'), - tooltip: '', - ), - Texts( - DateUtil.yearMonthDay(babyInfo.dOB), - ), - ], - ), - Row(children: [ - IconButton( - icon: new Image.asset('assets/images/new-design/garbage.png'), - tooltip: '', - onPressed: () async { - onTapDelete(); - }, - ), - Texts(TranslationBase.of(context).delete), - ]), - SizedBox( - height: 12, - ), - ], - ), - ), - ); - } -} diff --git a/lib/pages/ChildVaccines/add_newchild_page.dart b/lib/pages/ChildVaccines/add_newchild_page.dart index 10dea666..51b89f98 100644 --- a/lib/pages/ChildVaccines/add_newchild_page.dart +++ b/lib/pages/ChildVaccines/add_newchild_page.dart @@ -11,7 +11,6 @@ import 'package:diplomaticquarterapp/pages/ChildVaccines/child_page.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; import 'package:diplomaticquarterapp/pages/medical/active_medications/DayCheckBoxDialog.dart'; import 'package:diplomaticquarterapp/uitl/app_toast.dart'; -import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/buttons/secondary_button.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; @@ -22,16 +21,39 @@ import 'package:flutter_datetime_picker/flutter_datetime_picker.dart'; import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; enum Gender { Male, Female, NON } +enum BeneficiaryType { MyAccount, MyFamilyFiles, OtherAccount, NON } class AddNewChildPage extends StatefulWidget { + final int frequency; + final int days; + final String itemDescription; String dateAdd; + List _scheduleList = List(); + List daysOfWeek = [ + DayOfWeek.Monday, + DayOfWeek.Tuesday, + DayOfWeek.Wednesday, + DayOfWeek.Thursday, + DayOfWeek.Friday, + DayOfWeek.Saturday, + DayOfWeek.Sunday + ]; + DateTime startDay; DateTime endDay; - AddNewChildPage() { + //AddNewChildPage({Key key, this.frequency, this.days, this.itemDescription}) : super(key: key); + AddNewChildPage({Key key, this.frequency, this.days, this.itemDescription}) { startDay = DateTime.now(); - endDay = DateTime.now(); + endDay = + DateTime.now(); //endDay = DateTime.now().add(Duration(days: days)); + int hour = 24; //(24 / frequency).round(); + int durations = 24 ~/ hour; + for (int count = 0; count < durations; count++) { + _scheduleList.add(DateTime(DateTime.now().year, DateTime.now().month, + DateTime.now().day, (hour * count))); + } } @override @@ -39,140 +61,150 @@ class AddNewChildPage extends StatefulWidget { } class _AddNewChildPageState extends State { + int tappedIndex; int checkedValue; + @override + void initState() { + super.initState(); + tappedIndex = -1; + } + TextEditingController _firstTextController = TextEditingController(); TextEditingController _secondTextController = TextEditingController(); + TextEditingController _notesTextController = TextEditingController(); + BeneficiaryType beneficiaryType = BeneficiaryType.NON; Gender gender = Gender.Male; CreateNewUser_New newUserChild = CreateNewUser_New(); + //ChildVaccinesViewModel addvancedModel = ChildVaccinesViewModel(); + List_BabyInformationModel addvancedModel = List_BabyInformationModel(); CreateNewBaby newChild = CreateNewBaby(); - - String firstName = ""; - String secondName = ""; + List_UserInformationModel informationModel = List_UserInformationModel(); @override Widget build(BuildContext context) { return BaseView( builder: (_, model, w) => AppScaffold( isShowAppBar: true, - appBarTitle: TranslationBase.of(context).vaccination, + appBarTitle: "Vaccintion", body: SingleChildScrollView( physics: ScrollPhysics(), child: Container( margin: EdgeInsets.all(12), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + // crossAxisAlignment: CrossAxisAlignment.center, children: [ SizedBox( - height: 25, + height: 50, + ), + Texts( + "Add the child's information below to recieve the schedule of vaccinations.", + //+model.user.firstName, + textAlign: TextAlign.center, ), - Texts(TranslationBase.of(context).addInstructions), SizedBox( - height: 20, + height: 12, ), NewTextFields( - hintText: TranslationBase.of(context).firstName, + hintText: "First Name", controller: _firstTextController, - onChanged: (value) { - setState(() { - firstName = value; - }); - }, ), SizedBox( height: 12, ), NewTextFields( - hintText: TranslationBase.of(context).lastName, + hintText: "Second Name", controller: _secondTextController, - onChanged: (value) { - secondName = value; - }, ), SizedBox( - height: 20, + height: 12, ), Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - TranslationBase.of(context).gender + " :", + "Gender:", textAlign: TextAlign.end, ), ], ), - SizedBox( - height: 15, - ), Container( - height: 60, + height: MediaQuery.of(context).size.height * 0.12, width: double.infinity, + padding: EdgeInsets.all(12), + + child: Row( crossAxisAlignment: CrossAxisAlignment.stretch, mainAxisAlignment: MainAxisAlignment.center, children: [ - Expanded( - child: AnimatedContainer( - duration: Duration(milliseconds: 400), - height: 60, - color: Colors.white, - child: SecondaryButton( - textColor: - checkedValue == 1 ? Colors.white : Colors.black, - color: - checkedValue == 1 ? Colors.red : Colors.white, - label: TranslationBase.of(context).male, - onTap: () { - setState(() { - checkedValue = 1; - }); - }, - ), + Container( + height: MediaQuery.of(context).size.height * 0.12, + width: 175, + color: Colors.white, + child: SecondaryButton( + textColor: + checkedValue == 1 ? Colors.white : Colors.black, + color: checkedValue == 1 ? Colors.red : Colors.white, + + label: "Male", + // + onTap: () { + + setState(() { + checkedValue = 1; + print("checkedValue=" + checkedValue.toString()); + }); + + // bloodDetails. + }, ), ), - Expanded( - child: AnimatedContainer( - duration: Duration(milliseconds: 400), - height: 60, - color: Colors.white, - child: SecondaryButton( - textColor: - checkedValue == 2 ? Colors.white : Colors.black, - color: - checkedValue == 2 ? Colors.red : Colors.white, - label: TranslationBase.of(context).female, - onTap: () { - setState(() { - checkedValue = 2; - }); - }, - ), + Container( + height: MediaQuery.of(context).size.height * 0.12, + width: 175, + color: Colors.white, + child: SecondaryButton( + textColor: + checkedValue == 2 ? Colors.white : Colors.black, + color: checkedValue == 2 ? Colors.red : Colors.white, + label: "Female", + // + onTap: () { + setState(() { + checkedValue = 2; + print("checkedValue=" + checkedValue.toString()); + }); + // bloodDetails.city=_selectedHospital.toString(); + + // bloodDetails. + }, ), ) ], ), ), + //========== SizedBox( - height: 20, + height: 6, ), Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - TranslationBase.of(context).dob + " :", + "Date Of Birth::", textAlign: TextAlign.end, ), ], ), - SizedBox( - height: 8, - ), InkWell( onTap: () { DatePicker.showDatePicker( context, showTitleActions: true, + // minTime: DateTime( + // DateTime.now().year, DateTime.now().month - 1, 1), minTime: DateTime(1, 1, 1), maxTime: DateTime.now(), onConfirm: (date) { @@ -181,6 +213,7 @@ class _AddNewChildPageState extends State { }); }, currentTime: widget.startDay, + // locale: projectViewModel.localeType ); }, child: Container( @@ -191,63 +224,99 @@ class _AddNewChildPageState extends State { borderRadius: BorderRadius.circular(12), color: Colors.white), child: Row( - // mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + Texts(//getStartDay() + // DateUtil.yearMonthDay(DateTime.now()) + getStartDay()), Icon( Icons.calendar_today, color: Colors.black, - ), - SizedBox( - width: 25, - ), - Expanded(child: Texts(getStartDay())), + ) ], ), ), ), SizedBox( - height: 25, + height: 12, ), Container( - height: 60, + height: MediaQuery.of(context).size.height * 0.12, width: double.infinity, + padding: EdgeInsets.all(15), child: SecondaryButton( textColor: Colors.white, - color: Colors.grey[800], - disabled: (checkedValue == null || - firstName.isEmpty || - secondName.isEmpty), - label: TranslationBase.of(context).add, - onTap: () async { - newChild.babyName = _firstTextController.text + - " " + - _secondTextController.text; + color: checkedValue == false + ? Colors.white24 + : Color.fromRGBO( + 63, + 72, + 74, + 1, + ), + label: "Add", + // + onTap: () async{ + newChild.babyName = _firstTextController.text + " " + _secondTextController.text; newChild.gender = checkedValue.toString(); - newChild.strDOB = widget.startDay.toIso8601String(); + newChild.strDOB = getStartDay(); newChild.tempValue = true; newChild.isLogin = true; await model.createNewBabyOrders(newChild: newChild); - if (model.isAdded) { - AppToast.showSuccessToast( - message: TranslationBase.of(context).addedChild); - Navigator.pop(context, model.isAdded); - } else { - AppToast.showSuccessToast(message: model.error); + if(model.isAdded){ + AppToast.showSuccessToast(message: "Record Added"); + Navigator.pop(context,model.isAdded); + }else{ + + //TODO handling error } + }, ), ), + //========= ], ), ), ), - // bottomSheet: + // bottomSheet: ), ); } String getStartDay() { - return "${widget.startDay.day}-${widget.startDay.month}-${widget.startDay.year}"; + return "${DateUtil.getMonth(widget.startDay.month)} ${widget.startDay.day}, ${widget.startDay.year}"; + } + + String getEndDay() { + return "${DateUtil.getMonth(widget.endDay.month)} ${widget.endDay.day}, ${widget.endDay.year}"; + } + + String getDateTime(DateTime dateTime) { + return '${dateTime.hour}:${dateTime.minute}'; + } + + String getDays() { + String days = ""; + widget.daysOfWeek.forEach((element) { + days += "${DateUtil.getDay(element)},"; + }); + return days; + } + + void confirmSelectDayDialog() { + showDialog( + context: context, + child: DayCheckBoxDialog( + title: 'Select Day', + selectedDaysOfWeek: widget.daysOfWeek, + onValueSelected: (value) { + setState(() { + widget.daysOfWeek = value; + }); + }, + ), + ); } } diff --git a/lib/pages/ChildVaccines/child_page.dart b/lib/pages/ChildVaccines/child_page.dart index 45020f79..806a5b71 100644 --- a/lib/pages/ChildVaccines/child_page.dart +++ b/lib/pages/ChildVaccines/child_page.dart @@ -1,12 +1,10 @@ import 'package:diplomaticquarterapp/core/model/childvaccines/List_BabyInformationModel.dart'; import 'package:diplomaticquarterapp/core/model/childvaccines/delete_baby_model.dart'; -import 'package:diplomaticquarterapp/core/model/childvaccines/user_information_model.dart'; import 'package:diplomaticquarterapp/core/viewModels/child_vaccines/child_vaccines_view_model.dart'; import 'package:diplomaticquarterapp/pages/ChildVaccines/add_newchild_page.dart'; import 'package:diplomaticquarterapp/pages/ChildVaccines/vaccinationtable_page.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/secondary_button.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; @@ -14,109 +12,191 @@ import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; -import 'package:flutter_flexible_toast/flutter_flexible_toast.dart'; -import 'ChidDetailsWidget.dart'; import 'dialogs/delete_child.dart'; class ChildPage extends StatefulWidget { - final List_UserInformationModel informationModel; - - const ChildPage({Key key, this.informationModel}) : super(key: key); - @override _ChildPageState createState() => _ChildPageState(); } class _ChildPageState extends State with SingleTickerProviderStateMixin { + DeleteBaby deleteBaby = DeleteBaby(); @override Widget build(BuildContext context) { var checkedValue = true; return BaseView( - onModelReady: (model) => model.getNewUserOrders(), - builder: (_, model, w) => AppScaffold( - isShowAppBar: true, - appBarTitle: TranslationBase.of(context).vaccination, - baseViewModel: model, - body: SingleChildScrollView( - child: Container( - margin: EdgeInsets.only(left: 10, right: 10, top: 10), - child: Column( - children: [ - GridView.builder( - shrinkWrap: true, - primary: false, - physics: NeverScrollableScrollPhysics(), - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - childAspectRatio: MediaQuery.of(context).size.width / - (MediaQuery.of(context).size.height / 1.45), - ), - itemCount: model.babyInformationModelList.length, - itemBuilder: (BuildContext context, int index) { - return ChildDetailsWidget( - model: model, - babyInfo: model.babyInformationModelList[index], - informationModel: widget.informationModel, - onTapDelete: () { - showDialog( - context: context, - child: DeleteChild(onTap: () async { - await model.deleteBabyOrders(babyInfo: model.babyInformationModelList[index]); - if (model.isDeleted) { - AppToast.showSuccessToast( - message: - TranslationBase.of(context).emailSuccess, - toastLength: Toast.LENGTH_LONG); - } else { - AppToast.showSuccessToast(message: model.error); - } - }), - ); - }, - ); + onModelReady: (model) => model.getNewUserOrders(), + builder: (_, model, widget) => AppScaffold( + isShowAppBar: true, + appBarTitle: " Vaccination", + baseViewModel: model, + body: SingleChildScrollView( + child: Container( + margin: EdgeInsets.only(left: 15, right: 15, top: 70), + child: Column( + children: [ + ...List.generate( + model.babyInformationModelList.length, + (index) => Container( + margin: EdgeInsets.only( + left: 0, right: 0, bottom: 20), + + decoration: BoxDecoration( + shape: BoxShape.rectangle, + border: Border.all( + color: Colors.white, width: 0.5), + borderRadius: + BorderRadius.all(Radius.circular(5)), + color: Colors.white, + ), + padding: EdgeInsets.all(12), + width: 200,//double.infinity, + child: Column( + children: [ + Row(children: [ + Texts("CHILD NAME"), + ]), + Row(children: [ + Texts(model + .babyInformationModelList[index] + .babyName + .trim()), + ]), + Row(children: [ + IconButton( + icon: Image.asset(model + .babyInformationModelList[ + index] + .gender == + 1 + ? 'assets/images/new-design/male.png' + : 'assets/images/new-design/female.png'), + tooltip: '', + onPressed: () { + setState(() { + // _volume += 10; + // launch("tel://" +model.FindusHospitalModelList[index].phoneNumber); + }); + }, + ), + Texts(model + .babyInformationModelList[index] + .genderDescription), + IconButton( + icon: Icon( + Icons.remove_red_eye, + color: Colors.red, + ), + tooltip: '', + onPressed: () { + Navigator.push( + context, + FadePage( + + + page: VaccinationTablePage(), + + + ), + ); + + }, + ) + ]), + Row(children: [ + Texts("Birthday"), + ]), + Row(children: [ + IconButton( + icon: new Image.asset( + 'assets/images/new-design/calender-secondary.png'), + tooltip: '', + onPressed: () { + setState(() { + + }); + }, + ), + Texts(DateUtil.yearMonthDay(model + .babyInformationModelList[index] + .dOB)), + ]), + Row(children: [ + IconButton( + icon: new Image.asset( + 'assets/images/new-design/garbage.png'), + tooltip: '', + onPressed: ()async { + + //===================== + await model.deleteBabyOrders(newChild:deleteBaby ); + + + deleteBaby.babyID=model.babyInformationModelList[index] + .babyID; + + await model.deleteBabyOrders(newChild:deleteBaby ); + if(model.isDeleted){ + AppToast.showSuccessToast(message: "Record Deleted"); + Navigator.pop(context,model.isDeleted); + }else{ + + //TODO handling error + } + + + + + + }, + ), + Texts("Delete"), + ]), + SizedBox( + height: 12, + ), + ], + ), + + ), + + + ) + ], + )) + ), + bottomSheet: Container( + height: MediaQuery.of(context).size.height * 0.12, + width: double.infinity, + padding: EdgeInsets.all(15), + child: SecondaryButton( + textColor: Colors.white, + color: checkedValue == false + ? Colors.white24 + : Color.fromRGBO( + 63, + 72, + 74, + 1, + ), + label: "ADD NEW CHILD ", + // + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => AddNewChildPage(), + ), + ).then((value) { + if (value) model.getNewUserOrders(); + }); }, ), - SizedBox( - height: 15, - ), - ], - ), - ), - ), - bottomSheet: Container( - height: MediaQuery.of(context).size.height * 0.10, - width: double.infinity, - padding: EdgeInsets.all(15), - child: SecondaryButton( - textColor: Colors.white, - color: checkedValue == false - ? Colors.white24 - : Color.fromRGBO( - 63, - 72, - 74, - 1, - ), - label: TranslationBase.of(context).addChild, - // - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => AddNewChildPage(), - ), - ).then((value) { - if (value!=null) - model.getNewUserOrders(); - }); - }, - ), - ), - ), - ); + ), + )); } } diff --git a/lib/pages/ChildVaccines/child_vaccines_page.dart b/lib/pages/ChildVaccines/child_vaccines_page.dart index e3503894..92f3a0be 100644 --- a/lib/pages/ChildVaccines/child_vaccines_page.dart +++ b/lib/pages/ChildVaccines/child_vaccines_page.dart @@ -1,10 +1,10 @@ + import 'package:diplomaticquarterapp/core/viewModels/child_vaccines/child_vaccines_view_model.dart'; import 'package:diplomaticquarterapp/core/viewModels/child_vaccines/user_information_view_model.dart'; import 'package:diplomaticquarterapp/core/viewModels/medical/my_balance_view_model.dart'; import 'package:diplomaticquarterapp/pages/ChildVaccines/child_page.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/secondary_button.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/input/text_field.dart'; @@ -13,142 +13,214 @@ import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; + + class ChildVaccinesPage extends StatefulWidget { @override _ChildVaccinesPageState createState() => _ChildVaccinesPageState(); } class _ChildVaccinesPageState extends State - with SingleTickerProviderStateMixin { + with SingleTickerProviderStateMixin{ TextEditingController titleController = TextEditingController(); - var checkedValue = false; - String addEmail = ""; - final updateEmailFormKey = GlobalKey(); - + var checkedValue=false; + String addEmail=""; @override Widget build(BuildContext context) { + return BaseView( onModelReady: (model) => model.getUserInformationRequestOrders(), builder: (_, model, w) => AppScaffold( - isShowAppBar: true, - baseViewModel: model, - appBarTitle: TranslationBase.of(context).vaccination, - body: SingleChildScrollView( - physics: ScrollPhysics(), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - SizedBox( - height: 20, - ), - Padding( - padding: const EdgeInsets.all(10.0), - child: Container( - child: Texts( - TranslationBase.of(context).welcomeBackV, - fontSize: 20, + isShowAppBar: true, + baseViewModel: model, + appBarTitle: " Vaccination",//TranslationBase.of(context).advancePayment, + body: SingleChildScrollView( + physics: ScrollPhysics(), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + SizedBox( + height: 20, ), - ), - ), - Divider( - color: Colors.black, - indent: 10, - endIndent: 10, - ), - SizedBox( - height: 20, - ), - Padding( - padding: const EdgeInsets.all(10.0), - child: Container( - child: Texts( - TranslationBase.of(context).instructions, - fontSize: 20, + + Padding( + padding: const EdgeInsets.all(10.0), + child:Container( + child: Texts("Welcome back",fontSize: 20,), + ) , ), - ), - ), - Divider( - color: Colors.black, - indent: 10, - endIndent: 10, - ), - Form( - key: updateEmailFormKey, - child: Padding( - padding: const EdgeInsets.all(10.0), - child: Container( - margin: EdgeInsets.only(left: 10, right: 10, top: 15), - child: TextFields( - fillColor: Colors.red, - initialValue: model.userInformationModelList.emailAddress, - fontSize: 20, - hintColor: Colors.black, - fontWeight: FontWeight.w600, - onChanged: (text) { - setState(() { - addEmail = text; - }); - }, - validator: (value) { - if (value.isEmpty) - return TranslationBase.of(context).enterEmail; - else if (!RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+").hasMatch(value)) - return TranslationBase.of(context).validEmail; - return null; - }, + Divider(color:Colors.black , indent: 10, + endIndent: 10,), + SizedBox( + height: 20, + ), + Padding( + padding: const EdgeInsets.all(10.0), + child:Container( + child: Texts("Please ensure that the email address is up-to-date and process to view the schedule",fontSize: 20,), + ) , + ), + + Divider(color:Colors.black , indent: 10, + endIndent: 10,), + Padding( + padding: const EdgeInsets.all(10.0), + child:Container( + + margin: EdgeInsets.only(left: 10, right: 10, top: 15), + child: TextFields( + fillColor: Colors.red, + + hintText: model.user.emailAddress, + controller: titleController, + fontSize: 20, + hintColor: Colors.black, + fontWeight: FontWeight.w600, + onChanged: (text) { + addEmail=text; + model.user.emailAddress==addEmail?checkedValue=false:checkedValue=true; + + + }, + validator: (value) { + + if (value == null) + { + return model.user.emailAddress; + + } + else + + { + return model.user.emailAddress;} + }, + ), ), ), - ), - ), - Container( - height: MediaQuery.of(context).size.height * 0.10, - width: double.infinity, - padding: EdgeInsets.all(15), - child: SecondaryButton( - textColor: Colors.white, - color: model.userInformationModelList.emailAddress == addEmail ? Colors.white24 : Color.fromRGBO(63, 72, 74, 1,), - disabled: addEmail.isEmpty, - label: TranslationBase.of(context).updateEmail, - onTap: () async{ - final form = updateEmailFormKey.currentState; - if (form.validate()) { - form.save(); - await model.updateEmail(addEmail); - AppToast.showSuccessToast(message: TranslationBase.of(context).updatedEmail); - } - - }, - ), - ), - Container( - height: MediaQuery.of(context).size.height * 0.10, - width: double.infinity, - padding: EdgeInsets.all(15), - child: SecondaryButton( - textColor: Colors.white, - color: Color.fromRGBO( - 63, - 72, - 74, - 1, + Container( + height: MediaQuery.of(context).size.height * 0.12, + width: double.infinity, + + padding: EdgeInsets.all(15), + child: SecondaryButton( + textColor: Colors.white, + color: checkedValue== false ?Colors.white24:Color.fromRGBO(63, 72, 74, 1,), + label: "UPDATE EMAIL", + // + onTap: (){ + model.user.emailAddress=addEmail.toString(); + AppToast.showSuccessToast( + message: "Email updated"); + // bloodDetails.city=_selectedHospital.toString(); + + // bloodDetails. + }, + + + ), ), - label: TranslationBase.of(context).viewListChildren, - onTap: () => Navigator.push( - context, - FadePage( - page: ChildPage(informationModel: model.userInformationModelList,), + Container( + height: MediaQuery.of(context).size.height * 0.12, + width: double.infinity, + + padding: EdgeInsets.all(15), + child: SecondaryButton( + textColor: Colors.white, + color: Color.fromRGBO(63, 72, 74, 1,), + label: " VIEW LIST OF CHILDREN", + // + onTap: () => Navigator.push( + context, + FadePage( + page: ChildPage(), + + + + ), + ), + + ), ), - ), + + // Texts( + // // TranslationBase.of(context).advancePaymentLabel, + // model.user.emailAddress, + // textAlign: TextAlign.center, + // ), + SizedBox( + height: 12, + ), + SizedBox( + height: 12, + ), + SizedBox( + height: 12, + ), + + SizedBox( + height: 12, + ), + + SizedBox( + height: 12, + ), + + SizedBox( + height: 10, + ), + // Row( + // mainAxisAlignment: MainAxisAlignment.center, + // crossAxisAlignment: CrossAxisAlignment.center, + // children: [ + // Center( + // child: Container( + // color: Colors.white, + // width: 350, + // child: InkWell( + // onTap: () { + // showDialog( + // context: context, + // builder: (_) => + // AssetGiffyDialog( + // title: Text( + // "", + // style: TextStyle( + // fontSize: 22.0, + // fontWeight: + // FontWeight + // .w600), + // ), + // image: Image.asset( + // 'assets/images/BloodChrt_EN.png'), + // buttonCancelText: + // Text('cancel'), + // buttonCancelColor: + // Colors.grey, + // onlyCancelButton: true, + // )); + // }, + // child: Container( + // width: 250, + // height: 200, + // child:Image.asset( + // 'assets/images/BloodChrt_EN.png')), + // ), + // ), + // ), + // ], + // ), + + SizedBox( + height: MediaQuery.of(context).size.height * 0.15, + ) + ], ), - SizedBox( - height: MediaQuery.of(context).size.height * 0.15, - ) - ], + + ), ), - ), - ), ); } } + diff --git a/lib/pages/ChildVaccines/dialogs/ConfirmSendEmailDialog.dart b/lib/pages/ChildVaccines/dialogs/SelectGenderDialog.dart similarity index 70% rename from lib/pages/ChildVaccines/dialogs/ConfirmSendEmailDialog.dart rename to lib/pages/ChildVaccines/dialogs/SelectGenderDialog.dart index 2279dd51..259bbdb7 100644 --- a/lib/pages/ChildVaccines/dialogs/ConfirmSendEmailDialog.dart +++ b/lib/pages/ChildVaccines/dialogs/SelectGenderDialog.dart @@ -5,18 +5,15 @@ import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -class ConfirmSendEmailDialog extends StatefulWidget { - final email; - final Function onTap; - - const ConfirmSendEmailDialog({Key key, this.email, this.onTap}) - : super(key: key); +class SelectGenderDialog extends StatefulWidget { + final Email; + const SelectGenderDialog({Key key, this.Email}) : super(key: key); @override - _ConfirmSendEmailDialogState createState() => _ConfirmSendEmailDialogState(); + _SelectGenderDialogState createState() => _SelectGenderDialogState(); } -class _ConfirmSendEmailDialogState extends State { +class _SelectGenderDialogState extends State { @override Widget build(BuildContext context) { return SimpleDialog( @@ -24,15 +21,22 @@ class _ConfirmSendEmailDialogState extends State { Container( child: Column( children: [ - Texts(TranslationBase.of(context).confirm), Divider(), Row( children: [ Expanded( flex: 1, - child: ListTile( - title: Text(TranslationBase.of(context).confirmSend + - "\n ${widget.email} "), + child: InkWell( + onTap: () { + setState(() { + //beneficiaryType = Gender.Male; + }); + }, + child: ListTile( + title: Text("Send the child's schedule to the email\n Tamer.dasdasdas@gmail.com "), + + + ), ), ) ], @@ -40,7 +44,15 @@ class _ConfirmSendEmailDialogState extends State { SizedBox( height: 5.0, ), + + SizedBox( + height: 5.0, + ), + SizedBox( + height: 5.0, + ), Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( flex: 1, @@ -70,7 +82,8 @@ class _ConfirmSendEmailDialogState extends State { flex: 1, child: InkWell( onTap: () { - widget.onTap(); + AppToast.showSuccessToast(message: "Email Sended"); + // widget.onValueSelected(beneficiaryType); Navigator.pop(context); }, child: Padding( @@ -92,4 +105,7 @@ class _ConfirmSendEmailDialogState extends State { ], ); } + + + } diff --git a/lib/pages/ChildVaccines/dialogs/delete_child.dart b/lib/pages/ChildVaccines/dialogs/delete_child.dart index 41b02bd5..250f40d3 100644 --- a/lib/pages/ChildVaccines/dialogs/delete_child.dart +++ b/lib/pages/ChildVaccines/dialogs/delete_child.dart @@ -6,10 +6,6 @@ import 'package:flutter/material.dart'; class DeleteChild extends StatefulWidget { - final Function onTap; - - const DeleteChild({Key key, this.onTap}) : super(key: key); - @override _DeleteChildState createState() => _DeleteChildState(); } @@ -22,14 +18,21 @@ class _DeleteChildState extends State { Container( child: Column( children: [ - Texts(TranslationBase.of(context).confirm), Divider(), Row( children: [ Expanded( - child: ListTile( - title: Texts(TranslationBase.of(context).deletedChild), + flex: 1, + child: InkWell( + onTap: () { + setState(() { + //beneficiaryType = Gender.Male; + }); + }, + child: ListTile( + title: Text("Delete the child "), + ), ), ) ], @@ -37,7 +40,15 @@ class _DeleteChildState extends State { SizedBox( height: 5.0, ), + + SizedBox( + height: 5.0, + ), + SizedBox( + height: 5.0, + ), Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( flex: 1, @@ -67,7 +78,7 @@ class _DeleteChildState extends State { flex: 1, child: InkWell( onTap: () { - widget.onTap(); + // widget.onValueSelected(beneficiaryType); Navigator.pop(context); }, child: Padding( diff --git a/lib/pages/ChildVaccines/vaccinationtable_page.dart b/lib/pages/ChildVaccines/vaccinationtable_page.dart index 68734c9a..c160acfb 100644 --- a/lib/pages/ChildVaccines/vaccinationtable_page.dart +++ b/lib/pages/ChildVaccines/vaccinationtable_page.dart @@ -1,181 +1,101 @@ -import 'package:diplomaticquarterapp/core/model/childvaccines/List_BabyInformationModel.dart'; -import 'package:diplomaticquarterapp/core/model/childvaccines/user_information_model.dart'; import 'package:diplomaticquarterapp/core/viewModels/child_vaccines/vaccination_table_view_model.dart'; import 'package:diplomaticquarterapp/core/viewModels/medical/reports_monthly_view_model.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; -import 'package:diplomaticquarterapp/uitl/app_toast.dart'; -import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/buttons/secondary_button.dart'; -import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_flexible_toast/flutter_flexible_toast.dart'; import 'package:flutter_html/flutter_html.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'dialogs/ConfirmSendEmailDialog.dart'; +import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; -class VaccinationTablePage extends StatelessWidget { - final List_BabyInformationModel babyInfo; - final List_UserInformationModel informationModel; - - const VaccinationTablePage({Key key, this.babyInfo, this.informationModel}) - : super(key: key); +import 'dialogs/SelectGenderDialog.dart'; +class VaccinationTablePage extends StatelessWidget { @override Widget build(BuildContext context) { var checkedValue; return BaseView( - onModelReady: (model) => model.getCreateVaccinationTable(babyInfo: babyInfo, informationModel: informationModel), + onModelReady: (model) => model.getCreateVaccinationTable(),//getUserTermsAndConditions(), builder: (_, model, w) => AppScaffold( isShowAppBar: true, baseViewModel: model, - appBarTitle: TranslationBase.of(context).vaccination, + appBarTitle: "Vaccination", body: SingleChildScrollView( - child: Container( - margin: EdgeInsets.only(left: 15, right: 15, top: 10), + child:Container( + margin: EdgeInsets.only(left: 15,right: 15,top: 70), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Expanded( - child: Column( - children: [ - Texts(TranslationBase.of(context).childName), - Texts( - babyInfo.babyName ?? '', - fontWeight: FontWeight.w600, - ), - ], - ), - ), - Expanded( - child: Column( - children: [ - Texts(TranslationBase.of(context).childDob), - Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - FontAwesomeIcons.calendarCheck, - color: Colors.red, - ), - SizedBox( - width: 15, - ), - Texts(DateUtil.yearMonthDay(babyInfo.dOB) ?? ''), - ], - ), - ], - ), - ), - ], - ), - SizedBox( - height: 15, - ), - Divider(), - Column( - children: [ - Row( - children: [ - Texts(TranslationBase.of(context).visit), - SizedBox( - width: 10, - ), - Expanded( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Texts(TranslationBase.of(context) - .descriptionVaccination), - ], - ), + children: [//babyInformationModelList.length + ...List.generate(model.creteVaccinationTableModelList.length, (index) => + Container( + decoration: BoxDecoration( + shape: BoxShape.rectangle, + border: Border.all(color: Colors.white, width: 0.5), + borderRadius: BorderRadius.all(Radius.circular(5)), + color: Colors.white, + ), - Texts(TranslationBase.of(context).dueDate), - ], - ), - ], - ), - ...List.generate( - model.creteVaccinationTableModelList.length, - (index) => Container( - padding: EdgeInsets.all(12), - width: double.infinity, - child: Column( - children: [ - Row( + padding: EdgeInsets.all(12), + width: double.infinity, + child: Column( + children: [ - Texts(model - .creteVaccinationTableModelList[index].visit), - SizedBox( - width: 10, - ), - Expanded( - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Html( - data: model - .creteVaccinationTableModelList[index] - .vaccinesDescription, - ), - ], - ), - ), - Texts(model - .creteVaccinationTableModelList[index].givenAt), + Row(children: [ + Text(model.creteVaccinationTableModelList[index].visit), + SizedBox(width: 10,), + + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Html( + // data:"
BCG
HEPATITIS B
"//model.creteVaccinationTableModelList[index].vaccinesDescription + data:model.creteVaccinationTableModelList[index].vaccinesDescription, + + ), + ],), + ), + Text(model.creteVaccinationTableModelList[index].givenAt), + + + ],), + Divider(color:Colors.black ,), + ], - ), - Divider( - color: Colors.white, - height: 3, - thickness: 1.0, - ), - ], - ), - ), + ) + + + ) + ) ], ), - ), + ), - bottomSheet: Padding( - padding: const EdgeInsets.all(8.0), - child: Container( - height: MediaQuery.of(context).size.height * 0.10, - width: double.infinity, - padding: EdgeInsets.all(12), - child: SecondaryButton( - textColor: Colors.white, - color: checkedValue == false - ? Colors.white24 - : Color.fromRGBO( - 63, - 72, - 74, - 1, - ), - label: TranslationBase.of(context).sendEmail, - onTap: () { - showDialog( - context: context, - child: ConfirmSendEmailDialog( - email: informationModel.emailAddress, - onTap: () async { - await model.getCreateVaccinationTable(babyInfo: babyInfo, informationModel: informationModel,isSendEmail: true); - AppToast.showSuccessToast(message: TranslationBase.of(context).emailSuccess,toastLength: Toast.LENGTH_LONG); - - }, - ), - ); - }, - ), + ), + bottomSheet: Container( + height: MediaQuery.of(context).size.height * 0.12, + width: double.infinity, + + padding: EdgeInsets.all(12), + child: SecondaryButton( + textColor: Colors.white, + color: checkedValue== false ?Colors.white24:Color.fromRGBO(63, 72, 74, 1,), + label: "Send Email ", + // + onTap: () { + //SelectGenderDialog(); +//=============== + showDialog( + context: context, + child: SelectGenderDialog( + ), + ); + //========= + } + + ), ), ), diff --git a/lib/pages/ContactUs/LiveChat/hospitalsLivechat_page.dart b/lib/pages/ContactUs/LiveChat/hospitalsLivechat_page.dart index 5bffe17c..d85971bb 100644 --- a/lib/pages/ContactUs/LiveChat/hospitalsLivechat_page.dart +++ b/lib/pages/ContactUs/LiveChat/hospitalsLivechat_page.dart @@ -1,11 +1,15 @@ import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; import 'package:diplomaticquarterapp/core/viewModels/contactus/livechat_view_model.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/button.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/secondary_button.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -27,13 +31,14 @@ class _HospitalsLiveChatPageState extends State { @override Widget build(BuildContext context) { + ProjectViewModel projectViewModel = Provider.of(context); return BaseView( onModelReady: (model) => model.getLiveChatRequestOrders(), builder: (_, model, widget) => AppScaffold( baseViewModel: model, + isShowDecPage: false, body: SingleChildScrollView( child: Container( - margin: EdgeInsets.only(left: 15, right: 15), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -43,11 +48,11 @@ class _HospitalsLiveChatPageState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( - height: 20, + height: 70, ), Container( width: double.infinity, - height: 200, + height: 230, decoration: BoxDecoration( image: DecorationImage( image: ExactAssetImage( @@ -56,10 +61,29 @@ class _HospitalsLiveChatPageState extends State { ), child: Padding( padding: const EdgeInsets.all(8.0), - child: Texts( - 'You can now talk directly to the appointments department by chat or request a call back\n \nChoose Hospital :', - color: Colors.white, - textAlign: TextAlign.start, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + height: projectViewModel.isArabic? 10:20, + ), + Texts( + TranslationBase.of(context).instructions, + color: Colors.white, + textAlign: TextAlign.start, + ), + SizedBox( + height:projectViewModel.isArabic? 8:25, + ), + Texts( + TranslationBase.of(context) + .selectHospitalDec + + " :", + color: Colors.white, + fontWeight: FontWeight.w700, + textAlign: TextAlign.start, + ), + ], ), ), ), @@ -91,7 +115,7 @@ class _HospitalsLiveChatPageState extends State { borderRadius: BorderRadius.all( Radius.circular(5)), color: tappedIndex == index - ? Colors.red + ? Theme.of(context).primaryColor : Colors.white, ), child: Padding( @@ -104,8 +128,7 @@ class _HospitalsLiveChatPageState extends State { onTap: () { setState(() { tappedIndex = index; - chat = - "http://chat.dshmg.com:7788/hmgchatapp/hmgchattest/Index.aspx?Name=${model.user.firstName}&PatientID=${model.user.patientID}&MobileNo=${model.user.mobileNumber}&Language=en&WorkGroup=${model.LiveChatModelList[index].value}"; + chat = "http://chat.dshmg.com:7788/hmgchatapp/hmgchattest/Index.aspx?Name=${model.user.firstName}&PatientID=${model.user.patientID}&MobileNo=${model.user.mobileNumber}&Language=${projectViewModel.currentLanguage}&WorkGroup=${model.LiveChatModelList[index].value}"; }); }, child: Row( @@ -135,7 +158,8 @@ class _HospitalsLiveChatPageState extends State { .black, textAlign: TextAlign .center, - ))), //model.cOCItemList[index].cOCTitl + ))), + //model.cOCItemList[index].cOCTitl IconButton( icon: Icon( Icons.arrow_forward_ios, @@ -171,18 +195,19 @@ class _HospitalsLiveChatPageState extends State { ), ), bottomSheet: Container( - height: MediaQuery.of(context).size.height * 0.13, + height: MediaQuery.of(context).size.height * 0.10, width: double.infinity, padding: EdgeInsets.all(8.0), child: Center( child: Container( - height: MediaQuery.of(context).size.height * 0.1, + height: MediaQuery.of(context).size.height * 0.07, width: MediaQuery.of(context).size.width * 0.8, - child: Button( - label: 'ٍStart', + child: SecondaryButton( + label: TranslationBase.of(context).start, loading: model.state == ViewState.BusyLocal, + textColor: Colors.white, + disabled: chat.isEmpty, onTap: () { - print("chat=" + chat); launch(chat); }, ), diff --git a/lib/pages/ContactUs/LiveChat/livechat_page.dart b/lib/pages/ContactUs/LiveChat/livechat_page.dart index b870234a..a747db3d 100644 --- a/lib/pages/ContactUs/LiveChat/livechat_page.dart +++ b/lib/pages/ContactUs/LiveChat/livechat_page.dart @@ -1,6 +1,8 @@ import 'dart:ui'; +import 'package:diplomaticquarterapp/core/model/ImagesInfo.dart'; import 'package:diplomaticquarterapp/pages/ContactUs/LiveChat/pharmaciesLivechat_page.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:flutter/cupertino.dart'; @@ -16,9 +18,15 @@ class LiveChatPage extends StatefulWidget { class _LiveChatPageState extends State with SingleTickerProviderStateMixin { TabController _tabController; + List imagesInfo = List(); + @override void initState() { super.initState(); + imagesInfo.add(ImagesInfo(imageEn: 'https://hmgwebservices.com/Images/MobileApp/imges-info/live-chat/en/0.png',imageAr: 'https://hmgwebservices.com/Images/MobileApp/imges-info/live-chat/ar/0.png')); + imagesInfo.add(ImagesInfo(imageEn: 'https://hmgwebservices.com/Images/MobileApp/imges-info/live-chat/en/1.png',imageAr: 'https://hmgwebservices.com/Images/MobileApp/imges-info/live-chat/ar/1.png')); + imagesInfo.add(ImagesInfo(imageEn: 'https://hmgwebservices.com/Images/MobileApp/imges-info/live-chat/en/2.png',imageAr: 'https://hmgwebservices.com/Images/MobileApp/imges-info/live-chat/ar/2.png')); + _tabController = TabController(length: 2, vsync: this); } @@ -33,7 +41,10 @@ class _LiveChatPageState extends State Widget build(BuildContext context) { return AppScaffold( isShowAppBar: true, - appBarTitle: 'Locations', + imagesInfo: imagesInfo, + title: TranslationBase.of(context).liveChat, + description: TranslationBase.of(context).infoChat, + appBarTitle: TranslationBase.of(context).service, body: Scaffold( extendBodyBehindAppBar: true, appBar: PreferredSize( @@ -71,25 +82,22 @@ class _LiveChatPageState extends State isScrollable: true, controller: _tabController, indicatorWeight: 5.0, - //indicatorSize: TabBarIndicatorSize.label, indicatorSize: TabBarIndicatorSize.tab, - - indicatorColor: Colors.red[800], + indicatorColor: Theme.of(context).primaryColor, labelColor: Theme.of(context).primaryColor, - labelPadding: - EdgeInsets.only(top: 4.0, left: 35.0, right: 35.0), + labelPadding: EdgeInsets.only(top: 4.0, left: 35.0, right: 35.0), unselectedLabelColor: Colors.grey[800], tabs: [ Container( width: MediaQuery.of(context).size.width * 0.30, child: Center( - child: Texts(' Hospitals '), + child: Texts(TranslationBase.of(context).hospitals), ), ), Container( width: MediaQuery.of(context).size.width * 0.30, child: Center( - child: Texts(' Pharmacies '), + child: Texts(TranslationBase.of(context).pharmacies), ), ), ], diff --git a/lib/pages/ContactUs/LiveChat/pharmaciesLivechat_page.dart b/lib/pages/ContactUs/LiveChat/pharmaciesLivechat_page.dart index cbda0828..c5300b5d 100644 --- a/lib/pages/ContactUs/LiveChat/pharmaciesLivechat_page.dart +++ b/lib/pages/ContactUs/LiveChat/pharmaciesLivechat_page.dart @@ -1,12 +1,15 @@ import 'package:diplomaticquarterapp/core/viewModels/contactus/findus_view_model.dart'; import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; import 'package:diplomaticquarterapp/core/viewModels/contactus/livechat_view_model.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/button.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -28,10 +31,11 @@ class _PhamaciesLiveChatPageState extends State { @override Widget build(BuildContext context) { + ProjectViewModel projectViewModel = Provider.of(context); return BaseView( - onModelReady: (model) => model.getLiveChatRequestOrders(), builder: (_, model, widget) => AppScaffold( baseViewModel: model, + isShowDecPage: false, body: SingleChildScrollView( child: Container( margin: EdgeInsets.only(left: 15, right: 15), @@ -43,12 +47,9 @@ class _PhamaciesLiveChatPageState extends State { Container( width: double.infinity, height: 200, - decoration: BoxDecoration( - image: DecorationImage( - image: ExactAssetImage(''), fit: BoxFit.cover), - ), + child: Texts( - 'You can now talk directly to the pharmacist by chat or request a call back', + TranslationBase.of(context).instructionsPharmacies, color: Colors.black, textAlign: TextAlign.center, ), @@ -63,20 +64,20 @@ class _PhamaciesLiveChatPageState extends State { ), ), bottomSheet: Container( - height: MediaQuery.of(context).size.height * 0.13, + height: MediaQuery.of(context).size.height * 0.10, width: double.infinity, padding: EdgeInsets.all(8.0), child: Center( child: Container( - height: MediaQuery.of(context).size.height * 0.1, + height: MediaQuery.of(context).size.height * 0.87, width: MediaQuery.of(context).size.width * 0.8, child: Button( - label: 'ٍStart', + label: TranslationBase.of(context).start, loading: model.state == ViewState.BusyLocal, onTap: () { print("chat=" + chat); chat = - "http://chat.dshmg.com:7788/EPharmacyChat/EIndex.aspx?CustomerID=undefined&Name=${model.user.firstName}&MobileNo=${model.user.mobileNumber}&Language=1"; + "http://chat.dshmg.com:7788/EPharmacyChat/EIndex.aspx?CustomerID=undefined&Name=${model.user.firstName}&MobileNo=${model.user.mobileNumber}&Language=${projectViewModel.isArabic? 1:2}"; launch(chat); }, ), diff --git a/lib/pages/ContactUs/findus/findus_page.dart b/lib/pages/ContactUs/findus/findus_page.dart index f920de9f..80648292 100644 --- a/lib/pages/ContactUs/findus/findus_page.dart +++ b/lib/pages/ContactUs/findus/findus_page.dart @@ -4,7 +4,6 @@ import 'package:diplomaticquarterapp/core/viewModels/contactus/findus_view_model import 'package:diplomaticquarterapp/pages/ContactUs/findus/hospitrals_page.dart'; import 'package:diplomaticquarterapp/pages/ContactUs/findus/pharmacies_page.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; -import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; @@ -40,7 +39,7 @@ class _FindUsPageState extends State builder: (_, model, w) => AppScaffold( isShowAppBar: true, isShowDecPage: false, - appBarTitle: TranslationBase.of(context).ourLocation, + appBarTitle: 'Locations', baseViewModel: model, body: Scaffold( extendBodyBehindAppBar: true, @@ -79,10 +78,7 @@ class _FindUsPageState extends State isScrollable: true, controller: _tabController, indicatorWeight: 5.0, - //indicatorSize: TabBarIndicatorSize.label, indicatorSize: TabBarIndicatorSize.tab, - - indicatorColor: Colors.red[800], labelColor: Theme.of(context).primaryColor, labelPadding: EdgeInsets.only(top: 4.0, left: 35.0, right: 35.0), @@ -91,13 +87,13 @@ class _FindUsPageState extends State Container( width: MediaQuery.of(context).size.width * 0.30, child: Center( - child: Texts(TranslationBase.of(context).hospitals), + child: Texts(' Hospitals '), ), ), Container( width: MediaQuery.of(context).size.width * 0.30, child: Center( - child: Texts(TranslationBase.of(context).pharmacies), + child: Texts(' Pharmacies '), ), ), ], diff --git a/lib/pages/ContactUs/findus/hospitrals_page.dart b/lib/pages/ContactUs/findus/hospitrals_page.dart index 7aa968a5..308dbeca 100644 --- a/lib/pages/ContactUs/findus/hospitrals_page.dart +++ b/lib/pages/ContactUs/findus/hospitrals_page.dart @@ -116,9 +116,9 @@ class _HospitalsPageState extends State { CrossAxisAlignment.center, children: [ IconButton( - // icon: Icon(Icons.location_on,color: Colors.red,), - icon: new Image.asset( - 'assets/images/new-design/navigate.png'), + icon: Icon(Icons.location_on,color: Theme.of(context).primaryColor,size: 35,), + // icon: new Image.asset( + // 'assets/images/new-design/navigate.png'), tooltip: '', onPressed: () { setState(() { @@ -139,9 +139,9 @@ class _HospitalsPageState extends State { }, ), IconButton( - // icon: Icon(Icons.phone,color: Colors.red,), - icon: new Image.asset( - 'assets/images/new-design/call.png'), + icon: Icon(Icons.phone,color: Theme.of(context).primaryColor,size: 35,), + // icon: new Image.asset( + // 'assets/images/new-design/call.png'), tooltip: '', onPressed: () { setState(() { diff --git a/lib/pages/ContactUs/findus/pharmacies_page.dart b/lib/pages/ContactUs/findus/pharmacies_page.dart index cab201e3..6cf94728 100644 --- a/lib/pages/ContactUs/findus/pharmacies_page.dart +++ b/lib/pages/ContactUs/findus/pharmacies_page.dart @@ -140,13 +140,7 @@ class _PharmaciesPageState extends State { child: Row( children: [ IconButton( - // icon: Icon( - // Icons - // .location_on, - // color: Colors.red, - // ), - icon: new Image.asset( - 'assets/images/new-design/navigate.png'), + icon: Icon(Icons.location_on,color: Theme.of(context).primaryColor,size: 35,), tooltip: '', onPressed: () { setState(() { @@ -163,21 +157,15 @@ class _PharmaciesPageState extends State { .findusPharmaciesModelList[ index] .locationName); - // _volume += 10; }); }, ), IconButton( - // icon: Icon( - // Icons.phone, - // color: Colors.red, - // ), - icon: new Image.asset( - 'assets/images/new-design/call.png'), + icon: Icon(Icons.phone,color: Theme.of(context).primaryColor,size: 35,), tooltip: 'I', onPressed: () { setState(() { - // _volume += 10; + launch("tel://" + widget .findusPharmaciesModelList[ diff --git a/lib/pages/ContactUs/widgets/card_common_contat.dart b/lib/pages/ContactUs/widgets/card_common_contat.dart index 67580dbf..8848e2ff 100644 --- a/lib/pages/ContactUs/widgets/card_common_contat.dart +++ b/lib/pages/ContactUs/widgets/card_common_contat.dart @@ -2,10 +2,13 @@ import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/pages/ContactUs/LiveChat/livechat_page.dart'; import 'package:diplomaticquarterapp/pages/ContactUs/findus/findus_page.dart'; import 'package:diplomaticquarterapp/pages/feedback/feedback_home_page.dart'; +import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import '../../../Constants.dart'; + class CardCommonContact extends StatelessWidget { final image; final text; @@ -34,19 +37,16 @@ class CardCommonContact extends StatelessWidget { children: [ Container( margin: EdgeInsets.fromLTRB(10.0, 10.0, 10.0, 0.0), - child: Text(this.text, - overflow: TextOverflow.clip, - style: TextStyle( - color: new Color(0xFFc5272d), - letterSpacing: 1.0, - fontSize: 20.0)), + child: Texts(this.text, + // overflow: TextOverflow.clip, + color:secondaryColor, + fontWeight: FontWeight.w700, + fontSize: 20.0), ), Container( margin: EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0), - child: Text(this.subText, - overflow: TextOverflow.clip, - style: TextStyle( - color: Colors.black, letterSpacing: 1.0, fontSize: 15.0)), + child: Texts(this.subText, + color: Colors.black, fontSize: 15.0), ), Align( alignment: projectViewModel.isArabic? Alignment.bottomLeft:Alignment.bottomRight, diff --git a/lib/pages/Covid-DriveThru/Covid-TimeSlots.dart b/lib/pages/Covid-DriveThru/Covid-TimeSlots.dart index 8375e337..3e58b657 100644 --- a/lib/pages/Covid-DriveThru/Covid-TimeSlots.dart +++ b/lib/pages/Covid-DriveThru/Covid-TimeSlots.dart @@ -9,13 +9,13 @@ import 'package:diplomaticquarterapp/services/covid-drivethru/covid-drivethru.da 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/dialogs/confirm_dialog.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:intl/intl.dart'; +import 'package:smart_progress_bar/smart_progress_bar.dart'; import 'package:table_calendar/table_calendar.dart'; class CovidTimeSlots extends StatefulWidget { @@ -481,7 +481,6 @@ class _CovidTimeSlotsState extends State insertAppointmentCovidTest(context, DoctorList docObject) { DoctorsListService service = new DoctorsListService(); - GifLoaderDialogUtils.showMyDialog(context); AppoitmentAllHistoryResultList appo; service .insertAppointment( @@ -492,7 +491,7 @@ class _CovidTimeSlotsState extends State CovidTimeSlots.selectedDate, context) .then((res) { - GifLoaderDialogUtils.hideDialog(context); + print(res); if (res['MessageStatus'] == 1) { AppToast.showSuccessToast(message: "Appointment Booked Successfully"); Future.delayed(new Duration(milliseconds: 1800), () { @@ -522,19 +521,17 @@ class _CovidTimeSlotsState extends State dialog.showAlertDialog(context); } }).catchError((err) { - GifLoaderDialogUtils.hideDialog(context); AppToast.showErrorToast(message: err); print(err); - }); + }).showProgressBar( + text: "Loading", backgroundColor: Colors.blue.withOpacity(0.6)); } cancelAppointment(DoctorList docObject, AppoitmentAllHistoryResultList appo, BuildContext context) { ConfirmDialog.closeAlertDialog(context); - GifLoaderDialogUtils.showMyDialog(context); DoctorsListService service = new DoctorsListService(); service.cancelAppointment(appo, context).then((res) { - GifLoaderDialogUtils.hideDialog(context); if (res['MessageStatus'] == 1) { Future.delayed(new Duration(milliseconds: 1500), () { insertAppointmentCovidTest(context, docObject); @@ -543,27 +540,28 @@ class _CovidTimeSlotsState extends State AppToast.showErrorToast(message: res['ErrorEndUserMessage']); } }).catchError((err) { - GifLoaderDialogUtils.hideDialog(context); - AppToast.showErrorToast(message: err); print(err); - }); + }).showProgressBar( + text: "Loading", backgroundColor: Colors.blue.withOpacity(0.6)); } getPatientShare(context, String appointmentNo, int clinicID, int projectID, DoctorList docObject) { - GifLoaderDialogUtils.showMyDialog(context); DoctorsListService service = new DoctorsListService(); service .getPatientShare(appointmentNo, clinicID, projectID, context) .then((res) { - GifLoaderDialogUtils.hideDialog(context); - widget.patientShareResponse = new PatientShareResponse.fromJson(res); - navigateToPaymentAlert(); - }).catchError((err) { - GifLoaderDialogUtils.hideDialog(context); - AppToast.showErrorToast(message: err); - print(err); - }); + print(res); + widget.patientShareResponse = new PatientShareResponse.fromJson(res); + }) + .catchError((err) { + print(err); + }) + .showProgressBar( + text: "Loading", backgroundColor: Colors.blue.withOpacity(0.6)) + .then((value) { + navigateToPaymentAlert(); + }); } navigateToPaymentAlert() { @@ -575,10 +573,8 @@ class _CovidTimeSlotsState extends State } getCovidFreeSlots(BuildContext context, int projectID) { - GifLoaderDialogUtils.showMyDialog(context); CovidDriveThruService service = new CovidDriveThruService(); service.getCovidFreeSlots(context, projectID).then((res) { - GifLoaderDialogUtils.hideDialog(context); print(res['COVID19_FreeTimeSlots']); if (res['MessageStatus'] == 1) { if (res['COVID19_FreeTimeSlots'].length != 0) { @@ -599,9 +595,8 @@ class _CovidTimeSlotsState extends State AppToast.showErrorToast(message: res['ErrorEndUserMessage']); } }).catchError((err) { - GifLoaderDialogUtils.hideDialog(context); - AppToast.showErrorToast(message: err); print(err); - }); + }).showProgressBar( + text: "Loading", backgroundColor: Colors.blue.withOpacity(0.6)); } } diff --git a/lib/pages/Covid-DriveThru/covid-drivethru-location.dart b/lib/pages/Covid-DriveThru/covid-drivethru-location.dart index 245bcbaf..0563c4bd 100644 --- a/lib/pages/Covid-DriveThru/covid-drivethru-location.dart +++ b/lib/pages/Covid-DriveThru/covid-drivethru-location.dart @@ -3,12 +3,11 @@ import 'package:diplomaticquarterapp/models/CovidDriveThru/DriveThroughTestingCe import 'package:diplomaticquarterapp/pages/Covid-DriveThru/covid-payment-details.dart'; import 'package:diplomaticquarterapp/routes.dart'; import 'package:diplomaticquarterapp/services/covid-drivethru/covid-drivethru.dart'; -import 'package:diplomaticquarterapp/uitl/app_toast.dart'; -import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; import 'package:diplomaticquarterapp/uitl/utils.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:flutter/material.dart'; import 'package:maps_launcher/maps_launcher.dart'; +import 'package:smart_progress_bar/smart_progress_bar.dart'; class CovidDrivethruLocation extends StatefulWidget { @override @@ -259,38 +258,37 @@ class _CovidDrivethruLocationState extends State { CovidPaymentInfoResponse covidPaymentInfoResponse = new CovidPaymentInfoResponse(); - GifLoaderDialogUtils.showMyDialog(context); - service .getCovidPaymentInformation(context, int.parse(projectID)) .then((res) { - GifLoaderDialogUtils.hideDialog(context); if (res['MessageStatus'] == 1) { setState(() { covidPaymentInfoResponse = CovidPaymentInfoResponse.fromJson( res['COVID19_PatientShare']); + print(covidPaymentInfoResponse.procedureNameField); }); - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => CovidPaymentDetails( - covidPaymentInfoResponse: covidPaymentInfoResponse, - projectID: int.parse(projectID), - ))); } else {} }) .catchError((err) { - GifLoaderDialogUtils.hideDialog(context); - AppToast.showErrorToast(message: err); print(err); + }) + .showProgressBar( + text: "Loading", backgroundColor: Colors.blue.withOpacity(0.6)) + .then((value) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => CovidPaymentDetails( + covidPaymentInfoResponse: covidPaymentInfoResponse, + projectID: int.parse(projectID), + ))); }); } getProjectsList(BuildContext context) { CovidDriveThruService service = new CovidDriveThruService(); - GifLoaderDialogUtils.showMyDialog(context); service.getCovidProjectsList(context).then((res) { - GifLoaderDialogUtils.hideDialog(context); + print(res); if (res['MessageStatus'] == 1) { print(res); setState(() { @@ -300,9 +298,8 @@ class _CovidDrivethruLocationState extends State { }); } else {} }).catchError((err) { - GifLoaderDialogUtils.hideDialog(context); - AppToast.showErrorToast(message: err); print(err); - }); + }).showProgressBar( + text: "Loading", backgroundColor: Colors.blue.withOpacity(0.6)); } } diff --git a/lib/pages/DrawerPages/family/add-family-member.dart b/lib/pages/DrawerPages/family/add-family-member.dart index 084b43e6..35b19ccd 100644 --- a/lib/pages/DrawerPages/family/add-family-member.dart +++ b/lib/pages/DrawerPages/family/add-family-member.dart @@ -5,7 +5,6 @@ import 'package:diplomaticquarterapp/routes.dart'; import 'package:diplomaticquarterapp/services/authentication/auth_provider.dart'; import 'package:diplomaticquarterapp/services/family_files/family_files_provider.dart'; import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; -import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/uitl/utils.dart'; import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart'; @@ -145,7 +144,7 @@ class _AddMember extends State { request.zipCode = countryCode; request.isRegister = false; request.patientStatus = 2; - GifLoaderDialogUtils.showMyDialog(context); + loading(true); familyFileProvider .addFamilyFile(request) .then((value) => manageFamily(value)) @@ -155,21 +154,18 @@ class _AddMember extends State { } manageFamily(addMemberResult) { - GifLoaderDialogUtils.hideDialog(context); - if(addMemberResult is String ==false){ - ConfirmDialog dialog = new ConfirmDialog( - context: context, - confirmMessage: addMemberResult['ShareFamilyFileObj']['Message'], - okText: TranslationBase.of(context).confirm, - cancelText: TranslationBase.of(context).cancel_nocaps, - okFunction: () => { - insertFamilyData(addMemberResult), - ConfirmDialog.closeAlertDialog(context) - }, - cancelFunction: () => {}); - dialog.showAlertDialog(context); - } - + loading(false); + ConfirmDialog dialog = new ConfirmDialog( + context: context, + confirmMessage: addMemberResult['ShareFamilyFileObj']['Message'], + okText: TranslationBase.of(context).confirm, + cancelText: TranslationBase.of(context).cancel_nocaps, + okFunction: () => { + insertFamilyData(addMemberResult), + ConfirmDialog.closeAlertDialog(context) + }, + cancelFunction: () => {}); + dialog.showAlertDialog(context); } insertFamilyData(addMemberResult) { diff --git a/lib/pages/DrawerPages/family/add-family_type.dart b/lib/pages/DrawerPages/family/add-family_type.dart index 2c85b043..33e39397 100644 --- a/lib/pages/DrawerPages/family/add-family_type.dart +++ b/lib/pages/DrawerPages/family/add-family_type.dart @@ -27,7 +27,7 @@ class AddFamilyMemberType extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Image.asset( - 'assets/images/habib-logo.png', + 'assets/images/DQ/dq_logo_icon.png', height: 80, width: 80, ), @@ -75,7 +75,7 @@ class AddFamilyMemberType extends StatelessWidget { ), AppText( TranslationBase.of(context) - .idNo, + .nationalID, fontSize: SizeConfig .textMultiplier * 2, @@ -113,10 +113,9 @@ class AddFamilyMemberType extends StatelessWidget { AppText( TranslationBase.of(context) .fileNo, - textAlign: TextAlign.center, fontSize: SizeConfig .textMultiplier * - 1.8, + 2, ) ], ), diff --git a/lib/pages/DrawerPages/family/my-family.dart b/lib/pages/DrawerPages/family/my-family.dart index 791c33b3..b161c6e0 100644 --- a/lib/pages/DrawerPages/family/my-family.dart +++ b/lib/pages/DrawerPages/family/my-family.dart @@ -1,25 +1,33 @@ import 'dart:ui'; import 'package:diplomaticquarterapp/config/size_config.dart'; -import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; -import 'package:diplomaticquarterapp/models/Authentication/check_activation_code_response.dart'; import 'package:diplomaticquarterapp/core/model/ImagesInfo.dart'; import 'package:diplomaticquarterapp/core/service/AuthenticatedUserObject.dart'; +import 'package:diplomaticquarterapp/core/service/medical/vital_sign_service.dart'; import 'package:diplomaticquarterapp/core/viewModels/appointment_rate_view_model.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/locator.dart'; import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; import 'package:diplomaticquarterapp/models/Authentication/check_activation_code_response.dart' as list; import 'package:diplomaticquarterapp/models/FamilyFiles/GetAllSharedRecordByStatusResponse.dart'; +import 'package:diplomaticquarterapp/pages/BookAppointment/widgets/BranchView.dart'; +import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/pages/landing/landing_page.dart'; +import 'package:diplomaticquarterapp/pages/rateAppointment/rate_appointment_doctor.dart'; import 'package:diplomaticquarterapp/services/family_files/family_files_provider.dart'; import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; import 'package:diplomaticquarterapp/uitl/app_toast.dart'; import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/uitl/utils.dart'; import 'package:diplomaticquarterapp/widgets/card/rounded_container.dart'; import 'package:diplomaticquarterapp/widgets/dialogs/confirm_dialog.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:diplomaticquarterapp/widgets/others/bottom_bar.dart'; +import 'package:diplomaticquarterapp/widgets/progress_indicator/app_circular_progress_Indeicator.dart'; import 'package:diplomaticquarterapp/widgets/text/app_texts_widget.dart'; +import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart'; @@ -35,6 +43,7 @@ class MyFamily extends StatefulWidget { } class _MyFamily extends State with TickerProviderStateMixin { + List imagesInfo = List(); final familyFileProvider = FamilyFilesProvider(); AppSharedPreferences sharedPref = new AppSharedPreferences(); var userID; @@ -46,7 +55,8 @@ class _MyFamily extends State with TickerProviderStateMixin { locator(); ProjectViewModel projectViewModel; AuthenticatedUser user; - List imagesInfo = List(); + VitalSignService _vitalSignService = locator(); + var isVaiable = false; @override void initState() { _tabController = new TabController(length: 2, vsync: this, initialIndex: 0); @@ -219,7 +229,8 @@ class _MyFamily extends State with TickerProviderStateMixin { if (snapshot.hasError) return Padding( padding: EdgeInsets.all(10), - child: Text("No data found")); + child: Text( + TranslationBase.of(context).noDataAvailable)); else return Padding( padding: EdgeInsets.only(top: 50), @@ -345,7 +356,8 @@ class _MyFamily extends State with TickerProviderStateMixin { if (snapshot.hasError) return Padding( padding: EdgeInsets.all(10), - child: Text('No data found')); + child: Text(TranslationBase.of(context) + .noDataAvailable)); else return Column( children: [ @@ -459,12 +471,25 @@ class _MyFamily extends State with TickerProviderStateMixin { if (snapshot.hasError) return Padding( padding: EdgeInsets.all(10), - child: Text('No data found')); + child: Text(TranslationBase.of(context) + .noDataAvailable)); else - return SingleChildScrollView( - child: Container( - height: SizeConfig.screenHeight * .3, - child: ListView( + return Container( + height: SizeConfig.screenHeight * .3, + child: SingleChildScrollView( + child: Column( + children: [ + Padding( + padding: EdgeInsets.only( + left: 10, right: 10), + child: Row(children: [ + Expanded( + flex: 3, + child: AppText( + TranslationBase.of(context) + .theName)) + ])), + Column( children: snapshot .data.getAllSharedRecordsByStatusList .map((result) { @@ -487,7 +512,9 @@ class _MyFamily extends State with TickerProviderStateMixin { ], )); }).toList(), - ))); + ) + ], + ))); } }) ], @@ -512,7 +539,8 @@ class _MyFamily extends State with TickerProviderStateMixin { if (snapshot.hasError) return Padding( padding: EdgeInsets.all(10), - child: Text('No data found')); + child: Text(TranslationBase.of(context) + .noDataAvailable)); else return Column( children: [ @@ -590,6 +618,15 @@ class _MyFamily extends State with TickerProviderStateMixin { ); } + String isAvailable() { + if (isVaiable == false) { + this.isVaiable = true; + return TranslationBase.of(context).noDataAvailable; + } else { + return ""; + } + } + Future getFamilyFiles() async { if (user != null) { if (await sharedPref.getObject(FAMILY_FILE) != null) { @@ -671,22 +708,54 @@ class _MyFamily extends State with TickerProviderStateMixin { var familyFile = await sharedPref.getObject(FAMILY_FILE); Provider.of(context, listen: false) .setPrivilege(privilegeList: result, isLoginChild: true); - result = CheckActivationCode.fromJson(result); + result = list.CheckActivationCode.fromJson(result); var mainUser = await sharedPref.getObject(MAIN_USER); + var bloodType = await sharedPref.getString(BLOOD_TYPE); this.sharedPref.clear(); if (mainUser["PatientID"] != result.list.patientID) { result.list.isFamily = true; } + this.sharedPref.setString(APP_LANGUAGE, currentLang); this.sharedPref.setObject(MAIN_USER, mainUser); this.sharedPref.setString(APP_LANGUAGE, currentLang); this.sharedPref.setObject(USER_PROFILE, result.list); this.sharedPref.setObject(FAMILY_FILE, familyFile); this.sharedPref.setObject(LOGIN_TOKEN_ID, result.logInTokenID); this.sharedPref.setString(TOKEN, result.authenticationTokenID); - //this.checkIfUserAgreedBefore(result), - Navigator.of(context).pushNamed( - HOME, - ); + await authenticatedUserObject.getUser(getUser: true); + Provider.of(context, listen: false).user = + authenticatedUserObject.user; + Provider.of(context, listen: false) + .setUser(authenticatedUserObject.user); + appointmentRateViewModel + .getIsLastAppointmentRatedList() + .then((value) => { + //getToDoCount(), + // Utils.hideProgressDialog(), + if (appointmentRateViewModel.isHaveAppointmentNotRate) + { + Navigator.pushAndRemoveUntil( + context, + FadePage( + page: RateAppointmentDoctor(), + ), + (r) => false) + } + else + { + Navigator.pushAndRemoveUntil( + context, + FadePage( + page: LandingPage(), + ), + (r) => false) + } + }) + .catchError((err) { + print(err); + // Utils.hideProgressDialog(); + // GifLoaderDialogUtils.hideDialog(context); + }); } deactivateRequest(ID, status, context) { diff --git a/lib/pages/ErService/AmbulanceReq.dart b/lib/pages/ErService/AmbulanceReq.dart index 1690254a..fe245133 100644 --- a/lib/pages/ErService/AmbulanceReq.dart +++ b/lib/pages/ErService/AmbulanceReq.dart @@ -79,7 +79,7 @@ class _AmbulanceReqState extends State child: Container( height: 60.0, margin: EdgeInsets.only(top: 10.0), - width: MediaQuery.of(context).size.width * 0.93, + width: MediaQuery.of(context).size.width * 0.90, decoration: BoxDecoration( border: Border( bottom: BorderSide( @@ -93,7 +93,6 @@ class _AmbulanceReqState extends State controller: _tabController, indicatorWeight: 5.0, indicatorSize: TabBarIndicatorSize.label, - indicatorColor: Colors.red[800], labelColor: Theme.of(context).primaryColor, labelPadding: EdgeInsets.only(top: 4.0, left: 18.0, right: 18.0), diff --git a/lib/pages/ErService/AmbulanceRequestIndexPages/AmbulanceRequestIndex.dart b/lib/pages/ErService/AmbulanceRequestIndexPages/AmbulanceRequestIndex.dart index 5f303846..c07adabc 100644 --- a/lib/pages/ErService/AmbulanceRequestIndexPages/AmbulanceRequestIndex.dart +++ b/lib/pages/ErService/AmbulanceRequestIndexPages/AmbulanceRequestIndex.dart @@ -46,7 +46,7 @@ class _AmbulanceRequestIndexPageState extends State { @override Widget build(BuildContext context) { return AppScaffold( - body: widget.amRequestViewModel.pickUpRequestPresOrder != null + body: false ? Column( children: [ SizedBox( @@ -62,18 +62,18 @@ class _AmbulanceRequestIndexPageState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ OrderLogItem( - title: 'Request ID', + title: TranslationBase.of(context).reqId, value: widget.amRequestViewModel.pickUpRequestPresOrder .presOrderID .toString(), ), OrderLogItem( - title: 'Status', + title: TranslationBase.of(context).status, value: widget.amRequestViewModel.pickUpRequestPresOrder .ambulateDescription, ), OrderLogItem( - title: 'Last edit time', + title: TranslationBase.of(context).pickupDate, value: DateUtil.getDayMonthYearDateFormatted( DateUtil.convertStringToDate(widget .amRequestViewModel @@ -81,17 +81,17 @@ class _AmbulanceRequestIndexPageState extends State { .lastEditDate)), ), OrderLogItem( - title: 'Pickup Location', + title: TranslationBase.of(context).pickupLocation, value: widget.amRequestViewModel.pickUpRequestPresOrder .pickupLocationName, ), OrderLogItem( - title: 'Drop off Location', + title: TranslationBase.of(context).dropoffLocation, value: widget.amRequestViewModel.pickUpRequestPresOrder .dropoffLocationName, ), OrderLogItem( - title: 'Trasfaer way', + title: TranslationBase.of(context).transportMethod, value: widget .amRequestViewModel.pickUpRequestPresOrder.title, ), diff --git a/lib/pages/ErService/AmbulanceRequestIndexPages/BillAmount.dart b/lib/pages/ErService/AmbulanceRequestIndexPages/BillAmount.dart index 16945a1e..aeb61609 100644 --- a/lib/pages/ErService/AmbulanceRequestIndexPages/BillAmount.dart +++ b/lib/pages/ErService/AmbulanceRequestIndexPages/BillAmount.dart @@ -201,7 +201,7 @@ class _BillAmountState extends State { leading: Radio( value: Ambulate.Wheelchair, groupValue: _ambulate, - activeColor: Theme.of(context).primaryColor, + activeColor: Colors.red[800], onChanged: (value) { setState(() { _ambulate = value; @@ -232,7 +232,7 @@ class _BillAmountState extends State { leading: Radio( value: Ambulate.Walker, groupValue: _ambulate, - activeColor: Theme.of(context).primaryColor, + activeColor: Colors.red[800], onChanged: (value) { setState(() { _ambulate = value; @@ -268,7 +268,7 @@ class _BillAmountState extends State { leading: Radio( value: Ambulate.Stretcher, groupValue: _ambulate, - activeColor: Theme.of(context).primaryColor, + activeColor: Colors.red[800], onChanged: (value) { setState(() { _ambulate = value; @@ -299,7 +299,7 @@ class _BillAmountState extends State { leading: Radio( value: Ambulate.None, groupValue: _ambulate, - activeColor: Theme.of(context).primaryColor, + activeColor: Colors.red[800], onChanged: (value) { setState(() { _ambulate = value; diff --git a/lib/pages/ErService/AmbulanceRequestIndexPages/PickupLocation.dart b/lib/pages/ErService/AmbulanceRequestIndexPages/PickupLocation.dart index 78574e06..f6ebfde9 100644 --- a/lib/pages/ErService/AmbulanceRequestIndexPages/PickupLocation.dart +++ b/lib/pages/ErService/AmbulanceRequestIndexPages/PickupLocation.dart @@ -183,7 +183,7 @@ class _PickupLocationState extends State { color: Colors.white, ), child: ListTile( - title: Text(TranslationBase.of(context).yes), + title: Texts(TranslationBase.of(context).yes), leading: Radio( value: HaveAppointment.YES, groupValue: _haveAppointment, @@ -218,7 +218,7 @@ class _PickupLocationState extends State { color: Colors.white, ), child: ListTile( - title: Text(TranslationBase.of(context).no), + title: Texts(TranslationBase.of(context).no), leading: Radio( value: HaveAppointment.NO, groupValue: _haveAppointment, @@ -287,7 +287,7 @@ class _PickupLocationState extends State { Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Texts('Pickup Location'), + Texts(TranslationBase.of(context).pickupLocation), SizedBox( height: 15, ), @@ -456,7 +456,7 @@ class _PickupLocationState extends State { return _selectedHospital == null ? title : _selectedHospital.name; } - String getSelectFromMapName(BuildContext context) { + String getSelectFromMapName(context) { return _result != null ? _result.formattedAddress : TranslationBase.of(context).selectMap; } diff --git a/lib/pages/ErService/AmbulanceRequestIndexPages/SelectTransportationMethod.dart b/lib/pages/ErService/AmbulanceRequestIndexPages/SelectTransportationMethod.dart index 952716c8..69669ed3 100644 --- a/lib/pages/ErService/AmbulanceRequestIndexPages/SelectTransportationMethod.dart +++ b/lib/pages/ErService/AmbulanceRequestIndexPages/SelectTransportationMethod.dart @@ -97,7 +97,7 @@ class _SelectTransportationMethodState value: widget .amRequestViewModel.amRequestModeList[index], groupValue: _erTransportationMethod, - activeColor: Theme.of(context).primaryColor, + activeColor: Colors.red[800], onChanged: (value) { setState(() { _erTransportationMethod = value; @@ -149,7 +149,7 @@ class _SelectTransportationMethodState leading: Radio( value: Direction.ToHospital, groupValue: _direction, - activeColor: Theme.of(context).primaryColor, + activeColor: Colors.red[800], onChanged: (value) { setState(() { _direction = value; @@ -180,7 +180,7 @@ class _SelectTransportationMethodState leading: Radio( value: Direction.FromHospital, groupValue: _direction, - activeColor: Theme.of(context).primaryColor, + activeColor: Colors.red[800], onChanged: (value) { setState(() { _direction = value; @@ -227,7 +227,7 @@ class _SelectTransportationMethodState leading: Radio( value: Way.OneWay, groupValue: _way, - activeColor:Theme.of(context).primaryColor, + activeColor: Colors.red[800], onChanged: (value) { setState(() { _way = value; @@ -258,7 +258,7 @@ class _SelectTransportationMethodState leading: Radio( value: Way.TwoWays, groupValue: _way, - activeColor: Theme.of(context).primaryColor, + activeColor: Colors.red[800], onChanged: (value) { setState(() { _way = value; diff --git a/lib/pages/ErService/AmbulanceRequestIndexPages/Summary.dart b/lib/pages/ErService/AmbulanceRequestIndexPages/Summary.dart index 66da39df..8fd72b8f 100644 --- a/lib/pages/ErService/AmbulanceRequestIndexPages/Summary.dart +++ b/lib/pages/ErService/AmbulanceRequestIndexPages/Summary.dart @@ -18,7 +18,7 @@ class Summary extends StatefulWidget { _SummaryState createState() => _SummaryState(); } -//TODO it should be dynamic fix it +//TODO it should be dynamic class _SummaryState extends State { @override Widget build(BuildContext context) { @@ -67,7 +67,7 @@ class _SummaryState extends State { ), ), SizedBox(height: 20,), - Texts(TranslationBase.of(context).RRTSummary,textAlign: TextAlign.start,), + Texts('Bill Amount',textAlign: TextAlign.start,), SizedBox(height: 5,), Container( height: 55, diff --git a/lib/pages/ErService/ErOptions.dart b/lib/pages/ErService/ErOptions.dart index e3438af5..886d47d2 100644 --- a/lib/pages/ErService/ErOptions.dart +++ b/lib/pages/ErService/ErOptions.dart @@ -31,13 +31,13 @@ class _ErOptionsState extends State { Widget build(BuildContext context) { return AppScaffold( isShowAppBar: widget.isAppbar, - isShowDecPage: false, appBarTitle: TranslationBase.of(context).bookAppo, body: Container( margin: EdgeInsets.fromLTRB(10.0, 20.0, 10.0, 10.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ + Container( margin: EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0), child: Row( diff --git a/lib/pages/ErService/NearestEr.dart b/lib/pages/ErService/NearestEr.dart index 1c786954..eaf0d4ef 100644 --- a/lib/pages/ErService/NearestEr.dart +++ b/lib/pages/ErService/NearestEr.dart @@ -20,6 +20,10 @@ class NearestEr extends StatelessWidget { @override Widget build(BuildContext context) { + var size = MediaQuery.of(context).size; + final double itemHeight = (size.height - kToolbarHeight - 24) / 2; + final double itemWidth = size.width / 2; + return BaseView( onModelReady: appointmentNo != null && projectID != null ? (model) => model.getProjectAvgERWaitingTimeOrders( @@ -27,15 +31,14 @@ class NearestEr extends StatelessWidget { : (model) => model.getProjectAvgERWaitingTimeOrders(), builder: (_, mode, widget) => AppScaffold( isShowAppBar: true, - appBarTitle: TranslationBase.of(context).er, - description: TranslationBase.of(context).erContant, + appBarTitle: TranslationBase.of(context).NearestEr, baseViewModel: mode, body: mode.ProjectAvgERWaitingTimeModeList.length > 0 ? Container( child: ListView( children: [ Text( - TranslationBase.of(context).erContant, + "${TranslationBase.of(context).NearestErDesc}", textAlign: TextAlign.center, style: TextStyle( fontSize: 18.0, @@ -43,301 +46,55 @@ class NearestEr extends StatelessWidget { fontWeight: FontWeight.w900, color: new Color(0xFF60686b))), Container( - margin: EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Row( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded( - child: Container( - child: CardPosition( - text: mode - .ProjectAvgERWaitingTimeModeList[0] - .projectName - .toString(), - image: - 'assets/images/new-design/find_us_icon.png', - subText: mode - .ProjectAvgERWaitingTimeModeList[0] - .distanceInKilometers - .toString(), - type: mode - .ProjectAvgERWaitingTimeModeList[0].iD - .toString(), - telephone: mode - .ProjectAvgERWaitingTimeModeList[0] - .phoneNumber - .toString(), - networkImage: mode - .ProjectAvgERWaitingTimeModeList[0] - .projectImageURL - .toString(), - latitude: mode - .ProjectAvgERWaitingTimeModeList[0] - .latitude, - longitude: mode - .ProjectAvgERWaitingTimeModeList[0] - .longitude, - projectname: mode - .ProjectAvgERWaitingTimeModeList[0] - .projectName, - ), - ), - - ), - Expanded( - child: Container( - child: CardPosition( - text: mode - .ProjectAvgERWaitingTimeModeList[1] - .projectName - .toString(), - image: - 'assets/images/new-design/find_us_icon.png', - subText: mode - .ProjectAvgERWaitingTimeModeList[1] - .distanceInKilometers - .toString(), - type: mode - .ProjectAvgERWaitingTimeModeList[1].iD - .toString(), - telephone: mode - .ProjectAvgERWaitingTimeModeList[1] - .phoneNumber - .toString(), - networkImage: mode - .ProjectAvgERWaitingTimeModeList[1] - .projectImageURL - .toString(), - latitude: mode - .ProjectAvgERWaitingTimeModeList[1] - .latitude, - longitude: mode - .ProjectAvgERWaitingTimeModeList[1] - .longitude, - projectname: mode - .ProjectAvgERWaitingTimeModeList[1] - .projectName, - ), - ), - - ) - ], - ), - Row( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded( - child: Container( - child: CardPosition( - - text: mode - .ProjectAvgERWaitingTimeModeList[2] - .projectName - .toString(), - image: - 'assets/images/new-design/find_us_icon.png', - - subText: mode - .ProjectAvgERWaitingTimeModeList[2] - .distanceInKilometers - .toString(), - type: mode - .ProjectAvgERWaitingTimeModeList[2].iD - .toString(), - telephone: mode - .ProjectAvgERWaitingTimeModeList[2] - .phoneNumber - .toString(), - networkImage: mode - .ProjectAvgERWaitingTimeModeList[2] - .projectImageURL - .toString(), - latitude: mode - .ProjectAvgERWaitingTimeModeList[2] - .latitude, - longitude: mode - .ProjectAvgERWaitingTimeModeList[2] - .longitude, - projectname: mode - .ProjectAvgERWaitingTimeModeList[2] - .projectName, - ), - ), - - ), - Expanded( - child: Container( - child: CardPosition( - - text: mode - .ProjectAvgERWaitingTimeModeList[3] - .projectName - .toString(), - image: - 'assets/images/new-design/find_us_icon.png', - - subText: mode - .ProjectAvgERWaitingTimeModeList[3] - .distanceInKilometers - .toString(), - type: mode - .ProjectAvgERWaitingTimeModeList[3].iD - .toString(), - telephone: mode - .ProjectAvgERWaitingTimeModeList[3] - .phoneNumber - .toString(), - networkImage: mode - .ProjectAvgERWaitingTimeModeList[3] - .projectImageURL - .toString(), - latitude: mode - .ProjectAvgERWaitingTimeModeList[3] - .latitude, - longitude: mode - .ProjectAvgERWaitingTimeModeList[3] - .longitude, - projectname: mode - .ProjectAvgERWaitingTimeModeList[3] - .projectName, - ), - ), - flex: 0, - ) - ], - ), - Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded( - child: Container( - child: CardPosition( - - text: mode - .ProjectAvgERWaitingTimeModeList[4] - .projectName - .toString(), - image: - 'assets/images/new-design/find_us_icon.png', - - subText: mode - .ProjectAvgERWaitingTimeModeList[4] - .distanceInKilometers - .toString(), - type: mode - .ProjectAvgERWaitingTimeModeList[4].iD - .toString(), - telephone: mode - .ProjectAvgERWaitingTimeModeList[4] - .phoneNumber - .toString(), - networkImage: mode - .ProjectAvgERWaitingTimeModeList[4] - .projectImageURL - .toString(), - latitude: mode - .ProjectAvgERWaitingTimeModeList[4] - .latitude, - longitude: mode - .ProjectAvgERWaitingTimeModeList[4] - .longitude, - projectname: mode - .ProjectAvgERWaitingTimeModeList[4] - .projectName, - ), - ), - - ), - Expanded( - child: Container( - child: CardPosition( - text: mode - .ProjectAvgERWaitingTimeModeList[5] - .projectName - .toString(), - image: - 'assets/images/new-design/find_us_icon.png', - subText: mode - .ProjectAvgERWaitingTimeModeList[5] - .distanceInKilometers - .toString(), - type: mode - .ProjectAvgERWaitingTimeModeList[5].iD - .toString(), - telephone: mode - .ProjectAvgERWaitingTimeModeList[5] - .phoneNumber - .toString(), - networkImage: mode - .ProjectAvgERWaitingTimeModeList[5] - .projectImageURL - .toString(), - latitude: mode - .ProjectAvgERWaitingTimeModeList[5] - .latitude, - longitude: mode - .ProjectAvgERWaitingTimeModeList[5] - .longitude, - projectname: mode - .ProjectAvgERWaitingTimeModeList[5] - .projectName, - ), - ), - - ) - ], + margin: EdgeInsets.fromLTRB(2.0, 10.0, 0.0, 10.0), + child: GridView.count( + crossAxisCount: 2, + childAspectRatio: (itemWidth / itemWidth), + crossAxisSpacing: 10, + mainAxisSpacing: 10, + controller: + new ScrollController(keepScrollOffset: false), + shrinkWrap: true, + padding: const EdgeInsets.all(4.0), + children: List.generate(7, (index) { + return Container( + child: CardPosition( + text: mode + .ProjectAvgERWaitingTimeModeList[index] + .projectName + .toString(), + image: + 'assets/images/new-design/find_us_icon.png', + subText: mode + .ProjectAvgERWaitingTimeModeList[index] + .distanceInKilometers + .toString(), + type: mode + .ProjectAvgERWaitingTimeModeList[index].iD + .toString(), + telephone: mode + .ProjectAvgERWaitingTimeModeList[index] + .phoneNumber + .toString(), + networkImage: mode + .ProjectAvgERWaitingTimeModeList[index] + .projectImageURL + .toString(), + latitude: mode + .ProjectAvgERWaitingTimeModeList[index] + .latitude, + longitude: mode + .ProjectAvgERWaitingTimeModeList[index] + .longitude, + projectname: mode + .ProjectAvgERWaitingTimeModeList[index] + .projectName, + cardSize: itemWidth, ), - Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded( - child: Container( - child: CardPosition( - text: mode - .ProjectAvgERWaitingTimeModeList[6] - .projectName - .toString(), - image: - 'assets/images/new-design/find_us_icon.png', - subText: mode - .ProjectAvgERWaitingTimeModeList[6] - .distanceInKilometers - .toString(), - type: mode - .ProjectAvgERWaitingTimeModeList[6].iD - .toString(), - telephone: mode - .ProjectAvgERWaitingTimeModeList[6] - .phoneNumber - .toString(), - networkImage: mode - .ProjectAvgERWaitingTimeModeList[6] - .projectImageURL - .toString(), - latitude: mode - .ProjectAvgERWaitingTimeModeList[6] - .latitude, - longitude: mode - .ProjectAvgERWaitingTimeModeList[6] - .longitude, - projectname: mode - .ProjectAvgERWaitingTimeModeList[6] - .projectName, - ), - ), - flex: 0, - ), - ], - ), - ], - )), + ); + }), + ), + ), ], ), ) @@ -348,4 +105,3 @@ class NearestEr extends StatelessWidget { ); } } - diff --git a/lib/pages/ErService/widgets/StepsWidget.dart b/lib/pages/ErService/widgets/StepsWidget.dart index 40af61d0..c5864710 100644 --- a/lib/pages/ErService/widgets/StepsWidget.dart +++ b/lib/pages/ErService/widgets/StepsWidget.dart @@ -13,7 +13,7 @@ class StepsWidget extends StatelessWidget { @override Widget build(BuildContext context) { ProjectViewModel projectViewModel = Provider.of(context); - return !projectViewModel.isArabic? Stack( + return projectViewModel.isArabic? Stack( children: [ Container( height: 50, diff --git a/lib/pages/ErService/widgets/card_common.dart b/lib/pages/ErService/widgets/card_common.dart index 0796a5bc..35ece966 100644 --- a/lib/pages/ErService/widgets/card_common.dart +++ b/lib/pages/ErService/widgets/card_common.dart @@ -11,7 +11,6 @@ class CardCommonEr extends StatelessWidget { final text; final subText; final type; - const CardCommonEr( {@required this.image, @required this.text, @@ -23,6 +22,7 @@ class CardCommonEr extends StatelessWidget { return GestureDetector( onTap: () { navigateToSearch(context, this.type); + }, child: Container( margin: EdgeInsets.fromLTRB(9.0, 9.0, 9.0, 9.0), @@ -60,10 +60,24 @@ class CardCommonEr extends StatelessWidget { } Future navigateToSearch(context, type) async { - if (type == 0) { - Navigator.push(context, FadePage(page: AmbulanceReq())); - } else { - Navigator.push(context, FadePage(page: NearestEr())); +//===Switch case=== + if(type==0) + { + + Navigator.push( + context, + FadePage( + page: AmbulanceReq())); + } + else{ + + Navigator.push( + context, + FadePage( + page: NearestEr())); + } + + } } diff --git a/lib/pages/ErService/widgets/card_position.dart b/lib/pages/ErService/widgets/card_position.dart index 8647ad62..69ccaffe 100644 --- a/lib/pages/ErService/widgets/card_position.dart +++ b/lib/pages/ErService/widgets/card_position.dart @@ -19,6 +19,8 @@ class CardPosition extends StatelessWidget { final latitude; final longitude; final projectname; + final cardSize; + const CardPosition( { @required this.image, @@ -30,6 +32,7 @@ class CardPosition extends StatelessWidget { @required this.latitude, @required this.longitude, @required this.projectname , + @required this.cardSize , }); @override @@ -40,17 +43,17 @@ class CardPosition extends StatelessWidget { }, child: Container( - width:MediaQuery.of(context).size.width * 0.47,//165, - margin: EdgeInsets.fromLTRB(7.0, 7.0, 7.0, 7.0), + // width:MediaQuery.of(context).size.width * 0.47,//165, + margin: EdgeInsets.fromLTRB(8.0, 8.0, 8.0, 8.0), decoration: BoxDecoration(boxShadow: [ BoxShadow(color: Colors.grey[400], blurRadius: 2.0, spreadRadius: 0.0) ], borderRadius: BorderRadius.circular(10), color: Colors.white), child: Column( - crossAxisAlignment: CrossAxisAlignment.center, children: [ Container( - margin: EdgeInsets.fromLTRB(10.0, 10.0, 10.0, 0.0), + height: cardSize * 0.2 - 8, + margin: EdgeInsets.fromLTRB(8.0, 8.0, 8.0, 0.0), child: Text(this.text, overflow: TextOverflow.clip, style: TextStyle( @@ -59,12 +62,14 @@ class CardPosition extends StatelessWidget { fontSize: 2 * SizeConfig.textMultiplier)), ), Container( + height: cardSize * 0.5 - 8, alignment: Alignment.center, - margin: EdgeInsets.fromLTRB(0.0, 0.0, 10.0, 8.0), - child: Image.asset(this.image, width: 60.0, height: 60.0), + margin: EdgeInsets.fromLTRB(0.0, 0.0, 8.0, 8.0), + child: Image.asset(this.image, width: 60.0, height: cardSize * 0.4), ), Container( - margin: EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0), + margin: EdgeInsets.fromLTRB(8.0, 0.0, 8.0, 0.0), + height: cardSize * 0.2 - 8, child: Text(this.subText, overflow: TextOverflow.clip, style: TextStyle( diff --git a/lib/pages/MyAppointments/AppointmentDetails.dart b/lib/pages/MyAppointments/AppointmentDetails.dart index 109af9d1..17b6d57b 100644 --- a/lib/pages/MyAppointments/AppointmentDetails.dart +++ b/lib/pages/MyAppointments/AppointmentDetails.dart @@ -1,11 +1,17 @@ +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/DoctorRateDetails.dart'; import 'package:diplomaticquarterapp/pages/BookAppointment/BookConfirm.dart'; import 'package:diplomaticquarterapp/pages/BookAppointment/components/DocAvailableAppointments.dart'; +import 'package:diplomaticquarterapp/services/appointment_services/GetDoctorsList.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/others/app_scaffold_widget.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import 'package:rating_bar/rating_bar.dart'; import 'widgets/AppointmentActions.dart'; @@ -26,46 +32,51 @@ class _AppointmentDetailsState extends State with SingleTickerProviderStateMixin { static TabController _tabController; + List doctorDetailsList = List(); + @override void initState() { _tabController = new TabController(length: 2, vsync: this); + AppointmentDetails.showFooterButton = false; super.initState(); } + @override void dispose() { - // TODO: implement dispose super.dispose(); _tabController.dispose(); + AppointmentDetails.showFooterButton = false; } @override Widget build(BuildContext context) { + ProjectViewModel projectViewModel = Provider.of(context); return AppScaffold( appBarTitle: widget.appo.doctorNameObj, isShowAppBar: true, bottomSheet: AppointmentDetails.showFooterButton ? Container( - width: MediaQuery.of(context).size.width, - height: 50.0, - margin: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0), - child: ButtonTheme( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10.0), - ), - minWidth: MediaQuery.of(context).size.width * 0.7, - height: 45.0, - child: RaisedButton( - color: new Color(0xFF60686b), - textColor: Colors.white, - disabledTextColor: Colors.white, - disabledColor: new Color(0xFFbcc2c4), - onPressed: goToBookConfirm, - child: Text(TranslationBase.of(context).bookNow, - style: TextStyle(fontSize: 18.0)), - ), - ), - ) + width: MediaQuery.of(context).size.width, + height: 50.0, + margin: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0), + child: ButtonTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10.0), + ), + minWidth: MediaQuery.of(context).size.width * 0.7, + height: 45.0, + child: RaisedButton( + color: new Color(0xFF60686b), + textColor: Colors.white, + disabledTextColor: Colors.white, + disabledColor: new Color(0xFFbcc2c4), + onPressed: goToBookConfirm, + child: Text(TranslationBase.of(context).bookNow, + style: TextStyle(fontSize: 18.0)), + ), + ), + ) : null, body: Container( color: new Color(0xFFf6f6f6), @@ -88,7 +99,8 @@ class _AppointmentDetailsState extends State ), ), Container( - margin: EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0), + margin: + EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0), alignment: Alignment.center, child: Text( widget.appo.doctorTitle + @@ -103,7 +115,7 @@ class _AppointmentDetailsState extends State Container( margin: EdgeInsets.only(top: 10.0), alignment: Alignment.center, - child: Text(widget.appo.clinicName, + child: Text(getDoctorSpeciality(widget.appo.doctorSpeciality), style: TextStyle( fontSize: 12.0, color: Colors.grey[900], @@ -123,19 +135,37 @@ class _AppointmentDetailsState extends State emptyIcon: Icons.star, ), ), + InkWell( + onTap: () { + getDoctorRatingsDetails(); + }, + child: Container( + margin: EdgeInsets.only(top: 5.0), + alignment: Alignment.center, + child: Text( + "(" + + widget.appo.noOfPatientsRate.toString() + + " " + + TranslationBase.of(context).reviews + + ")", + style: TextStyle( + fontSize: 14.0, + color: Colors.blue[800], + letterSpacing: 1.0, + decoration: TextDecoration.underline, + )), + ), + ), Container( - margin: EdgeInsets.only(top: 5.0), alignment: Alignment.center, - child: Text( - "(" + - widget.appo.noOfPatientsRate.toString() + - " Reviews)", - style: TextStyle( - fontSize: 14.0, - color: Colors.blue[800], - letterSpacing: 1.0, - decoration: TextDecoration.underline, - )), + child: Text(DateUtil.getWeekDayMonthDayYearDateFormatted( + DateUtil.convertStringToDate( + widget.appo.appointmentDate), + projectViewModel.isArabic ? "ar" : "en")), + ), + Container( + alignment: Alignment.center, + child: Text(widget.appo.startTime.substring(0, 5)), ), Container( margin: EdgeInsets.only(top: 10.0), @@ -171,8 +201,14 @@ class _AppointmentDetailsState extends State child: TabBarView( physics: NeverScrollableScrollPhysics(), children: [ - AppointmentActions(appo: widget.appo, tabController: _tabController, enableFooterButton: enableFooterButton), - DocAvailableAppointments(doctor: getDoctorObject(), isLiveCareAppointment: widget.appo.isLiveCareAppointment) + AppointmentActions( + appo: widget.appo, + tabController: _tabController, + enableFooterButton: enableFooterButton), + DocAvailableAppointments( + doctor: getDoctorObject(), + isLiveCareAppointment: + widget.appo.isLiveCareAppointment) ], controller: _tabController, ), @@ -203,12 +239,296 @@ class _AppointmentDetailsState extends State MaterialPageRoute( builder: (context) => BookConfirm( doctor: getDoctorObject(), - isLiveCareAppointment: widget.appo.isLiveCareAppointment, selectedDate: DocAvailableAppointments.selectedDate, selectedTime: DocAvailableAppointments.selectedTime))); } + getDoctorRatingsDetails() { + GifLoaderDialogUtils.showMyDialog(context); + DoctorsListService service = new DoctorsListService(); + service.getDoctorsRatingDetails(widget.appo.doctorID, context).then((res) { + GifLoaderDialogUtils.hideDialog(context); + if (res['MessageStatus'] == 1) { + doctorDetailsList.clear(); + res['DoctorRatingDetailsList'].forEach((v) { + doctorDetailsList.add(new DoctorRateDetails.fromJson(v)); + }); + showRatingDialog(doctorDetailsList); + } else { + AppToast.showErrorToast(message: res['ErrorEndUserMessage']); + } + }).catchError((err) { + GifLoaderDialogUtils.hideDialog(context); + AppToast.showErrorToast(message: err); + print(err); + }); + } + void showRatingDialog(List doctorDetailsList) { + showGeneralDialog( + barrierColor: Colors.black.withOpacity(0.5), + transitionBuilder: (context, a1, a2, widget) { + final curvedValue = Curves.easeInOutBack.transform(a1.value) - 1.0; + return Transform( + transform: Matrix4.translationValues(0.0, curvedValue * 200, 0.0), + child: Opacity( + opacity: a1.value, + child: Dialog( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + // height: 400.0, + width: MediaQuery.of(context).size.width * 0.8, + color: Colors.white, + child: Column( + children: [ + Container( + alignment: Alignment.center, + width: MediaQuery.of(context).size.width, + color: Theme.of(context).primaryColor, + margin: EdgeInsets.only(bottom: 5.0), + padding: EdgeInsets.all(10.0), + child: Text( + TranslationBase.of(context).doctorRating, + style: TextStyle( + fontSize: 22.0, color: Colors.white))), + Container( + margin: EdgeInsets.only(top: 0.0), + child: Text( + this + .widget + .appo + .actualDoctorRate + .ceilToDouble() + .toString(), + style: TextStyle( + fontSize: 32.0, color: Colors.black))), + Container( + margin: EdgeInsets.only(top: 5.0), + alignment: Alignment.center, + child: RatingBar.readOnly( + initialRating: + this.widget.appo.actualDoctorRate.toDouble(), + size: 35.0, + filledColor: Colors.yellow[700], + emptyColor: Colors.grey[500], + isHalfAllowed: true, + halfFilledIcon: Icons.star_half, + filledIcon: Icons.star, + emptyIcon: Icons.star, + ), + ), + Container( + margin: EdgeInsets.only(top: 10.0), + child: Text( + this.widget.appo.noOfPatientsRate.toString() + + " " + + TranslationBase.of(context).reviews, + style: TextStyle( + fontSize: 14.0, color: Colors.black))), + Container( + margin: EdgeInsets.only(top: 10.0), + child: Row( + children: [ + Container( + width: 100.0, + margin: EdgeInsets.only( + top: 10.0, left: 15.0, right: 15.0), + child: Text( + TranslationBase.of(context).excellent, + style: TextStyle( + fontSize: 13.0, + color: Colors.black))), + Container( + margin: EdgeInsets.only(top: 10.0), + child: SizedBox( + width: getRatingWidth( + doctorDetailsList[0].patientNumber), + height: 6.0, + child: Container( + color: Colors.green[700], + ), + ), + ), + ], + ), + ), + Container( + child: Row( + children: [ + Container( + width: 100.0, + margin: EdgeInsets.only( + top: 10.0, left: 15.0, right: 15.0), + child: Text( + TranslationBase.of(context).v_good, + style: TextStyle( + fontSize: 13.0, + color: Colors.black))), + Container( + margin: EdgeInsets.only(top: 10.0), + child: SizedBox( + width: getRatingWidth( + doctorDetailsList[1].patientNumber), + height: 6.0, + child: Container( + color: Color(0xffB7B723), + ), + ), + ), + ], + ), + ), + Container( + child: Row( + children: [ + Container( + width: 100.0, + margin: EdgeInsets.only( + top: 10.0, left: 15.0, right: 15.0), + child: Text( + TranslationBase.of(context).good, + style: TextStyle( + fontSize: 13.0, + color: Colors.black))), + Container( + margin: EdgeInsets.only(top: 10.0), + child: SizedBox( + width: getRatingWidth( + doctorDetailsList[2].patientNumber), + height: 6.0, + child: Container( + color: Color(0xffEBA727), + ), + ), + ), + ], + ), + ), + Container( + child: Row( + children: [ + Container( + width: 100.0, + margin: EdgeInsets.only( + top: 10.0, left: 15.0, right: 15.0), + child: Text( + TranslationBase.of(context).average, + style: TextStyle( + fontSize: 13.0, + color: Colors.black))), + Container( + margin: EdgeInsets.only(top: 10.0), + child: SizedBox( + width: getRatingWidth( + doctorDetailsList[3].patientNumber), + height: 6.0, + child: Container( + color: Color(0xffEB7227), + ), + ), + ), + ], + ), + ), + Container( + child: Row( + children: [ + Container( + width: 100.0, + margin: EdgeInsets.only( + top: 10.0, left: 15.0, right: 15.0), + child: Text( + TranslationBase.of(context) + .below_average, + style: TextStyle( + fontSize: 13.0, + color: Colors.black))), + Container( + margin: EdgeInsets.only(top: 10.0), + child: SizedBox( + width: getRatingWidth( + doctorDetailsList[4].patientNumber), + height: 6.0, + child: Container( + color: Color(0xffE20C0C), + ), + ), + ), + ], + ), + ), + Container( + margin: EdgeInsets.only(top: 40.0), + child: Divider()), + Container( + margin: EdgeInsets.only(top: 0.0), + child: Align( + alignment: FractionalOffset.bottomCenter, + child: ButtonTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10.0), + ), + minWidth: MediaQuery.of(context).size.width, + height: 40.0, + child: RaisedButton( + elevation: 0.0, + color: Colors.white, + textColor: Colors.red, + hoverColor: Colors.transparent, + focusColor: Colors.transparent, + highlightColor: Colors.transparent, + disabledColor: new Color(0xFFbcc2c4), + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text( + TranslationBase.of(context).cancel, + style: TextStyle(fontSize: 18.0)), + ), + ), + ), + ), + ], + ), + ), + ], + ), + ), + ), + ); + }, + transitionDuration: Duration(milliseconds: 500), + barrierDismissible: true, + barrierLabel: '', + context: context, + pageBuilder: (context, animation1, animation2) {}); + } + + double getRatingWidth(int patientNumber) { + var width = (patientNumber / this.widget.appo.noOfPatientsRate) * 100; + return width; + } + + String getDate(String date) { + DateTime dateObj = DateUtil.convertStringToDate(date); + return DateUtil.getWeekDay(dateObj.weekday) + + ", " + + dateObj.day.toString() + + " " + + DateUtil.getMonth(dateObj.month) + + " " + + dateObj.year.toString(); + } + + String getDoctorSpeciality(List docSpecial) { + String docSpeciality = ""; + docSpecial.forEach((v) { + docSpeciality = docSpeciality + v + " "; + }); + return docSpeciality; + } DoctorList getDoctorObject() { DoctorList docObj = new DoctorList(); diff --git a/lib/pages/MyAppointments/MyAppointments.dart b/lib/pages/MyAppointments/MyAppointments.dart index aa3b72ae..a49149b5 100644 --- a/lib/pages/MyAppointments/MyAppointments.dart +++ b/lib/pages/MyAppointments/MyAppointments.dart @@ -1,4 +1,5 @@ import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/core/enum/filter_type.dart'; import 'package:diplomaticquarterapp/core/model/ImagesInfo.dart'; import 'package:diplomaticquarterapp/core/service/AuthenticatedUserObject.dart'; import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; @@ -28,6 +29,10 @@ class MyAppointments extends StatefulWidget { List(); List _patientArrivedAppointmentListHospital = List(); + List _patientBookedAppointmentListClinic = List(); + List _patientConfirmedAppointmentListClinic = List(); + List _patientArrivedAppointmentListClinic = List(); + @override _MyAppointmentsState createState() => _MyAppointmentsState(); } @@ -43,9 +48,12 @@ class _MyAppointmentsState extends State List imagesInfo = List(); + FilterType filterType; + @override void initState() { _tabController = new TabController(length: 3, vsync: this); + filterType = FilterType.Clinic; WidgetsBinding.instance.addPostFrameCallback((_) { if (Provider.of(context, listen: false).isLogin) getPatientAppointmentHistory(); @@ -84,17 +92,55 @@ class _MyAppointmentsState extends State color: Colors.grey[600], thickness: 0.5, ), - Expanded( - child: new TabBarView( - physics: NeverScrollableScrollPhysics(), - children: [ - isDataLoaded ? getBookedAppointments() : Container(), - isDataLoaded ? getConfirmedAppointments() : Container(), - isDataLoaded ? getArrivedAppointments() : Container() - ], - controller: _tabController, - ), + Row( + children: [ + Expanded( + flex: 1, + child: InkWell( + onTap: () => setFilterType(FilterType.Clinic), + child: ListTile( + title: Text(TranslationBase.of(context).clinic), + leading: Radio( + value: FilterType.Clinic, + groupValue: filterType, + activeColor: Theme.of(context).primaryColor, + onChanged: (FilterType value) { + setFilterType(value); + }, + ), + ), + ), + ), + Expanded( + flex: 1, + child: InkWell( + onTap: () => setFilterType(FilterType.Hospital), + child: ListTile( + title: Text(TranslationBase.of(context).hospital), + leading: Radio( + value: FilterType.Hospital, + groupValue: filterType, + activeColor: Theme.of(context).primaryColor, + onChanged: (FilterType value) => setFilterType(value), + ), + ), + ), + ) + ], ), + isDataLoaded + ? Expanded( + child: new TabBarView( + physics: NeverScrollableScrollPhysics(), + children: [ + getBookedAppointments(), + getConfirmedAppointments(), + getArrivedAppointments() + ], + controller: _tabController, + ), + ) + : Container(), ]), ), ); @@ -112,24 +158,30 @@ class _MyAppointmentsState extends State widget._patientConfirmedAppointmentListHospital.clear(); widget._patientArrivedAppointmentListHospital.clear(); + widget._patientBookedAppointmentListClinic.clear(); + widget._patientConfirmedAppointmentListClinic.clear(); + widget._patientArrivedAppointmentListClinic.clear(); + service.getPatientAppointmentHistory(false, context).then((res) { print(res['AppoimentAllHistoryResultList'].length); - if (res['MessageStatus'] == 1) { - GifLoaderDialogUtils.hideDialog(context); - setState(() { - isDataLoaded = true; + GifLoaderDialogUtils.hideDialog(context); + setState(() { + if (res['MessageStatus'] == 1) { + // setState(() { if (res['AppoimentAllHistoryResultList'].length != 0) { - isDataLoaded = true; + // isDataLoaded = true; res['AppoimentAllHistoryResultList'].forEach((v) { widget.appoList .add(new AppoitmentAllHistoryResultList.fromJson(v)); }); sortAppointmentList(); } else {} - }); - } else { - AppToast.showErrorToast(message: res['ErrorEndUserMessage']); - } + // }); + } else { + AppToast.showErrorToast(message: res['ErrorEndUserMessage']); + } + isDataLoaded = true; + }); }).catchError((err) { GifLoaderDialogUtils.hideDialog(context); print(err); @@ -166,11 +218,31 @@ class _MyAppointmentsState extends State }); widget.bookedAppoList.forEach((element) { + List doctorByClinic = + widget._patientBookedAppointmentListClinic + .where( + (elementClinic) => + elementClinic.filterName == element.clinicName, + ) + .toList(); + + if (doctorByClinic.length != 0) { + widget + ._patientBookedAppointmentListClinic[widget + ._patientBookedAppointmentListClinic + .indexOf(doctorByClinic[0])] + .patientDoctorAppointmentList + .add(element); + } else { + widget._patientBookedAppointmentListClinic.add(PatientAppointmentList( + filterName: element.clinicName, patientDoctorAppointment: element)); + } + List doctorByHospital = widget._patientBookedAppointmentListHospital .where( (elementClinic) => - elementClinic.filterName == element.clinicName, + elementClinic.filterName == element.projectName, ) .toList(); @@ -183,16 +255,39 @@ class _MyAppointmentsState extends State .add(element); } else { widget._patientBookedAppointmentListHospital.add(PatientAppointmentList( - filterName: element.clinicName, patientDoctorAppointment: element)); + filterName: element.projectName, + patientDoctorAppointment: element)); } }); widget.confirmedAppoList.forEach((element) { + List doctorByClinic = + widget._patientConfirmedAppointmentListClinic + .where( + (elementClinic) => + elementClinic.filterName == element.clinicName, + ) + .toList(); + + if (doctorByClinic.length != 0) { + widget + ._patientConfirmedAppointmentListClinic[widget + ._patientConfirmedAppointmentListClinic + .indexOf(doctorByClinic[0])] + .patientDoctorAppointmentList + .add(element); + } else { + widget._patientConfirmedAppointmentListClinic.add( + PatientAppointmentList( + filterName: element.clinicName, + patientDoctorAppointment: element)); + } + List doctorByHospital = widget._patientConfirmedAppointmentListHospital .where( (elementClinic) => - elementClinic.filterName == element.clinicName, + elementClinic.filterName == element.projectName, ) .toList(); @@ -206,17 +301,37 @@ class _MyAppointmentsState extends State } else { widget._patientConfirmedAppointmentListHospital.add( PatientAppointmentList( - filterName: element.clinicName, + filterName: element.projectName, patientDoctorAppointment: element)); } }); widget.arrivedAppoList.forEach((element) { + List doctorByClinic = + widget._patientArrivedAppointmentListClinic + .where( + (elementClinic) => + elementClinic.filterName == element.clinicName, + ) + .toList(); + + if (doctorByClinic.length != 0) { + widget + ._patientArrivedAppointmentListClinic[widget + ._patientArrivedAppointmentListClinic + .indexOf(doctorByClinic[0])] + .patientDoctorAppointmentList + .add(element); + } else { + widget._patientArrivedAppointmentListClinic.add(PatientAppointmentList( + filterName: element.clinicName, patientDoctorAppointment: element)); + } + List doctorByHospital = widget._patientArrivedAppointmentListHospital .where( (elementClinic) => - elementClinic.filterName == element.clinicName, + elementClinic.filterName == element.projectName, ) .toList(); @@ -230,9 +345,10 @@ class _MyAppointmentsState extends State } else { widget._patientArrivedAppointmentListHospital.add( PatientAppointmentList( - filterName: element.clinicName, + filterName: element.projectName, patientDoctorAppointment: element)); } + openAppointmentsTab(); }); } @@ -247,11 +363,11 @@ class _MyAppointmentsState extends State } else if (flag == 3) { _tabController.index = 2; } else { - if (widget._patientBookedAppointmentListHospital.length != 0) { + if (widget._patientBookedAppointmentListClinic.length != 0) { _tabController.index = 0; - } else if (widget._patientConfirmedAppointmentListHospital.length != 0) { + } else if (widget._patientConfirmedAppointmentListClinic.length != 0) { _tabController.index = 1; - } else if (widget._patientArrivedAppointmentListHospital.length != 0) { + } else if (widget._patientArrivedAppointmentListClinic.length != 0) { _tabController.index = 2; return; } @@ -267,24 +383,42 @@ class _MyAppointmentsState extends State child: Column( children: [ ...List.generate( - widget._patientBookedAppointmentListHospital.length, + filterType == FilterType.Clinic + ? widget._patientBookedAppointmentListClinic.length + : widget._patientBookedAppointmentListHospital.length, (index) => AppExpandableNotifier( - title: widget - ._patientBookedAppointmentListHospital[index] - .filterName, + title: filterType == FilterType.Clinic + ? widget + ._patientBookedAppointmentListClinic[index] + .filterName + : widget + ._patientBookedAppointmentListHospital[index] + .filterName, bodyWidget: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: widget - ._patientBookedAppointmentListHospital[index] - .patientDoctorAppointmentList - .map((doctor) { - return AppointmentCard( - appo: doctor, - onReloadAppointmentHistory: - getPatientAppointmentHistory, - ); - }).toList(), + children: filterType == FilterType.Clinic + ? widget + ._patientBookedAppointmentListClinic[index] + .patientDoctorAppointmentList + .map((doctor) { + return AppointmentCard( + appo: doctor, + onReloadAppointmentHistory: + getPatientAppointmentHistory, + ); + }).toList() + : widget + ._patientBookedAppointmentListHospital[ + index] + .patientDoctorAppointmentList + .map((doctor) { + return AppointmentCard( + appo: doctor, + onReloadAppointmentHistory: + getPatientAppointmentHistory, + ); + }).toList(), )), ) ], @@ -322,24 +456,43 @@ class _MyAppointmentsState extends State child: Column( children: [ ...List.generate( - widget._patientConfirmedAppointmentListHospital.length, + filterType == FilterType.Clinic + ? widget._patientConfirmedAppointmentListClinic.length + : widget + ._patientConfirmedAppointmentListHospital.length, (index) => AppExpandableNotifier( - title: widget - ._patientConfirmedAppointmentListHospital[index] - .filterName, + title: filterType == FilterType.Clinic + ? widget + ._patientConfirmedAppointmentListClinic[index] + .filterName + : widget + ._patientConfirmedAppointmentListHospital[index] + .filterName, bodyWidget: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: widget - ._patientConfirmedAppointmentListHospital[index] - .patientDoctorAppointmentList - .map((doctor) { - return AppointmentCard( - appo: doctor, - onReloadAppointmentHistory: - getPatientAppointmentHistory, - ); - }).toList(), + children: filterType == FilterType.Clinic + ? widget + ._patientConfirmedAppointmentListClinic[index] + .patientDoctorAppointmentList + .map((doctor) { + return AppointmentCard( + appo: doctor, + onReloadAppointmentHistory: + getPatientAppointmentHistory, + ); + }).toList() + : widget + ._patientConfirmedAppointmentListHospital[ + index] + .patientDoctorAppointmentList + .map((doctor) { + return AppointmentCard( + appo: doctor, + onReloadAppointmentHistory: + getPatientAppointmentHistory, + ); + }).toList(), )), ) ], @@ -375,24 +528,38 @@ class _MyAppointmentsState extends State child: Column( children: [ ...List.generate( - widget._patientArrivedAppointmentListHospital.length, + filterType == FilterType.Clinic + ? widget._patientArrivedAppointmentListClinic.length + : widget._patientArrivedAppointmentListHospital.length, (index) => AppExpandableNotifier( - title: widget - ._patientArrivedAppointmentListHospital[index] - .filterName, + title: filterType == FilterType.Clinic + ? widget._patientArrivedAppointmentListClinic[index] + .filterName + : widget._patientArrivedAppointmentListHospital[index] + .filterName, bodyWidget: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: widget - ._patientArrivedAppointmentListHospital[index] - .patientDoctorAppointmentList - .map((doctor) { - return AppointmentCard( - appo: doctor, - onReloadAppointmentHistory: - getPatientAppointmentHistory, - ); - }).toList(), + children: filterType == FilterType.Clinic + ? widget._patientArrivedAppointmentListClinic[index] + .patientDoctorAppointmentList + .map((doctor) { + return AppointmentCard( + appo: doctor, + onReloadAppointmentHistory: + getPatientAppointmentHistory, + ); + }).toList() + : widget + ._patientArrivedAppointmentListHospital[index] + .patientDoctorAppointmentList + .map((doctor) { + return AppointmentCard( + appo: doctor, + onReloadAppointmentHistory: + getPatientAppointmentHistory, + ); + }).toList(), ), ), ) @@ -419,4 +586,10 @@ class _MyAppointmentsState extends State ), ); } + + setFilterType(FilterType filterType) { + setState(() { + this.filterType = filterType; + }); + } } diff --git a/lib/pages/MyAppointments/models/ArrivedButtons.dart b/lib/pages/MyAppointments/models/ArrivedButtons.dart index a30349ba..136bd30f 100644 --- a/lib/pages/MyAppointments/models/ArrivedButtons.dart +++ b/lib/pages/MyAppointments/models/ArrivedButtons.dart @@ -2,13 +2,7 @@ import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; class ArrivedButtons { - static var buttons = [ - { - "title": TranslationBase.of(AppGlobal.context).arrived, - "subtitle": TranslationBase.of(AppGlobal.context).status, - "icon": "assets/images/new-design/waiting-room.png", - "caller": "openReschedule" - }, + var buttons = [ { "title": TranslationBase.of(AppGlobal.context).medicines, "subtitle": TranslationBase.of(AppGlobal.context).medicinesSubtitle, @@ -40,13 +34,13 @@ class ArrivedButtons { "caller": "insertComplaint" }, { - "title": TranslationBase.of(AppGlobal.context).insurance, + "title": TranslationBase.of(AppGlobal.context).insuranceApproval, "subtitle": TranslationBase.of(AppGlobal.context).insuranceSubtitle, "icon": "assets/images/new-design/insurance_approvals_icon.png", "caller": "Insurance" }, { - "title": TranslationBase.of(AppGlobal.context).askYour, + "title": TranslationBase.of(AppGlobal.context).askDoctor, "subtitle": TranslationBase.of(AppGlobal.context).askYourSubtitle, "icon": "assets/images/new-design/ask_doctor_icon.png", "caller": "askDoc" @@ -58,4 +52,4 @@ class ArrivedButtons { "caller": "Survey" } ]; -} +} \ No newline at end of file diff --git a/lib/pages/MyAppointments/models/BookedButtons.dart b/lib/pages/MyAppointments/models/BookedButtons.dart index 1a76be63..709b3b1f 100644 --- a/lib/pages/MyAppointments/models/BookedButtons.dart +++ b/lib/pages/MyAppointments/models/BookedButtons.dart @@ -2,7 +2,7 @@ import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; class BookedButtons { - static var buttons = [ + var buttons = [ { "title": TranslationBase.of(AppGlobal.context).confirm, "subtitle": TranslationBase.of(AppGlobal.context).appointment, diff --git a/lib/pages/MyAppointments/models/BookedButtonsAllowCheckIn.dart b/lib/pages/MyAppointments/models/BookedButtonsAllowCheckIn.dart index 374ebf45..9548b7c8 100644 --- a/lib/pages/MyAppointments/models/BookedButtonsAllowCheckIn.dart +++ b/lib/pages/MyAppointments/models/BookedButtonsAllowCheckIn.dart @@ -2,7 +2,7 @@ import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; class BookedButtonsAllowCheckIn { - static var buttons = [ + var buttons = [ { "title": TranslationBase.of(AppGlobal.context).confirm, "subtitle": TranslationBase.of(AppGlobal.context).appointment, diff --git a/lib/pages/MyAppointments/models/ConfirmedButtons.dart b/lib/pages/MyAppointments/models/ConfirmedButtons.dart index d5b7836e..b02021c7 100644 --- a/lib/pages/MyAppointments/models/ConfirmedButtons.dart +++ b/lib/pages/MyAppointments/models/ConfirmedButtons.dart @@ -2,7 +2,7 @@ import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; class ConfirmedButtons { - static var buttons = [ + var buttons = [ { "title": TranslationBase.of(AppGlobal.context).reschedule, "subtitle": TranslationBase.of(AppGlobal.context).appointment, diff --git a/lib/pages/MyAppointments/models/ConfirmedButtonsAllowCheckIn.dart b/lib/pages/MyAppointments/models/ConfirmedButtonsAllowCheckIn.dart index 1368e3f3..07ba333e 100644 --- a/lib/pages/MyAppointments/models/ConfirmedButtonsAllowCheckIn.dart +++ b/lib/pages/MyAppointments/models/ConfirmedButtonsAllowCheckIn.dart @@ -2,7 +2,7 @@ import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; class ConfirmedButtonsAllowCheckIn { - static var buttons = [ + var buttons = [ { "title": TranslationBase.of(AppGlobal.context).reschedule, "subtitle": TranslationBase.of(AppGlobal.context).appointment, diff --git a/lib/pages/MyAppointments/widgets/AppointmentActions.dart b/lib/pages/MyAppointments/widgets/AppointmentActions.dart index c0399b8a..60035ee1 100644 --- a/lib/pages/MyAppointments/widgets/AppointmentActions.dart +++ b/lib/pages/MyAppointments/widgets/AppointmentActions.dart @@ -1,3 +1,4 @@ +import 'package:diplomaticquarterapp/core/model/labs/patient_lab_orders.dart'; import 'package:diplomaticquarterapp/core/model/prescriptions/prescription_report_enh.dart'; import 'package:diplomaticquarterapp/core/model/radiology/final_radiology.dart'; import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; @@ -16,6 +17,7 @@ import 'package:diplomaticquarterapp/pages/MyAppointments/widgets/askDocDialog.d import 'package:diplomaticquarterapp/pages/MyAppointments/widgets/reminder_dialog.dart'; import 'package:diplomaticquarterapp/pages/feedback/feedback_home_page.dart'; import 'package:diplomaticquarterapp/pages/insurance/insurance_approval_screen.dart'; +import 'package:diplomaticquarterapp/pages/medical/labs/laboratory_result_page.dart'; import 'package:diplomaticquarterapp/pages/medical/radiology/radiology_details_page.dart'; import 'package:diplomaticquarterapp/pages/medical/vital_sign/vital_sign_details_screen.dart'; import 'package:diplomaticquarterapp/services/appointment_services/GetDoctorsList.dart'; @@ -62,8 +64,8 @@ class _AppointmentActionsState extends State { toDoProvider = Provider.of(context); var size = MediaQuery.of(context).size; final double itemHeight = projectViewModel.isArabic - ? ((size.height - kToolbarHeight - 24) * 0.47) / 2 - : ((size.height - kToolbarHeight - 24) * 0.4) / 2; + ? ((size.height - kToolbarHeight - 24) * 0.5) / 2 + : ((size.height - kToolbarHeight - 24) * 0.45) / 2; final double itemWidth = size.width / 2; return Container( @@ -83,12 +85,12 @@ class _AppointmentActionsState extends State { _handleButtonClicks(e); }, child: Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: MainAxisSize.max, children: [ Container( // height: 100.0, margin: EdgeInsets.all(7.0), - padding: EdgeInsets.only(bottom: 15.0), + padding: EdgeInsets.only(bottom: 4.0), decoration: BoxDecoration( boxShadow: [ BoxShadow( @@ -100,7 +102,7 @@ class _AppointmentActionsState extends State { color: Colors.white), child: Column( crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, + mainAxisSize: MainAxisSize.max, children: [ Container( margin: @@ -196,6 +198,10 @@ class _AppointmentActionsState extends State { openAppointmentRadiology(); break; + case "labResult": + openAppointmentLabResults(); + break; + case "prescriptions": openPrescriptionReport(); break; @@ -270,14 +276,15 @@ class _AppointmentActionsState extends State { Future> _getBookedAppoActionsList() async { print("_getBookedAppoActionsList"); - print(BookedButtons.buttons); + BookedButtons bookedButtons = new BookedButtons(); + print(bookedButtons.buttons); List buttonsList = []; - for (var i = 0; i < BookedButtons.buttons.length; i++) { + for (var i = 0; i < bookedButtons.buttons.length; i++) { buttonsList.add(AppoDetailsButton( - title: BookedButtons.buttons[i]['title'], - subtitle: BookedButtons.buttons[i]['subtitle'], - icon: BookedButtons.buttons[i]['icon'], - caller: BookedButtons.buttons[i]['caller'], + title: bookedButtons.buttons[i]['title'], + subtitle: bookedButtons.buttons[i]['subtitle'], + icon: bookedButtons.buttons[i]['icon'], + caller: bookedButtons.buttons[i]['caller'], )); } setState(() { @@ -287,14 +294,16 @@ class _AppointmentActionsState extends State { Future> _getBookedCheckInAppoActionsList() async { print("_getBookedCheckInAppoActionsList"); - print(BookedButtonsAllowCheckIn.buttons); + BookedButtonsAllowCheckIn bookedButtonsAllowCheckIn = + new BookedButtonsAllowCheckIn(); + print(bookedButtonsAllowCheckIn.buttons); List buttonsList = []; - for (var i = 0; i < BookedButtonsAllowCheckIn.buttons.length; i++) { + for (var i = 0; i < bookedButtonsAllowCheckIn.buttons.length; i++) { buttonsList.add(AppoDetailsButton( - title: BookedButtonsAllowCheckIn.buttons[i]['title'], - subtitle: BookedButtonsAllowCheckIn.buttons[i]['subtitle'], - icon: BookedButtonsAllowCheckIn.buttons[i]['icon'], - caller: BookedButtonsAllowCheckIn.buttons[i]['caller'], + title: bookedButtonsAllowCheckIn.buttons[i]['title'], + subtitle: bookedButtonsAllowCheckIn.buttons[i]['subtitle'], + icon: bookedButtonsAllowCheckIn.buttons[i]['icon'], + caller: bookedButtonsAllowCheckIn.buttons[i]['caller'], )); } setState(() { @@ -304,14 +313,15 @@ class _AppointmentActionsState extends State { Future> _getConfirmedAppoActionsList() async { print("_getConfirmedAppoActionsList"); - print(ConfirmedButtons.buttons); + ConfirmedButtons confirmedButtons = new ConfirmedButtons(); + print(confirmedButtons.buttons); List buttonsList = []; - for (var i = 0; i < ConfirmedButtons.buttons.length; i++) { + for (var i = 0; i < confirmedButtons.buttons.length; i++) { buttonsList.add(AppoDetailsButton( - title: ConfirmedButtons.buttons[i]['title'], - subtitle: ConfirmedButtons.buttons[i]['subtitle'], - icon: ConfirmedButtons.buttons[i]['icon'], - caller: ConfirmedButtons.buttons[i]['caller'], + title: confirmedButtons.buttons[i]['title'], + subtitle: confirmedButtons.buttons[i]['subtitle'], + icon: confirmedButtons.buttons[i]['icon'], + caller: confirmedButtons.buttons[i]['caller'], )); } setState(() { @@ -321,14 +331,16 @@ class _AppointmentActionsState extends State { Future> _getConfirmedCheckInAppoActionsList() async { print("_getConfirmedAllowCheckInAppoActionsList"); - print(ConfirmedButtonsAllowCheckIn.buttons); + ConfirmedButtonsAllowCheckIn confirmedButtonsAllowCheckIn = + new ConfirmedButtonsAllowCheckIn(); + print(confirmedButtonsAllowCheckIn.buttons); List buttonsList = []; - for (var i = 0; i < ConfirmedButtonsAllowCheckIn.buttons.length; i++) { + for (var i = 0; i < confirmedButtonsAllowCheckIn.buttons.length; i++) { buttonsList.add(AppoDetailsButton( - title: ConfirmedButtonsAllowCheckIn.buttons[i]['title'], - subtitle: ConfirmedButtonsAllowCheckIn.buttons[i]['subtitle'], - icon: ConfirmedButtonsAllowCheckIn.buttons[i]['icon'], - caller: ConfirmedButtonsAllowCheckIn.buttons[i]['caller'], + title: confirmedButtonsAllowCheckIn.buttons[i]['title'], + subtitle: confirmedButtonsAllowCheckIn.buttons[i]['subtitle'], + icon: confirmedButtonsAllowCheckIn.buttons[i]['icon'], + caller: confirmedButtonsAllowCheckIn.buttons[i]['caller'], )); } setState(() { @@ -338,14 +350,15 @@ class _AppointmentActionsState extends State { Future> _getArrivedAppoActionsList() async { print("_getArrivedAppoActionsList"); - print(ArrivedButtons.buttons); + ArrivedButtons arrivedButtons = new ArrivedButtons(); + print(arrivedButtons.buttons); List buttonsList = []; - for (var i = 0; i < ArrivedButtons.buttons.length; i++) { + for (var i = 0; i < arrivedButtons.buttons.length; i++) { buttonsList.add(AppoDetailsButton( - title: ArrivedButtons.buttons[i]['title'], - subtitle: ArrivedButtons.buttons[i]['subtitle'], - icon: ArrivedButtons.buttons[i]['icon'], - caller: ArrivedButtons.buttons[i]['caller'], + title: arrivedButtons.buttons[i]['title'], + subtitle: arrivedButtons.buttons[i]['subtitle'], + icon: arrivedButtons.buttons[i]['icon'], + caller: arrivedButtons.buttons[i]['caller'], )); } setState(() { @@ -355,14 +368,14 @@ class _AppointmentActionsState extends State { Future> _getArrivedInvoiceAppoActionsList() async { print("_getArrivedInvoiceAppoActionsList"); - print(ArrivedButtons.buttons); + ArrivedButtons arrivedButtons = new ArrivedButtons(); List buttonsList = []; - for (var i = 0; i < ArrivedButtons.buttons.length; i++) { + for (var i = 0; i < arrivedButtons.buttons.length; i++) { buttonsList.add(AppoDetailsButton( - title: ArrivedButtons.buttons[i]['title'], - subtitle: ArrivedButtons.buttons[i]['subtitle'], - icon: ArrivedButtons.buttons[i]['icon'], - caller: ArrivedButtons.buttons[i]['caller'], + title: arrivedButtons.buttons[i]['title'], + subtitle: arrivedButtons.buttons[i]['subtitle'], + icon: arrivedButtons.buttons[i]['icon'], + caller: arrivedButtons.buttons[i]['caller'], )); } setState(() { @@ -391,18 +404,48 @@ class _AppointmentActionsState extends State { } getToDoCount() { - toDoProvider.setState(0); + toDoProvider.setState(0, true); ClinicListService service = new ClinicListService(); service.getActiveAppointmentNo(context).then((res) { print(res['AppointmentActiveNumber']); if (res['MessageStatus'] == 1) { - toDoProvider.setState(res['AppointmentActiveNumber']); + toDoProvider.setState(res['AppointmentActiveNumber'], true); } else {} }).catchError((err) { print(err); }); } + openAppointmentLabResults() { + GifLoaderDialogUtils.showMyDialog(context); + DoctorsListService service = new DoctorsListService(); + PatientLabOrders patientLabOrders = new PatientLabOrders(); + service + .getPatientLabOrdersByAppoNo(widget.appo.appointmentNo, + widget.appo.projectID, widget.appo.clinicID, context) + .then((res) { + print(res['ListLabResultsByAppNo']); + GifLoaderDialogUtils.hideDialog(context); + if (res['ListLabResultsByAppNo'] != null) { + patientLabOrders.orderNo = + res['ListLabResultsByAppNo'][0]['OrderNo'].toString(); + patientLabOrders.invoiceNo = + res['ListLabResultsByAppNo'][0]['InvoiceNo'].toString(); + patientLabOrders.clinicID = widget.appo.clinicID; + patientLabOrders.projectID = widget.appo.projectID.toString(); + print(patientLabOrders.invoiceNo); + print(patientLabOrders.orderNo); + navigateToLabResults(patientLabOrders); + } else { + AppToast.showErrorToast(message: res['ErrorEndUserMessage']); + } + }).catchError((err) { + GifLoaderDialogUtils.hideDialog(context); + print(err); + AppToast.showErrorToast(message: err); + }); + } + openAppointmentRadiology() { GifLoaderDialogUtils.showMyDialog(context); DoctorsListService service = new DoctorsListService(); @@ -411,11 +454,15 @@ class _AppointmentActionsState extends State { .getPatientRadOrders(widget.appo.appointmentNo.toString(), context) .then((res) { GifLoaderDialogUtils.hideDialog(context); - print(res['FinalRadiologyList']); - finalRadiology = - new FinalRadiology.fromJson(res['FinalRadiologyList'][0]); - print(finalRadiology.reportData); - navigateToRadiologyDetails(finalRadiology); + if (res['FinalRadiologyList'] != null) { + print(res['FinalRadiologyList']); + finalRadiology = + new FinalRadiology.fromJson(res['FinalRadiologyList'][0]); + print(finalRadiology.reportData); + navigateToRadiologyDetails(finalRadiology); + } else { + AppToast.showErrorToast(message: res['ErrorEndUserMessage']); + } }).catchError((err) { GifLoaderDialogUtils.hideDialog(context); print(err); @@ -429,19 +476,19 @@ class _AppointmentActionsState extends State { DoctorsListService service = new DoctorsListService(); service.getPatientPrescriptionReports(widget.appo, context).then((res) { GifLoaderDialogUtils.hideDialog(context); - res['ListPRM'].forEach((report) { - prescriptionReportEnhList.add(PrescriptionReportEnh.fromJson(report)); - }); - print(prescriptionReportEnhList.length); - if (prescriptionReportEnhList.length != 0) { + if (res['ListPRM'].length != 0) { + res['ListPRM'].forEach((report) { + prescriptionReportEnhList.add(PrescriptionReportEnh.fromJson(report)); + }); + print(prescriptionReportEnhList.length); navigateToMedicinePrescriptionReport( prescriptionReportEnhList, res['ListPRM']); } else { - AppToast.showErrorToast(message: "Sorry there is no data"); + AppToast.showErrorToast(message: TranslationBase.of(context).noRecords); } }).catchError((err) { - GifLoaderDialogUtils.hideDialog(context); print(err); + GifLoaderDialogUtils.hideDialog(context); AppToast.showErrorToast(message: err); }); } @@ -458,6 +505,15 @@ class _AppointmentActionsState extends State { appo: widget.appo))); } + Future navigateToLabResults(PatientLabOrders patientLabOrders) async { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + LaboratoryResultPage(patientLabOrders: patientLabOrders))) + .then((value) {}); + } + Future navigateToRadiologyDetails(FinalRadiology finalRadiology) async { Navigator.push( context, @@ -612,7 +668,7 @@ class _AppointmentActionsState extends State { context, FadePage( page: VitalSignDetailsScreen( - appointmentNo: appoNo, projectID: projectID))); + appointmentNo: appoNo, projectID: projectID,isNotOneAppointment: false,))); } navigateToInsertComplaint() { diff --git a/lib/pages/MyAppointments/widgets/AppointmentCardView.dart b/lib/pages/MyAppointments/widgets/AppointmentCardView.dart index 1bbe471a..c4299e33 100644 --- a/lib/pages/MyAppointments/widgets/AppointmentCardView.dart +++ b/lib/pages/MyAppointments/widgets/AppointmentCardView.dart @@ -1,10 +1,13 @@ +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/models/Appointments/AppoimentAllHistoryResultList.dart'; import 'package:diplomaticquarterapp/pages/MyAppointments/models/AppointmentType.dart'; import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_countdown_timer/countdown_timer_controller.dart'; import 'package:flutter_countdown_timer/current_remaining_time.dart'; import 'package:flutter_countdown_timer/flutter_countdown_timer.dart'; +import 'package:provider/provider.dart'; import 'package:rating_bar/rating_bar.dart'; import '../AppointmentDetails.dart'; @@ -21,8 +24,20 @@ class AppointmentCard extends StatefulWidget { } class _ApointmentCardState extends State { + CountdownTimerController controller; + + @override + void initState() { + super.initState(); + int endTime = DateTime.now().millisecondsSinceEpoch + 1000 * 30; + controller = CountdownTimerController( + endTime: endTime, + ); + } + @override Widget build(BuildContext context) { + ProjectViewModel projectViewModel = Provider.of(context); return InkWell( onTap: () { navigateToAppointmentDetails(context, widget.appo); @@ -40,92 +55,157 @@ class _ApointmentCardState extends State { child: Row( mainAxisAlignment: MainAxisAlignment.start, children: [ + Container( + width: projectViewModel.isArabic ? 27 : 20, + height: projectViewModel.isArabic ? 165 : 140, + decoration: BoxDecoration( + //Colors.red[900] Color(0xff404545) + color: widget.appo.isLiveCareAppointment + ? Color(0xff404545) + : !widget.appo.isInOutPatient + ? Colors.red[900] + : Theme.of(context).primaryColor, + borderRadius: BorderRadius.only( + topLeft: projectViewModel.isArabic + ? Radius.circular(0) + : Radius.circular(8), + bottomLeft: projectViewModel.isArabic + ? Radius.circular(0) + : Radius.circular(8), + topRight: projectViewModel.isArabic + ? Radius.circular(8) + : Radius.circular(0), + bottomRight: projectViewModel.isArabic + ? Radius.circular(8) + : Radius.circular(0), + ), + ), + child: RotatedBox( + quarterTurns: 3, + child: Center( + child: Text( + widget.appo.isLiveCareAppointment + ? TranslationBase.of(context) + .liveCare + .toUpperCase() + : !widget.appo.isInOutPatient + ? TranslationBase.of(context) + .inPatient + .toUpperCase() + : TranslationBase.of(context) + .outpatient + .toUpperCase(), + style: TextStyle(color: Colors.white), + ), + )), + ), + SizedBox(width: 8,), ClipRRect( borderRadius: BorderRadius.circular(100.0), child: Image.network(widget.appo.doctorImageURL, fit: BoxFit.fill, height: 60.0, width: 60.0), ), - Container( - width: MediaQuery.of(context).size.width * 0.57, - margin: EdgeInsets.fromLTRB(20.0, 10.0, 10.0, 0.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - widget.appo.doctorTitle + - " " + - widget.appo.doctorNameObj, - style: TextStyle( - fontSize: 14.0, - color: Colors.grey[700], - letterSpacing: 1.0)), - Container( - margin: EdgeInsets.only(top: 3.0), - child: Text(widget.appo.clinicName, - style: TextStyle( - fontSize: 12.0, - color: Colors.grey[600], - letterSpacing: 1.0)), - ), - Container( - margin: EdgeInsets.only(top: 3.0), - child: Text(widget.appo.projectName, + Expanded( + child: Container( + width: MediaQuery.of(context).size.width * 0.61, + margin: EdgeInsets.fromLTRB(20.0, 10.0, 10.0, 0.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + widget.appo.doctorTitle + + " " + + widget.appo.doctorNameObj, style: TextStyle( - fontSize: 12.0, - color: Colors.grey[600], + fontSize: 14.0, + color: Colors.grey[700], letterSpacing: 1.0)), - ), - Container( - margin: EdgeInsets.only(top: 3.0, bottom: 3.0), - child: Text(getDate(widget.appo.appointmentDate).trim(), - style: TextStyle( - fontSize: 12.0, - color: Colors.grey[600], - letterSpacing: 1.0)), - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - mainAxisSize: MainAxisSize.max, - children: [ - RatingBar.readOnly( - initialRating: - widget.appo.actualDoctorRate.toDouble(), - size: 20.0, - filledColor: Colors.yellow[700], - emptyColor: Colors.grey[500], - isHalfAllowed: true, - halfFilledIcon: Icons.star_half, - filledIcon: Icons.star, - emptyIcon: Icons.star, - ), - Container( - transform: - Matrix4.translationValues(15.0, -40.0, 0.0), - child: Image.asset( - "assets/images/new-design/arrow.png", - width: 25.0, - height: 25.0), - ), - ], - ), - widget.appo.patientStatusType == AppointmentType.BOOKED ? - Container( - child: CountdownTimer( - endTime: DateTime.now().millisecondsSinceEpoch + - (widget.appo.remaniningHoursTocanPay * 1000) * - 60, - widgetBuilder: (_, CurrentRemainingTime time) { - return Text( - '${time.days}:${time.hours}:${time.min}:${time.sec} ' + - TranslationBase.of(context) - .upcomingTimeLeft, - style: TextStyle( - fontSize: 12.0, - color: Color(0xff40ACC9))); - }, + Container( + margin: EdgeInsets.only(top: 3.0), + child: Text(widget.appo.clinicName, + style: TextStyle( + fontSize: 12.0, + color: Colors.grey[600], + letterSpacing: 1.0)), + ), + Container( + margin: EdgeInsets.only(top: 3.0), + child: Text(widget.appo.projectName, + style: TextStyle( + fontSize: 12.0, + color: Colors.grey[600], + letterSpacing: 1.0)), + ), + Container( + margin: EdgeInsets.only(top: 3.0, bottom: 3.0), + child: Text( + DateUtil.getWeekDayMonthDayYearDateFormatted( + DateUtil.convertStringToDate( + widget.appo.appointmentDate), + projectViewModel.isArabic ? "ar" : "en") + .trim(), + style: TextStyle( + fontSize: 12.0, + color: Colors.grey[600], + letterSpacing: 1.0)), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisSize: MainAxisSize.max, + children: [ + RatingBar.readOnly( + initialRating: + widget.appo.actualDoctorRate.toDouble(), + size: 20.0, + filledColor: Colors.yellow[700], + emptyColor: Colors.grey[500], + isHalfAllowed: true, + halfFilledIcon: Icons.star_half, + filledIcon: Icons.star, + emptyIcon: Icons.star, + ), + Container( + transform: + Matrix4.translationValues(15.0, -40.0, 0.0), + child: projectViewModel.isArabic + ? Image.asset( + "assets/images/new-design/arrow_menu_black-ar.png", + width: 25.0, + height: 25.0) + : Image.asset( + "assets/images/new-design/arrow_menu_black-en.png", + width: 25.0, + height: 25.0), ), - ) : Container(), - ], + ], + ), + (widget.appo.patientStatusType == AppointmentType.BOOKED || + widget.appo.patientStatusType == + AppointmentType.CONFIRMED) + ? Container( + child: CountdownTimer( + controller: new CountdownTimerController( + endTime: + DateTime.now().millisecondsSinceEpoch + + (widget.appo.remaniningHoursTocanPay * + 1000) * + 60), + widgetBuilder: (_, CurrentRemainingTime time) { + return time != null + ? Text( + '${time.days}:${time.hours}:${time.min}:${time.sec} ' + + TranslationBase.of(context) + .upcomingTimeLeft, + style: TextStyle( + fontSize: 12.0, + color: Color(0xff40ACC9))) + : Container(); + }, + ), + ) + : Container(), + ], + ), ), ), ], diff --git a/lib/pages/MyAppointments/widgets/custom_radio.dart b/lib/pages/MyAppointments/widgets/custom_radio.dart index 2ea9a39c..b21e34ec 100644 --- a/lib/pages/MyAppointments/widgets/custom_radio.dart +++ b/lib/pages/MyAppointments/widgets/custom_radio.dart @@ -1,6 +1,7 @@ import 'package:diplomaticquarterapp/pages/MyAppointments/models/AskDocRequestTypeModel.dart'; import 'package:diplomaticquarterapp/pages/MyAppointments/widgets/askDocDialog.dart'; import 'package:diplomaticquarterapp/pages/MyAppointments/widgets/reminder_dialog.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:flutter/material.dart'; class CustomRadio extends StatefulWidget { @@ -21,17 +22,23 @@ class CustomRadioState extends State { void initState() { super.initState(); - if (widget.requestData != null) { - widget.requestData.forEach((element) { - sampleData.add( - new RadioModel(false, element.description, element.parameterCode)); - }); - } else { - sampleData.add(new RadioModel(false, "Before 30 Mins", 30)); - sampleData.add(new RadioModel(false, 'Before 1 Hour', 60)); - sampleData.add(new RadioModel(false, 'Before 2 Hours', 120)); - sampleData.add(new RadioModel(false, 'Before 4 Hours', 240)); - } + WidgetsBinding.instance.addPostFrameCallback((_) { + if (widget.requestData != null) { + widget.requestData.forEach((element) { + sampleData.add(new RadioModel( + false, element.description, element.parameterCode)); + }); + } else { + sampleData.add(new RadioModel( + false, TranslationBase.of(context).appoReminder30, 30)); + sampleData.add(new RadioModel( + false, TranslationBase.of(context).appoReminder60, 60)); + sampleData.add(new RadioModel( + false, TranslationBase.of(context).appoReminder90, 90)); + sampleData.add(new RadioModel( + false, TranslationBase.of(context).appoReminder120, 120)); + } + }); } @override @@ -96,7 +103,7 @@ class RadioItem extends StatelessWidget { ), ), new Container( - margin: new EdgeInsets.only(left: 15.0), + margin: new EdgeInsets.only(left: 15.0, right: 15.0), child: new Text(_item.text, style: TextStyle(fontSize: 16.0)), ), ], diff --git a/lib/pages/MyAppointments/widgets/reminder_dialog.dart b/lib/pages/MyAppointments/widgets/reminder_dialog.dart index 13955e5b..b8803469 100644 --- a/lib/pages/MyAppointments/widgets/reminder_dialog.dart +++ b/lib/pages/MyAppointments/widgets/reminder_dialog.dart @@ -27,19 +27,18 @@ class _ReminderDialogState extends State { shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.0)), child: Container( - height: MediaQuery.of(context).size.height * 0.57, + // height: MediaQuery.of(context).size.height * 0.57, width: 450.0, child: Column( crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.max, + mainAxisSize: MainAxisSize.min, children: [ Container( margin: EdgeInsets.all(20.0), child: Text(TranslationBase.of(context).setReminder, style: TextStyle( fontSize: 20.0, - fontWeight: FontWeight.bold, - fontFamily: "Open-Sans-Bold")), + fontWeight: FontWeight.bold)), ), Container( transform: Matrix4.translationValues(0.0, -30.0, 0.0), @@ -61,13 +60,12 @@ class _ReminderDialogState extends State { child: Text(TranslationBase.of(context).confirm, style: TextStyle( color: Colors.white, - fontWeight: FontWeight.bold, - fontFamily: 'Open-Sans-Bold')), + fontWeight: FontWeight.bold)), ), ), Container( width: MediaQuery.of(context).size.width, - margin: EdgeInsets.only(left: 100.0, top: 20.0, right: 100.0), + margin: EdgeInsets.only(left: 100.0, top: 20.0, right: 100.0, bottom: 20.0), child: OutlineButton( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10.0)), @@ -81,8 +79,7 @@ class _ReminderDialogState extends State { child: Text(TranslationBase.of(context).cancel_nocaps, style: TextStyle( color: Colors.red, - fontWeight: FontWeight.bold, - fontFamily: 'Open-Sans-Bold')), + fontWeight: FontWeight.bold)), ), ), ]), diff --git a/lib/pages/ToDoList/ToDo.dart b/lib/pages/ToDoList/ToDo.dart index fb8990b2..1066ca15 100644 --- a/lib/pages/ToDoList/ToDo.dart +++ b/lib/pages/ToDoList/ToDo.dart @@ -1,15 +1,19 @@ import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/core/model/ImagesInfo.dart'; import 'package:diplomaticquarterapp/core/service/AuthenticatedUserObject.dart'; +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/models/Appointments/toDoCountProviderModel.dart'; import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; import 'package:diplomaticquarterapp/pages/BookAppointment/QRCode.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/routes.dart'; import 'package:diplomaticquarterapp/services/appointment_services/GetDoctorsList.dart'; +import 'package:diplomaticquarterapp/services/clinic_services/get_clinic_service.dart'; import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; import 'package:diplomaticquarterapp/uitl/app_toast.dart'; import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; @@ -19,9 +23,11 @@ import 'package:diplomaticquarterapp/uitl/utils.dart'; import 'package:diplomaticquarterapp/widgets/in_app_browser/InAppBrowser.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_countdown_timer/countdown_timer_controller.dart'; import 'package:flutter_countdown_timer/current_remaining_time.dart'; import 'package:flutter_countdown_timer/flutter_countdown_timer.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:provider/provider.dart'; import 'package:rating_bar/rating_bar.dart'; class ToDo extends StatefulWidget { @@ -30,6 +36,10 @@ class ToDo extends StatefulWidget { var languageID; MyInAppBrowser browser; + bool isShowAppBar = true; + + ToDo({@required this.isShowAppBar}); + @override _ToDoState createState() => _ToDoState(); } @@ -43,6 +53,9 @@ class _ToDoState extends State { List imagesInfo = List(); + ToDoCountProviderModel toDoProvider; + CountdownTimerController controller; + @override void initState() { widget.patientShareResponse = new PatientShareResponse(); @@ -55,14 +68,19 @@ class _ToDoState extends State { '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')); + int endTime = DateTime.now().millisecondsSinceEpoch + 1000 * 30; + controller = CountdownTimerController(endTime: endTime); } @override Widget build(BuildContext context) { + toDoProvider = Provider.of(context); + ProjectViewModel projectViewModel = Provider.of(context); return AppScaffold( appBarTitle: TranslationBase.of(context).todoList, imagesInfo: imagesInfo, - isShowAppBar: true, + isShowAppBar: widget.isShowAppBar, + isShowDecPage: true, description: TranslationBase.of(context).infoTodo, body: SingleChildScrollView( child: Column( @@ -98,11 +116,19 @@ class _ToDoState extends State { height: 20.0), Container( margin: - EdgeInsets.only(left: 5.0, right: 20.0), + EdgeInsets.only(left: 10.0, right: 10.0), child: Text( - getDate(widget - .appoList[index].appointmentDate), - style: TextStyle(fontSize: 11.0)), + DateUtil.getWeekDayMonthDayYearDateFormatted( + DateUtil.convertStringToDate( + widget.appoList[index] + .appointmentDate), + projectViewModel.isArabic + ? "ar" + : "en") + + " " + + widget.appoList[index].startTime + .substring(0, 5), + style: TextStyle(fontSize: 10.0)), ), widget.appoList[index].isLiveCareAppointment ? SvgPicture.asset( @@ -130,7 +156,7 @@ class _ToDoState extends State { : "-", overflow: TextOverflow.clip, maxLines: 2, - style: TextStyle(fontSize: 11.0)), + style: TextStyle(fontSize: 10.0)), ), ], ), @@ -212,17 +238,26 @@ class _ToDoState extends State { ), Container( child: CountdownTimer( - endTime: DateTime.now().millisecondsSinceEpoch + - (widget.appoList[index] - .remaniningHoursTocanPay * - 1000) * - 60, - widgetBuilder: (_, CurrentRemainingTime time) { - return Text( - '${time.days}:${time.hours}:${time.min}:${time.sec} ' + TranslationBase.of(context).upcomingTimeLeft, - style: TextStyle( - fontSize: 12.0, - color: Color(0xff40ACC9))); + controller: new CountdownTimerController( + endTime: DateTime.now() + .millisecondsSinceEpoch + + (widget.appoList[index] + .remaniningHoursTocanPay * + 1000) * + 60), + widgetBuilder: + (_, CurrentRemainingTime time) { + return time != null + ? Text( + '${time.days}:${time.hours}:${time.min}:${time.sec} ' + + TranslationBase.of( + context) + .upcomingTimeLeft, + style: TextStyle( + fontSize: 12.0, + color: Color( + 0xff40ACC9))) + : Container(); }, ), ), @@ -507,6 +542,7 @@ class _ToDoState extends State { GifLoaderDialogUtils.showMyDialog(context); DoctorsListService service = new DoctorsListService(); service.getPatientAppointmentHistory(true, context).then((res) { + widget.appoList.clear(); GifLoaderDialogUtils.hideDialog(context); if (res['MessageStatus'] == 1) { setState(() { @@ -516,12 +552,9 @@ class _ToDoState extends State { widget.appoList .add(new AppoitmentAllHistoryResultList.fromJson(v)); }); - } else {} - }); - widget.appoList.forEach((element) { - print(element.isLiveCareAppointment); - print(element.nextAction); - print(element.remaniningHoursTocanPay); + } else { + Navigator.of(context).popAndPushNamed(HOME); + } }); } else { AppToast.showErrorToast(message: res['ErrorEndUserMessage']); @@ -529,7 +562,7 @@ class _ToDoState extends State { }).catchError((err) { print(err); GifLoaderDialogUtils.hideDialog(context); - AppToast.showErrorToast(message: err); + err != null ?? AppToast.showErrorToast(message: err); }); } diff --git a/lib/pages/ToDoList/payment_method_select.dart b/lib/pages/ToDoList/payment_method_select.dart index fe2a217b..3a0734dc 100644 --- a/lib/pages/ToDoList/payment_method_select.dart +++ b/lib/pages/ToDoList/payment_method_select.dart @@ -163,45 +163,45 @@ class _PaymentMethodState extends State { ], ), ), - // Container( - // margin: EdgeInsets.only(top: 25.0), - // child: Flex( - // direction: Axis.horizontal, - // children: [ - // Expanded( - // child: Container( - // child: InkWell( - // onTap: () { - // updateSelectedPaymentMethod("ApplePay"); - // }, - // child: Card( - // elevation: 3.0, - // margin: EdgeInsets.fromLTRB(8.0, 16.0, 8.0, 8.0), - // color: Colors.white, - // shape: RoundedRectangleBorder( - // borderRadius: BorderRadius.circular(10), - // side: selectedPaymentMethod == "ApplePay" - // ? BorderSide( - // color: Colors.green, width: 5.0) - // : BorderSide( - // color: Colors.transparent, width: 0.0), - // ), - // child: Container( - // height: 120.0, - // padding: EdgeInsets.all(20.0), - // child: SvgPicture.asset( - // "assets/images/new-design/applepay.svg"), - // ), - // ), - // ), - // ), - // ), - // Expanded( - // child: Container(), - // ), - // ], - // ), - // ), + Container( + margin: EdgeInsets.only(top: 25.0), + child: Flex( + direction: Axis.horizontal, + children: [ + Expanded( + child: Container( + child: InkWell( + onTap: () { + updateSelectedPaymentMethod("ApplePay"); + }, + child: Card( + elevation: 3.0, + margin: EdgeInsets.fromLTRB(8.0, 16.0, 8.0, 8.0), + color: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + side: selectedPaymentMethod == "ApplePay" + ? BorderSide( + color: Colors.green, width: 5.0) + : BorderSide( + color: Colors.transparent, width: 0.0), + ), + child: Container( + height: 120.0, + padding: EdgeInsets.all(20.0), + child: SvgPicture.asset( + "assets/images/new-design/applepay.svg"), + ), + ), + ), + ), + ), + Expanded( + child: Container(), + ), + ], + ), + ), SizedBox( height: 150.0, ), @@ -218,7 +218,7 @@ class _PaymentMethodState extends State { shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10.0), ), - minWidth: MediaQuery.of(context).size.width * 0.7, + minWidth: MediaQuery.of(context).size.height * 0.1, height: 45.0, child: RaisedButton( color: new Color(0xFF60686b), diff --git a/lib/pages/base/base_view.dart b/lib/pages/base/base_view.dart index 38b70e23..5977e97e 100644 --- a/lib/pages/base/base_view.dart +++ b/lib/pages/base/base_view.dart @@ -63,4 +63,4 @@ class _BaseViewState extends State> { super.dispose(); } -} \ No newline at end of file +} diff --git a/lib/pages/feedback/feedback_home_page.dart b/lib/pages/feedback/feedback_home_page.dart index 3d761bd3..f7f998bf 100644 --- a/lib/pages/feedback/feedback_home_page.dart +++ b/lib/pages/feedback/feedback_home_page.dart @@ -73,8 +73,7 @@ class _FeedbackHomePageState extends State isScrollable: true, controller: _tabController, indicatorWeight: 5.0, - indicatorSize: TabBarIndicatorSize.label, - indicatorColor: Theme.of(context).primaryColor, + indicatorSize: TabBarIndicatorSize.tab, labelColor: Theme.of(context).primaryColor, labelPadding: EdgeInsets.only(top: 4.0, left: 18.0, right: 18.0), diff --git a/lib/pages/feedback/send_feedback_page.dart b/lib/pages/feedback/send_feedback_page.dart index 14463825..aded1a3b 100644 --- a/lib/pages/feedback/send_feedback_page.dart +++ b/lib/pages/feedback/send_feedback_page.dart @@ -3,10 +3,12 @@ import 'package:diplomaticquarterapp/core/viewModels/feedback/feedback_view_mode import 'package:diplomaticquarterapp/pages/base/base_view.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/avatar/large_avatar.dart'; import 'package:diplomaticquarterapp/widgets/bottom_options/BottomSheet.dart'; import 'package:diplomaticquarterapp/widgets/buttons/button.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/secondary_button.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/input/text_field.dart'; import 'package:diplomaticquarterapp/widgets/others/StarRating.dart'; @@ -14,7 +16,8 @@ import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; - +import 'dart:convert'; +import 'dart:io'; import 'appointment_history.dart'; class SendFeedbackPage extends StatefulWidget { @@ -31,6 +34,41 @@ class _SendFeedbackPageState extends State { bool isShowListAppointHistory = true; String message; final formKey = GlobalKey(); + MessageType messageType = MessageType.NON; + + + String getSelected(BuildContext context) { + switch (messageType) { + case MessageType.ComplaintOnAnAppointment: + return TranslationBase.of(context).complainAppo; + break; + case MessageType.ComplaintWithoutAppointment: + return TranslationBase.of(context).complainWithoutAppo; + break; + case MessageType.Question: + return TranslationBase.of(context).question; + break; + case MessageType.Compliment: + return TranslationBase.of(context).compliment; + break; + case MessageType.Suggestion: + return TranslationBase.of(context).suggestion; + break; + case MessageType.NON: + return TranslationBase.of(context).notClassified; + break; + } + return TranslationBase.of(context).notClassified; + } + + + + setMessageType(MessageType messageType) { + setState(() { + this.messageType = messageType; + }); + + } @override Widget build(BuildContext context) { @@ -55,7 +93,6 @@ class _SendFeedbackPageState extends State { child: Texts( TranslationBase.of(context).likeToHear, textAlign: TextAlign.center, - variant: 'body2Link', ), ), InkWell( @@ -75,9 +112,8 @@ class _SendFeedbackPageState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Container( - child: Texts( - model.getSelected(context), + getSelected(context), variant: 'bodyText', ), margin: EdgeInsets.only(left: 10,right: 10), @@ -91,7 +127,7 @@ class _SendFeedbackPageState extends State { ), ), ), - if (appointHistory != null && model.messageType == + if (appointHistory != null && messageType == MessageType.ComplaintOnAnAppointment) InkWell( onTap: () { @@ -167,12 +203,10 @@ class _SendFeedbackPageState extends State { ), ), ), - if (model.messageType == - MessageType.ComplaintOnAnAppointment && - model.appointHistoryList.length != 0 && + if (messageType == MessageType.ComplaintOnAnAppointment && model.appointHistoryList.length != 0 && isShowListAppointHistory) Container( - height: MediaQuery.of(context).size.height * 0.4, + height: model.appointHistoryList.length>2?MediaQuery.of(context).size.height * 0.25:MediaQuery.of(context).size.height * 0.15, child: ListView.builder( itemCount: model.appointHistoryList.length, itemBuilder: (context, index) => InkWell( @@ -285,7 +319,7 @@ class _SendFeedbackPageState extends State { hintColor: Colors.black, fontWeight: FontWeight.w600, validator: (value) { - if (value == null) + if (value.isEmpty) return TranslationBase.of(context).emptySubject; else return null; @@ -303,7 +337,7 @@ class _SendFeedbackPageState extends State { minLines: 13, controller: messageController, validator: (value) { - if (value == null) + if (value.isEmpty) return TranslationBase.of(context).emptyMessage; else return null; @@ -311,11 +345,11 @@ class _SendFeedbackPageState extends State { ), InkWell( onTap: () { - ImageOptions.showImageOptions(context, (String image) { + ImageOptions.showImageOptions(context, (String image,File file) { setState(() { images.add(image); }); - }); + } ); }, child: Container( margin: EdgeInsets.only(left: 10, right: 10, top: 15), @@ -376,7 +410,7 @@ class _SendFeedbackPageState extends State { ), )), SizedBox( - height: 30, + height: 45, ), ], ), @@ -384,27 +418,26 @@ class _SendFeedbackPageState extends State { ), ), bottomSheet: Container( - height: MediaQuery.of(context).size.height * 0.13, + height: MediaQuery.of(context).size.height * 0.09, width: double.infinity, - padding: EdgeInsets.all(8.0), + padding: EdgeInsets.all(15.0), child: Center( child: Container( - height: MediaQuery.of(context).size.height * 0.1, - width: MediaQuery.of(context).size.width * 0.8, - child: Button( + height: MediaQuery.of(context).size.height * 0.8, + child: SecondaryButton( label: TranslationBase.of(context).send, - loading: model.state == ViewState.BusyLocal, + disabled: (titleController.text.toString().isEmpty || messageController.text.toString().isEmpty|| messageType == MessageType.NON), onTap: () { final form = formKey.currentState; - if (form.validate()) if (model.messageType != MessageType.NON) - model - .sendCOCItem( + if (form.validate()) + if (messageType != MessageType.NON){ + GifLoaderDialogUtils.showMyDialog(context); + model.sendCOCItem( title: titleController.text, attachment: images.length > 0 ? images[0] : "", details: messageController.text, - cOCTypeName: getCOCName(model), - appointHistory: model.messageType == - MessageType.ComplaintOnAnAppointment + cOCTypeName: getCOCName(), + appointHistory:messageType == MessageType.ComplaintOnAnAppointment ? appointHistory : null) .then((value) { @@ -414,13 +447,15 @@ class _SendFeedbackPageState extends State { messageController.text = ""; images = []; }); - model.setMessageType(MessageType.NON); + setMessageType(MessageType.NON); + GifLoaderDialogUtils.hideDialog(context); AppToast.showSuccessToast( message: TranslationBase.of(context).yourFeedback); } else { AppToast.showErrorToast(message: model.error); + GifLoaderDialogUtils.hideDialog(context); } - }); + });} else { AppToast.showErrorToast(message: TranslationBase.of(context).selectPart); } @@ -433,8 +468,8 @@ class _SendFeedbackPageState extends State { ); } - String getCOCName(FeedbackViewModel model) { - switch (model.messageType) { + String getCOCName() { + switch (messageType) { case MessageType.ComplaintOnAnAppointment: return "1"; break; @@ -462,15 +497,18 @@ class _SendFeedbackPageState extends State { showDialog( context: context, child: FeedbackTypeDialog( + messageTypeDialog: messageType, onValueSelected: (MessageType value) { if (value == MessageType.ComplaintOnAnAppointment) { + GifLoaderDialogUtils.showMyDialog(context); model.getPatentAppointmentHistory().then((value) { + GifLoaderDialogUtils.hideDialog(context); setState(() { appointHistory = null; }); }); } - model.setMessageType(value); + setMessageType(value); }, )); } @@ -478,14 +516,30 @@ class _SendFeedbackPageState extends State { class FeedbackTypeDialog extends StatefulWidget { final Function(MessageType) onValueSelected; + final MessageType messageTypeDialog; - const FeedbackTypeDialog({Key key, this.onValueSelected}) : super(key: key); + const FeedbackTypeDialog({Key key, this.onValueSelected, this.messageTypeDialog=MessageType.NON}) : super(key: key); @override State createState() => new FeedbackTypeDialogState(); } class FeedbackTypeDialogState extends State { + + + MessageType messageTypeDialog = MessageType.NON; + + setMessageDialogType(MessageType messageType) { + setState(() { + messageTypeDialog = messageType; + }); + } + @override + void initState() { + messageTypeDialog = widget.messageTypeDialog; + super.initState(); + } + Widget build(BuildContext context) { return BaseView( builder: (_, model, widge) => SimpleDialog( @@ -507,16 +561,16 @@ class FeedbackTypeDialogState extends State { Expanded( flex: 1, child: InkWell( - onTap: () => model.setMessageDialogType( + onTap: () => setMessageDialogType( MessageType.ComplaintOnAnAppointment), child: ListTile( title: Texts(TranslationBase.of(context).complainAppo), leading: Radio( value: MessageType.ComplaintOnAnAppointment, - groupValue: model.messageTypeDialog, + groupValue: messageTypeDialog, activeColor: Theme.of(context).primaryColor, onChanged: (MessageType value) => - model.setMessageDialogType(value), + setMessageDialogType(value), ), ), ), @@ -531,16 +585,16 @@ class FeedbackTypeDialogState extends State { Expanded( flex: 1, child: InkWell( - onTap: () => model.setMessageDialogType( + onTap: () => setMessageDialogType( MessageType.ComplaintWithoutAppointment), child: ListTile( title: Texts(TranslationBase.of(context).complainWithoutAppo), leading: Radio( value: MessageType.ComplaintWithoutAppointment, - groupValue: model.messageTypeDialog, + groupValue: messageTypeDialog, activeColor: Theme.of(context).primaryColor, onChanged: (MessageType value) => - model.setMessageDialogType(value), + setMessageDialogType(value), ), ), ), @@ -556,15 +610,15 @@ class FeedbackTypeDialogState extends State { flex: 1, child: InkWell( onTap: () => - model.setMessageDialogType(MessageType.Question), + setMessageDialogType(MessageType.Question), child: ListTile( title: Texts(TranslationBase.of(context).question), leading: Radio( value: MessageType.Question, - groupValue: model.messageTypeDialog, + groupValue: messageTypeDialog, activeColor: Theme.of(context).primaryColor, onChanged: (MessageType value) => - model.setMessageDialogType(value), + setMessageDialogType(value), ), ), ), @@ -580,15 +634,15 @@ class FeedbackTypeDialogState extends State { flex: 1, child: InkWell( onTap: () => - model.setMessageDialogType(MessageType.Compliment), + setMessageDialogType(MessageType.Compliment), child: ListTile( title: Texts(TranslationBase.of(context).compliment), leading: Radio( value: MessageType.Compliment, - groupValue: model.messageTypeDialog, + groupValue: messageTypeDialog, activeColor: Theme.of(context).primaryColor, onChanged: (MessageType value) => - model.setMessageDialogType(value), + setMessageDialogType(value), ), ), ), @@ -604,15 +658,14 @@ class FeedbackTypeDialogState extends State { flex: 1, child: InkWell( onTap: () => - model.setMessageDialogType(MessageType.Suggestion), + setMessageDialogType(MessageType.Suggestion), child: ListTile( title: Texts(TranslationBase.of(context).suggestion), leading: Radio( value: MessageType.Suggestion, - groupValue: model.messageTypeDialog, + groupValue: messageTypeDialog, activeColor: Theme.of(context).primaryColor, - onChanged: (MessageType value) => - model.setMessageDialogType(value), + onChanged: (MessageType value) => setMessageDialogType(value), ), ), ), @@ -660,7 +713,7 @@ class FeedbackTypeDialogState extends State { flex: 1, child: InkWell( onTap: () { - widget.onValueSelected(model.messageTypeDialog); + widget.onValueSelected(messageTypeDialog); Navigator.pop(context); }, child: Padding( diff --git a/lib/pages/feedback/status_feedback_page.dart b/lib/pages/feedback/status_feedback_page.dart index 457ded60..59d68fa2 100644 --- a/lib/pages/feedback/status_feedback_page.dart +++ b/lib/pages/feedback/status_feedback_page.dart @@ -14,73 +14,92 @@ class StatusFeedbackPage extends StatefulWidget { } class _StatusFeedbackPageState extends State { - @override Widget build(BuildContext context) { return BaseView( - allowAny: true, onModelReady: (model) => model.getCOC(), builder: (_, model, widget) => AppScaffold( baseViewModel: model, isShowDecPage: false, - body: Container( - margin: EdgeInsets.only(top: 8.0,left: 8.0,right: 8.0 ), - padding: EdgeInsets.all(15.0), - child: ListView.builder( - itemCount: model.cOCItemList.length, - itemBuilder: (context, index) => Container( - decoration: BoxDecoration( - shape: BoxShape.rectangle, - border: Border.all(color: Colors.white, width: 0.5), - borderRadius: BorderRadius.all(Radius.circular(5)), - color: Colors.white, - ), - margin: EdgeInsets.all(4), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox(height: 8,), - Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Texts('${model.cOCItemList[index].cOCTitle}'), - Texts( - TranslationBase.of(context).number + ' : ${model.cOCItemList[index].itemID}', - variant: 'overline', - ), - ], - ), + body: model.cOCItemList.isNotEmpty + ? Container( + margin: EdgeInsets.only(top: 8.0, left: 8.0, right: 8.0), + padding: EdgeInsets.all(15.0), + child: ListView.builder( + itemCount: model.cOCItemList.length, + itemBuilder: (context, index) => Container( + decoration: BoxDecoration( + shape: BoxShape.rectangle, + border: Border.all(color: Colors.white, width: 0.5), + borderRadius: BorderRadius.all(Radius.circular(5)), + color: Colors.white, ), - Expanded( + margin: EdgeInsets.all(4), + child: Padding( + padding: const EdgeInsets.all(8.0), child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Texts('${model.cOCItemList[index].status}'), - Texts( - '${model.cOCItemList[index].date}', - variant: 'overline', + SizedBox( + height: 8, ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Texts( + '${model.cOCItemList[index].cOCTitle}'), + Texts( + TranslationBase.of(context).number + + ' : ${model.cOCItemList[index].itemID}', + variant: 'overline', + ), + ], + ), + ), + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Texts( + '${model.cOCItemList[index].status}'), + Texts( + '${model.cOCItemList[index].date}', + variant: 'overline', + ), + ], + ), + ), + ], + ), + Texts('${model.cOCItemList[index].formType}'), + Divider( + height: 4.5, + color: Colors.grey[500], + ) ], ), ), - ], - ), - Texts('${model.cOCItemList[index].formType}'), - Divider(height: 4.5,color: Colors.grey[500],) + )), + ) + : Container( + child: Center( + child: Column( + children: [ + SizedBox(height: MediaQuery.of(context).size.height*0.4,), + Image.asset('assets/images/comments.png',width: 80,height: 80,), + SizedBox(height: 15,), + Texts(TranslationBase.of(context).noSearchResult), ], ), ), - )), - ), + ), ), ); } diff --git a/lib/pages/final_products_page.dart b/lib/pages/final_products_page.dart new file mode 100644 index 00000000..03adee97 --- /dev/null +++ b/lib/pages/final_products_page.dart @@ -0,0 +1,480 @@ +import 'package:diplomaticquarterapp/core/viewModels/pharmacy_categorise_view_model.dart'; +import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; +import 'package:diplomaticquarterapp/widgets/others/StarRating.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_pharmacy_widget.dart'; +import 'package:diplomaticquarterapp/widgets/others/network_base_view.dart'; +import 'package:flutter/material.dart'; + +import 'base/base_view.dart'; + +class FinalProductsPage extends StatefulWidget { + String id; + FinalProductsPage({this.id}); + @override + _FinalProductsPageState createState() => _FinalProductsPageState(id: id); +} + +class _FinalProductsPageState extends State { + String id; + _FinalProductsPageState({this.id}); + String categoriseName = "Personal Care"; + bool styleOne = true; + bool styleTwo = false; + Icon styleIcon = Icon( + Icons.widgets_sharp, + color: Colors.blue, + size: 29.0, + ); + @override + Widget build(BuildContext context) { + return BaseView( + onModelReady: (model) => model.getFinalProducts(i: id), + builder: (BuildContext context, PharmacyCategoriseViewModel model, + Widget child) => + PharmacyAppScaffold( + appBarTitle: 'Products', + isBottomBar: false, + isShowAppBar: true, + backgroundColor: Colors.white, + isShowDecPage: false, + baseViewModel: model, + body: Container( + height: MediaQuery.of(context).size.height * 5.87, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ +//Expanded widget heree if nassery + + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: EdgeInsets.all(8.0), + child: Texts( + 'Products', + fontWeight: FontWeight.w600, + ), + ), + Row( + children: [ + Container( + height: 44.0, + child: VerticalDivider( + color: Colors.black45, + thickness: 1.0, + //width: 0.3, + // indent: 0.0, + ), + ), + Padding( + padding: EdgeInsets.all(8.0), + child: InkWell( + child: styleIcon, + onTap: () { + setState(() { + if (styleOne == true) { + styleOne = false; + styleTwo = true; + styleIcon = Icon( + Icons.auto_awesome_mosaic, + color: Colors.blue, + size: 29.0, + ); + } else { + styleOne = true; + styleTwo = false; + styleIcon = Icon( + Icons.widgets_sharp, + color: Colors.blue, + size: 29.0, + ); + } + }); + }, + ), + ), + ], + ), + ], + ), + Divider( + thickness: 1.0, + color: Colors.grey.shade400, + ), + styleOne == true + ? Expanded( + child: Container( + height: MediaQuery.of(context).size.height * 3.90, + child: GridView.builder( + gridDelegate: + SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + crossAxisSpacing: 0.5, + mainAxisSpacing: 2.0, + childAspectRatio: 1.0, + ), + itemCount: model.finalProducts.length, + itemBuilder: (BuildContext context, int index) { + return NetworkBaseView( + baseViewModel: model, + child: Card( + color: model.finalProducts[index] + .discountName != + null + ? Color(0xffFFFF00) + : Colors.white, + elevation: 0, + shape: Border( + right: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + left: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + bottom: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + top: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + ), + margin: EdgeInsets.symmetric( + horizontal: 8, + vertical: 4, + ), + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(110.0), + ), + color: Colors.white, + ), + padding: EdgeInsets.symmetric( + horizontal: 0), + width: MediaQuery.of(context) + .size + .width / + 3, + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Stack( + children: [ + Container( + margin: EdgeInsets.fromLTRB( + 0, 16, 0, 0), + alignment: Alignment.center, + child: Image.network( + model.finalProducts[index] + .images.isNotEmpty + ? model + .finalProducts[ + index] + .images[0] + .thumb + : 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/No_image_3x4.svg/1200px-No_image_3x4.svg.png', + fit: BoxFit.cover, + height: 80, + ), + ), + Container( + width: model + .finalProducts[ + index] + .rxMessage != + null + ? MediaQuery.of(context) + .size + .width / + 2.8 + : 0, + padding: EdgeInsets.all(4), + decoration: BoxDecoration( + color: Color(0xffb23838), + borderRadius: + BorderRadius.only( + topLeft: Radius + .circular(6)), + ), + child: Texts( + model.finalProducts[index] + .rxMessage != + null + ? model + .finalProducts[ + index] + .rxMessage + : "", + color: Colors.white, + regular: true, + fontSize: 10, + fontWeight: + FontWeight.w600, + ), + ), + ], + ), + Container( + margin: EdgeInsets.symmetric( + horizontal: 6, + vertical: 0, + ), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + if (model + .finalProducts[ + index] + .discountName != + null) + Container( + width: double.infinity, + height: 13.0, + decoration: + BoxDecoration( + color: + Color(0xff5AB145), + ), + child: Center( + child: Texts( + model + .finalProducts[ + index] + .discountName, + regular: true, + color: Colors.white, + fontSize: 10.4, + ), + ), + ), + Texts( + model.finalProducts[index] + .name, + regular: true, + fontSize: 12, + fontWeight: + FontWeight.w400, + ), + Padding( + padding: + const EdgeInsets.only( + top: 4, + bottom: 4), + child: Texts( + "SAR ${model.finalProducts[index].price}", + bold: true, + fontSize: 14, + ), + ), + Row( + children: [ + StarRating( + totalAverage: model + .finalProducts[ + index] + .approvedRatingSum > + 0 + ? (model.finalProducts[index].approvedRatingSum + .toDouble() / + model + .finalProducts[index] + .approvedRatingSum + .toDouble()) + .toDouble() + : 0, + forceStars: true), + Texts( + "(${model.finalProducts[index].approvedTotalReviews})", + regular: true, + fontSize: 10, + fontWeight: + FontWeight.w400, + ) + ], + ), + ], + ), + ), + ], + ), + ), + )); + }, + ), + ), + ) + : Expanded( + child: Container( + height: MediaQuery.of(context).size.height * 5.0, + child: ListView.builder( + itemCount: model.finalProducts.length, + itemBuilder: + (BuildContext context, int index) { + return Card( + child: Row( + children: [ + Stack( + children: [ + Column( + children: [ + Container( + decoration: BoxDecoration(), + child: Padding( + padding: EdgeInsets.only( + left: 9.0, + top: 8.0, + right: 10.0, + ), + ), + ), + Container( + margin: EdgeInsets.fromLTRB( + 0, 0, 0, 0), + alignment: Alignment.center, + child: Image.network( + model.finalProducts[index] + .images.isNotEmpty + ? model + .finalProducts[ + index] + .images[0] + .thumb + : 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/No_image_3x4.svg/1200px-No_image_3x4.svg.png', + fit: BoxFit.contain, + height: 80, + ), + ), + ], + ), + Column( + children: [ + Container( + width: model + .finalProducts[ + index] + .rxMessage != + null + ? MediaQuery.of(context) + .size + .width / + 3.5 + : 0, + padding: EdgeInsets.all(4), + decoration: BoxDecoration( + color: Color(0xffb23838), + borderRadius: + BorderRadius.only( + topLeft: Radius + .circular(6)), + ), + child: Texts( + model.finalProducts[index] + .rxMessage != + null + ? model + .finalProducts[ + index] + .rxMessage + : "", + color: Colors.white, + regular: true, + fontSize: 10, + fontWeight: + FontWeight.w600, + ), + ), + ], + ), + ], + ), + Container( + height: 100.0, + margin: EdgeInsets.symmetric( + horizontal: 6, + vertical: 0, + ), + child: Column( + mainAxisAlignment: + MainAxisAlignment.spaceAround, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + SizedBox( + height: 4.0, + ), + Container( + height: 35.0, + width: 250.0, + child: Texts( + model.finalProducts[index] + .name, + regular: true, + fontSize: 13.2, + fontWeight: FontWeight.w500, + maxLines: 2, + ), + ), + SizedBox( + height: 8.0, + ), + Padding( + padding: + const EdgeInsets.only( + top: 4, bottom: 4), + child: Texts( + "SAR ${model.finalProducts[index].price}", + bold: true, + fontSize: 14, + ), + ), + Row( + children: [ + StarRating( + totalAverage: model + .finalProducts[ + index] + .approvedRatingSum > + 0 + ? (model + .finalProducts[ + index] + .approvedRatingSum + .toDouble() / + model + .finalProducts[ + index] + .approvedRatingSum + .toDouble()) + .toDouble() + : 0, + forceStars: true), + Texts( + "(${model.finalProducts[index].approvedTotalReviews})", + regular: true, + fontSize: 10, + fontWeight: + FontWeight.w400, + ) + ], + ), + ], + ), + ), + ], + ), + ); + }), + ), + ) + ], + ), + ), + )); + } +} diff --git a/lib/pages/insurance/AttachInsuranceCardImageDialog.dart b/lib/pages/insurance/AttachInsuranceCardImageDialog.dart new file mode 100644 index 00000000..20e17593 --- /dev/null +++ b/lib/pages/insurance/AttachInsuranceCardImageDialog.dart @@ -0,0 +1,147 @@ +import 'dart:io'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/bottom_options/BottomSheet.dart'; +import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +class AttachInsuranceCardImageDialog extends StatefulWidget { + final String name; + final String fileNo; + final Function(File file, String image) image; + + const AttachInsuranceCardImageDialog( + {Key key, this.name, this.fileNo, this.image}) + : super(key: key); + + @override + _AttachInsuranceCardImageDialogState createState() => + _AttachInsuranceCardImageDialogState(); +} + +class _AttachInsuranceCardImageDialogState + extends State { + @override + void initState() { + super.initState(); + } + + String image; + File file; + + @override + Widget build(BuildContext context) { + return SimpleDialog( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Texts(TranslationBase.of(context).attachInsuraceImage), + Divider(), + Texts(widget.name), + SizedBox( + height: 3, + ), + Texts(TranslationBase.of(context).fileNo + " " + widget.fileNo), + SizedBox( + height: 5.0, + ), + InkWell( + onTap: () { + ImageOptions.showImageOptions(context, (String image,File file) { + setState(() { + this.image = image; + this.file = file; + }); + }); + }, + child: image == null + ? Padding( + padding: const EdgeInsets.all(18.0), + child: Container( + width: double.maxFinite, + height: 250, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(2), + border: Border.all(color: Colors.grey, width: 1.5)), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + // mainAxisAlignment: MainAxisAlignment., + children: [ + SizedBox(height: 25,), + Icon( + Icons.camera_enhance_rounded, + size: 85, + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.attach_file), + Texts(TranslationBase.of(context).selectAttachment.toUpperCase()) + ], + ), + ], + ), + ), + ) + : Image.file( + file, + fit: BoxFit.fill, + height: 250, + ), + ), + SizedBox( + height: 25.0, + ), + Divider(), + Row( + children: [ + Expanded( + flex: 1, + child: InkWell( + onTap: () { + Navigator.pop(context); + }, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Container( + child: Center( + child: Texts( + TranslationBase.of(context).cancel.toUpperCase(), + color: Colors.red, + ), + ), + ), + ), + ), + ), + Container( + width: 1, + height: 30, + color: Colors.grey[500], + ), + Expanded( + flex: 1, + child: InkWell( + onTap: () { + Navigator.pop(context); + widget.image(file, image); + }, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Center( + child: Texts( + TranslationBase.of(context).ok, + fontWeight: FontWeight.w400, + )), + ), + ), + ), + ], + ) + ], + ) + ], + ); + } +} diff --git a/lib/pages/insurance/insurance_approval_screen.dart b/lib/pages/insurance/insurance_approval_screen.dart index d21e06a5..d81e704e 100644 --- a/lib/pages/insurance/insurance_approval_screen.dart +++ b/lib/pages/insurance/insurance_approval_screen.dart @@ -63,27 +63,24 @@ class _InsuranceApprovalState extends State { child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ - Text( + Texts( TranslationBase.of(context).totalApproval, - style: TextStyle( color: Color(0xff60688B), fontSize: 19.0, fontWeight: FontWeight.w600, - ), ), if (model.insuranceApproval.length > 0) Container( width: 60, - height: 35, + height: 40, decoration: BoxDecoration( color: Theme.of(context).primaryColor, borderRadius: BorderRadius.circular(19.0)), child: Center( - child: Text( + child: Texts( model.insuranceApproval[0].unUsedCount .toString(), - style: TextStyle( - color: Colors.white, fontSize: 19.0), + color: Colors.white, fontSize: 17.0, ), )) ], @@ -138,22 +135,18 @@ class _InsuranceApprovalState extends State { Padding( padding: EdgeInsets.symmetric( vertical: 10.0), - child: Text( + child: Texts( model.insuranceApproval[index] .clinicName, - style: TextStyle( - fontSize: 20.0, - color: Color(0xff60686B), - fontWeight: FontWeight.w600, - ), + fontSize: 20.0, + color: Color(0xff60686B), + fontWeight: FontWeight.w600, ), ), - Text( + Texts( model.insuranceApproval[index] .doctorName, - style: TextStyle( - fontSize: 17.0, - fontStyle: FontStyle.italic), + fontSize: 17.0, ), ], ), @@ -166,45 +159,53 @@ class _InsuranceApprovalState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - TranslationBase.of(context) - .approvalNo + - model.insuranceApproval[index] - .approvalNo - .toString(), - style: TextStyle( - fontSize: 18.0, - fontWeight: FontWeight.w600, - ), + Row( + children: [ + Texts( + TranslationBase.of(context).approvalNo, + fontSize: 18.0, + ), + Texts(model.insuranceApproval[index].approvalNo.toString(), + fontSize: 18.0, + fontWeight: FontWeight.w600,), + ], ), Divider( color: Colors.black, height: 25.0, thickness: 1.0, ), - Text( - TranslationBase.of(context) - .procedureStatus + - model.insuranceApproval[index] - .approvalStatusDescption, - style: TextStyle( + Row( + children: [ + Texts( + TranslationBase.of(context).procedureStatus , + fontSize: 17.5, + ), + SizedBox(width: 12,), + Texts( + model.insuranceApproval[index].approvalStatusDescption, fontWeight: FontWeight.w600, - fontSize: 17.5), + fontSize: 17.5, + ), + ], ), Divider( color: Colors.black, height: 25.0, thickness: 1.0, ), - Text( - TranslationBase.of(context) - .unusedCount + - model.insuranceApproval[index] - .unUsedCount - .toString(), - style: TextStyle( + Row( + children: [ + Texts( + TranslationBase.of(context).unusedCount, + fontSize: 17.5, + ), + Texts( + model.insuranceApproval[index].unUsedCount.toString(), fontSize: 17.5, - fontWeight: FontWeight.w600), + fontWeight: FontWeight.w600, + ), + ], ), Divider( color: Colors.black, @@ -223,13 +224,10 @@ class _InsuranceApprovalState extends State { // fontSize: 17.5, // fontWeight: FontWeight.w600), // ), - Text( - TranslationBase.of(context) - .companyName, - style: TextStyle( + Texts( + TranslationBase.of(context).companyName, fontWeight: FontWeight.w600, fontSize: 17.5, - ), ), Divider( @@ -237,32 +235,42 @@ class _InsuranceApprovalState extends State { height: 25.0, thickness: 1.0, ), - Text( - TranslationBase.of(context) - .receiptOn + - convertDateFormat(model - .insuranceApproval[index] - .rceiptOn), - style: TextStyle( - fontSize: 17.5, - fontWeight: FontWeight.w600, - ), + Row( + children: [ + Texts( + TranslationBase.of(context).receiptOn , + fontSize: 17.5, + fontWeight: FontWeight.w600, + + ), + Texts( + convertDateFormat(model.insuranceApproval[index].rceiptOn), + fontSize: 17.5, + fontWeight: FontWeight.w600, + + ), + ], ), Divider( color: Colors.black, height: 25.0, thickness: 1.0, ), - Text( - TranslationBase.of(context) - .expiryDate + - convertDateFormat(model - .insuranceApproval[index] - .expiryDate), - style: TextStyle( - fontSize: 17.5, - fontWeight: FontWeight.w600, - ), + Row( + children: [ + Texts( + TranslationBase.of(context).expiryDate, + fontSize: 17.5, + fontWeight: FontWeight.w600, + + ), + Texts( + convertDateFormat(model.insuranceApproval[index].expiryDate), + fontSize: 17.5, + fontWeight: FontWeight.w600, + + ), + ], ), Divider( color: Colors.black, diff --git a/lib/pages/insurance/insurance_card_screen.dart b/lib/pages/insurance/insurance_card_screen.dart index 5f8c6777..42efc179 100644 --- a/lib/pages/insurance/insurance_card_screen.dart +++ b/lib/pages/insurance/insurance_card_screen.dart @@ -20,18 +20,23 @@ import '../base/base_view.dart'; class InsuranceCard extends StatefulWidget { int appointmentNo; - InsuranceCard({this.appointmentNo}); @override _InsuranceCardState createState() => _InsuranceCardState(); } + class _InsuranceCardState extends State { InsuranceCardService _insuranceCardService = locator(); List imagesInfo = List(); + @override Widget build(BuildContext context) { - imagesInfo.add(ImagesInfo(imageEn: 'https://hmgwebservices.com/Images/MobileApp/imges-info/insurance-card/en/0.png',imageAr: 'https://hmgwebservices.com/Images/MobileApp/imges-info/insurance-card/ar/0.png')); + imagesInfo.add(ImagesInfo( + imageEn: + 'https://hmgwebservices.com/Images/MobileApp/imges-info/insurance-card/en/0.png', + imageAr: + 'https://hmgwebservices.com/Images/MobileApp/imges-info/insurance-card/ar/0.png')); return BaseView( onModelReady: (model) => model.getInsurance(), @@ -39,7 +44,6 @@ class _InsuranceCardState extends State { AppScaffold( isShowAppBar: true, baseViewModel: model, - image: 'assets/images/medical/insurance_card_icon.png', appBarTitle: TranslationBase.of(context).insuranceCards, description: TranslationBase.of(context).infoInsuranceCards, infoList: TranslationBase.of(context).infoInsuranceCardsPoints, @@ -79,16 +83,16 @@ class _InsuranceCardState extends State { padding: EdgeInsets.all(14), width: double.infinity, decoration: BoxDecoration( - shape: BoxShape.rectangle, - border: Border.all(color: Colors.grey,width: 0.2), - borderRadius: BorderRadius.all(Radius.circular(2)), - boxShadow: [ - BoxShadow( - color: Colors.white70, - ), - - ] - ), + shape: BoxShape.rectangle, + border: Border.all( + color: Colors.grey, width: 0.2), + borderRadius: + BorderRadius.all(Radius.circular(2)), + boxShadow: [ + BoxShadow( + color: Colors.white70, + ), + ]), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -96,6 +100,7 @@ class _InsuranceCardState extends State { TranslationBase.of(context).companyName + model.insurance[index].companyName, fontSize: 20.0, + fontWeight: FontWeight.w700, ), Divider( color: Colors.black, @@ -103,45 +108,59 @@ class _InsuranceCardState extends State { thickness: 0.5, ), Column( - crossAxisAlignment: CrossAxisAlignment.stretch, + crossAxisAlignment: + CrossAxisAlignment.stretch, children: [ - Text( - TranslationBase.of(context).category + - model.insurance[index].subCategoryDesc, - style: TextStyle(fontSize: 18.5), + Texts( + TranslationBase.of(context).category +": "+ + model.insurance[index] + .subCategoryDesc, + fontSize: 18.5, ), - Text( - TranslationBase.of(context).expirationDate + - convertDateFormat( - model.insurance[index].cardValidTo), - style: TextStyle(fontSize: 18.5), + Row( + children: [ + Texts( + TranslationBase.of(context) + .expirationDate +": "+ + convertDateFormat(model + .insurance[index].cardValidTo), + fontSize: 18.5, + ), + Expanded( + child: Column( + children: [ + model.insurance[index].isActive == true + ? Texts( + TranslationBase.of(context) + .activeInsurence, + color: Colors.green, + fontWeight: FontWeight.w900, + fontSize: 17.9) + : Texts( + TranslationBase.of(context) + .notActive, + color: Colors.red, + fontWeight: FontWeight.w900, + fontSize: 17.9) + ], + ), + ), + ], ), - Text( - TranslationBase.of(context).patientCard + - model.insurance[index].patientCardID, - style: TextStyle(fontSize: 18.5), - ), - Text( - TranslationBase.of(context).policyNumber + + Texts( + TranslationBase.of(context) + .patientCard +": "+ model - .insurance[index].insurancePolicyNumber, - style: TextStyle(fontSize: 18.5), + .insurance[index].patientCardID, + fontSize: 18.5, + ), + Texts( + TranslationBase.of(context) + .policyNumber +" "+ + model.insurance[index] + .insurancePolicyNumber, + fontSize: 18.5, ), - ], - ), - Column( - children: [ - model.insurance[index].isActive == true - ? Text('Active', - style: TextStyle( - color: Colors.green, - fontWeight: FontWeight.w900, - fontSize: 17.9)) - : Text('Not Active', - style: TextStyle( - color: Colors.red, - fontWeight: FontWeight.w900, - fontSize: 17.9)) ], ), SizedBox( @@ -151,8 +170,11 @@ class _InsuranceCardState extends State { Container( color: Colors.transparent, child: SecondaryButton( - onTap:()=>{ getDetails(model.insurance[index])}, - label: TranslationBase.of(context).seeDetails, + onTap: () => { + getDetails(model.insurance[index]) + }, + label: TranslationBase.of(context) + .seeDetails, textColor: Colors.white, ), width: double.infinity, @@ -160,8 +182,6 @@ class _InsuranceCardState extends State { ], ), ), - - ], ), ], @@ -191,13 +211,13 @@ class _InsuranceCardState extends State { return newDate.toString(); } - getDetails(data){ + + getDetails(data) { GifLoaderDialogUtils.showMyDialog(context); _insuranceCardService.getInsuranceDetails(data).then((value) => { - GifLoaderDialogUtils.hideDialog(context), - Navigator.push(context, - FadePage(page: InsuranceCardDetails(data:value[0]['CheckList']))) - - }); + GifLoaderDialogUtils.hideDialog(context), + Navigator.push(context, + FadePage(page: InsuranceCardDetails(data: value[0]['CheckList']))) + }); } } diff --git a/lib/pages/insurance/insurance_card_update_details.dart b/lib/pages/insurance/insurance_card_update_details.dart new file mode 100644 index 00000000..5e9db38a --- /dev/null +++ b/lib/pages/insurance/insurance_card_update_details.dart @@ -0,0 +1,346 @@ +import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; +import 'package:diplomaticquarterapp/core/model/insurance/Insurance_card_details.dart'; +import 'package:diplomaticquarterapp/core/viewModels/insurance_card_View_model.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/gif_loader_dialog_utils.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/secondary_button.dart'; +import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'AttachInsuranceCardImageDialog.dart'; + +class InsuranceCardUpdateDetails extends StatelessWidget { + final List insuranceCardDetailsModel; + final String patientIdentificationID; + final int patientID; + final String name; + + const InsuranceCardUpdateDetails( + {Key key, + this.insuranceCardDetailsModel, + this.patientIdentificationID, + this.patientID, + this.name}) + : super(key: key); + + @override + Widget build(BuildContext context) { + ProjectViewModel projectViewModel = Provider.of(context); + return BaseView( + builder: (context, model, w) => AppScaffold( + isShowAppBar: true, + isShowDecPage: false, + appBarTitle: TranslationBase.of(context).cardDetail, + body: SingleChildScrollView( + child: Column( + children: [ + ...List.generate( + insuranceCardDetailsModel.length, + (index) => Padding( + padding: const EdgeInsets.all(8.0), + child: Container( + width: double.maxFinite, + margin: EdgeInsets.only(left: 8, right: 8, top: 8), + height: projectViewModel.isArabic ? 320 : 240, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(25), + color: Color(0xff515B5D), + ), + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + insuranceCardDetailsModel[index].memberID, + textScaleFactor: 2.1, + style: TextStyle( + color: Colors.white, + letterSpacing: 8.0, + fontWeight: FontWeight.w400, + fontSize: 15), + ), + SizedBox( + height: 5, + ), + Texts( + insuranceCardDetailsModel[index].companyName, + fontSize: 14, + color: Colors.white, + ), + SizedBox( + height: 25, + ), + Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Texts( + TranslationBase.of(context).policyHolder, + color: Colors.white, + fontSize: 14, + ), + Texts( + insuranceCardDetailsModel[index] + .memberName, + color: Colors.white, + fontSize: 14, + ), + ], + ), + ), + Expanded( + child: Column( + children: [ + Texts(TranslationBase.of(context).policyNo, + color: Colors.white), + Texts( + insuranceCardDetailsModel[index] + .policyNumber, + color: Colors.white), + ], + ), + ), + ], + ), + SizedBox( + height: 25, + ), + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Texts( + TranslationBase.of(context) + .expiryDateTitle, + color: Colors.white, + fontSize: 12, + ), + Texts( + insuranceCardDetailsModel[index].dOB, + color: Colors.white, + fontSize: 12, + ), + ], + ), + ), + Expanded( + child: Column( + children: [ + Texts( + TranslationBase.of(context).classTitle, + color: Colors.white, + fontSize: 12, + ), + Texts( + insuranceCardDetailsModel[index] + .subCategory, + color: Colors.white, + fontSize: 12, + ), + ], + ), + ), + Expanded( + child: Column( + children: [ + Texts( + TranslationBase.of(context).approval, + color: Colors.white, + fontSize: 12, + ), + Texts( + insuranceCardDetailsModel[index] + .approvalLimit + .toString(), + color: Colors.white, + fontSize: 12, + ), + ], + ), + ), + ], + ) + ], + ), + ), + ), + ), + ), + if(insuranceCardDetailsModel.isEmpty) + Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + margin: EdgeInsets.all(10.0), + child: Card( + margin: EdgeInsets.fromLTRB( + 8.0, 16.0, 8.0, 8.0), + color: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular(10), + ), + child: Container( + width: MediaQuery.of(context).size.width, + padding: EdgeInsets.all(10.0), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: [ + Expanded( + flex: 3, + child: Container( + margin: EdgeInsets.only( + top: 2.0, + left: 10.0, + right: 20.0), + child: Column( + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + Texts( + name, + fontSize: 14, + color: Colors.black, + fontWeight: + FontWeight.w500, + ), + SizedBox( + height: 8, + ), + Texts( + TranslationBase.of( + context) + .fileno + + ": " +patientID.toString(), + fontSize: 14, + color: Colors.black, + fontWeight: + FontWeight.w500, + ) + ], + ), + ), + ), + ], + ), + ), + ), + ), + SizedBox(height: 150,), + Image.asset('assets/images/no-data-found.png',width: 80,height: 80,), + SizedBox(height: 8,), + Texts(TranslationBase.of(context).noDataAvailable) + ], + ) + ], + ), + ), + bottomSheet: Container( + width: double.infinity, + height:insuranceCardDetailsModel.isEmpty? MediaQuery.of(context).size.height * 0.14:MediaQuery.of(context).size.height * 0.21, + child: Container( + margin: EdgeInsets.only(left: 8, right: 8), + child: Column( + children: [ + SizedBox( + height: 8, + ), + if(insuranceCardDetailsModel.isEmpty) + SecondaryButton( + textColor: Colors.white, + label: TranslationBase.of(context).scanNow.toUpperCase(), + color: Theme.of(context).primaryColor, + onTap: () async { + confirmAttachInsuranceCardImageDialogDialog( + context: context, + name: name, + fileNo: patientID.toString(), + model: model); + }, + ), + if(insuranceCardDetailsModel.isNotEmpty) + SecondaryButton( + textColor: Colors.white, + label: TranslationBase.of(context).agree.toUpperCase(), + color: Theme.of(context).primaryColor, + onTap: () async { + GifLoaderDialogUtils.showMyDialog(context); + await model.uploadInsuranceCard( + patientIdentificationID: patientIdentificationID, + patientID: patientID); + GifLoaderDialogUtils.hideDialog(context); + if (model.state == ViewState.ErrorLocal) { + AppToast.showErrorToast(message: model.error); + } else { + AppToast.showSuccessToast( + message: TranslationBase.of(context).requestSent); + } + }, + ),if(insuranceCardDetailsModel.isNotEmpty) + SizedBox( + height: 12, + ),if(insuranceCardDetailsModel.isNotEmpty) + SecondaryButton( + textColor: Colors.white, + label: TranslationBase.of(context).disagree.toUpperCase(), + color: Colors.grey[800], + onTap: () async { + confirmAttachInsuranceCardImageDialogDialog( + context: context, + name: name, + fileNo: patientID.toString(), + model: model); + }, + ) + ], + ), + ), + ), + ), + ); + } + + void confirmAttachInsuranceCardImageDialogDialog( + {BuildContext context, + String name, + String fileNo, + InsuranceViewModel model}) { + showDialog( + context: context, + child: AttachInsuranceCardImageDialog( + fileNo: fileNo, + name: name, + image: (file, image) async { + GifLoaderDialogUtils.showMyDialog(context); + await model.uploadInsuranceCard( + patientIdentificationID: patientIdentificationID, + patientID: patientID, + image: image); + GifLoaderDialogUtils.hideDialog(context); + if (model.state == ViewState.ErrorLocal || + model.state == ViewState.Error) { + AppToast.showErrorToast(message: model.error); + } else { + AppToast.showSuccessToast( + message: TranslationBase.of(context).requestSent); + } + Navigator.pop(context); + }, + ), + ); + } +} diff --git a/lib/pages/insurance/insurance_details.dart b/lib/pages/insurance/insurance_details.dart index d0a829be..16745e9e 100644 --- a/lib/pages/insurance/insurance_details.dart +++ b/lib/pages/insurance/insurance_details.dart @@ -1,35 +1,29 @@ import 'package:diplomaticquarterapp/config/size_config.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:flutter_html/flutter_html.dart'; import 'package:html/dom.dart' as dom; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -class InsuranceCardDetails extends StatefulWidget { +class InsuranceCardDetails extends StatelessWidget { final String data; InsuranceCardDetails({this.data}); - @override - _InsuranceCardInsuranceCardDetailsState createState() => _InsuranceCardInsuranceCardDetailsState(); -} -//TODO fix it -class _InsuranceCardInsuranceCardDetailsState extends State { @override Widget build(BuildContext context) { - return - AppScaffold( - isShowAppBar: true, - - body: Center( - child: SingleChildScrollView( + return AppScaffold( + isShowAppBar: true, + appBarTitle: TranslationBase.of(context).cardDetail, + body: Center( + child: SingleChildScrollView( child: Html( - data:widget.data, - ) - ) + data: data, + ), + ), ), ); } - } diff --git a/lib/pages/insurance/insurance_page.dart b/lib/pages/insurance/insurance_page.dart new file mode 100644 index 00000000..f938d9e5 --- /dev/null +++ b/lib/pages/insurance/insurance_page.dart @@ -0,0 +1,261 @@ +import 'package:diplomaticquarterapp/core/service/insurance_service.dart'; +import 'package:diplomaticquarterapp/core/viewModels/insurance_card_View_model.dart'; +import 'package:diplomaticquarterapp/uitl/app_toast.dart'; +import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/secondary_button.dart'; +import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; +import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +import '../../locator.dart'; +import 'insurance_card_update_details.dart'; + +class InsurancePage extends StatelessWidget { + final InsuranceViewModel model; + InsuranceCardService _insuranceCardService = locator(); + + InsurancePage({Key key, this.model}) : super(key: key); + @override + Widget build(BuildContext context) { + return SingleChildScrollView( + child: Column( + children: [ + SizedBox( + height: 65, + ), + Container( + margin: EdgeInsets.all(10.0), + color: Colors.white, + width: MediaQuery.of(context).size.width, + padding: EdgeInsets.all(10.0), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: [ + if (model.user != null) + Expanded( + flex: 3, + child: Container( + margin: EdgeInsets.only( + top: 2.0, + left: 10.0, + right: 20.0), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Texts( + model.user.firstName ?? '' + " " + model.user.lastName ?? '', + fontSize: 14, + color: Colors.black, + fontWeight: FontWeight.w500, + ), + SizedBox( + height: 8, + ), + Texts( + TranslationBase.of(context) + .fileno + + ": " + + model.user.patientID + .toString(), + fontSize: 14, + color: Colors.black, + fontWeight: FontWeight.w500, + ) + ], + ), + ), + ), + Expanded( + flex: 2, + child: Container( + margin: EdgeInsets.only(top: 2.0), + child: Column( + children: [ + Container( + child: SecondaryButton( + label: TranslationBase.of( + context) + .fetchData, + small: true, + textColor: Colors.white, + onTap: () { + getDetails( + setupID: '010266', + projectID: 15, + patientIdentificationID: + model.user + .patientIdentificationNo, + patientID: model + .user.patientID, + name: model.user + .firstName + + " " + + model + .user.lastName,context: context); + }, + ), + ), + ], + ), + ), + ) + ], + ), + ), + if(model.getAllSharedRecordsByStatusResponse.getAllSharedRecordsByStatusList != null ?? false) + ...List.generate(model.getAllSharedRecordsByStatusResponse.getAllSharedRecordsByStatusList.length, (index) => + model.getAllSharedRecordsByStatusResponse.getAllSharedRecordsByStatusList[index].status == 3 + ? Container( + margin: EdgeInsets.all(10.0), + child: Card( + margin: EdgeInsets.fromLTRB( + 8.0, 16.0, 8.0, 8.0), + color: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular(10), + ), + child: Container( + width: MediaQuery.of(context).size.width, + padding: EdgeInsets.all(10.0), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: [ + Expanded( + flex: 3, + child: Container( + margin: EdgeInsets.only( + top: 2.0, + left: 10.0, + right: 20.0), + child: Column( + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + Texts( + model + .getAllSharedRecordsByStatusResponse + .getAllSharedRecordsByStatusList[ + index] + .patientName, + fontSize: 14, + color: Colors.black, + fontWeight: + FontWeight.w500, + ), + SizedBox( + height: 8, + ), + Texts( + TranslationBase.of( + context) + .fileno + + ": " + + model + .getAllSharedRecordsByStatusResponse + .getAllSharedRecordsByStatusList[ + index] + .patientID + .toString(), + fontSize: 14, + color: Colors.black, + fontWeight: + FontWeight.w500, + ) + ], + ), + ), + ), + Expanded( + flex: 2, + child: Container( + margin: + EdgeInsets.only(top: 2.0), + child: Column( + children: [ + Container( + child: SecondaryButton( + label: TranslationBase + .of(context) + .fetchData, + small: true, + textColor: + Colors.white, + onTap: () { + getDetails( + projectID: 15, + patientIdentificationID: model + .getAllSharedRecordsByStatusResponse + .getAllSharedRecordsByStatusList[ + index] + .patientIdenficationNumber, + setupID: + '010266', + patientID: model + .getAllSharedRecordsByStatusResponse + .getAllSharedRecordsByStatusList[ + index] + .responseID, + name: model + .getAllSharedRecordsByStatusResponse + .getAllSharedRecordsByStatusList[ + index].patientName,context: context); + }, + ), + ), + ], + ), + ), + ) + ], + ), + ), + ), + ) + : Container() + ), + + ], + ), + ); + } + + getDetails( + {String setupID, + int projectID, + String patientIdentificationID, + int patientID, + String name,BuildContext context}) { + GifLoaderDialogUtils.showMyDialog(context); + _insuranceCardService + .getPatientInsuranceDetails( + setupID: setupID, + projectID: projectID, + patientID: patientID, + patientIdentificationID: patientIdentificationID) + .then((value) { + GifLoaderDialogUtils.hideDialog(context); + if (!_insuranceCardService.hasError && _insuranceCardService.isHaveInsuranceCard) { + Navigator.push( + context, + FadePage( + page: InsuranceCardUpdateDetails( + insuranceCardDetailsModel: _insuranceCardService.insuranceCardDetailsList, + patientID: patientID, + patientIdentificationID: patientIdentificationID, + name: name, + ))); + } else { + AppToast.showErrorToast(message: _insuranceCardService.error); + } + }); + } +} diff --git a/lib/pages/insurance/insurance_update_screen.dart b/lib/pages/insurance/insurance_update_screen.dart index 1e616108..36b424a8 100644 --- a/lib/pages/insurance/insurance_update_screen.dart +++ b/lib/pages/insurance/insurance_update_screen.dart @@ -1,14 +1,22 @@ +import 'package:diplomaticquarterapp/core/model/ImagesInfo.dart'; +import 'package:diplomaticquarterapp/core/service/insurance_service.dart'; +import 'package:diplomaticquarterapp/locator.dart'; +import 'package:diplomaticquarterapp/pages/insurance/insurance_details.dart'; +import 'package:diplomaticquarterapp/uitl/app_toast.dart'; +import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/uitl/utils.dart'; import 'package:diplomaticquarterapp/widgets/buttons/secondary_button.dart'; +import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/material.dart'; -import 'package:diplomaticquarterapp/config/size_config.dart'; import 'package:flutter/cupertino.dart'; import '../base/base_view.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/core/viewModels/insurance_card_View_model.dart'; -import 'package:diplomaticquarterapp/widgets/others/rounded_container.dart'; -import 'package:rating_bar/rating_bar.dart'; -import 'package:diplomaticquarterapp/widgets/buttons/button.dart'; + +import 'insurance_card_update_details.dart'; +import 'insurance_page.dart'; class InsuranceUpdate extends StatefulWidget { @override @@ -18,11 +26,13 @@ class InsuranceUpdate extends StatefulWidget { class _InsuranceUpdateState extends State with SingleTickerProviderStateMixin { TabController _tabController; - + List imagesInfo = List(); @override void initState() { super.initState(); _tabController = TabController(length: 2, vsync: this); + + imagesInfo.add(ImagesInfo(imageEn: 'https://hmgwebservices.com/Images/MobileApp/imges-info/insurance-card/en/0.png',imageAr: 'https://hmgwebservices.com/Images/MobileApp/imges-info/insurance-card/ar/0.png')); } void dispose() { @@ -35,8 +45,12 @@ class _InsuranceUpdateState extends State onModelReady: (model) => model.getInsuranceUpdated(), builder: (BuildContext context, InsuranceViewModel model, Widget child) => AppScaffold( - appBarTitle: 'Insurance Cards', + appBarTitle: TranslationBase.of(context).insurCards, + description: TranslationBase.of(context).infoInsurCards, + infoList: TranslationBase.of(context).infoPrescriptionsPoints, + imagesInfo: imagesInfo, isShowAppBar: true, + isShowDecPage: true, baseViewModel: model, body: Scaffold( extendBodyBehindAppBar: true, @@ -63,7 +77,7 @@ class _InsuranceUpdateState extends State controller: _tabController, isScrollable: true, indicatorWeight: 4.0, - indicatorColor: Colors.red, + indicatorColor: Theme.of(context).primaryColor, labelColor: Theme.of(context).primaryColor, labelPadding: EdgeInsets.symmetric( horizontal: 13.0, vertical: 2.0), @@ -72,13 +86,14 @@ class _InsuranceUpdateState extends State Container( width: MediaQuery.of(context).size.width * 0.35, child: Center( - child: Texts('Card'), + child: Texts(TranslationBase.of(context) + .updateInsuranceSubtitle), ), ), Container( width: MediaQuery.of(context).size.width * 0.35, child: Center( - child: Texts('History'), + child: Texts(TranslationBase.of(context).history), ), ), ], @@ -96,85 +111,7 @@ class _InsuranceUpdateState extends State physics: BouncingScrollPhysics(), controller: _tabController, children: [ - Container( - child: ListView.builder( - itemCount: model.getAllSharedRecordsByStatusResponse.getAllSharedRecordsByStatusList.length, - itemBuilder: (BuildContext context, int index) { - return Container( - margin: EdgeInsets.all(10.0), - child: Card( - margin: EdgeInsets.fromLTRB(8.0, 16.0, 8.0, 8.0), - color: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10), - ), - child: Container( - width: MediaQuery.of(context).size.width, - padding: EdgeInsets.all(10.0), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.max, - children: [ - Expanded( - flex: 3, - child: Container( - margin: EdgeInsets.only( - top: 2.0, left: 10.0, right: 20.0), - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - model.getAllSharedRecordsByStatusResponse - .getAllSharedRecordsByStatusList[ - index].patientName, - style: TextStyle( - fontSize: 14.0, - color: Colors.black, - fontWeight: FontWeight.w500, - letterSpacing: 1.0)), - Text( - 'File No.' + - model.getAllSharedRecordsByStatusResponse - .getAllSharedRecordsByStatusList[ - index].patientID.toString(), - style: TextStyle( - fontSize: 14.0, - color: Colors.black, - fontWeight: FontWeight.w500, - letterSpacing: 1.0)), - ], - ), - ), - ), - Expanded( - flex: 2, - child: Container( - // height: MediaQuery.of(context).size.height * 0.12, - margin: EdgeInsets.only(top: 2.0), - child: Column( - children: [ - Container( - child: SecondaryButton( - label: 'Update', - small: true, - textColor: Colors.white, - // color: Colors.grey, - ), - //height: 45, - // width:90 - ), - ], - ), - ), - ) - ], - ), - ), - ), - ); - }), - ), + InsurancePage(model:model), Container( child: ListView.builder( itemCount: model.insuranceUpdate == null @@ -210,35 +147,40 @@ class _InsuranceUpdateState extends State crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("TAMER FANASHEH ", - style: TextStyle( - fontSize: 14.0, - color: Colors.black, - fontWeight: - FontWeight.w500, - letterSpacing: 1.0)), - Text( - 'File No.' + - model - .insuranceUpdate[ - index] - .patientID - .toString(), - style: TextStyle( - fontSize: 14.0, - color: Colors.black, - fontWeight: - FontWeight.w500, - letterSpacing: 1.0)), - Text( - model.insuranceUpdate[index] - .createdOn, - style: TextStyle( - fontSize: 14.0, - color: Colors.black, - fontWeight: - FontWeight.w500, - letterSpacing: 1.0)), + Texts( + model.user.firstName + + " " + + model.user.lastName, + fontSize: 14, + fontWeight: FontWeight.w500, + color: Colors.black, + ), + SizedBox( + height: 8, + ), + Texts( + TranslationBase.of(context) + .fileno + + ": " + + model + .insuranceUpdate[ + index] + .patientID + .toString(), + fontSize: 14, + fontWeight: FontWeight.w500, + color: Colors.black, + ), + SizedBox( + height: 8, + ), + Texts( + model.insuranceUpdate[index] + .createdOn, + fontSize: 14, + fontWeight: FontWeight.w500, + color: Colors.black, + ), ], ), ), @@ -246,7 +188,6 @@ class _InsuranceUpdateState extends State Expanded( flex: 1, child: Container( -// height: MediaQuery.of(context).size.height * 0.12, margin: EdgeInsets.only(top: 20.0), child: Column( children: [ @@ -257,15 +198,13 @@ class _InsuranceUpdateState extends State Container( margin: EdgeInsets.only( top: 13.5, left: 2.0), - child: Text( - model - .insuranceUpdate[ - index] - .statusDescription, - textAlign: - TextAlign.center, - style: TextStyle( - fontSize: 12.0)), + child: Texts( + model.insuranceUpdate[index] + .statusDescription, + textAlign: TextAlign.center, + fontSize: 12, + color: Colors.black, + ), ), ], ), @@ -288,4 +227,6 @@ class _InsuranceUpdateState extends State ), ); } + + } diff --git a/lib/pages/landing/home_page.dart b/lib/pages/landing/home_page.dart index 1a8b8637..87afb17f 100644 --- a/lib/pages/landing/home_page.dart +++ b/lib/pages/landing/home_page.dart @@ -1,11 +1,8 @@ import 'package:diplomaticquarterapp/config/size_config.dart'; -import 'package:diplomaticquarterapp/core/service/AuthenticatedUserObject.dart'; import 'package:diplomaticquarterapp/core/viewModels/dashboard_view_model.dart'; import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; -import 'package:diplomaticquarterapp/locator.dart'; -import 'package:diplomaticquarterapp/models/Appointments/toDoCountProviderModel.dart'; import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/ComprehensiveMedicalCheckup/cmc_page.dart'; -import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/HomeHealthCare/home_health_care_page.dart'; +import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/HomeHealthCare/home_health_care_index_page.dart'; import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/all_habib_medical_service_page.dart'; import 'package:diplomaticquarterapp/pages/ContactUs/contact_us_page.dart'; import 'package:diplomaticquarterapp/pages/Covid-DriveThru/covid-drivethru-location.dart'; @@ -25,6 +22,8 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:hexcolor/hexcolor.dart'; import 'package:provider/provider.dart'; +import 'landing_page_pharmcy.dart'; + class HomePage extends StatefulWidget { final Function goToMyProfile; @@ -35,18 +34,6 @@ class HomePage extends StatefulWidget { } class _HomePageState extends State { - ToDoCountProviderModel toDoProvider; - - @override - // void initState() { - // WidgetsBinding.instance.addPostFrameCallback((timeStamp) { - // getToDoCount(); - // }); - // super.initState(); - // } - AuthenticatedUserObject authenticatedUserObject = - locator(); - @override Widget build(BuildContext context) { ProjectViewModel projectViewModel = Provider.of(context); @@ -54,7 +41,6 @@ class _HomePageState extends State { onModelReady: (model) => model.getPatientRadOrders(), builder: (_, model, wi) => AppScaffold( isShowDecPage: false, - isHelp: true, body: Container( width: double.infinity, child: SingleChildScrollView( @@ -82,12 +68,12 @@ class _HomePageState extends State { right: 5, child: Container( width: - MediaQuery.of(context).size.width * 0.8, + MediaQuery.of(context).size.width * 0.8, child: Row( children: [ Expanded( child: Container( - height: 120, + height: 125, padding: EdgeInsets.all(5), margin: EdgeInsets.all(5), decoration: BoxDecoration( @@ -97,78 +83,54 @@ class _HomePageState extends State { fit: BoxFit.fill, ), color: - Colors.white.withOpacity(0.3), + Colors.white.withOpacity(0.3), borderRadius: BorderRadius.all( Radius.circular(5))), child: Container( - margin: EdgeInsets.only(top: 10.0), + child: Column( children: [ - Text("COVID-19 TEST", - style: TextStyle( - color: Colors.white, - fontWeight: - FontWeight.bold, - fontSize: 18.0)), + Texts(TranslationBase.of(context).covidTest, + color: Colors.white, + fontWeight: FontWeight.w700, + ), Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Container( margin: EdgeInsets.only( - top: 15.0, - left: 3.5, - right: 3.5), + top: 15.0,), child: SvgPicture.asset( 'assets/images/new-design/covid-19-car.svg', width: 45.0, height: 45.0), ), Container( - margin: EdgeInsets.only( - left: 10.0, - top: 10.0), + margin: EdgeInsets.only(top: 5.0), child: Column( children: [ - Text("Drive-Thru", - style: TextStyle( - color: Colors - .white, - fontWeight: - FontWeight - .bold, - fontSize: - 16.0)), + Texts(TranslationBase.of(context).driveThru, + fontWeight: FontWeight.w700, + color: Colors.white,), ButtonTheme( - shape: - RoundedRectangleBorder( + shape: RoundedRectangleBorder( borderRadius: - BorderRadius - .circular( - 5.0), - ), - minWidth: MediaQuery.of( - context) - .size - .width * - 0.15, + BorderRadius.circular(5.0),), + minWidth: MediaQuery.of(context).size.width * 0.15, height: 25.0, child: RaisedButton( - color: Colors - .red[800], - textColor: - Colors.white, - disabledTextColor: - Colors.white, - disabledColor: - new Color( - 0xFFbcc2c4), + color: Colors.red[800], + textColor: Colors.white, + disabledTextColor: Colors.white, + disabledColor: new Color(0xFFbcc2c4), onPressed: () { navigateToCovidDriveThru(); }, - child: Text( - "BOOK NOW", - style: TextStyle( - fontSize: - 12.0)), + child: Texts( + TranslationBase.of(context).bookNow, + fontWeight: FontWeight.w700, + color: Colors.white, + ), ), ), ], @@ -186,7 +148,7 @@ class _HomePageState extends State { onTap: () => Navigator.push(context, FadePage(page: LiveCareHome())), child: Container( - height: 120, + height: 125, padding: EdgeInsets.all(15), margin: EdgeInsets.all(5), decoration: BoxDecoration( @@ -209,367 +171,360 @@ class _HomePageState extends State { ], ), ), - Container(width: double.infinity, height: 80) + Container(width: double.infinity, height:projectViewModel.isArabic ?110: 80) ], ), Positioned( top: 155, left: MediaQuery.of(context).size.width * (MediaQuery.of(context).orientation == - Orientation.landscape + Orientation.landscape ? 0.02 : 0.03), right: MediaQuery.of(context).size.width * (MediaQuery.of(context).orientation == - Orientation.landscape + Orientation.landscape ? 0.02 : 0.03), - child: (!model.isLogin && projectViewModel.user == null) + child: (!model.isLogin) ? Container( - width: double.infinity, - height: 125, - decoration: BoxDecoration( - color: HexColor('#A59E9E'), - shape: BoxShape.rectangle, - border: Border.all( - color: Colors.transparent, width: 0.5), - borderRadius: - BorderRadius.all(Radius.circular(9)), - image: DecorationImage( - image: ExactAssetImage( - 'assets/images/bg_graphic.png'), - fit: BoxFit.cover)), - child: Container( - margin: EdgeInsets.all(5), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - height: 8, - ), - Texts( - TranslationBase.of(context).myMedicalFile, - color: Colors.black87, - bold: true, - fontSize: 23, - ), - SizedBox( - height: 5, + width: double.infinity, + height: 125, + decoration: BoxDecoration( + color: HexColor('#A59E9E'), + shape: BoxShape.rectangle, + border: Border.all( + color: Colors.transparent, width: 0.5), + borderRadius: + BorderRadius.all(Radius.circular(9)), + image: DecorationImage( + image: ExactAssetImage( + 'assets/images/bg_graphic.png'), + fit: BoxFit.cover)), + child: Container( + margin: EdgeInsets.all(5), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + height: 2, + ), + Texts( + TranslationBase.of(context).myMedicalFile, + color: Colors.black87, + fontWeight: FontWeight.w700, + fontSize: 23, + ), + + Texts( + TranslationBase.of(context) + .myMedicalFileSubTitle, + color: Colors.black, + fontSize: 16, + ), + Align( + alignment: projectViewModel.isArabic + ? Alignment.bottomLeft + : Alignment.bottomRight, + child: InkWell( + onTap: () { + widget.goToMyProfile(); + }, + child: Container( + margin: EdgeInsets.only(left: 15,right: 15), + width: 90, + height: 30, + decoration: BoxDecoration( + color: HexColor('#D81A2E'), + shape: BoxShape.rectangle, + border: Border.all( + color: Colors.transparent, + width: 0.5), + borderRadius: BorderRadius.all( + Radius.circular(0)), ), - Texts( - TranslationBase.of(context) - .myMedicalFileSubTitle, - color: Colors.black, - fontSize: 16, + child: Center( + child: Texts( + TranslationBase.of(context).viewMore, + color: Colors.white, + fontWeight: FontWeight.w700, + fontSize: 12, + ), ), - Align( - alignment: projectViewModel.isArabic - ? Alignment.bottomRight - : Alignment.bottomLeft, - child: InkWell( - onTap: () { - widget.goToMyProfile(); - }, - child: Container( - margin: EdgeInsets.all(2), - width: 90, - height: 30, - decoration: BoxDecoration( - color: HexColor('#D81A2E'), - shape: BoxShape.rectangle, - border: Border.all( - color: Colors.transparent, - width: 0.5), - borderRadius: BorderRadius.all( - Radius.circular(9)), + ), + ), + ) + ], + ), + ), + ) + : Container( + width: double.infinity, + height: projectViewModel.isArabic ? 160:130, + decoration: BoxDecoration( + color: HexColor('#A59E9E'), + shape: BoxShape.rectangle, + border: Border.all( + color: Colors.transparent, width: 0.5), + borderRadius: + BorderRadius.all(Radius.circular(9)), + image: DecorationImage( + image: ExactAssetImage( + 'assets/images/bg_graphic.png'), + fit: BoxFit.cover), + ), + child: Container( + margin: EdgeInsets.all(5), + child: Column( + children: [ + Row( + children: [ + if (projectViewModel.user != null && model.isLogin) + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + SizedBox( + height: 8, ), - child: Center( - child: Texts( - TranslationBase.of(context) - .viewMore, - color: Colors.white, - fontSize: 12, - ), + Texts( + model.user.firstName + + " " + + model.user.lastName, + color: Colors.grey[100], + bold: true, + fontSize: 15, ), + Texts( + '${model.user.patientID}', + color: Colors.white, + fontSize: 14, + ), + SizedBox( + height: 5, + ), + Texts( + '${DateUtil.getMonthDayYearDateFormatted(model.user.dateofBirthDataTime)} ,${model.user.genderDescription} ${model.user.ageDesc}', + color: Colors.grey[100], + fontWeight: FontWeight.normal, + fontSize: 14, + ), + ], + ), + ), + InkWell( + onTap: () { + widget.goToMyProfile(); + }, + child: Container( + margin: EdgeInsets.all(2), + width: 90, + height: 30, + decoration: BoxDecoration( + color: HexColor('#D81A2E'), + shape: BoxShape.rectangle, + border: Border.all( + color: Colors.transparent, + width: 0.5), + borderRadius: BorderRadius.all( + Radius.circular(5), ), ), - ) - ], - ), - ), - ) - : Container( - width: double.infinity, - height: 130, - decoration: BoxDecoration( - color: HexColor('#A59E9E'), - shape: BoxShape.rectangle, - border: Border.all( - color: Colors.transparent, width: 0.5), - borderRadius: - BorderRadius.all(Radius.circular(9)), - image: DecorationImage( - image: ExactAssetImage( - 'assets/images/bg_graphic.png'), - fit: BoxFit.cover), + child: Center( + child: Texts( + TranslationBase.of(context) + .viewMore, + color: Colors.white, + fontSize: 12, + ), + ), + ), + ) + ], ), - child: Container( - margin: EdgeInsets.all(5), - child: Column( - children: [ - Row( + Row( + children: [ + Expanded( + child: Row( children: [ - if (model.user != null) - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - SizedBox( - height: 8, - ), - Texts( - model.user.firstName + - " " + - model.user.lastName, - color: Colors.grey[100], - bold: true, - fontSize: 15, - ), - Texts( - '${model.user.patientID}', - color: Colors.white, - fontSize: 14, - ), - SizedBox( - height: 5, - ), - Texts( - '${DateUtil.getMonthDayYearDateFormatted(model.user.dateofBirthDataTime)} ,${model.user.genderDescription} ${model.user.ageDesc}', - color: Colors.grey[100], - fontWeight: FontWeight.normal, - fontSize: 14, - ), - ], - ), - ), - InkWell( - onTap: () { - widget.goToMyProfile(); - }, - child: Container( - margin: EdgeInsets.all(2), - width: 90, - height: 30, - decoration: BoxDecoration( - color: HexColor('#D81A2E'), - shape: BoxShape.rectangle, - border: Border.all( - color: Colors.transparent, - width: 0.5), - borderRadius: BorderRadius.all( - Radius.circular(5), - ), - ), - child: Center( - child: Texts( - TranslationBase.of(context) - .viewMore, - color: Colors.white, - fontSize: 12, - ), - ), - ), + Image.asset( + 'assets/images/height_icon.png', + width: 35, + height: 40, + ), + Texts( + "${model.heightCm}", + color: Colors.white, + fontSize: 17, ) ], ), - Row( - //crossAxisAlignment: CrossAxisAlignment.center, - //mainAxisAlignment: MainAxisAlignment.spaceAround, + ), + SizedBox( + width: 3, + ), + Expanded( + child: Row( children: [ - Expanded( - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Image.asset( - 'assets/images/height_icon.png', - width: 35, - height: 40, - ), - Texts( - "${model.heightCm}", - color: Colors.white, - ) - ], - ), - ), - SizedBox( - width: 3, - ), - Expanded( - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Image.asset( - 'assets/images/weight_icon.png', - width: 25, - height: 40, - ), - Texts( - '${model.weightKg}', - color: Colors.white, - ) - ], - ), + Image.asset( + 'assets/images/weight_icon.png', + width: 25, + height: 40, ), - SizedBox( - width: 3, - ), - Expanded( - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Image.asset( - 'assets/images/blood_icon.png', - width: 35, - height: 40, - ), - Texts( - '${model.bloadType}', - color: Colors.white, - ) - ], - ), + Texts( + '${model.weightKg}', + color: Colors.white, + fontSize: 17 + ) + ], + ), + ), + SizedBox( + width: 3, + ), + Expanded( + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Image.asset( + 'assets/images/blood_icon.png', + width: 35, + height: 40, ), + Texts( + '${model.booldType}', + color: Colors.white, + ) ], - ) - ], - ), - ), - ), + ), + ), + ], + ) + ], + ), + ), + ), ), ], ), if(projectViewModel.havePrivilege(64)||projectViewModel.havePrivilege(65)||projectViewModel.havePrivilege(67)) - Container( - margin: EdgeInsets.only(left: 15, right: 15), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - if(projectViewModel.havePrivilege(64)) - DashboardItem( - onTap: () { - Navigator.push( - context, - FadePage( - page: HomeHealthCarePage(), - ), - ); - }, - child: Center( - child: Padding( - padding: const EdgeInsets.all(15.0), - child: Column( - children: [ - Image.asset( - 'assets/images/home_health_care_icon.png', - width: 50, - height: 50, + Container( + margin: EdgeInsets.only(left: 15, right: 15), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + if(projectViewModel.havePrivilege(64)) + DashboardItem( + onTap: () { + Navigator.push( + context, + FadePage( + page: HomeHealthCareIndexPage(), ), - SizedBox( - height: 3, + ); + }, + child: Center( + child: Padding( + padding: const EdgeInsets.all(15.0), + child: Column( + children: [ + Image.asset( + 'assets/images/home_health_care_icon.png', + width: 50, + height: 50, + ), + SizedBox( + height: 3, + ), + Texts( + TranslationBase.of(context).homeHealthCareService, + textAlign: TextAlign.center, + color: Colors.white, + fontWeight: FontWeight.w700, + fontSize: SizeConfig.textMultiplier * 1.55, + ) + ], ), - Texts( - TranslationBase.of(context) - .homeHealthCareService, - textAlign: TextAlign.center, - color: Colors.white, - bold: true, - fontSize: SizeConfig.textMultiplier * 1.7, - ) - ], + ), ), + height: MediaQuery.of(context).size.width * 0.4, + imageName: 'home_healthcare_service_bg.png', + opacity: 0.5, ), - ), - height: MediaQuery.of(context).size.width * 0.4, - imageName: 'home_healthcare_service_bg.png', - opacity: 0.5, - ), - if(projectViewModel.havePrivilege(65)) - DashboardItem( - //onTap: () => Navigator.push(context, FadePage(page: PharmacyPage())), + if(projectViewModel.havePrivilege(65)) + DashboardItem( + onTap: () => Navigator.push(context, FadePage(page: LandingPagePharmacy())), - child: Center( - child: Padding( - padding: const EdgeInsets.all(15.0), - child: Column( - children: [ - Image.asset( - 'assets/images/pharmacy_logo.png', - width: 40, - height: 40, - ), - SizedBox( - height: 20, + child: Center( + child: Padding( + padding: const EdgeInsets.all(15.0), + child: Column( + children: [ + Image.asset( + 'assets/images/pharmacy_logo.png', + width: 40, + height: 40, + ), + SizedBox( + height: 20, + ), + Texts( + TranslationBase.of(context).onlinePharmacy, + textAlign: TextAlign.center, + color: Colors.white, + fontWeight: FontWeight.w700, + fontSize: SizeConfig.textMultiplier * 1.55, + ) + ], ), - Texts( - TranslationBase.of(context).onlinePharmacy, - textAlign: TextAlign.center, - color: Colors.white, - bold: true, - fontSize: SizeConfig.textMultiplier * 1.7, - ) - ], + ), ), + height: MediaQuery.of(context).size.width * 0.4, + imageName: 'al-habib_onlne_pharmacy_bg.png', ), - ), - height: MediaQuery.of(context).size.width * 0.4, - imageName: 'al-habib_onlne_pharmacy_bg.png', - ), - if(projectViewModel.havePrivilege(67)) - DashboardItem( - onTap: () { - Navigator.push( - context, - FadePage( - page: CMCPage(), - ), - ); - }, - child: Center( - child: Padding( - padding: const EdgeInsets.all(15.0), - child: Column( - children: [ - Image.asset( - 'assets/images/comprehensive_medical_checkup_logo.png', - width: 50, - height: 50, + if(projectViewModel.havePrivilege(67)) + DashboardItem( + onTap: (){ + Navigator.push( + context, + FadePage( + page: CMCPage(), ), - SizedBox( - height: 3, + ); + }, + child: Center( + child: Padding( + padding: const EdgeInsets.all(15.0), + child: Column( + children: [ + Image.asset( + 'assets/images/comprehensive_medical_checkup_logo.png', + width: 50, + height: 50, + ), + SizedBox( + height: 3, + ), + Texts( + TranslationBase.of(context).emergencyService, + textAlign: TextAlign.center, + color: Colors.white, + fontWeight: FontWeight.w700, + fontSize: SizeConfig.textMultiplier * 1.55, + ) + ], ), - Texts( - TranslationBase.of(context).emergencyService, - textAlign: TextAlign.center, - color: Colors.white, - bold: true, - fontSize: SizeConfig.textMultiplier * 1.7, - ) - ], + ), ), + height: MediaQuery.of(context).size.width * 0.4, + color: HexColor("#747C80"), + imageName: 'emergency_service_image.png', ), - ), - height: MediaQuery.of(context).size.width * 0.4, - color: HexColor("#747C80"), - imageName: 'emergency_service_image.png', - ), - ], + ], + ), ), - ), SizedBox( height: 8, ), @@ -646,47 +601,47 @@ class _HomePageState extends State { color: Colors.white, )), if(projectViewModel.havePrivilege(60)) - Container( - width: MediaQuery.of(context).size.width * 0.29, - child: InkWell( - onTap: () => Navigator.push( - context, - FadePage( - page: ErOptions( - isAppbar: true, - ))), - child: Center( - child: Padding( - padding: const EdgeInsets.all(15.0), - child: Column( - children: [ - Image.asset( - 'assets/images/Dr_Schedule_report.png', - width: 50, - height: 50, - ), - SizedBox( - height: 10, - ), - Texts( - TranslationBase.of(context) - .emergencyServices, - textAlign: TextAlign.center, - color: Colors.black87, - bold: false, - fontSize: SizeConfig.textMultiplier * 1.7, - ) - ], + Container( + width: MediaQuery.of(context).size.width * 0.29, + child: InkWell( + onTap: () => Navigator.push( + context, + FadePage( + page: ErOptions( + isAppbar: true, + ))), + child: Center( + child: Padding( + padding: const EdgeInsets.all(15.0), + child: Column( + children: [ + Image.asset( + 'assets/images/Dr_Schedule_report.png', + width: 50, + height: 50, + ), + SizedBox( + height: 10, + ), + Texts( + TranslationBase.of(context) + .emergencyServices, + textAlign: TextAlign.center, + color: Colors.black87, + bold: false, + fontSize: SizeConfig.textMultiplier * 1.7, + ) + ], + ), ), ), ), + height: MediaQuery.of(context).size.width * 0.4, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(6.0), + color: Colors.white, + ), ), - height: MediaQuery.of(context).size.width * 0.4, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(6.0), - color: Colors.white, - ), - ), ], ), ), @@ -772,7 +727,7 @@ class _HomePageState extends State { ], ), ), - height: 106, + height: 100, imageName: 'contact_us_bg.png', opacity: 0.5, color: Colors.grey[700], @@ -801,15 +756,15 @@ class _HomePageState extends State { class DashboardItem extends StatelessWidget { const DashboardItem( {this.hasBorder = false, - this.imageName, - @required this.child, - this.onTap, - Key key, - this.width, - this.height, - this.color, - this.opacity = 0.4, - this.hasColorFilter = true}) + this.imageName, + @required this.child, + this.onTap, + Key key, + this.width, + this.height, + this.color, + this.opacity = 0.4, + this.hasColorFilter = true}) : super(key: key); final bool hasBorder; final String imageName; @@ -827,16 +782,14 @@ class DashboardItem extends StatelessWidget { onTap: onTap, child: Container( width: width != null ? width : MediaQuery.of(context).size.width * 0.29, - height: height != null - ? height - : MediaQuery.of(context).orientation == Orientation.portrait - ? MediaQuery.of(context).size.height * 0.19 - : MediaQuery.of(context).size.height * 0.35, + height: height != null ? height : MediaQuery.of(context).orientation == Orientation.portrait + ? MediaQuery.of(context).size.height * 0.17 + : MediaQuery.of(context).size.height * 0.35, decoration: BoxDecoration( color: !hasBorder ? color != null - ? color - : HexColor('#050705').withOpacity(opacity) + ? color + : HexColor('#050705').withOpacity(opacity) : Colors.white, borderRadius: BorderRadius.circular(6.0), border: hasBorder @@ -844,13 +797,11 @@ class DashboardItem extends StatelessWidget { : Border.all(width: 0.0, color: Colors.transparent), image: imageName != null ? DecorationImage( - image: ExactAssetImage('assets/images/$imageName'), - fit: BoxFit.cover, - colorFilter: hasColorFilter - ? new ColorFilter.mode( - Colors.black.withOpacity(0.2), BlendMode.dstIn) - : null, - ) + image: ExactAssetImage('assets/images/$imageName'), + fit: BoxFit.cover, + colorFilter: hasColorFilter ? new ColorFilter.mode( + Colors.black.withOpacity(0.2), BlendMode.dstIn) : null, + ) : null, ), child: Center( diff --git a/lib/pages/landing/landing_page_pharmcy.dart b/lib/pages/landing/landing_page_pharmcy.dart new file mode 100644 index 00000000..fda83fc2 --- /dev/null +++ b/lib/pages/landing/landing_page_pharmcy.dart @@ -0,0 +1,175 @@ +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/pages/parent_categorise_page.dart'; +import 'package:diplomaticquarterapp/pages/pharmacies/screens/cart-order-page.dart'; +import 'package:diplomaticquarterapp/pages/pharmacies/screens/pharmacy_module_page.dart'; +import 'package:diplomaticquarterapp/pages/pharmacy/profile/profile.dart'; +import 'package:diplomaticquarterapp/pages/pharmacy_categorise.dart'; +import 'package:diplomaticquarterapp/pages/search_products_page.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; +import 'package:diplomaticquarterapp/widgets/drawer/app_drawer_widget.dart'; +import 'package:diplomaticquarterapp/widgets/pharmacy/bottom_nav_pharmacy_bar.dart'; +import 'package:flutter/material.dart'; +import 'package:diplomaticquarterapp/pages/pharmacies/wishlist.dart'; + +import '../offers_categorise_page.dart'; + +class LandingPagePharmacy extends StatefulWidget { + @override + _LandingPagePharmacyState createState() => _LandingPagePharmacyState(); +} + +class _LandingPagePharmacyState extends State { + int currentTab = 0; + PageController pageController; + ProjectViewModel projectProvider; + + _changeCurrentTab(int tab) { + setState(() { + currentTab = tab; + pageController.jumpToPage(tab); + }); + } + + void initState() { + super.initState(); + pageController = PageController(keepPage: true); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: currentTab == 0 || currentTab == 1 + ? AppBar( + backgroundColor: Color(0xff5AB145), + elevation: 0, + title: Container( + height: MediaQuery.of(context).size.height * 0.056, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(5.0), + color: Colors.white, + ), + child: InkWell( + child: Padding( + padding: EdgeInsets.all(8.0), + child: Row( + //crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Icon(Icons.search, size: 25.0), + SizedBox( + width: 15.0, + ), + Texts( + TranslationBase.of(context).searchProductHere, + fontSize: 13, + ) + ], + ), + ), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => SearchProductsPage()), + ); + }, + ), + ), + leading: Builder( + builder: (BuildContext context) { + return InkWell( + onTap: (){ + setState(() { + currentTab = 0; + pageController.jumpToPage(0); + }); + }, + child: Container( + height: 2.0, + width: 10.0, + child: Image.asset( + 'assets/images/pharmacy_logo.png', + ), + ), + ); + }, + ), + actions: [ + // IconButton( + // iconSize: 70, + // icon: SvgPicture.asset('assets/images/svg/robort_svg.svg', + // height: 100, width: 100, fit: BoxFit.cover), + // onPressed: () { + // triggerRobot(); + // } //do something, + // ) + ], + centerTitle: true, + ) + : currentTab == 4 + ? null + : AppBar( + backgroundColor: Color(0xff5AB145), + elevation: 0, + textTheme: TextTheme( + headline6: TextStyle( + color: Colors.white, fontWeight: FontWeight.bold), + ), + title: Text(getText(currentTab).toUpperCase()), + leading: Builder( + builder: (BuildContext context) { + return IconButton( + icon: Icon(Icons.arrow_back), + color: Colors.white, + onPressed: () => Scaffold.of(context).openDrawer(), + ); + }, + ), + actions: [ + // IconButton( + // iconSize: 70, + // icon: SvgPicture.asset('assets/images/svg/robort_svg.svg', + // height: 100, width: 100, fit: BoxFit.cover), + // onPressed: () { + // triggerRobot(); + // } //do something, + // ) + ], + centerTitle: true, + ), + extendBody: false, + body: PageView( + physics: NeverScrollableScrollPhysics(), + controller: pageController, + children: [ + // TODO mosa_comeback + PharmacyPage(), + PharmacyCategorisePage(), +// OffersCategorisePage(), + WishlistPage(), + PharmacyProfilePage(), +// Container( +// child: Text('text'), +// ), + CartOrderPage(), + ], // Please do not remove the BookingOptions from this array + ), + bottomNavigationBar: BottomNavPharmacyBar( + changeIndex: _changeCurrentTab, + index: currentTab, + ), + ); + } + + getText(currentTab) { + switch (currentTab) { + case 2: + return 'Wishlist'; + case 3: + return 'My Account'; + case 4: + return 'Shopping Cart'; + } + } +} diff --git a/lib/pages/livecare/livecare_home.dart b/lib/pages/livecare/livecare_home.dart index 3243b269..fc5c4eab 100644 --- a/lib/pages/livecare/livecare_home.dart +++ b/lib/pages/livecare/livecare_home.dart @@ -3,11 +3,12 @@ import 'package:diplomaticquarterapp/pages/livecare/widgets/LiveCarePendingReque import 'package:diplomaticquarterapp/pages/livecare/widgets/clinic_list.dart'; import 'package:diplomaticquarterapp/pages/livecare/widgets/livecare_logs.dart'; import 'package:diplomaticquarterapp/services/livecare_services/livecare_provider.dart'; -import 'package:diplomaticquarterapp/uitl/app_toast.dart'; -import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.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:smart_progress_bar/smart_progress_bar.dart'; + +import 'livecare_type_select.dart'; class LiveCareHome extends StatefulWidget { static bool showFooterButton = true; @@ -92,37 +93,40 @@ class _LiveCareHomeState extends State hasLiveCareRequest = false; }); LiveCareService service = new LiveCareService(); - GifLoaderDialogUtils.showMyDialog(context); PatientERVirtualHistoryResponse patientERVirtualHistoryResponse = new PatientERVirtualHistoryResponse(); - service.getLivecareHistory(context).then((res) { - GifLoaderDialogUtils.hideDialog(context); - setState(() { - print(res['ErRequestHistoryList'].length); - if (res['ErRequestHistoryList'].length != 0) { - patientERVirtualHistoryResponse = - PatientERVirtualHistoryResponse.fromJson(res); - erRequestHistoryList = - patientERVirtualHistoryResponse.erRequestHistoryList; + service + .getLivecareHistory(context) + .then((res) { + setState(() { + print(res['ErRequestHistoryList'].length); + if (res['ErRequestHistoryList'].length != 0) { + patientERVirtualHistoryResponse = + PatientERVirtualHistoryResponse.fromJson(res); + erRequestHistoryList = + patientERVirtualHistoryResponse.erRequestHistoryList; - if (patientERVirtualHistoryResponse - .erRequestHistoryList[0].callStatus < - 4) { - pendingERRequestHistoryList = - patientERVirtualHistoryResponse.erRequestHistoryList[0]; - hasLiveCareRequest = true; - } else { - hasLiveCareRequest = false; - } - } - }); - setState(() { - isDataLoaded = true; - }); - }).catchError((err) { - GifLoaderDialogUtils.hideDialog(context); - AppToast.showErrorToast(message: err); - print(err); - }); + if (patientERVirtualHistoryResponse + .erRequestHistoryList[0].callStatus < + 4) { + pendingERRequestHistoryList = + patientERVirtualHistoryResponse.erRequestHistoryList[0]; + hasLiveCareRequest = true; + } else { + hasLiveCareRequest = false; + } + } + }); + }) + .catchError((err) { + print(err); + }) + .showProgressBar( + text: "Loading", backgroundColor: Colors.blue.withOpacity(0.6)) + .then((value) { + setState(() { + isDataLoaded = true; + }); + }); } } diff --git a/lib/pages/livecare/widgets/LiveCareHistoryCard.dart b/lib/pages/livecare/widgets/LiveCareHistoryCard.dart index e80f79ee..25ec8514 100644 --- a/lib/pages/livecare/widgets/LiveCareHistoryCard.dart +++ b/lib/pages/livecare/widgets/LiveCareHistoryCard.dart @@ -5,11 +5,11 @@ import 'package:diplomaticquarterapp/pages/feedback/feedback_home_page.dart'; import 'package:diplomaticquarterapp/services/livecare_services/livecare_provider.dart'; import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; import 'package:diplomaticquarterapp/uitl/app_toast.dart'; -import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/dialogs/confirm_dialog.dart'; import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/material.dart'; +import 'package:smart_progress_bar/smart_progress_bar.dart'; class LiveCareHistoryCard extends StatefulWidget { ErRequestHistoryList erRequestHistoryList; @@ -177,7 +177,6 @@ class _LiveCareHistoryCardState extends State { sendInvoiceEmail(context) { ConfirmDialog.closeAlertDialog(context); LiveCareService service = new LiveCareService(); - GifLoaderDialogUtils.showMyDialog(context); service .sendLiveCareInvoiceEmail( widget.erRequestHistoryList.appointmentNo.toString(), @@ -185,13 +184,12 @@ class _LiveCareHistoryCardState extends State { authUser.emailAddress, context) .then((res) { - GifLoaderDialogUtils.hideDialog(context); AppToast.showSuccessToast(message: "LiveCare invoice sent successfully"); }).catchError((err) { - GifLoaderDialogUtils.hideDialog(context); AppToast.showErrorToast(message: err); print(err); - }); + }).showProgressBar( + text: "Loading", backgroundColor: Colors.blue.withOpacity(0.6)); } getAuthenticatedUser() async { diff --git a/lib/pages/livecare/widgets/LiveCarePendingRequest.dart b/lib/pages/livecare/widgets/LiveCarePendingRequest.dart index 7ce39804..bfd42e62 100644 --- a/lib/pages/livecare/widgets/LiveCarePendingRequest.dart +++ b/lib/pages/livecare/widgets/LiveCarePendingRequest.dart @@ -3,9 +3,9 @@ import 'package:diplomaticquarterapp/models/FamilyFiles/PatientERVirtualHistoryR import 'package:diplomaticquarterapp/services/livecare_services/livecare_provider.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:flutter/material.dart'; +import 'package:smart_progress_bar/smart_progress_bar.dart'; class LiveCarePendingRequest extends StatefulWidget { ErRequestHistoryList pendingERRequestHistoryList; @@ -149,19 +149,19 @@ class _LiveCarePendingRequestState extends State { cancelLiveCareRequest() { LiveCareService service = new LiveCareService(); - GifLoaderDialogUtils.showMyDialog(context); service .cancelLiveCareRequest(widget.pendingERRequestHistoryList.vCID, context) .then((res) { - GifLoaderDialogUtils.hideDialog(context); AppToast.showSuccessToast( message: "LiveCare request cancelled successfully"); - widget.getLiveCareHistory(); }) .catchError((err) { - GifLoaderDialogUtils.hideDialog(context); - AppToast.showErrorToast(message: err); print(err); + }) + .showProgressBar( + text: "Loading", backgroundColor: Colors.blue.withOpacity(0.6)) + .then((value) { + widget.getLiveCareHistory(); }); } } diff --git a/lib/pages/livecare/widgets/clinic_card.dart b/lib/pages/livecare/widgets/clinic_card.dart index 410b7170..56613034 100644 --- a/lib/pages/livecare/widgets/clinic_card.dart +++ b/lib/pages/livecare/widgets/clinic_card.dart @@ -2,8 +2,8 @@ import 'package:diplomaticquarterapp/models/LiveCare/ClinicsServiceTimingsRespon import 'package:diplomaticquarterapp/models/LiveCare/LiveCareClinicsListResponse.dart'; import 'package:diplomaticquarterapp/services/livecare_services/livecare_provider.dart'; import 'package:diplomaticquarterapp/uitl/app_toast.dart'; -import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; import 'package:flutter/material.dart'; +import 'package:smart_progress_bar/smart_progress_bar.dart'; import 'ClinicTimingsDialog.dart'; @@ -90,11 +90,9 @@ class _State extends State { getClinicTimings(PatientERGetClinicsList patientERGetClinicsList) { LiveCareService service = new LiveCareService(); - GifLoaderDialogUtils.showMyDialog(context); service .getLivecareClinicTiming(patientERGetClinicsList.serviceID, context) .then((res) { - GifLoaderDialogUtils.hideDialog(context); if (res['MessageStatus'] == 1) { setState(() { clinicsServiceTimingsResponse = @@ -131,9 +129,8 @@ class _State extends State { AppToast.showErrorToast(message: res['ErrorEndUserMessage']); } }).catchError((err) { - GifLoaderDialogUtils.hideDialog(context); - AppToast.showErrorToast(message: err); print(err); - }); + }).showProgressBar( + text: "Loading", backgroundColor: Colors.blue.withOpacity(0.6)); } } diff --git a/lib/pages/login/confirm-login.dart b/lib/pages/login/confirm-login.dart index 2b02540b..646158db 100644 --- a/lib/pages/login/confirm-login.dart +++ b/lib/pages/login/confirm-login.dart @@ -4,12 +4,16 @@ import 'package:diplomaticquarterapp/core/service/AuthenticatedUserObject.dart'; import 'package:diplomaticquarterapp/core/viewModels/appointment_rate_view_model.dart'; import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/locator.dart'; +import 'package:diplomaticquarterapp/models/Appointments/toDoCountProviderModel.dart'; import 'package:diplomaticquarterapp/models/Authentication/check_activation_code_response.dart'; import 'package:diplomaticquarterapp/models/Authentication/check_paitent_authentication_req.dart'; import 'package:diplomaticquarterapp/models/Authentication/select_device_imei_res.dart'; import 'package:diplomaticquarterapp/models/Authentication/send_activation_request.dart'; +import 'package:diplomaticquarterapp/pages/landing/landing_page.dart'; +import 'package:diplomaticquarterapp/pages/rateAppointment/rate_appointment_doctor.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/uitl/app_shared_preferences.dart'; import 'package:diplomaticquarterapp/uitl/app_toast.dart'; import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; @@ -20,6 +24,7 @@ import 'package:diplomaticquarterapp/widgets/card/rounded_container.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:diplomaticquarterapp/widgets/otp/sms-popup.dart'; import 'package:diplomaticquarterapp/widgets/text/app_texts_widget.dart'; +import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -74,6 +79,8 @@ class _ConfirmLogin extends State { locator(); ProjectViewModel projectViewModel; + ToDoCountProviderModel toDoProvider; + @override void initState() { _getAvailableBiometrics(); @@ -84,6 +91,7 @@ class _ConfirmLogin extends State { @override Widget build(BuildContext context) { projectViewModel = Provider.of(context); + toDoProvider = Provider.of(context); return AppScaffold( appBarTitle: TranslationBase.of(context).confirm, isShowAppBar: true, @@ -95,127 +103,132 @@ class _ConfirmLogin extends State { width: SizeConfig.realScreenWidth, child: Column( children: [ - Expanded( - flex: 3, - child: user != null && isMoreOption == false - ? Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Image.asset( - 'assets/images/DQ/dq_logo_icon.png', - height: 90, - width: 90, - ), - AppText( - TranslationBase.of(context).welcomeBack + - ' ' + - user.name, - fontSize: SizeConfig.textMultiplier * 3.5, - ), - AppText( - TranslationBase.of(context).accountInfo, - fontSize: SizeConfig.textMultiplier * 2.5, - ), - Card( - color: Colors.grey[300], - child: Row( - children: [ - Expanded( - child: ListTile( - title: Text( - TranslationBase.of(context).lastLoginAt, - textAlign: TextAlign.center, - ), - subtitle: Text( - user.editedOn != null + user != null && isMoreOption == false + ? Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Image.asset( + 'assets/images/DQ/dq_logo_icon.png', + height: 90, + width: 90, + ), + AppText( + TranslationBase.of(context).welcomeBack + + ' ' + + user.name, + fontSize: SizeConfig.textMultiplier * 3.5, + ), + SizedBox( + height: 20, + ), + AppText( + TranslationBase.of(context).accountInfo, + fontSize: SizeConfig.textMultiplier * 2.5, + ), + SizedBox( + height: 20, + ), + Card( + color: Colors.grey[300], + child: Row( + children: [ + Flexible( + child: ListTile( + title: Text( + TranslationBase.of(context).lastLoginAt, + textAlign: TextAlign.center, + overflow: TextOverflow.ellipsis, + ), + subtitle: Text( + user.editedOn != null + ? formatDate( + DateUtil.convertStringToDate( + user.editedOn)) + : user.createdOn != null ? formatDate( DateUtil.convertStringToDate( - user.editedOn)) + user.createdOn)) : '--', - textAlign: TextAlign.center), - )), - Expanded( - child: ListTile( - title: Text( - TranslationBase.of(context) - .lastLoginWith, - textAlign: TextAlign.center), - subtitle: Text( - getType(user.logInType, context), - textAlign: TextAlign.center), - )) - ], + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.center), + )), + Flexible( + child: ListTile( + title: Text( + TranslationBase.of(context).lastLoginWith, + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.center), + subtitle: Text( + getType(user.logInType, context), + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.center), )) - ], - ) - : Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Image.asset( - 'assets/images/DQ/dq_logo_icon.png', - height: 90, - width: 90, - ), - this.onlySMSBox == false - ? AppText( - TranslationBase.of(context) - .verifyLoginWith, - fontSize: SizeConfig.textMultiplier * 3.5, - textAlign: TextAlign.left, - ) - : AppText( - TranslationBase.of(context) - .verifyFingerprint2, - fontSize: SizeConfig.textMultiplier * 2.5, - textAlign: TextAlign.start, - ), - ])), + ], + )), + ], + ) + : Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Image.asset( + 'assets/images/DQ/dq_logo_icon.png', + height: 90, + width: 90, + ), + this.onlySMSBox == false + ? AppText( + TranslationBase.of(context).verifyLoginWith, + fontSize: SizeConfig.textMultiplier * 3.5, + textAlign: TextAlign.left, + ) + : AppText( + TranslationBase.of(context) + .verifyFingerprint2, + fontSize: SizeConfig.textMultiplier * 2.5, + textAlign: TextAlign.start, + ), + ]), user != null && isMoreOption == false - ? Expanded( - flex: 2, - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded( - child: InkWell( - onTap: () => { - authenticateUser( - 3, BiometricType.face.index) - }, - child: getButton(user.logInType))), - Expanded(child: getButton(5)) - ]) - ])) - : Expanded( - flex: 4, - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - onlySMSBox == false - ? Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded(child: getButton(3)), - Expanded(child: getButton(2)) - ], - ) - : SizedBox(), - Row( + ? Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - Expanded(child: getButton(1)), - Expanded(child: getButton(4)) - ], - ), - ]), - ), + Expanded( + child: InkWell( + onTap: () => { + authenticateUser( + 3, BiometricType.face.index) + }, + child: getButton(user.logInType))), + Expanded(child: getButton(5)) + ]) + ]) + : Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + onlySMSBox == false + ? Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded(child: getButton(3)), + Expanded(child: getButton(2)) + ], + ) + : SizedBox(), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded(child: getButton(1)), + Expanded(child: getButton(4)) + ], + ), + ]), Expanded( flex: 1, child: Column( @@ -352,8 +365,11 @@ class _ConfirmLogin extends State { context, type, this.mobileNumber, - (value) => {this.checkActivationCode(value: value)}, + (value) { + this.checkActivationCode(value: value); + }, () => { + Navigator.pop(context), print('Faild..'), }, ).displayDialog(context); @@ -379,55 +395,34 @@ class _ConfirmLogin extends State { } getMobileInfo(request) { - GifLoaderDialogUtils.showMyDialog(context); - this - .authService - .getLoginInfo(request) - .then((result) => { - GifLoaderDialogUtils.hideDialog(context), - if (result['SMSLoginRequired'] == false) - { - this.loginTokenID = result.logInTokenID, - this.patientOutSA = result.patientOutSA, - // sms for register the biometric - if (result.isSMSSent) - { - this.onlySMSBox = false, - //this.button(); - } - else - {checkActivationCode()} - } - else - { - if (result['IsAuthenticated'] == true) - { - setState(() { - isMoreOption = true; - this.onlySMSBox = true; - // this.fingrePrintBefore = true; - }), - - //sharedPref.setBool(ONLY_SMS, true), - // this.cs.sharedService.setSharedData(true, AuthenticationService.ONLY_SMS); - //this.cs.sharedService.setSharedData(this.selectedOption, AuthenticationService.FINGUREPRINT_BEFORE); - // this.cs.confirmLogin(); - //this.button(); - } - // else - // { - // // this.cs.presentAlert(result.ErrorEndUserMessage); - // } - } - }) - .catchError((err) { + // GifLoaderDialogUtils.showMyDialog(context); + this.authService.getLoginInfo(request).then((result) { + GifLoaderDialogUtils.hideDialog(context); + if (result['SMSLoginRequired'] == false) { + this.loginTokenID = result.logInTokenID; + this.patientOutSA = result.patientOutSA; + // sms for register the biometric + if (result.isSMSSent) { + this.onlySMSBox = false; + //this.button(); + } else { + checkActivationCode(); + } + } else { + if (result['IsAuthenticated'] == true) { + setState(() { + isMoreOption = true; + this.onlySMSBox = true; + // this.fingrePrintBefore = true; + }); + } + } + }).catchError((err) { GifLoaderDialogUtils.hideDialog(context); print(err); }); } - setUser() async {} - setDefault() async { if (await sharedPref.getObject(IMEI_USER_DATA) != null) user = SelectDeviceIMEIRES.fromJson( @@ -515,8 +510,8 @@ class _ConfirmLogin extends State { .then((result) => { if (result is Map) { - projectViewModel.setPrivilege(privilegeList: result), - result = CheckActivationCode.fromJson(result), + projectViewModel.setPrivilege(privilegeList: result), + result = CheckActivationCode.fromJson(result), if (this.registerd_data != null && this.registerd_data.isRegister == true) { @@ -529,6 +524,8 @@ class _ConfirmLogin extends State { sharedPref.remove(FAMILY_FILE), result.list.isFamily = false, userData = result.list, + // sharedPref.setString( + // BLOOD_TYPE, result['PatientBloodType']), sharedPref.setObject(MAIN_USER, result.list), sharedPref.setObject(USER_PROFILE, result.list), loginTokenID = result.logInTokenID, @@ -549,6 +546,9 @@ class _ConfirmLogin extends State { .catchError((err) { print(err); GifLoaderDialogUtils.hideDialog(context); + Future.delayed(Duration(seconds: 1), () { + AppToast.showErrorToast(message: err); + }); }); } @@ -569,11 +569,57 @@ class _ConfirmLogin extends State { }); } - goToHome() { + getToDoCount() { + toDoProvider.setState(0, true); + ClinicListService service = new ClinicListService(); + service.getActiveAppointmentNo(context).then((res) { + print(res['AppointmentActiveNumber']); + if (res['MessageStatus'] == 1) { + toDoProvider.setState(res['AppointmentActiveNumber'], true); + } else {} + }).catchError((err) { + print(err); + }); + } + + goToHome() async { + await authenticatedUserObject.getUser(getUser: true); authenticatedUserObject.isLogin = true; appointmentRateViewModel.isLogin = true; projectViewModel.isLogin = true; - Navigator.of(context).pushNamed(HOME); + projectViewModel.user = authenticatedUserObject.user; + Provider.of(context, listen: false) + .setUser(authenticatedUserObject.user); + getToDoCount(); + appointmentRateViewModel + .getIsLastAppointmentRatedList() + .then((value) => { + getToDoCount(), + // GifLoaderDialogUtils.hideDialog(context), + if (appointmentRateViewModel.isHaveAppointmentNotRate) + { + Navigator.pushAndRemoveUntil( + context, + FadePage( + page: RateAppointmentDoctor(), + ), + (r) => false) + } + else + { + Navigator.pushAndRemoveUntil( + context, + FadePage( + page: LandingPage(), + ), + (r) => false) + } + }) + .catchError((err) { + print(err); + //GifLoaderDialogUtils.hideDialog(context); + }); + // SMSOTP.showLoadingDialog(context, false), } loading(flag) { @@ -588,10 +634,11 @@ class _ConfirmLogin extends State { return InkWell( onTap: () => {authenticateUser(4, true)}, child: RoundedContainer( + height: 140, borderColor: Colors.grey, showBorder: true, child: Padding( - padding: EdgeInsets.fromLTRB(25, 10, 25, 10), + padding: EdgeInsets.fromLTRB(5, 15, 5, 15), child: Column( children: [ Image.asset( @@ -614,10 +661,11 @@ class _ConfirmLogin extends State { return InkWell( onTap: () => {authenticateUser(1, true)}, child: RoundedContainer( + height: 140, borderColor: Colors.grey, showBorder: true, child: Padding( - padding: EdgeInsets.fromLTRB(20, 10, 20, 10), + padding: EdgeInsets.fromLTRB(5, 15, 5, 15), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -626,12 +674,19 @@ class _ConfirmLogin extends State { height: SizeConfig.imageSizeMultiplier * 13, width: SizeConfig.imageSizeMultiplier * 16, ), - SizedBox( - height: 20, - ), + projectViewModel.isArabic + ? SizedBox( + height: 20, + ) + : SizedBox( + height: 20, + ), AppText( TranslationBase.of(context).verifySMS, - fontSize: SizeConfig.textMultiplier * 2, + fontSize: projectViewModel.isArabic + ? SizeConfig.textMultiplier * 1.8 + : SizeConfig.textMultiplier * 2, + textAlign: TextAlign.center, ) ], ), @@ -641,13 +696,14 @@ class _ConfirmLogin extends State { return InkWell( onTap: () => {authenticateUser(2, BiometricType.fingerprint.index)}, child: RoundedContainer( + height: 140, backgroundColor: BiometricType.fingerprint.index == 1 ? Colors.white : Colors.white.withOpacity(.7), borderColor: Colors.grey, showBorder: true, child: Padding( - padding: EdgeInsets.fromLTRB(25, 10, 25, 10), + padding: EdgeInsets.fromLTRB(5, 15, 5, 15), child: Column( children: [ Image.asset( @@ -670,13 +726,14 @@ class _ConfirmLogin extends State { return InkWell( onTap: () => {authenticateUser(3, BiometricType.face.index)}, child: RoundedContainer( + height: 140, backgroundColor: checkIfBiometricAvailable(BiometricType.face) ? Colors.white : Colors.white.withOpacity(.7), borderColor: Colors.grey, showBorder: true, child: Padding( - padding: EdgeInsets.fromLTRB(20, 10, 20, 10), + padding: EdgeInsets.fromLTRB(5, 15, 5, 15), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -705,13 +762,14 @@ class _ConfirmLogin extends State { }) }, child: RoundedContainer( + height: 140, backgroundColor: BiometricType.fingerprint.index == 1 ? Colors.white : Colors.white.withOpacity(.7), borderColor: Colors.grey, showBorder: true, child: Padding( - padding: EdgeInsets.fromLTRB(0, 0, 0, 5), + padding: EdgeInsets.fromLTRB(5, 15, 5, 15), child: Column( children: [ Image.asset( @@ -719,9 +777,13 @@ class _ConfirmLogin extends State { height: SizeConfig.imageSizeMultiplier * 13, width: SizeConfig.imageSizeMultiplier * 16, ), - SizedBox( - height: 20, - ), + projectViewModel.isArabic + ? SizedBox( + height: 15, + ) + : SizedBox( + height: 10, + ), AppText( TranslationBase.of(context).moreVerification, fontSize: SizeConfig.textMultiplier * 2, diff --git a/lib/pages/login/login-type.dart b/lib/pages/login/login-type.dart index dcd58b9d..69a66d9e 100644 --- a/lib/pages/login/login-type.dart +++ b/lib/pages/login/login-type.dart @@ -14,159 +14,168 @@ class LoginType extends StatelessWidget { @override Widget build(BuildContext context) { return AppScaffold( - appBarTitle: TranslationBase.of(context).login, + appBarTitle: TranslationBase.of(context).login, isShowAppBar: true, isShowDecPage: false, - body: Padding( - padding: EdgeInsets.all(20), - child: Column( - children: [ - Expanded( - flex: 4, - child: Column( - // mainAxisAlignment: MainAxisAlignment.spaceEvenly, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Image.asset( - 'assets/images/DQ/dq_logo_icon.png', - height: 90, - width: 90, - ), - AppText( - TranslationBase.of(context).logintypeRadio, - fontSize: SizeConfig.textMultiplier * 3.5, - textAlign: TextAlign.start, - marginBottom: 20.0, - marginTop: 20.0, - ), - Row( - mainAxisAlignment: MainAxisAlignment.center, + body: SingleChildScrollView( + child: Container( + padding: + EdgeInsets.only(top: 10, left: 20, right: 20, bottom: 30), + height: SizeConfig.realScreenHeight * .9, + width: SizeConfig.realScreenWidth, + child: Column( + children: [ + Expanded( + flex: 4, + child: Column( + // mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Expanded( - child: InkWell( - onTap: () => { - LoginType.loginType = 1, - Navigator.of(context) - .pushNamed(LOGIN_PAGE) - }, - child: RoundedContainer( - borderColor: Colors.grey, - showBorder: true, - child: Padding( - padding: EdgeInsets.fromLTRB( - 20, 10, 20, 10), - child: Column( - mainAxisAlignment: - MainAxisAlignment.center, - children: [ - Image.asset( - 'assets/images/id_card_icon.png', - height: SizeConfig - .imageSizeMultiplier * - 12, - width: SizeConfig - .imageSizeMultiplier * - 15, - ), - SizedBox( - height: 20, + Image.asset( + 'assets/images/DQ/logo.png', + height: 90, + width: 90, + ), + AppText( + TranslationBase.of(context).logintypeRadio, + fontSize: SizeConfig.textMultiplier * 3.5, + textAlign: TextAlign.start, + marginBottom: 20.0, + marginTop: 20.0, + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: InkWell( + onTap: () => { + LoginType.loginType = 1, + Navigator.of(context) + .pushNamed(LOGIN_PAGE) + }, + child: RoundedContainer( + borderColor: Colors.grey, + showBorder: true, + child: Padding( + padding: EdgeInsets.fromLTRB( + 20, 10, 20, 10), + child: Column( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Image.asset( + 'assets/images/id_card_icon.png', + height: SizeConfig + .imageSizeMultiplier * + 12, + width: SizeConfig + .imageSizeMultiplier * + 15, + ), + SizedBox( + height: 20, + ), + AppText( + TranslationBase.of(context) + .idNo, + fontSize: SizeConfig + .textMultiplier * + 2, + fontWeight: FontWeight.bold, + ) + ], ), - AppText( - TranslationBase.of(context) - .idNo, - fontSize: - SizeConfig.textMultiplier * + )))), + Expanded( + child: InkWell( + onTap: () => { + LoginType.loginType = 2, + Navigator.of(context) + .pushNamed(LOGIN_PAGE) + }, + child: RoundedContainer( + borderColor: Colors.grey, + showBorder: true, + child: Padding( + padding: EdgeInsets.fromLTRB( + 25, 10, 25, 10), + child: Column( + children: [ + Image.asset( + 'assets/images/my_file_white_icon.png', + height: SizeConfig + .imageSizeMultiplier * + 12, + width: SizeConfig + .imageSizeMultiplier * + 15, + ), + SizedBox( + height: 20, + ), + AppText( + TranslationBase.of(context) + .fileNo, + fontSize: SizeConfig + .textMultiplier * 2, - fontWeight: FontWeight.bold, - ) - ], - ), - )))), - Expanded( + fontWeight: FontWeight.bold, + ) + ], + ), + )))) + ], + ), + SizedBox( + height: 25, + ), + Divider( + color: Colors.grey, + height: 2, + ), + Center( child: InkWell( onTap: () => { - LoginType.loginType = 2, Navigator.of(context) - .pushNamed(LOGIN_PAGE) + .pushNamed(FORGOT_PASSWORD) }, - child: RoundedContainer( - borderColor: Colors.grey, - showBorder: true, - child: Padding( - padding: EdgeInsets.fromLTRB( - 25, 10, 25, 10), - child: Column( - children: [ - Image.asset( - 'assets/images/my_file_white_icon.png', - height: SizeConfig - .imageSizeMultiplier * - 12, - width: SizeConfig - .imageSizeMultiplier * - 15, - ), - SizedBox( - height: 20, - ), - AppText( - TranslationBase.of(context) - .fileNo, - fontSize: - SizeConfig.textMultiplier * - 2, - fontWeight: FontWeight.bold, - ) - ], - ), - )))) - ], - ), - SizedBox(height: 25,), - Divider( - color: Colors.grey, - height: 2, - ), - Center( - child: InkWell( - onTap: () => { - Navigator.of(context) - .pushNamed(FORGOT_PASSWORD) - }, - child: AppText( - TranslationBase.of(context).forgotPassword, - fontSize: SizeConfig.textMultiplier * 2.5, - marginTop: 20.0, - underline: true))) - ]), - ), - Expanded( - flex: 1, - child: Column( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Divider( - color: Colors.grey, - height: 2, - ), - SizedBox(height: 10,), - Row( + child: AppText( + TranslationBase.of(context) + .forgotPassword, + fontSize: + SizeConfig.textMultiplier * 2.5, + marginTop: 20.0, + underline: true))) + ]), + ), + Expanded( + flex: 1, + child: Column( + mainAxisAlignment: MainAxisAlignment.end, children: [ - - Expanded( - child: DefaultButton( - TranslationBase.of(context).registerNow, - () => { - Navigator.of(context).pushNamed( - REGISTER, - ) - }, - )), + Divider( + color: Colors.grey, + height: 2, + ), + SizedBox( + height: 10, + ), + Row( + children: [ + Expanded( + child: DefaultButton( + TranslationBase.of(context).registerNow, + () => { + Navigator.of(context).pushNamed( + REGISTER, + ) + }, + )), + ], + ), ], - ), - ], - )) - ], - ))); + )) + ], + )))); } } diff --git a/lib/pages/login/login.dart b/lib/pages/login/login.dart index cc1a0350..c2a943d2 100644 --- a/lib/pages/login/login.dart +++ b/lib/pages/login/login.dart @@ -4,6 +4,7 @@ import 'package:diplomaticquarterapp/core/service/AuthenticatedUserObject.dart'; import 'package:diplomaticquarterapp/core/viewModels/appointment_rate_view_model.dart'; import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/locator.dart'; +import 'package:diplomaticquarterapp/models/Appointments/toDoCountProviderModel.dart'; import 'package:diplomaticquarterapp/models/Authentication/check_activation_code_response.dart'; import 'package:diplomaticquarterapp/models/Authentication/check_paitent_authentication_req.dart'; import 'package:diplomaticquarterapp/pages/landing/landing_page.dart'; @@ -11,6 +12,7 @@ import 'package:diplomaticquarterapp/pages/login/login-type.dart'; import 'package:diplomaticquarterapp/pages/rateAppointment/rate_appointment_doctor.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/uitl/app_shared_preferences.dart'; import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; @@ -20,6 +22,7 @@ import 'package:diplomaticquarterapp/widgets/dialogs/confirm_dialog.dart'; import 'package:diplomaticquarterapp/widgets/input/text_field.dart'; import 'package:diplomaticquarterapp/widgets/mobile-no/mobile_no.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:diplomaticquarterapp/widgets/progress_indicator/app_circular_progress_Indeicator.dart'; import 'package:diplomaticquarterapp/widgets/text/app_texts_widget.dart'; import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/cupertino.dart'; @@ -48,6 +51,7 @@ class _Login extends State { locator(); ProjectViewModel projectViewModel; + ToDoCountProviderModel toDoProvider; @override void initState() { @@ -64,6 +68,7 @@ class _Login extends State { @override Widget build(BuildContext context) { projectViewModel = Provider.of(context); + toDoProvider = Provider.of(context); return AppScaffold( appBarTitle: TranslationBase.of(context).login, isShowAppBar: true, @@ -87,14 +92,12 @@ class _Login extends State { child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - MobileNo( - onNumberChange: (value) => - {mobileNo = value, validateForm()}, - onCountryChange: (value) => countryCode = value), + MobileNo(onNumberChange: (value) => {mobileNo = value, validateForm()}, onCountryChange: (value) => countryCode = value), Directionality( textDirection: TextDirection.ltr, child: Container( child: TextFields( + keyboardType: TextInputType.number, fontWeight: FontWeight.normal, controller: nationalIDorFile, onChanged: (value) => {validateForm()}, @@ -153,18 +156,14 @@ class _Login extends State { } void validateForm() { - //TODO fix login - if (util.validateIDBox(nationalIDorFile.text, loginType) == - true /*&& - mobileNo.length >= 9 */ - && + if (util.validateIDBox(nationalIDorFile.text, loginType) == true && util.isSAUDIIDValid(nationalIDorFile.text, loginType) == true) { setState(() { isButtonDisabled = false; }); } else { setState(() { - isButtonDisabled = false; + isButtonDisabled = true; }); } } @@ -240,23 +239,27 @@ class _Login extends State { request['PatientID'] = int.parse(nationalIDorFile.text); } // request.isRegister = false; - this.authService.checkActivationCode(request, code).then((result) => { - sharedPref.remove(FAMILY_FILE), - projectViewModel.setPrivilege(privilegeList: result), - result = CheckActivationCode.fromJson(result), - result.list.isFamily = false, - this.sharedPref.setObject(USER_PROFILE, result.list), - this.sharedPref.setObject(MAIN_USER, result.list), - this.sharedPref.setObject(LOGIN_TOKEN_ID, result.logInTokenID), - this.sharedPref.setString(TOKEN, result.authenticationTokenID), - authenticatedUserObject.getUser(), - // authenticatedUserObject.user = AuthenticatedUser.fromJson(result.list), - authenticatedUserObject.isLogin = true, - appointmentRateViewModel.isLogin = true, - projectViewModel.isLogin = true, + this.authService.checkActivationCode(request, code).then((result) async { + sharedPref.remove(FAMILY_FILE); + // Register GeoZones after login + registerGeoZones(); + projectViewModel.setPrivilege(privilegeList: result); + result = CheckActivationCode.fromJson(result); + result.list.isFamily = false; + // this.sharedPref.setString(BLOOD_TYPE, result['PatientBloodType']), + this.sharedPref.setObject(USER_PROFILE, result.list); + this.sharedPref.setObject(MAIN_USER, result.list); + this.sharedPref.setObject(LOGIN_TOKEN_ID, result.logInTokenID); + this.sharedPref.setString(TOKEN, result.authenticationTokenID); + await authenticatedUserObject.getUser(getUser: true); + authenticatedUserObject.isLogin = true; + appointmentRateViewModel.isLogin = true; + projectViewModel.isLogin = true; + projectViewModel.user = authenticatedUserObject.user; appointmentRateViewModel .getIsLastAppointmentRatedList() .then((value) => { + getToDoCount(), GifLoaderDialogUtils.hideDialog(context), if (appointmentRateViewModel.isHaveAppointmentNotRate) { @@ -280,11 +283,28 @@ class _Login extends State { .catchError((err) { print(err); GifLoaderDialogUtils.hideDialog(context); - }), - // SMSOTP.showLoadingDialog(context, false), + }); + }); } + getToDoCount() { + toDoProvider.setState(0, true); + ClinicListService service = new ClinicListService(); + service.getActiveAppointmentNo(context).then((res) { + print(res['AppointmentActiveNumber']); + if (res['MessageStatus'] == 1) { + toDoProvider.setState(res['AppointmentActiveNumber'], true); + } else {} + }).catchError((err) { + print(err); + }); + } + + void registerGeoZones() { + projectViewModel.platformBridge().registerHmgGeofences(); + } + // showLoader(bool isTrue) { // setState(() { // isLoading = isTrue; diff --git a/lib/pages/login/register-info.dart b/lib/pages/login/register-info.dart index 4ede2683..467068cc 100644 --- a/lib/pages/login/register-info.dart +++ b/lib/pages/login/register-info.dart @@ -1,9 +1,5 @@ import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/config/size_config.dart'; -import 'package:diplomaticquarterapp/core/service/AuthenticatedUserObject.dart'; -import 'package:diplomaticquarterapp/core/viewModels/appointment_rate_view_model.dart'; -import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; -import 'package:diplomaticquarterapp/locator.dart'; import 'package:diplomaticquarterapp/models/Authentication/check_paitent_authentication_req.dart'; import 'package:diplomaticquarterapp/models/Authentication/register_info_response.dart'; import 'package:diplomaticquarterapp/models/Authentication/register_user_requet.dart'; @@ -11,7 +7,6 @@ import 'package:diplomaticquarterapp/pages/login/login-type.dart'; import 'package:diplomaticquarterapp/routes.dart'; import 'package:diplomaticquarterapp/services/authentication/auth_provider.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'; @@ -25,7 +20,6 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:hijri/hijri_calendar.dart'; import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; class RegisterInfo extends StatefulWidget { @override @@ -51,11 +45,6 @@ class _RegisterInfo extends State { String email = ''; String location = '1'; - AuthenticatedUserObject authenticatedUserObject = - locator(); - AppointmentRateViewModel appointmentRateViewModel = - locator(); - ProjectViewModel projectViewModel; @override void initState() { @@ -67,7 +56,6 @@ class _RegisterInfo extends State { @override Widget build(BuildContext context) { - projectViewModel = Provider.of(context); return AppScaffold( appBarTitle: TranslationBase.of(context).register, isShowAppBar: true, @@ -308,34 +296,27 @@ class _RegisterInfo extends State { }else { - sharedPref.remove(FAMILY_FILE), - result['List'][0]['IsFamily'] = false, - sharedPref.setObject(USER_PROFILE, result['List'][0]), - this.sharedPref.setObject(MAIN_USER, result['List'][0]), - sharedPref.setObject(LOGIN_TOKEN_ID, result["LogInTokenID"]), - sharedPref.setString(TOKEN, result["AuthenticationTokenID"]), - authenticatedUserObject.isLogin = true, - appointmentRateViewModel.isLogin = true, - projectViewModel.isLogin = true, - - Navigator.of(context).pushNamed(HOME), - AppToast.showSuccessToast(message: result["ErrorEndUserMessage"]) + result.list.isFamily = false, + sharedPref.setObject(USER_PROFILE, result.list), + this.sharedPref.setObject(MAIN_USER, result.list), + sharedPref.setObject(LOGIN_TOKEN_ID, result.logInTokenID), + sharedPref.setString(TOKEN, result.authenticationTokenID), + Navigator.of(context).pushNamed(HOME) } - }); - // .catchError((err) { - // GifLoaderDialogUtils.hideDialog(context); - // ConfirmDialog dialog = new ConfirmDialog( - // context: context, - // confirmMessage: err, - // okText: TranslationBase.of(context).confirm, - // cancelText: TranslationBase.of(context).cancel_nocaps, - // okFunction: () => { - // ConfirmDialog.closeAlertDialog(context) - // }, - // cancelFunction: () => {ConfirmDialog.closeAlertDialog(context)}); - // dialog.showAlertDialog(context); - // - // }); + }).catchError((err) { + GifLoaderDialogUtils.hideDialog(context); + ConfirmDialog dialog = new ConfirmDialog( + context: context, + confirmMessage: err, + okText: TranslationBase.of(context).confirm, + cancelText: TranslationBase.of(context).cancel_nocaps, + okFunction: () => { + ConfirmDialog.closeAlertDialog(context) + }, + cancelFunction: () => {ConfirmDialog.closeAlertDialog(context)}); + dialog.showAlertDialog(context); + + }); } getRegisterInfo() async { @@ -368,15 +349,15 @@ class _RegisterInfo extends State { "PatientOutSA": registerd_data.zipCode == '966' ? 0 : 1, "FirstNameN":registerInfo.firstNameAr =='-' ?"": registerInfo.firstNameAr, "FirstName": registerInfo.firstNameEn =='-' ?"":registerInfo.firstNameEn, - "MiddleNameN":registerInfo.secondNameAr, - "MiddleName":registerInfo.secondNameEn, + "MiddleNameN":registerInfo.secondNameAr =='-' ? "" : registerInfo.secondNameAr, + "MiddleName":registerInfo.secondNameEn == '-' ? "": registerInfo.secondNameEn, "LastNameN": registerInfo.lastNameAr =='-'? "" : registerInfo.lastNameAr, "LastName": registerInfo.lastNameEn =='-' ? "": registerInfo.lastNameEn, "StrDateofBirth": registerInfo.dateOfBirth, "DateofBirth": DateUtil.convertISODateToJsonDate( registerInfo.dateOfBirth.replaceAll('/', '-')), "Gender": registerInfo.gender == 'M' ? 1 : 2, - "NationalityID": registerInfo.nationalityCode, + "NationalityID": registerInfo.nationality, "DateofBirthN": date, "EmailAddress": email, "SourceType": location, @@ -393,8 +374,8 @@ class _RegisterInfo extends State { } bool isValid() { - if (location != null && - language != null && + if (location != null || + language != null || Utils.validEmail(email) == true) { return true; } else { diff --git a/lib/pages/login/register.dart b/lib/pages/login/register.dart index 9245d6c3..131db748 100644 --- a/lib/pages/login/register.dart +++ b/lib/pages/login/register.dart @@ -72,113 +72,113 @@ class _Register extends State { onNumberChange: (value) => {mobileNo = value, validateForm()}, onCountryChange: (value) => countryCode = value), - Directionality( - textDirection:TextDirection.ltr,child:Container( - child: TextFields( - controller: nationalIDorFile, - onChanged: (value) => validateForm(), - prefixIcon: - Icon(Icons.chrome_reader_mode, color: Color(0xFF40ACC9)), - padding: EdgeInsets.only( - top: 20, bottom: 20, left: 10, right: 10), - hintText: TranslationBase.of(context).nationalID, - ))), - Row( + Container( + child: TextFields( + controller: nationalIDorFile, + onChanged: (value) => validateForm(), + keyboardType: TextInputType.number, + prefixIcon: Icon(Icons.chrome_reader_mode, + color: Color(0xFF40ACC9)), + padding: EdgeInsets.only( + top: 20, bottom: 20, left: 10, right: 10), + hintText: TranslationBase.of(context).nationalID, + )), + Row( + children: [ + Expanded( + child: Row( children: [ - Expanded( - child: Row( - children: [ - Radio( - value: 1, - groupValue: isHijri, - onChanged: (value) { - setState(() { - isHijri = value; - }); - validateForm(); - }, - ), - Text(TranslationBase.of(context).hijriDate), - ], - ), + Radio( + value: 1, + groupValue: isHijri, + onChanged: (value) { + setState(() { + isHijri = value; + }); + validateForm(); + }, ), - Expanded( - child: Row( - children: [ - Radio( - value: 0, - groupValue: isHijri, - onChanged: (value) { - setState(() { - isHijri = value; - }); - validateForm(); - }, - ), - Text(TranslationBase.of(context) - .gregorianDate), - ], - ), + Text(TranslationBase.of(context).hijriDate), + ], + ), + ), + Expanded( + child: Row( + children: [ + Radio( + value: 0, + groupValue: isHijri, + onChanged: (value) { + setState(() { + isHijri = value; + }); + validateForm(); + }, ), + Text(TranslationBase.of(context).gregorianDate), ], ), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Container( + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Container( width: SizeConfig.realScreenWidth * .9, - height:60, - child: isHijri == 1 - ? TextFields( - onChanged: (value) => {dob = value}, - hintText: 'DD/MM/YYYY', - prefixIcon: Icon(Icons.date_range), - ) - : RaisedButton.icon( - shape: RoundedRectangleBorder( + height: 60, + child: isHijri == 1 + ? TextFields( + onChanged: (value) => {dob = value}, + hintText: 'DD/MM/YYYY', + prefixIcon: Icon(Icons.date_range), + ) + : RaisedButton.icon( + shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(15.0), - - ), - color:Colors.white, - onPressed: () => { - if (isHijri != null) - _selectDate(context) - }, - icon: Icon(Icons.date_range), - label: Text(selectedDate != null - ? "${selectedDate.toLocal()}" - .split(' ')[0] - : TranslationBase.of(context).dob))) - ]) + ), + color: Colors.white, + onPressed: () => { + if (isHijri != null) + _selectDate(context) + }, + icon: Icon(Icons.date_range), + label: Text(selectedDate != null + ? "${selectedDate.toLocal()}" + .split(' ')[0] + : TranslationBase.of(context).dob))) + ]) + ], + ), + ), + Expanded( + flex: 2, + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Divider( + color: Colors.grey, + height: 2, + ), + SizedBox( + height: 10, + ), + Row( + children: [ + Expanded( + child: DefaultButton( + TranslationBase.of(context).registerNow, + () => {startRegistration()}, + textColor: Colors.white, + color: isButtonDisabled == true + ? Colors.grey + : Colors.grey[900])) ], ), - ), - Expanded( - flex: 2, - child: Column( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Divider( - color: Colors.grey, - height: 2, - ), - SizedBox(height: 10,), - Row( - children: [ - Expanded( - child: DefaultButton( - TranslationBase.of(context).registerNow, - () => {startRegistration()}, - textColor: Colors.white, - color: isButtonDisabled == true - ? Colors.grey - : Colors.grey[900])) - ], - ), - ], - )) - ]), - ))); + ], + )) + ]), + ))); } Future _selectDate(BuildContext context) async { @@ -216,7 +216,8 @@ class _Register extends State { this .authService .checkPatientForRegisteration(request) - .then((response) => {checkUserStatus(response, request)}).catchError((err) { + .then((response) => {checkUserStatus(response, request)}) + .catchError((err) { GifLoaderDialogUtils.hideDialog(context); ConfirmDialog dialog = new ConfirmDialog( context: context, @@ -224,15 +225,13 @@ class _Register extends State { okText: TranslationBase.of(context).confirm, cancelText: TranslationBase.of(context).cancel_nocaps, okFunction: () => { - ConfirmDialog.closeAlertDialog(context), - Navigator.of(context).pushNamed( - REGISTER, - ), - - }, + ConfirmDialog.closeAlertDialog(context), + Navigator.of(context).pushNamed( + REGISTER, + ), + }, cancelFunction: () => {ConfirmDialog.closeAlertDialog(context)}); dialog.showAlertDialog(context); - }); } @@ -257,7 +256,7 @@ class _Register extends State { var nRequest = request.toJson(); nRequest['LogInTokenID'] = response['LogInTokenID']; if (response['hasFile'] == true) { - // AppToast.showErrorToast(message: response['ErrorEndUserMessage']); + // AppToast.showErrorToast(message: response['ErrorEndUserMessage']); AlertDialogBox( context: context, confirmMessage: response['ErrorEndUserMessage'], @@ -308,7 +307,7 @@ class _Register extends State { request.isHijri = isHijri; request.patientOutSA = countryCode == '966' ? 0 : 1; this.authService.checkUserStatus(request).then((result) => { - GifLoaderDialogUtils.hideDialog(context), + GifLoaderDialogUtils.hideDialog(context), if (result is Map) { result = CheckUserStatusResponse.fromJson(result), diff --git a/lib/pages/login/welcome.dart b/lib/pages/login/welcome.dart index 419df302..4b8e90ae 100644 --- a/lib/pages/login/welcome.dart +++ b/lib/pages/login/welcome.dart @@ -3,6 +3,7 @@ import 'package:diplomaticquarterapp/routes.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:eva_icons_flutter/eva_icons_flutter.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -36,7 +37,7 @@ class _WelcomeLogin extends State { mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Image.asset('assets/images/DQ/dq_logo_icon.png', + Image.asset('assets/images/DQ/logo.png', height: 90, width: 90), Text( TranslationBase.of(context).welcome, @@ -75,7 +76,7 @@ class _WelcomeLogin extends State { LOGIN_TYPE, ), }, - color: Color(0xFF40ACC9), + color: Color(0xFFc5272c), textColor: Colors.white, )) ], diff --git a/lib/pages/medical/ask_doctor/ask_doctor_home_page.dart b/lib/pages/medical/ask_doctor/ask_doctor_home_page.dart index 5f1938fd..902225b1 100644 --- a/lib/pages/medical/ask_doctor/ask_doctor_home_page.dart +++ b/lib/pages/medical/ask_doctor/ask_doctor_home_page.dart @@ -77,8 +77,6 @@ class _AskDoctorHomPageState extends State isScrollable: true, controller: _tabController, indicatorWeight: 5.0, - //indicatorSize: TabBarIndicatorSize.label, - indicatorColor: Colors.red[800], labelColor: Theme.of(context).primaryColor, labelPadding: EdgeInsets.only(top: 4.0, left: 18.0, right: 18.0), unselectedLabelColor: Colors.grey[800], diff --git a/lib/pages/medical/ask_doctor/ask_doctor_page.dart b/lib/pages/medical/ask_doctor/ask_doctor_page.dart index e6172b7a..6beed0dc 100644 --- a/lib/pages/medical/ask_doctor/ask_doctor_page.dart +++ b/lib/pages/medical/ask_doctor/ask_doctor_page.dart @@ -1,5 +1,7 @@ import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; import 'package:diplomaticquarterapp/core/viewModels/medical/ask_doctor_view_model.dart'; +import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart'; +import 'package:diplomaticquarterapp/pages/BookAppointment/widgets/DoctorView.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; import 'package:diplomaticquarterapp/pages/medical/ask_doctor/request_type.dart'; import 'package:diplomaticquarterapp/uitl/app_toast.dart'; @@ -10,6 +12,7 @@ import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:rating_bar/rating_bar.dart'; +import 'package:smart_progress_bar/smart_progress_bar.dart'; class AskDoctorPage extends StatelessWidget { @override diff --git a/lib/pages/medical/balance/advance_payment_page.dart b/lib/pages/medical/balance/advance_payment_page.dart index 85a0cc8f..fce664f7 100644 --- a/lib/pages/medical/balance/advance_payment_page.dart +++ b/lib/pages/medical/balance/advance_payment_page.dart @@ -20,6 +20,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:smart_progress_bar/smart_progress_bar.dart'; import '../../../core/model/my_balance/AdvanceModel.dart'; import 'confirm_payment_page.dart'; @@ -214,6 +215,7 @@ class _AdvancePaymentPageState extends State { SizedBox( height: 12, ), + if(model.user!=null) NewTextFields( hintText: TranslationBase.of(context).depositorEmail, initialValue: model.user.emailAddress, @@ -236,15 +238,13 @@ class _AdvancePaymentPageState extends State { ), ), bottomSheet: Container( - height: MediaQuery.of(context).size.height * 0.1, + height: MediaQuery.of(context).size.height * 0.10, width: double.infinity, - padding: EdgeInsets.all(12), + padding: EdgeInsets.all(18), child: SecondaryButton( textColor: Colors.white, label: TranslationBase.of(context).submit, - disabled: amount.isEmpty || - _fileTextController.text.isEmpty || - _selectedHospital == null, + disabled: amount.isEmpty || _fileTextController.text.isEmpty || _selectedHospital == null, onTap: () { var mobileNum; var patientName; diff --git a/lib/pages/medical/balance/confirm_payment_page.dart b/lib/pages/medical/balance/confirm_payment_page.dart index 679a16db..8a69bf5d 100644 --- a/lib/pages/medical/balance/confirm_payment_page.dart +++ b/lib/pages/medical/balance/confirm_payment_page.dart @@ -156,11 +156,12 @@ class ConfirmPaymentPage extends StatelessWidget { ), ), bottomSheet: Container( - height: MediaQuery.of(context).size.height * 0.1, + height: MediaQuery.of(context).size.height * 0.13, width: double.infinity, padding: EdgeInsets.all(12), child: SecondaryButton( textColor: Colors.white, + color: Theme.of(context).primaryColor, label: TranslationBase.of(context).confirm.toUpperCase(), disabled: model.state == ViewState.Busy, onTap: () { diff --git a/lib/pages/medical/balance/dialogs/ConfirmSMSDialog.dart b/lib/pages/medical/balance/dialogs/ConfirmSMSDialog.dart index 10d61f68..380f250c 100644 --- a/lib/pages/medical/balance/dialogs/ConfirmSMSDialog.dart +++ b/lib/pages/medical/balance/dialogs/ConfirmSMSDialog.dart @@ -175,7 +175,7 @@ class _ConfirmSMSDialogState extends State { fontSize: SizeConfig.textMultiplier * 3, ), focusNode: focusD1, - maxLength: 1, + //maxLength: 1, controller: digit1, textAlign: TextAlign.center, keyboardType: TextInputType.number, @@ -200,7 +200,7 @@ class _ConfirmSMSDialogState extends State { focusNode: focusD2, controller: digit2, textInputAction: TextInputAction.next, - maxLength: 1, + //maxLength: 1, textAlign: TextAlign.center, style: TextStyle( fontSize: SizeConfig.textMultiplier * 3, @@ -227,7 +227,7 @@ class _ConfirmSMSDialogState extends State { focusNode: focusD3, controller: digit3, textInputAction: TextInputAction.next, - maxLength: 1, + //maxLength: 1, textAlign: TextAlign.center, style: TextStyle( fontSize: SizeConfig.textMultiplier * 3, @@ -253,7 +253,7 @@ class _ConfirmSMSDialogState extends State { child: TextFormField( focusNode: focusD4, controller: digit4, - maxLength: 1, + // maxLength: 1, textAlign: TextAlign.center, style: TextStyle( fontSize: SizeConfig.textMultiplier * 3, diff --git a/lib/pages/medical/balance/dialogs/SelectBeneficiaryDialog.dart b/lib/pages/medical/balance/dialogs/SelectBeneficiaryDialog.dart index b004bc38..d7ce3fac 100644 --- a/lib/pages/medical/balance/dialogs/SelectBeneficiaryDialog.dart +++ b/lib/pages/medical/balance/dialogs/SelectBeneficiaryDialog.dart @@ -3,6 +3,7 @@ import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import '../../../../Constants.dart'; import '../advance_payment_page.dart'; class SelectBeneficiaryDialog extends StatefulWidget { @@ -45,7 +46,7 @@ class _SelectBeneficiaryDialogState extends State { leading: Radio( value: BeneficiaryType.MyAccount, groupValue: beneficiaryType, - activeColor: Color(0xFF40ACC9), + activeColor: secondaryColor, onChanged: (BeneficiaryType value) { setState(() { beneficiaryType = value; diff --git a/lib/pages/medical/balance/dialogs/SelectHospitalDialog.dart b/lib/pages/medical/balance/dialogs/SelectHospitalDialog.dart index 42bd66b7..a9a4fea2 100644 --- a/lib/pages/medical/balance/dialogs/SelectHospitalDialog.dart +++ b/lib/pages/medical/balance/dialogs/SelectHospitalDialog.dart @@ -4,6 +4,8 @@ import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import '../../../../Constants.dart'; + class SelectHospitalDialog extends StatefulWidget { final List hospitals; final Function(HospitalsModel) onValueSelected; @@ -54,7 +56,7 @@ class _SelectHospitalDialogState extends State { leading: Radio( value: widget.hospitals[index], groupValue: widget.selectedHospital, - activeColor: Color(0xFF40ACC9), + activeColor: secondaryColor, onChanged: (value) { setState(() { widget.selectedHospital = value; diff --git a/lib/pages/medical/balance/dialogs/SelectPatientFamilyDialog.dart b/lib/pages/medical/balance/dialogs/SelectPatientFamilyDialog.dart index 7d69f084..ab2b48d5 100644 --- a/lib/pages/medical/balance/dialogs/SelectPatientFamilyDialog.dart +++ b/lib/pages/medical/balance/dialogs/SelectPatientFamilyDialog.dart @@ -4,6 +4,8 @@ import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import '../../../../Constants.dart'; + class SelectPatientFamilyDialog extends StatefulWidget { final List getAllSharedRecordsByStatusList; final Function(GetAllSharedRecordsByStatusList) onValueSelected; @@ -35,11 +37,9 @@ class _SelectPatientFamilyDialogState extends State { (index) => Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - if(widget.getAllSharedRecordsByStatusList[index].status==3) SizedBox( height: 2, ), - if(widget.getAllSharedRecordsByStatusList[index].status==3) Row( children: [ Expanded( @@ -55,7 +55,7 @@ class _SelectPatientFamilyDialogState extends State { leading: Radio( value: widget.getAllSharedRecordsByStatusList[index], groupValue: widget.selectedPatientFamily, - activeColor: Colors.red[800], + activeColor: secondaryColor, onChanged: (value) { setState(() { widget.selectedPatientFamily = value; @@ -67,8 +67,6 @@ class _SelectPatientFamilyDialogState extends State { ) ], ), - if(widget.getAllSharedRecordsByStatusList[index].status==3) - SizedBox( height: 5.0, ), diff --git a/lib/pages/medical/balance/dialogs/SelectPatientInfoDialog.dart b/lib/pages/medical/balance/dialogs/SelectPatientInfoDialog.dart index bea4f694..3cce8e61 100644 --- a/lib/pages/medical/balance/dialogs/SelectPatientInfoDialog.dart +++ b/lib/pages/medical/balance/dialogs/SelectPatientInfoDialog.dart @@ -6,6 +6,8 @@ import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import '../../../../Constants.dart'; + class SelectPatientInfoDialog extends StatefulWidget { final List patientInfoList ; final Function(PatientInfo) onValueSelected; @@ -55,7 +57,7 @@ class _SelectPatientInfoDialogState extends State { leading: Radio( value: widget.patientInfoList[index], groupValue: widget.selectedPatientInfo, - activeColor: Colors.red[800], + activeColor: secondaryColor, onChanged: (value) { setState(() { widget.selectedPatientInfo = value; diff --git a/lib/pages/medical/balance/my_balance_page.dart b/lib/pages/medical/balance/my_balance_page.dart index 2fb8c51c..1edbcbf6 100644 --- a/lib/pages/medical/balance/my_balance_page.dart +++ b/lib/pages/medical/balance/my_balance_page.dart @@ -27,54 +27,26 @@ class MyBalancePage extends StatelessWidget { appBarTitle: TranslationBase.of(context).myBalances, imagesInfo: imagesInfo, description: TranslationBase.of(context).infoMyBalance, - body: Container( - margin: EdgeInsets.all(12), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Texts( - TranslationBase.of(context).balanceAmount, - color: Colors.black, - bold: true, - ), - SizedBox( - height: 15, - ), - Container( - padding: EdgeInsets.all(8), - width: double.infinity, - height: 65, - decoration: BoxDecoration( - color: HexColor('#B61422'), - shape: BoxShape.rectangle, - borderRadius: BorderRadius.circular(7), + body: SingleChildScrollView( + child: Container( + margin: EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Texts( + TranslationBase.of(context).balanceAmount, + color: Colors.black, + bold: true, ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Texts( - TranslationBase.of(context).totalBalance, - color: Colors.white, - ), - Texts( - '${model.totalAdvanceBalanceAmount ?? 0} '+ TranslationBase.of(context).sar, - color: Colors.white, - bold: true, - ), - ], + SizedBox( + height: 15, ), - ), - SizedBox( - height: 9, - ), - ...List.generate( - model.patientAdvanceBalanceAmountList.length, - (index) => Container( + Container( padding: EdgeInsets.all(8), + width: double.infinity, height: 65, - margin: EdgeInsets.only(top: 8), decoration: BoxDecoration( - color: Colors.white, + color: Theme.of(context).primaryColor, shape: BoxShape.rectangle, borderRadius: BorderRadius.circular(7), ), @@ -83,20 +55,53 @@ class MyBalancePage extends StatelessWidget { children: [ Texts( - '${model.patientAdvanceBalanceAmountList[index].patientAdvanceBalanceAmount} '+TranslationBase.of(context).sar, + '${model.totalAdvanceBalanceAmount ?? 0} '+ TranslationBase.of(context).sar, + color: Colors.white, bold: true, ), - Texts(model.patientAdvanceBalanceAmountList[index] - .projectDescription), + Texts( + TranslationBase.of(context).totalBalance, + color: Colors.white, + ), ], ), ), - ), - ], + SizedBox( + height: 9, + ), + ...List.generate( + model.patientAdvanceBalanceAmountList.length, + (index) => Container( + padding: EdgeInsets.all(8), + height: 65, + margin: EdgeInsets.only(top: 8), + decoration: BoxDecoration( + color: Colors.white, + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(7), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + + Texts( + '${model.patientAdvanceBalanceAmountList[index].patientAdvanceBalanceAmount} '+TranslationBase.of(context).sar, + bold: true, + ), + Texts(model.patientAdvanceBalanceAmountList[index] + .projectDescription), + ], + ), + ), + ), + SizedBox(height: MediaQuery.of(context).size.height * 0.13 ,) + ], + ), ), ), bottomSheet: Container( - height: MediaQuery.of(context).size.height * 0.1, + height: MediaQuery.of(context).size.height * 0.12, + color: Colors.white, width: double.infinity, padding: EdgeInsets.all(12), child: SecondaryButton( diff --git a/lib/pages/medical/doctor/doctor_home_page.dart b/lib/pages/medical/doctor/doctor_home_page.dart index 6a03b58b..c8fad3ce 100644 --- a/lib/pages/medical/doctor/doctor_home_page.dart +++ b/lib/pages/medical/doctor/doctor_home_page.dart @@ -48,7 +48,6 @@ class DoctorHomePage extends StatelessWidget { leading: Radio( value: FilterType.Clinic, groupValue: model.filterType, - activeColor: Colors.red[800], onChanged: (FilterType value) { model.setFilterType(value); }, @@ -65,7 +64,6 @@ class DoctorHomePage extends StatelessWidget { leading: Radio( value: FilterType.Hospital, groupValue: model.filterType, - activeColor: Colors.red[800], onChanged: (FilterType value) => model.setFilterType(value), ), diff --git a/lib/pages/medical/eye/EyeHomePage.dart b/lib/pages/medical/eye/EyeHomePage.dart index 18cc9b77..bce778b8 100644 --- a/lib/pages/medical/eye/EyeHomePage.dart +++ b/lib/pages/medical/eye/EyeHomePage.dart @@ -74,8 +74,7 @@ class _EyeHomePageState extends State isScrollable: true, controller: _tabController, indicatorWeight: 5.0, - indicatorSize: TabBarIndicatorSize.label, - indicatorColor: Colors.red[800], + indicatorSize: TabBarIndicatorSize.tab, labelColor: Theme.of(context).primaryColor, labelPadding: EdgeInsets.only(top: 4.0, left: 5.0, right: 5.0), diff --git a/lib/pages/medical/labs/laboratory_result_page.dart b/lib/pages/medical/labs/laboratory_result_page.dart index 9b1f5a26..a251a1ce 100644 --- a/lib/pages/medical/labs/laboratory_result_page.dart +++ b/lib/pages/medical/labs/laboratory_result_page.dart @@ -1,37 +1,50 @@ import 'package:diplomaticquarterapp/core/model/labs/patient_lab_orders.dart'; import 'package:diplomaticquarterapp/core/viewModels/medical/labs_view_model.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; -import 'package:diplomaticquarterapp/widgets/data_display/medical/laboratory_result_widget.dart'; +import 'package:diplomaticquarterapp/uitl/utils.dart'; +import 'package:diplomaticquarterapp/widgets/data_display/medical/LabResult/laboratory_result_widget.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -class LaboratoryResultPage extends StatelessWidget { +class LaboratoryResultPage extends StatefulWidget { final PatientLabOrders patientLabOrders; LaboratoryResultPage({Key key, this.patientLabOrders}); + @override + _LaboratoryResultPageState createState() => _LaboratoryResultPageState(); +} + +class _LaboratoryResultPageState extends State { + + @override Widget build(BuildContext context) { return BaseView( onModelReady: (model) => model.getLaboratoryResult( - invoiceNo: patientLabOrders.invoiceNo, - clinicID: patientLabOrders.clinicID, - projectID: patientLabOrders.projectID, - orderNo: patientLabOrders.orderNo), - builder: (_, model, widget) => AppScaffold( + invoiceNo: widget.patientLabOrders.invoiceNo, + clinicID: widget.patientLabOrders.clinicID, + projectID: widget.patientLabOrders.projectID, + orderNo: widget.patientLabOrders.orderNo), + builder: (_, model, w) => AppScaffold( isShowAppBar: true, appBarTitle: TranslationBase.of(context).labResults, baseViewModel: model, body: Scaffold( body: ListView.builder( itemBuilder: (context, index) => LaboratoryResultWidget( - onTap: () => model.sendLabReportEmail(patientLabOrder: patientLabOrders), - billNo: patientLabOrders.invoiceNo, + onTap: ()async { + GifLoaderDialogUtils.showMyDialog(context); + await model.sendLabReportEmail(patientLabOrder: widget.patientLabOrders,mes: TranslationBase.of(context).sendSuc); + GifLoaderDialogUtils.hideDialog(context); + }, + billNo: widget.patientLabOrders.invoiceNo, details: model.patientLabSpecialResult[index].resultDataHTML, - orderNo: patientLabOrders.orderNo, - patientLabOrder: patientLabOrders, + orderNo: widget.patientLabOrders.orderNo, + patientLabOrder: widget.patientLabOrders, ), itemCount: model.patientLabSpecialResult.length, ), diff --git a/lib/pages/medical/labs/labs_home_page.dart b/lib/pages/medical/labs/labs_home_page.dart index 4b412f5b..ce78a7dc 100644 --- a/lib/pages/medical/labs/labs_home_page.dart +++ b/lib/pages/medical/labs/labs_home_page.dart @@ -1,6 +1,7 @@ import 'package:diplomaticquarterapp/core/enum/filter_type.dart'; import 'package:diplomaticquarterapp/core/model/ImagesInfo.dart'; import 'package:diplomaticquarterapp/core/viewModels/medical/labs_view_model.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; @@ -10,6 +11,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 'laboratory_result_page.dart'; @@ -18,6 +20,7 @@ class LabsHomePage extends StatelessWidget { @override Widget build(BuildContext context) { + ProjectViewModel projectViewModel = Provider.of(context); imagesInfo.add(ImagesInfo(imageEn: 'https://hmgwebservices.com/Images/MobileApp/imges-info/my-lab/en/0.png',imageAr: 'https://hmgwebservices.com/Images/MobileApp/imges-info/my-lab/ar/0.png')); return BaseView( onModelReady: (model) => model.getLabs(), @@ -45,7 +48,6 @@ class LabsHomePage extends StatelessWidget { leading: Radio( value: FilterType.Clinic, groupValue: model.filterType, - activeColor: Theme.of(context).primaryColor, onChanged: (FilterType value) { model.setFilterType(value); }, @@ -62,7 +64,6 @@ class LabsHomePage extends StatelessWidget { leading: Radio( value: FilterType.Hospital, groupValue: model.filterType, - activeColor: Theme.of(context).primaryColor, onChanged: (FilterType value) => model.setFilterType(value), ), @@ -91,10 +92,11 @@ class LabsHomePage extends StatelessWidget { ), ),isInOutPatient: labOrder.isInOutPatient, name: labOrder.doctorName, + billNo: ' ${labOrder.invoiceNo}', profileUrl: labOrder.doctorImageURL, - subName: TranslationBase.of(context).billNo+' ${labOrder.invoiceNo}', - date: DateUtil.getMonthDayYearDateFormatted( - labOrder.orderDate), + subName: labOrder.projectName, + isLiveCareAppointment: labOrder.isLiveCareAppointment, + date: projectViewModel.isArabic?DateUtil.getMonthDayYearDateFormattedAr(labOrder.orderDate):DateUtil.getMonthDayYearDateFormatted(labOrder.orderDate), ); }).toList(), ), diff --git a/lib/pages/medical/medical_profile_page.dart b/lib/pages/medical/medical_profile_page.dart index 73e60ce6..f56fce76 100644 --- a/lib/pages/medical/medical_profile_page.dart +++ b/lib/pages/medical/medical_profile_page.dart @@ -7,6 +7,9 @@ import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/models/Appointments/toDoCountProviderModel.dart'; import 'package:diplomaticquarterapp/pages/MyAppointments/MyAppointments.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/pages/insurance/insurance_approval_screen.dart'; +import 'package:diplomaticquarterapp/pages/insurance/insurance_card_screen.dart'; +import 'package:diplomaticquarterapp/pages/insurance/insurance_update_screen.dart'; import 'package:diplomaticquarterapp/pages/medical/patient_sick_leave_page.dart'; import 'package:diplomaticquarterapp/pages/medical/reports/monthly_reports.dart'; import 'package:diplomaticquarterapp/pages/medical/smart_watch_health_data/smart_watch_instructions.dart'; @@ -21,6 +24,8 @@ import 'package:diplomaticquarterapp/uitl/utils.dart'; import 'package:diplomaticquarterapp/widgets/data_display/medical/medical_profile_item.dart'; import 'package:diplomaticquarterapp/widgets/data_display/medical/time_line_widget.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; +import 'package:diplomaticquarterapp/widgets/dialogs/alert_dialog.dart'; +import 'package:diplomaticquarterapp/widgets/dialogs/confirm_dialog.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:diplomaticquarterapp/widgets/others/sliver_app_bar_delegate.dart'; import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; @@ -29,6 +34,7 @@ import 'package:flutter/material.dart'; import 'package:diplomaticquarterapp/pages/insurance/insurance_card_screen.dart'; import 'package:provider/provider.dart'; import '../../locator.dart'; +import '../../uitl/gif_loader_dialog_utils.dart'; import 'active_medications/ActiveMedicationsPage.dart'; import 'allergies_page.dart'; import 'ask_doctor/ask_doctor_home_page.dart'; diff --git a/lib/pages/medical/my_trackers/Weight/WeightHomePage.dart b/lib/pages/medical/my_trackers/Weight/WeightHomePage.dart index 8e6f808c..9bd89a2c 100644 --- a/lib/pages/medical/my_trackers/Weight/WeightHomePage.dart +++ b/lib/pages/medical/my_trackers/Weight/WeightHomePage.dart @@ -70,7 +70,7 @@ class _WeightHomePageState extends State isScrollable: true, controller: _tabController, indicatorWeight: 5.0, - indicatorSize: TabBarIndicatorSize.label, + indicatorSize: TabBarIndicatorSize.tab, indicatorColor: Colors.red[800], labelColor: Theme.of(context).primaryColor, labelPadding: diff --git a/lib/pages/medical/my_trackers/blood_pressure/BloodPressureHomePage.dart b/lib/pages/medical/my_trackers/blood_pressure/BloodPressureHomePage.dart index d2bcde47..de8bb509 100644 --- a/lib/pages/medical/my_trackers/blood_pressure/BloodPressureHomePage.dart +++ b/lib/pages/medical/my_trackers/blood_pressure/BloodPressureHomePage.dart @@ -73,8 +73,7 @@ class _BloodPressureHomePageState extends State isScrollable: true, controller: _tabController, indicatorWeight: 5.0, - indicatorSize: TabBarIndicatorSize.label, - indicatorColor: Colors.red[800], + indicatorSize: TabBarIndicatorSize.tab, labelColor: Theme.of(context).primaryColor, labelPadding: EdgeInsets.only(top: 4.0, left: 5.0, right: 5.0), diff --git a/lib/pages/medical/my_trackers/blood_suger/blood_sugar_home_page.dart b/lib/pages/medical/my_trackers/blood_suger/blood_sugar_home_page.dart index c8c7fa4a..71df9a3a 100644 --- a/lib/pages/medical/my_trackers/blood_suger/blood_sugar_home_page.dart +++ b/lib/pages/medical/my_trackers/blood_suger/blood_sugar_home_page.dart @@ -74,8 +74,7 @@ class _BloodSugarHomePageState extends State isScrollable: true, controller: _tabController, indicatorWeight: 5.0, - indicatorSize: TabBarIndicatorSize.label, - indicatorColor: Colors.red[800], + indicatorSize: TabBarIndicatorSize.tab, labelColor: Theme.of(context).primaryColor, labelPadding: EdgeInsets.only(top: 4.0, left: 5.0, right: 5.0), diff --git a/lib/pages/medical/patient_sick_leave_page.dart b/lib/pages/medical/patient_sick_leave_page.dart index 4d561d60..196b5d79 100644 --- a/lib/pages/medical/patient_sick_leave_page.dart +++ b/lib/pages/medical/patient_sick_leave_page.dart @@ -1,11 +1,16 @@ import 'package:diplomaticquarterapp/core/model/ImagesInfo.dart'; +import 'package:diplomaticquarterapp/core/model/sick_leave/sick_leave.dart'; import 'package:diplomaticquarterapp/core/viewModels/medical/patient_sick_leave_view_model.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/data_display/medical/doctor_card.dart'; +import 'package:diplomaticquarterapp/widgets/dialogs/confirm_send_email_dialog.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; class PatientSickLeavePage extends StatefulWidget { @override @@ -14,9 +19,18 @@ class PatientSickLeavePage extends StatefulWidget { class _PatientSickLeavePageState extends State { List imagesInfo = List(); + + @override + void initState() { + imagesInfo.add(ImagesInfo( + imageEn: 'https://hmgwebservices.com/Images/MobileApp/imges-info/sick-leaves/en/0.png', + imageAr: 'https://hmgwebservices.com/Images/MobileApp/imges-info/sick-leaves/ar/0.png')); + super.initState(); + } + @override Widget build(BuildContext context) { - imagesInfo.add(ImagesInfo(imageEn: 'https://hmgwebservices.com/Images/MobileApp/imges-info/sick-leaves/en/0.png',imageAr: 'https://hmgwebservices.com/Images/MobileApp/imges-info/sick-leaves/ar/0.png')); + ProjectViewModel projectViewModel = Provider.of(context); return BaseView( onModelReady: (model) => model.getSickLeave(), builder: (_, model, w) => AppScaffold( @@ -31,23 +45,15 @@ class _PatientSickLeavePageState extends State { child: ListView.builder( itemCount: model.sickLeaveList.length, itemBuilder: (context, index) => DoctorCard( + isLiveCareAppointment: model.sickLeaveList[index].isLiveCareAppointment, name: model.sickLeaveList[index].doctorName, - date: DateUtil.getMonthDayYearDateFormatted( - model.sickLeaveList[index].requestDate), + date:projectViewModel.isArabic? DateUtil.getMonthDayYearDateFormattedAr(model.sickLeaveList[index].requestDate):DateUtil.getMonthDayYearDateFormatted(model.sickLeaveList[index].requestDate), profileUrl: model.sickLeaveList[index].doctorImageURL, rat: model.sickLeaveList[index].actualDoctorRate.toDouble(), subName: model.sickLeaveList[index].projectName, - isInOutPatient: - model.sickLeaveList[index].isInOutPatient, - + isInOutPatient: model.sickLeaveList[index].isInOutPatient, onEmailTap: () { - model.sendSickLeaveEmail( - message: TranslationBase.of(context).emailSentSuccessfully, - requestNo: model.sickLeaveList[index].requestNo, - doctorName: model.sickLeaveList[index].doctorName, - projectName: model.sickLeaveList[index].projectName, - setupID: model.sickLeaveList[index].setupID, - projectID: model.sickLeaveList[index].projectID); + showConfirmMessage(model, index); }, ), ), @@ -55,4 +61,22 @@ class _PatientSickLeavePageState extends State { ), ); } + + void showConfirmMessage(PatientSickLeaveViewMode model, int index) { + showDialog( + context: context, + child: ConfirmSendEmailDialog( + email: model.user.emailAddress, + onTapSendEmail: () { + model.sendSickLeaveEmail( + message: TranslationBase.of(context).emailSentSuccessfully, + requestNo: model.sickLeaveList[index].requestNo, + doctorName: model.sickLeaveList[index].doctorName, + projectName: model.sickLeaveList[index].projectName, + setupID: model.sickLeaveList[index].setupID, + projectID: model.sickLeaveList[index].projectID); + }, + ), + ); + } } diff --git a/lib/pages/medical/prescriptions/prescription_details_page.dart b/lib/pages/medical/prescriptions/prescription_details_page.dart index 024de17c..d59bc06d 100644 --- a/lib/pages/medical/prescriptions/prescription_details_page.dart +++ b/lib/pages/medical/prescriptions/prescription_details_page.dart @@ -105,22 +105,29 @@ class PrescriptionDetailsPage extends StatelessWidget { color: Colors.white, height: 30, width: double.infinity, - child: Center(child: Texts(TranslationBase.of(context).way))), + child: Center( + child: Texts(TranslationBase.of(context).way))), Container( color: Colors.white, height: 30, width: double.infinity, - child: Center(child: Texts(TranslationBase.of(context).average))), + child: Center( + child: + Texts(TranslationBase.of(context).average))), Container( color: Colors.white, height: 30, width: double.infinity, - child: Center(child: Texts(TranslationBase.of(context).dailyDoses))), + child: Center( + child: Texts( + TranslationBase.of(context).dailyDoses))), Container( color: Colors.white, height: 30, width: double.infinity, - child: Center(child: Texts(TranslationBase.of(context).period))), + child: Center( + child: + Texts(TranslationBase.of(context).period))), ], ), TableRow( @@ -136,7 +143,8 @@ class PrescriptionDetailsPage extends StatelessWidget { height: 50, width: double.infinity, child: Center( - child: Text(prescriptionReport.frequencyN?? ''))), + child: + Text(prescriptionReport.frequencyN ?? ''))), Container( color: Colors.white, height: 50, @@ -174,7 +182,7 @@ class PrescriptionDetailsPage extends StatelessWidget { SizedBox( height: 5, ), - Texts(prescriptionReport.remarks), + Texts(prescriptionReport.remarks ?? ''), ], ), ), diff --git a/lib/pages/medical/prescriptions/prescription_items_page.dart b/lib/pages/medical/prescriptions/prescription_items_page.dart index f70810dd..6fb07f68 100644 --- a/lib/pages/medical/prescriptions/prescription_items_page.dart +++ b/lib/pages/medical/prescriptions/prescription_items_page.dart @@ -13,6 +13,7 @@ import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import '../../../widgets/dialogs/confirm_send_email_dialog.dart'; class PrescriptionItemsPage extends StatelessWidget { final Prescriptions prescriptions; @@ -33,120 +34,154 @@ class PrescriptionItemsPage extends StatelessWidget { height: MediaQuery.of(context).size.height * 0.8, child: Column( children: [ - - if(!prescriptions.isInOutPatient) - ...List.generate(model.prescriptionReportList.length, (index) => InkWell( - onTap: () => Navigator.push( - context, - FadePage( - page: PrescriptionDetailsPage( - prescriptionReport: model.prescriptionReportList[index], - ), - ), - ), - child: Container( - width: double.infinity, - margin: EdgeInsets.only(top: 10, left: 10, right: 10), - padding: EdgeInsets.all(8.0), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all( - Radius.circular(10.0), - ), - border: Border.all(color: Colors.grey[200], width: 0.5), - ), - child: Row( - children: [ - ClipRRect( - borderRadius: BorderRadius.all(Radius.circular(5)), - child: Image.network( - model.prescriptionReportList[index].imageSRCUrl, - fit: BoxFit.cover, - width: 60, - height: 70, - ), - ), - Expanded( - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Center( - child: Texts(model.prescriptionReportList[index].itemDescription.isNotEmpty? - model.prescriptionReportList[index].itemDescription :model - .prescriptionReportList[index].itemDescriptionN)), - )), - Icon( - Icons.arrow_forward_ios, - size: 18, - color: Colors.grey[500], - ) - ], - ), - ), - )) - - else - ...List.generate( - model.prescriptionReportEnhList.length, + if (!prescriptions.isInOutPatient) + ...List.generate( + model.prescriptionReportList.length, (index) => InkWell( - onTap: (){ - PrescriptionReport prescriptionReport = PrescriptionReport( - imageSRCUrl: model.prescriptionReportEnhList[index].imageSRCUrl, - itemDescription: model.prescriptionReportEnhList[index].itemDescription, - itemDescriptionN: model.prescriptionReportEnhList[index].itemDescription, - routeN: model.prescriptionReportEnhList[index].route, - frequency: model.prescriptionReportEnhList[index].frequency, - frequencyN: model.prescriptionReportEnhList[index].frequency, - doseDailyQuantity: model.prescriptionReportEnhList[index].doseDailyQuantity, - days: model.prescriptionReportEnhList[index].days, - itemID: model.prescriptionReportEnhList[index].itemID, - remarks: model.prescriptionReportEnhList[index].remarks - ); - Navigator.push( - context, - FadePage( - page: PrescriptionDetailsPage( - prescriptionReport:prescriptionReport, + onTap: () => Navigator.push( + context, + FadePage( + page: PrescriptionDetailsPage( + prescriptionReport: + model.prescriptionReportList[index], + ), ), ), - ); - }, - child: Container( - margin: EdgeInsets.all(8.0), - color: Colors.white, - child: Row( - children: [ - ClipRRect( - borderRadius: BorderRadius.all(Radius.circular(5)), - child: Image.network( - model.prescriptionReportEnhList[index].imageSRCUrl, - fit: BoxFit.cover, - width: 60, - height: 70, - ), - ), - Expanded( - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + child: Container( + width: double.infinity, + margin: + EdgeInsets.only(top: 10, left: 10, right: 10), + padding: EdgeInsets.all(8.0), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all( + Radius.circular(10.0), + ), + border: Border.all( + color: Colors.grey[200], width: 0.5), + ), + child: Row( children: [ - Texts(model.prescriptionReportEnhList[index] - .itemDescription), + ClipRRect( + borderRadius: + BorderRadius.all(Radius.circular(5)), + child: Image.network( + model.prescriptionReportList[index] + .imageSRCUrl, + fit: BoxFit.cover, + width: 60, + height: 70, + ), + ), + SizedBox( + width: 10, + ), + Expanded( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Center( + child: Texts(model + .prescriptionReportList[index] + .itemDescription + .isNotEmpty + ? model.prescriptionReportList[index] + .itemDescription + : model.prescriptionReportList[index] + .itemDescriptionN)), + )), + Icon( + Icons.arrow_forward_ios, + size: 18, + color: Colors.grey[500], + ) ], ), ), + )) + else + ...List.generate( + model.prescriptionReportEnhList.length, + (index) => InkWell( + onTap: () { + PrescriptionReport prescriptionReport = + PrescriptionReport( + imageSRCUrl: model + .prescriptionReportEnhList[index].imageSRCUrl, + itemDescription: model + .prescriptionReportEnhList[index] + .itemDescription, + itemDescriptionN: model + .prescriptionReportEnhList[index] + .itemDescription, + routeN: + model.prescriptionReportEnhList[index].route, + frequency: model + .prescriptionReportEnhList[index].frequency, + frequencyN: model + .prescriptionReportEnhList[index].frequency, + doseDailyQuantity: model + .prescriptionReportEnhList[index] + .doseDailyQuantity, + days: model.prescriptionReportEnhList[index].days, + itemID: + model.prescriptionReportEnhList[index].itemID, + remarks: model + .prescriptionReportEnhList[index].remarks); + Navigator.push( + context, + FadePage( + page: PrescriptionDetailsPage( + prescriptionReport: prescriptionReport, + ), ), - ], - ), - ), + ); + }, + child: Container( + margin: EdgeInsets.all(8.0), + color: Colors.white, + child: Row( + children: [ + ClipRRect( + borderRadius: BorderRadius.all(Radius.circular(5)), + child: Image.network( + model + .prescriptionReportEnhList[index].imageSRCUrl, + fit: BoxFit.cover, + width: 60, + height: 70, + ), + ), + SizedBox( + width: 10, + ), + Expanded( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Texts(model.prescriptionReportEnhList[index] + .itemDescription), + ], + ), + ), + ), + Icon( + Icons.arrow_forward_ios, + size: 18, + color: Colors.grey[500], + ) + ], + ), ), - ) + ), + ) ], ), ), bottomSheet: Container( width: double.infinity, - height: MediaQuery.of(context).size.height * 0.23, + height: MediaQuery.of(context).size.height * 0.14, color: Colors.grey[100], child: Column( children: [ @@ -156,25 +191,41 @@ class PrescriptionItemsPage extends StatelessWidget { width: MediaQuery.of(context).size.width * 0.8, child: Button( label: TranslationBase.of(context).sendCopy, - onTap: () => model.sendPrescriptionEmail( - appointmentDate: prescriptions.appointmentDate, - patientID: prescriptions.patientID, - clinicName: prescriptions.companyName, - doctorName: prescriptions.doctorName, - projectID: prescriptions.projectID), + onTap: () { + showConfirmMessage(context,model); + }, loading: model.state == ViewState.BusyLocal, ), ), - Container( - width: MediaQuery.of(context).size.width * 0.8, - child: Button( - label:TranslationBase.of(context).resendOrder, - backgroundColor: Colors.green[200], - )) + if (false) + Container( + width: MediaQuery.of(context).size.width * 0.8, + child: Button( + label: TranslationBase.of(context).resendOrder, + backgroundColor: Colors.green[200], + )) ], ), ), ), ); } + + void showConfirmMessage(BuildContext context, PrescriptionsViewModel model) { + showDialog( + context: context, + child: ConfirmSendEmailDialog( + email: model.user.emailAddress, + onTapSendEmail: () { + model.sendPrescriptionEmail( + appointmentDate: prescriptions.appointmentDate, + patientID: prescriptions.patientID, + clinicName: prescriptions.companyName, + doctorName: prescriptions.doctorName, + mes: TranslationBase.of(context).sendSuc, + projectID: prescriptions.projectID); + }, + ), + ); + } } diff --git a/lib/pages/medical/prescriptions/prescriptions_history_details_page.dart b/lib/pages/medical/prescriptions/prescriptions_history_details_page.dart index 5061a8ba..30bfa13e 100644 --- a/lib/pages/medical/prescriptions/prescriptions_history_details_page.dart +++ b/lib/pages/medical/prescriptions/prescriptions_history_details_page.dart @@ -24,7 +24,6 @@ class PrescriptionsHistoryDetailsPage extends StatelessWidget { appBarTitle: TranslationBase.of(context).orderDetails, baseViewModel: model, body: SingleChildScrollView( - physics: BouncingScrollPhysics(), child: Container( margin: EdgeInsets.all(15.0), child: Column( @@ -33,9 +32,17 @@ class PrescriptionsHistoryDetailsPage extends StatelessWidget { SizedBox( height: 5, ), - Texts(TranslationBase.of(context).orderStatus +' : ${prescriptionsOrder.descriptionN}'), + Container( + width: double.infinity, + decoration: BoxDecoration( + color: prescriptionsOrder.status == 3 ?Colors.green : prescriptionsOrder.status ==2 ? Colors.grey: Colors.red, + borderRadius: BorderRadius.circular(5)), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Texts(TranslationBase.of(context).orderStatus +' : ${prescriptionsOrder.descriptionN}',color: Colors.white,), + )), SizedBox( - height: 5, + height: 15, ), Table( border: TableBorder.symmetric( @@ -60,17 +67,17 @@ class PrescriptionsHistoryDetailsPage extends StatelessWidget { ]), TableRow(children: [ Container( - height: 50, + height: 70, color: Colors.white, child: Center( child: Texts('${prescriptionsOrder.iD}'), ), ), Container( - height: 50, + height: 70, color: Colors.white, child: Center( - child: Texts('${prescriptionsOrder.createdOn}'), + child: Texts('${prescriptionsOrder.createdOn.year}-${prescriptionsOrder.createdOn.day}-${prescriptionsOrder.createdOn.day} ${prescriptionsOrder.createdOn.hour}:${prescriptionsOrder.createdOn.minute}'), ), ), ]) @@ -110,7 +117,8 @@ class PrescriptionsHistoryDetailsPage extends StatelessWidget { ], ), ), - ) + ), + SizedBox(height: 120,) ], ), ), diff --git a/lib/pages/medical/prescriptions/prescriptions_history_page.dart b/lib/pages/medical/prescriptions/prescriptions_history_page.dart index 9d63bf7d..84691773 100644 --- a/lib/pages/medical/prescriptions/prescriptions_history_page.dart +++ b/lib/pages/medical/prescriptions/prescriptions_history_page.dart @@ -1,4 +1,5 @@ import 'package:diplomaticquarterapp/core/viewModels/medical/prescriptions_view_model.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/pages/medical/prescriptions/prescriptions_history_details_page.dart'; import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; @@ -7,6 +8,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'; class PrescriptionsHistoryPage extends StatelessWidget { final PrescriptionsViewModel prescriptionsViewModel; @@ -15,6 +17,8 @@ class PrescriptionsHistoryPage extends StatelessWidget { @override Widget build(BuildContext context) { + ProjectViewModel projectViewModel = Provider.of(context); + return AppScaffold( baseViewModel: prescriptionsViewModel, body: ListView.builder( @@ -41,9 +45,7 @@ class PrescriptionsHistoryPage extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Texts( - DateUtil.getDayMonthYearHourMinuteDateFormatted( - prescriptionsViewModel - .prescriptionsHistory[index].createdOn), + DateUtil.getDayMonthYearHourMinuteDateFormatted(prescriptionsViewModel.prescriptionsHistory[index].createdOn), fontWeight: FontWeight.w300, ), SizedBox( diff --git a/lib/pages/medical/prescriptions/prescriptions_home_page.dart b/lib/pages/medical/prescriptions/prescriptions_home_page.dart index 94484340..380d6284 100644 --- a/lib/pages/medical/prescriptions/prescriptions_home_page.dart +++ b/lib/pages/medical/prescriptions/prescriptions_home_page.dart @@ -11,6 +11,8 @@ import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import '../../../Constants.dart'; + class HomePrescriptionsPage extends StatefulWidget { @override _HomePrescriptionsPageState createState() => _HomePrescriptionsPageState(); @@ -69,12 +71,12 @@ class _HomePrescriptionsPageState extends State child: Container( height: 60.0, margin: EdgeInsets.only(top: 10.0), - width: MediaQuery.of(context).size.width * 0.9, + width: MediaQuery.of(context).size.width * 0.92, decoration: BoxDecoration( border: Border( bottom: BorderSide( color: Theme.of(context).dividerColor, - width: 0.7), + width: 0.9), //width: 0.7 ), color: Colors.white), child: Center( @@ -82,11 +84,10 @@ class _HomePrescriptionsPageState extends State isScrollable: true, controller: _tabController, indicatorWeight: 5.0, - indicatorSize: TabBarIndicatorSize.label, - indicatorColor: Colors.red[800], + indicatorSize: TabBarIndicatorSize.tab, labelColor: Theme.of(context).primaryColor, labelPadding: - EdgeInsets.only(top: 4.0, left: 18.0, right: 18.0), + EdgeInsets.only(top: 4.0, left: 35.0, right: 35.0), unselectedLabelColor: Colors.grey[800], tabs: [ Container( diff --git a/lib/pages/medical/prescriptions/prescriptions_page.dart b/lib/pages/medical/prescriptions/prescriptions_page.dart index 6b852db9..abf68328 100644 --- a/lib/pages/medical/prescriptions/prescriptions_page.dart +++ b/lib/pages/medical/prescriptions/prescriptions_page.dart @@ -1,5 +1,6 @@ import 'package:diplomaticquarterapp/core/enum/filter_type.dart'; import 'package:diplomaticquarterapp/core/viewModels/medical/prescriptions_view_model.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/pages/medical/prescriptions/prescription_items_page.dart'; import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; @@ -9,6 +10,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'; class PrescriptionsPage extends StatelessWidget { final PrescriptionsViewModel prescriptionsViewModel; @@ -18,6 +20,7 @@ class PrescriptionsPage extends StatelessWidget { @override Widget build(BuildContext context) { + ProjectViewModel projectViewModel = Provider.of(context); return AppScaffold( baseViewModel: prescriptionsViewModel, body: FractionallySizedBox( @@ -37,7 +40,6 @@ class PrescriptionsPage extends StatelessWidget { leading: Radio( value: FilterType.Clinic, groupValue: prescriptionsViewModel.filterType, - activeColor: Colors.red[800], onChanged: (FilterType value) { prescriptionsViewModel.setFilterType(value); }, @@ -55,7 +57,6 @@ class PrescriptionsPage extends StatelessWidget { leading: Radio( value: FilterType.Hospital, groupValue: prescriptionsViewModel.filterType, - activeColor: Colors.red[800], onChanged: (FilterType value) { prescriptionsViewModel.setFilterType(value); }, @@ -88,9 +89,9 @@ class PrescriptionsPage extends StatelessWidget { profileUrl: prescriptions.doctorImageURL, rat: prescriptions.actualDoctorRate.toDouble(), subName: prescriptions.name, - isInOutPatient: prescriptions.isInOutPatient, - date: DateUtil.getMonthDayYearDateFormatted( - prescriptions.dischargeDate), + isInOutPatient: prescriptions.isInOutPatient, + isLiveCareAppointment: prescriptions.isLiveCareAppointment, + date:projectViewModel.isArabic? DateUtil.getMonthDayYearDateFormattedAr( DateUtil.convertStringToDate(prescriptions.appointmentDate) ):DateUtil.getMonthDayYearDateFormatted(DateUtil.convertStringToDate(prescriptions.appointmentDate)), ), ); }).toList(), diff --git a/lib/pages/medical/radiology/radiology_details_page.dart b/lib/pages/medical/radiology/radiology_details_page.dart index f7648aad..742e3ddf 100644 --- a/lib/pages/medical/radiology/radiology_details_page.dart +++ b/lib/pages/medical/radiology/radiology_details_page.dart @@ -1,3 +1,4 @@ +import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; import 'package:diplomaticquarterapp/core/model/radiology/final_radiology.dart'; import 'package:diplomaticquarterapp/core/viewModels/medical/radiology_view_model.dart'; @@ -5,6 +6,8 @@ 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/button.dart'; +import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; +import 'package:diplomaticquarterapp/widgets/dialogs/confirm_send_email_dialog.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -30,50 +33,81 @@ class RadiologyDetailsPage extends StatelessWidget { baseViewModel: model, body: SingleChildScrollView( child: Column( + mainAxisSize: MainAxisSize.max, crossAxisAlignment: CrossAxisAlignment.center, children: [ - Text( + Texts( '${finalRadiology.reportData}', textAlign: TextAlign.center, ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Texts( + '${finalRadiology.reportData}', + textAlign: TextAlign.start, + fontSize: 17, + ), + ), + SizedBox( + height: MediaQuery.of(context).size.height * 0.2, + ) ], ), ), bottomSheet: (projectViewModel.havePrivilege(9) || - projectViewModel.havePrivilege(8)) + projectViewModel.havePrivilege(8)) ? Container( - width: double.infinity, - height: MediaQuery.of(context).size.height * 0.2, - color: Colors.grey[100], - child: Column( - children: [ - Divider(), - if (projectViewModel.havePrivilege(9)) - Container( - width: MediaQuery.of(context).size.width * 0.8, - child: Button( - onTap: () { - launch(model.radImageURL); - }, - label: TranslationBase.of(context).openRad, - backgroundColor: Colors.grey[800], - ), - ), - if (projectViewModel.havePrivilege(8)) - Container( - width: MediaQuery.of(context).size.width * 0.8, - child: Button( - onTap: () => model.sendRadReportEmail( - finalRadiology: finalRadiology), - label: TranslationBase.of(context).sendCopyRad, - loading: model.state == ViewState.BusyLocal, - backgroundColor: Theme.of(context).primaryColor, - ), - ) - ], + width: double.infinity, + height: finalRadiology.dIAPACSURL != "" + ? MediaQuery.of(context).size.height * 0.25 + : MediaQuery.of(context).size.height * 0.14, + color: Colors.grey[100], + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Divider(), + if (finalRadiology.dIAPACSURL != "" && projectViewModel.havePrivilege(9)) + Container( + width: MediaQuery.of(context).size.width * 0.8, + child: Button( + onTap: () { + launch(model.radImageURL); + }, + label: TranslationBase.of(context).openRad, + backgroundColor: Colors.grey[800], + ), + ), + if (projectViewModel.havePrivilege(8)) + Container( + width: MediaQuery.of(context).size.width * 0.8, + child: Button( + onTap: () { + showConfirmMessage( + finalRadiology: finalRadiology, model: model); + }, + label: TranslationBase.of(context).sendCopyRad, + loading: model.state == ViewState.BusyLocal, + backgroundColor: Theme.of(context).primaryColor, ), ) - : Container()), + ], + ), + ):Container()), + ); + } + + void showConfirmMessage( + {FinalRadiology finalRadiology, RadiologyViewModel model}) { + showDialog( + context: AppGlobal.context, + child: ConfirmSendEmailDialog( + email: model.user.emailAddress, + onTapSendEmail: () { + model.sendRadReportEmail( + mes: TranslationBase.of(AppGlobal.context).sendSuc, + finalRadiology: finalRadiology); + }, + ), ); } } diff --git a/lib/pages/medical/radiology/radiology_home_page.dart b/lib/pages/medical/radiology/radiology_home_page.dart index ebc3527d..2123172a 100644 --- a/lib/pages/medical/radiology/radiology_home_page.dart +++ b/lib/pages/medical/radiology/radiology_home_page.dart @@ -1,6 +1,7 @@ import 'package:diplomaticquarterapp/core/enum/filter_type.dart'; import 'package:diplomaticquarterapp/core/model/ImagesInfo.dart'; import 'package:diplomaticquarterapp/core/viewModels/medical/radiology_view_model.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; import 'package:diplomaticquarterapp/pages/medical/radiology/radiology_details_page.dart'; import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; @@ -11,11 +12,13 @@ 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'; class RadiologyHomePage extends StatelessWidget { List imagesInfo = List(); @override Widget build(BuildContext context) { + ProjectViewModel projectViewModel = Provider.of(context); imagesInfo.add(ImagesInfo(imageEn: 'https://hmgwebservices.com/Images/MobileApp/imges-info/my-radiology/en/0.png',imageAr: 'https://hmgwebservices.com/Images/MobileApp/imges-info/my-radiology/ar/0.png')); imagesInfo.add(ImagesInfo(imageEn: 'https://hmgwebservices.com/Images/MobileApp/imges-info/my-radiology/en/1.png',imageAr: 'https://hmgwebservices.com/Images/MobileApp/imges-info/my-radiology/ar/1.png')); return BaseView( @@ -43,7 +46,6 @@ class RadiologyHomePage extends StatelessWidget { leading: Radio( value: FilterType.Clinic, groupValue: model.filterType, - activeColor: Theme.of(context).primaryColor, onChanged: (FilterType value) { model.setFilterType(value); }, @@ -61,7 +63,6 @@ class RadiologyHomePage extends StatelessWidget { leading: Radio( value: FilterType.Hospital, groupValue: model.filterType, - activeColor: Theme.of(context).primaryColor, onChanged: (FilterType value) { model.setFilterType(value); }, @@ -91,11 +92,12 @@ class RadiologyHomePage extends StatelessWidget { ), child: DoctorCard( isInOutPatient: radiology.isInOutPatient, + isLiveCareAppointment: radiology.isLiveCareAppointment, name: radiology.doctorName, profileUrl: radiology.doctorImageURL, - subName: '${radiology.projectName} \n${TranslationBase.of(context).billNo} ${radiology.invoiceNo}', - date: DateUtil.getMonthDayYearDateFormatted( - radiology.orderDate), + billNo: '${radiology.invoiceNo}', + subName: '${radiology.projectName}', + date: projectViewModel.isArabic? DateUtil.getMonthDayYearDateFormattedAr(radiology.orderDate):DateUtil.getMonthDayYearDateFormatted(radiology.orderDate), ), ); }).toList(), diff --git a/lib/pages/medical/reports/monthly_reports.dart b/lib/pages/medical/reports/monthly_reports.dart index ae9cc295..4484bd5f 100644 --- a/lib/pages/medical/reports/monthly_reports.dart +++ b/lib/pages/medical/reports/monthly_reports.dart @@ -2,10 +2,12 @@ import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; import 'package:diplomaticquarterapp/core/viewModels/medical/reports_monthly_view_model.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; import 'package:diplomaticquarterapp/pages/medical/reports/user_agreement_page.dart'; +import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/buttons/secondary_button.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/input/custom_switch.dart'; +import 'package:diplomaticquarterapp/widgets/input/text_field.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/cupertino.dart'; @@ -19,6 +21,8 @@ class MonthlyReportsPage extends StatefulWidget { class _MonthlyReportsPageState extends State { bool isAgree = false; bool isSummary = false; + String email = ""; + final formKey = GlobalKey(); @override Widget build(BuildContext context) { @@ -29,135 +33,161 @@ class _MonthlyReportsPageState extends State { body: SingleChildScrollView( child: Container( padding: EdgeInsets.all(12), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - padding: EdgeInsets.all(9), - height: 55, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all(Radius.circular(8)), - shape: BoxShape.rectangle, - border: Border.all(color: Colors.grey)), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Texts( - TranslationBase.of(context).patientHealthSummaryReport, - bold: true, - ), - CustomSwitch( - value: isSummary, - activeColor: Colors.red, - inactiveColor: Colors.grey, - onChanged: () async { - setState(() { - isSummary = !isSummary; - }); - }, - ) - ], + child: Form( + key: formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + padding: EdgeInsets.all(9), + height: 55, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(8)), + shape: BoxShape.rectangle, + border: Border.all(color: Colors.grey)), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + + Texts( + TranslationBase.of(context).patientHealthSummaryReport, + bold: true, + ), + CustomSwitch( + value: isSummary, + activeColor: Colors.red, + inactiveColor: Colors.grey, + onChanged: () async { + setState(() { + isSummary = !isSummary; + }); + if(!isSummary) { + GifLoaderDialogUtils.showMyDialog(context); + await model.updatePatientHealthSummaryReport( + message: TranslationBase + .of(context) + .updateSuccessfully, isSummary: isSummary); + GifLoaderDialogUtils.hideDialog(context); + } + }, + ) + ], + ), ), - ), - SizedBox( - height: 15, - ), - Container( - margin: EdgeInsets.all(8), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Texts( - model.user.emailAddress, - bold: true, - ), - ], + SizedBox( + height: 15, ), - ), - Divider( - height: 10.4, - thickness: 1.0, - ), - SizedBox( - height: 15, - ), - Container( - margin: EdgeInsets.all(8), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + Container( + margin: EdgeInsets.all(8), + child: TextFields( + fillColor: Colors.red, + hintText: 'email@email.com', + fontSize: 20, + initialValue: model.user.emailAddress, + fontWeight: FontWeight.w600, + onChanged: (text) { + email = text; + }, + validator: (value) { + if (value.isEmpty) + return TranslationBase.of(context).enterEmail; + else + return null; + }, + ), + ), + Divider( + height: 10.4, + thickness: 1.0, + ), + SizedBox( + height: 15, + ), + Container( + margin: EdgeInsets.all(8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + child: Texts(TranslationBase.of(context) + .toViewTheTermsAndConditions), + ), + InkWell( + onTap: () { + Navigator.push( + context, + FadePage( + page: UserAgreementContent(), + ), + ); + }, + child: Texts( + TranslationBase.of(context).clickHere, + color: Colors.blue, + ), + ) + ], + ), + ), + SizedBox( + height: 5, + ), + Row( crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, children: [ - Expanded( - child: Texts(TranslationBase.of(context) - .toViewTheTermsAndConditions), - ), - InkWell( - onTap: () { - Navigator.push( - context, - FadePage( - page: UserAgreementContent(), - ), - ); + Checkbox( + value: isAgree, + onChanged: (value) { + setState(() { + isAgree = !isAgree; + }); }, - child: Texts( - TranslationBase.of(context).clickHere, - color: Colors.blue, - ), - ) + activeColor: Colors.red, + ), + Texts(TranslationBase.of(context).iAgreeToTheTermsAndConditions), ], ), - ), - SizedBox( - height: 5, - ), - Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Checkbox( - value: isAgree, - onChanged: (value) { - setState(() { - isAgree = !isAgree; - }); + Container( + margin: EdgeInsets.all(8), + width: double.infinity, + child: SecondaryButton( + textColor: Colors.white, + label: TranslationBase.of(context).save, + disabled: (!isAgree || !isSummary ), + onTap: () async { + final form = formKey.currentState; + if (form.validate()) { + GifLoaderDialogUtils.showMyDialog(context); + await model.updatePatientHealthSummaryReport( + message: TranslationBase + .of(context) + .updateSuccessfully, + isSummary: isSummary, + isUpdateEmail: true, + email: email.isNotEmpty ? email : model.user + .emailAddress); + GifLoaderDialogUtils.hideDialog(context); + } }, - activeColor: Colors.red, ), - Texts(TranslationBase.of(context) - .iAgreeToTheTermsAndConditions), - ], - ), - Container( - margin: EdgeInsets.all(8), - width: double.infinity, - child: SecondaryButton( - textColor: Colors.white, - label: TranslationBase.of(context).save, - disabled: !isAgree, - loading: model.state == ViewState.BusyLocal, - onTap: () { - model.updatePatientHealthSummaryReport( - message: TranslationBase.of(context) - .updateSuccessfully, - isSummary: isSummary); - }, ), - ), - Padding( - padding: const EdgeInsets.all(5.0), - child: Texts( - TranslationBase.of(context) - .iAgreeToTheTermsAndConditionsSubtitle, - fontWeight: FontWeight.normal, + Padding( + padding: const EdgeInsets.all(5.0), + child: Texts( + TranslationBase.of(context) + .instructionAgree, + fontWeight: FontWeight.normal, + ), + ), + SizedBox( + height: 12, ), - ), - SizedBox( - height: 12, - ), - Center(child: Image.asset('assets/images/report.jpg')) - ], + Center(child: Image.asset('assets/images/report.jpg')) + ], + ), ), ), ), diff --git a/lib/pages/medical/reports/report_home_page.dart b/lib/pages/medical/reports/report_home_page.dart index 42f207da..42dcf40a 100644 --- a/lib/pages/medical/reports/report_home_page.dart +++ b/lib/pages/medical/reports/report_home_page.dart @@ -40,14 +40,27 @@ class _HomeReportPageState extends State @override Widget build(BuildContext context) { ProjectViewModel projectViewModel = Provider.of(context); - imagesInfo.add(ImagesInfo(imageEn: 'https://hmgwebservices.com/Images/MobileApp/imges-info/medical-reorts/en/0.png',imageAr: 'https://hmgwebservices.com/Images/MobileApp/imges-info/medical-reorts/ar/0.png')); - imagesInfo.add(ImagesInfo(imageEn: 'https://hmgwebservices.com/Images/MobileApp/imges-info/medical-reorts/en/1.png',imageAr: 'https://hmgwebservices.com/Images/MobileApp/imges-info/medical-reorts/ar/1.png')); - imagesInfo.add(ImagesInfo(imageEn: 'https://hmgwebservices.com/Images/MobileApp/imges-info/medical-reorts/en/2.png',imageAr: 'https://hmgwebservices.com/Images/MobileApp/imges-info/medical-reorts/ar/2.png')); + imagesInfo.add(ImagesInfo( + imageEn: + 'https://hmgwebservices.com/Images/MobileApp/imges-info/medical-reorts/en/0.png', + imageAr: + 'https://hmgwebservices.com/Images/MobileApp/imges-info/medical-reorts/ar/0.png')); + imagesInfo.add(ImagesInfo( + imageEn: + 'https://hmgwebservices.com/Images/MobileApp/imges-info/medical-reorts/en/1.png', + imageAr: + 'https://hmgwebservices.com/Images/MobileApp/imges-info/medical-reorts/ar/1.png')); + imagesInfo.add(ImagesInfo( + imageEn: + 'https://hmgwebservices.com/Images/MobileApp/imges-info/medical-reorts/en/2.png', + imageAr: + 'https://hmgwebservices.com/Images/MobileApp/imges-info/medical-reorts/ar/2.png')); return BaseView( onModelReady: (model) => model.getReports(), //model.getPrescriptions(), builder: (_, model, widget) => AppScaffold( isShowAppBar: true, - appBarTitle: TranslationBase.of(context).monthReport, + appBarTitle: TranslationBase.of(context).newMedReport, + title: TranslationBase.of(context).medReport, description: TranslationBase.of(context).infoMonthReport, baseViewModel: model, imagesInfo: imagesInfo, @@ -88,33 +101,34 @@ class _HomeReportPageState extends State isScrollable: true, controller: _tabController, indicatorWeight: 5.0, - indicatorSize: TabBarIndicatorSize.label, - indicatorColor: Theme.of(context).primaryColor, + indicatorSize: TabBarIndicatorSize.tab, labelColor: Theme.of(context).primaryColor, unselectedLabelColor: Colors.grey[800], tabs: [ Container( - width: MediaQuery.of(context).size.width * 0.22, + width: MediaQuery.of(context).size.width * 0.15, child: Center( - child: Texts(TranslationBase.of(context).requested), + child: Texts(TranslationBase.of(context).requested,fontSize: 11,), ), ), Container( - width: MediaQuery.of(context).size.width * 0.22, + width: MediaQuery.of(context).size.width * 0.15, child: Center( - child: Texts(TranslationBase.of(context).ready), + child: Texts(TranslationBase.of(context).ready,fontSize: 11,), ), ), Container( - width: MediaQuery.of(context).size.width * 0.22, + width: MediaQuery.of(context).size.width * 0.15, child: Center( - child: Texts(TranslationBase.of(context).completed), + child: + Texts(TranslationBase.of(context).completed,fontSize: 11,), ), ), Container( - width: MediaQuery.of(context).size.width * 0.22, + width: MediaQuery.of(context).size.width * 0.15, child: Center( - child: Texts(TranslationBase.of(context).cancelled), + child: + Texts(TranslationBase.of(context).cancelled,fontSize: 11,), ), ), ], @@ -127,6 +141,7 @@ class _HomeReportPageState extends State ), body: Column( children: [ + if(model.user!=null) Expanded( child: TabBarView( physics: BouncingScrollPhysics(), @@ -134,20 +149,26 @@ class _HomeReportPageState extends State children: [ ReportListWidget( reportList: model.reportsOrderRequestList, + emailAddress: model.user.emailAddress ), ReportListWidget( reportList: model.reportsOrderReadyList, + emailAddress: model.user.emailAddress ), ReportListWidget( reportList: model.reportsOrderCompletedList, + emailAddress: model.user.emailAddress ), ReportListWidget( reportList: model.reportsOrderCanceledList, + emailAddress: model.user.emailAddress ), ], ), ), - SizedBox(height: 110,) + SizedBox( + height: 110, + ) ], ), bottomSheet: projectViewModel.havePrivilege(21) ?Container( diff --git a/lib/pages/medical/reports/report_list_widget.dart b/lib/pages/medical/reports/report_list_widget.dart index 6408074a..72d0422b 100644 --- a/lib/pages/medical/reports/report_list_widget.dart +++ b/lib/pages/medical/reports/report_list_widget.dart @@ -1,13 +1,22 @@ +import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/core/model/reports/Reports.dart'; +import 'package:diplomaticquarterapp/core/service/medical/reports_service.dart'; +import 'package:diplomaticquarterapp/locator.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/avatar/large_avatar.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; +import 'package:diplomaticquarterapp/widgets/dialogs/confirm_send_email_dialog.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; class ReportListWidget extends StatelessWidget { final List reportList; + final String emailAddress; - ReportListWidget({@required this.reportList}); + ReportListWidget({@required this.reportList, this.emailAddress}); @override Widget build(BuildContext context) { @@ -16,7 +25,8 @@ class ReportListWidget extends StatelessWidget { itemBuilder: (context, index) => Padding( padding: const EdgeInsets.all(8.0), child: Container( - width: double.infinity,margin: EdgeInsets.only(left: 8,right: 8,top: 3), + width: double.infinity, + margin: EdgeInsets.only(left: 8, right: 8, top: 3), decoration: BoxDecoration( color: Colors.white, border: Border.all(color: Colors.white, width: 2), @@ -40,15 +50,39 @@ class ReportListWidget extends StatelessWidget { flex: 4, child: Padding( padding: const EdgeInsets.all(8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox(height: 12,), - Texts(reportList[index].projectName), - Texts(reportList[index].clinicDescription), - Texts('invoice No: ${reportList[index].invoiceNo}'), - SizedBox(height: 12,), - + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + height: 12, + ), + Texts(reportList[index].projectName), + Texts(reportList[index].clinicDescription), + Texts(TranslationBase.of(context).invoiceNo + + ': ${reportList[index].invoiceNo}'), + SizedBox(height: 12), + ], + ), + reportList[index].status == 2 + ? Container( + margin: + EdgeInsets.only(left: 15.0, right: 15.0), + child: InkWell( + onTap: () { + showConfirmMessage(reportList[index]); + // sendReportEmail(reportList[index]); + }, + child: Icon( + Icons.email, + color: Theme.of(context).primaryColor, + size: 35.0, + ), + ), + ) + : Container(), ], ), ), @@ -61,4 +95,39 @@ class ReportListWidget extends StatelessWidget { ), ); } + + void showConfirmMessage(Reports report) { + showDialog( + context: AppGlobal.context, + child: ConfirmSendEmailDialog( + email: emailAddress, + onTapSendEmail: () { + sendReportEmail(report); + }, + ), + ); + } + + sendReportEmail(Reports report) { + GifLoaderDialogUtils.showMyDialog(AppGlobal.context); + ReportsService _reportsService = locator(); + _reportsService + .sendEmailForMedicalReport( + report.projectName, + report.clinicDescription, + report.doctorName, + DateUtil.convertDateToString(report.requestDate), + report.invoiceNo.toString(), + report.projectID, + DateUtil.convertDateToString(report.requestDate), + report.setupId) + .then((value) { + GifLoaderDialogUtils.hideDialog(AppGlobal.context); + AppToast.showSuccessToast( + message: TranslationBase.of(AppGlobal.context).emailSentSuccessfully); + }).catchError((err) { + GifLoaderDialogUtils.hideDialog(AppGlobal.context); + print(err); + }); + } } diff --git a/lib/pages/medical/reports/reports_page.dart b/lib/pages/medical/reports/reports_page.dart index 5b64bc4e..d8cb2ca0 100644 --- a/lib/pages/medical/reports/reports_page.dart +++ b/lib/pages/medical/reports/reports_page.dart @@ -1,13 +1,16 @@ import 'package:diplomaticquarterapp/core/viewModels/medical/reports_view_model.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; import 'package:diplomaticquarterapp/pages/feedback/appointment_history.dart'; import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/avatar/large_avatar.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/others/StarRating.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; class MedicalReports extends StatelessWidget { @override @@ -18,17 +21,17 @@ class MedicalReports extends StatelessWidget { context: context, child: ConfirmDialog( appointmentHistory: model, - onOkSelected: (model) => reportsViewModel.insertRequestForMedicalReport(model), + onOkSelected: (model) => reportsViewModel.insertRequestForMedicalReport(model,TranslationBase.of(context).successSendReport), ), ); } - + ProjectViewModel projectViewModel = Provider.of(context); return BaseView( onModelReady: (model) => model.getPatentAppointmentHistory(), builder: (_, model, widget) => AppScaffold( baseViewModel: model, isShowAppBar: true, - appBarTitle: 'Medical Reports', + appBarTitle: TranslationBase.of(context).medReport, body: ListView.builder( itemCount: model.appointHistoryList.length, itemBuilder: (context, index) => Padding( @@ -69,8 +72,7 @@ class MedicalReports extends StatelessWidget { ), Texts(model.appointHistoryList[index].projectName), Texts(model.appointHistoryList[index].clinicName), - Texts(DateUtil.getMonthDayYearDateFormatted( - model.appointHistoryList[index].appointmentDate)), + Texts(projectViewModel.isArabic? DateUtil.getMonthDayYearDateFormattedAr(model.appointHistoryList[index].appointmentDate):DateUtil.getMonthDayYearDateFormatted(model.appointHistoryList[index].appointmentDate)), StarRating( totalAverage: model .appointHistoryList[index].actualDoctorRate @@ -89,7 +91,7 @@ class MedicalReports extends StatelessWidget { onTap: () => confirmBox(model.appointHistoryList[index], model), child: Container( - width: 80, + width: 85, height: 50, decoration: BoxDecoration( color: Colors.black54, @@ -102,7 +104,7 @@ class MedicalReports extends StatelessWidget { ), child: Center( child: Texts( - 'Request', + TranslationBase.of(context).requestReport, fontSize: 12, color: Colors.white, ), @@ -137,13 +139,13 @@ class _ConfirmDialogState extends State { @override Widget build(BuildContext context) { return SimpleDialog( - title: Text('Confirm'), + title: Texts(TranslationBase.of(context).confirm), children: [ Container( child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ - Texts('Request a medical report'), + Texts(TranslationBase.of(context).confirmMsgReport), SizedBox( height: 5.0, ), @@ -166,7 +168,7 @@ class _ConfirmDialogState extends State { child: Container( child: Center( child: Texts( - 'cancel', + TranslationBase.of(context).cancel, color: Colors.red, ), ), @@ -190,7 +192,7 @@ class _ConfirmDialogState extends State { padding: const EdgeInsets.all(8.0), child: Center( child: Texts( - 'ok', + TranslationBase.of(context).ok, fontWeight: FontWeight.w400, ), ), diff --git a/lib/pages/medical/smart_watch_health_data/health_data_list.dart b/lib/pages/medical/smart_watch_health_data/health_data_list.dart index 763948c0..2f9a3e60 100644 --- a/lib/pages/medical/smart_watch_health_data/health_data_list.dart +++ b/lib/pages/medical/smart_watch_health_data/health_data_list.dart @@ -1,6 +1,5 @@ import 'package:diplomaticquarterapp/widgets/buttons/button.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; -import 'package:fit_kit/fit_kit.dart'; import 'package:flutter/material.dart'; class HealthDataList extends StatefulWidget { @@ -9,19 +8,6 @@ class HealthDataList extends StatefulWidget { } class _HealthDataListState extends State { - List dataTypes = List(); - - @override - void initState() { - dataTypes.add(DataType.DISTANCE); - dataTypes.add(DataType.STEP_COUNT); - dataTypes.add(DataType.HEART_RATE); - dataTypes.add(DataType.SLEEP); - dataTypes.add(DataType.ENERGY); - - super.initState(); - } - @override Widget build(BuildContext context) { return AppScaffold( @@ -146,7 +132,7 @@ class _HealthDataListState extends State { width: MediaQuery.of(context).size.width * 0.8, child: Button( onTap: () { - readAll(); +// launch(model.radImageURL); }, label: 'Sync Health Data', backgroundColor: Colors.grey[800], @@ -156,26 +142,4 @@ class _HealthDataListState extends State { ), )); } - - void readLast() async { - final result = await FitKit.readLast(DataType.DISTANCE); - print(result); - print(result); - } - - void readAll() async { - if (await FitKit.requestPermissions(dataTypes)) { - for (DataType type in dataTypes) { - final results = await FitKit.read( - type, - dateFrom: DateTime.now().subtract(Duration(days: 15)), - dateTo: DateTime.now(), - limit: 100, - ); - print(results); - print(results.length); - } - readLast(); - } - } } diff --git a/lib/pages/medical/smart_watch_health_data/smart_watch_instructions.dart b/lib/pages/medical/smart_watch_health_data/smart_watch_instructions.dart index 1a5270f8..eb0c1675 100644 --- a/lib/pages/medical/smart_watch_health_data/smart_watch_instructions.dart +++ b/lib/pages/medical/smart_watch_health_data/smart_watch_instructions.dart @@ -3,9 +3,9 @@ import 'dart:io'; import 'package:carousel_slider/carousel_slider.dart'; import 'package:diplomaticquarterapp/pages/medical/smart_watch_health_data/health_data_list.dart'; import 'package:diplomaticquarterapp/services/smartwatch_integration/SmartWatchIntegrationService.dart'; -import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:flutter/material.dart'; +import 'package:smart_progress_bar/smart_progress_bar.dart'; import 'package:url_launcher/url_launcher.dart'; class SmartWatchInstructions extends StatefulWidget { @@ -31,7 +31,6 @@ class _SmartWatchInstructionsState extends State { return AppScaffold( appBarTitle: "Sync Health Data", isShowAppBar: true, - isShowDecPage: false, body: Container( child: Platform.isIOS ? _getAppleWatchInstructions() @@ -89,8 +88,6 @@ class _SmartWatchInstructionsState extends State { width: 70.0, height: 70.0), Container( - margin: EdgeInsets.only(left: 5.0), - width: 105.0, child: Text( "Apple Watch Series 1", style: TextStyle( @@ -111,12 +108,8 @@ class _SmartWatchInstructionsState extends State { width: 70.0, height: 70.0), Container( - margin: EdgeInsets.only(left: 5.0), - width: 105.0, child: Text( "Apple Watch Series 2", - overflow: TextOverflow.clip, - softWrap: true, style: TextStyle( fontSize: 12.0)), ) @@ -142,8 +135,6 @@ class _SmartWatchInstructionsState extends State { width: 70.0, height: 70.0), Container( - margin: EdgeInsets.only(left: 5.0), - width: 105.0, child: Text( "Apple Watch Series 3", style: TextStyle( @@ -164,8 +155,6 @@ class _SmartWatchInstructionsState extends State { width: 70.0, height: 70.0), Container( - margin: EdgeInsets.only(left: 5.0), - width: 105.0, child: Text( "Apple Watch Series 4", style: TextStyle( @@ -193,8 +182,6 @@ class _SmartWatchInstructionsState extends State { width: 70.0, height: 70.0), Container( - margin: EdgeInsets.only(left: 5.0), - width: 105.0, child: Text( "Apple Watch Series 5", style: TextStyle( @@ -215,8 +202,6 @@ class _SmartWatchInstructionsState extends State { width: 70.0, height: 70.0), Container( - margin: EdgeInsets.only(left: 5.0), - width: 105.0, child: Text( "Apple Watch Series 6", style: TextStyle( @@ -442,7 +427,7 @@ class _SmartWatchInstructionsState extends State { width: MediaQuery.of(context).size.width, margin: EdgeInsets.symmetric(horizontal: 5.0), child: Card( - margin: EdgeInsets.fromLTRB(8.0, 16.0, 8.0, 0.0), + margin: EdgeInsets.fromLTRB(8.0, 16.0, 8.0, 8.0), color: Colors.white.withOpacity(1.0), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), @@ -672,7 +657,7 @@ class _SmartWatchInstructionsState extends State { style: TextStyle(fontSize: 17.0)), ), Container( - margin: EdgeInsets.all(12.0), + margin: EdgeInsets.all(15.0), child: ButtonTheme( shape: RoundedRectangleBorder( borderRadius: @@ -811,9 +796,7 @@ class _SmartWatchInstructionsState extends State { getLastPatientRecord(BuildContext context) { SmartWatchIntegrationService service = new SmartWatchIntegrationService(); - GifLoaderDialogUtils.showMyDialog(context); service.getLastPatientRecord(context).then((res) { - GifLoaderDialogUtils.hideDialog(context); if (res['MessageStatus'] == 1) { print(res['Med_GetPatientLastRecordList']); setState(() { @@ -824,9 +807,9 @@ class _SmartWatchInstructionsState extends State { }); } else {} }).catchError((err) { - GifLoaderDialogUtils.hideDialog(context); print(err); - }); + }).showProgressBar( + text: "Loading", backgroundColor: Colors.blue.withOpacity(0.6)); } _openHealthDataList() { diff --git a/lib/pages/medical/vital_sign/LineChartCurved.dart b/lib/pages/medical/vital_sign/LineChartCurved.dart new file mode 100644 index 00000000..7b7449a8 --- /dev/null +++ b/lib/pages/medical/vital_sign/LineChartCurved.dart @@ -0,0 +1,217 @@ +import 'package:diplomaticquarterapp/widgets/charts/app_time_series_chart.dart'; +import 'package:fl_chart/fl_chart.dart'; +import 'package:flutter/material.dart'; + +class LineChartCurved extends StatelessWidget { + final String title; + final List timeSeries; + final int indexes; + + LineChartCurved({this.title, this.timeSeries, this.indexes}); + + List xAxixs = List(); + List yAxixs = List(); + + @override + Widget build(BuildContext context) { + getXaxix(); + getYaxix(); + return AspectRatio( + aspectRatio: 1.1, + child: Container( + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(18)), + // color: Colors.white, + ), + child: Stack( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const SizedBox( + height: 4, + ), + Text( + title, + style: TextStyle( + color: Colors.black, + fontSize: 15, + letterSpacing: 2), + textAlign: TextAlign.center, + ), + SizedBox(height: 10,), + Expanded( + child: Padding( + padding: const EdgeInsets.only(right: 18.0, left: 16.0), + child: LineChart( + sampleData1(context), + swapAnimationDuration: const Duration(milliseconds: 250), + ), + ), + ), + const SizedBox( + height: 10, + ), + ], + ), + ], + ), + ), + ); + } + + getXaxix() { + for (int index = 0; index < timeSeries.length; index++) { + int mIndex = indexes * index; + if (mIndex < timeSeries.length) { + xAxixs.add(mIndex); + } + } + } + getYaxix() { + int indexess= (timeSeries.length*0.30).toInt(); + for (int index = 0; index < timeSeries.length; index++) { + int mIndex = indexess * index; + if (mIndex < timeSeries.length) { + yAxixs.add(timeSeries[mIndex].sales); + } + } + } + + LineChartData sampleData1(context) { + return LineChartData( + lineTouchData: LineTouchData( + touchTooltipData: LineTouchTooltipData( + tooltipBgColor: Colors.white, + + ), + touchCallback: (LineTouchResponse touchResponse) {}, + handleBuiltInTouches: true, + ), + gridData: FlGridData( + show: true, drawVerticalLine: true, drawHorizontalLine: true), + titlesData: FlTitlesData( + bottomTitles: SideTitles( + showTitles: true, + getTextStyles: (value) => const TextStyle( + color: Colors.black, + fontSize: 10, + ), + rotateAngle:-65, + //rotateAngle:-65, + margin: 22, + getTitles: (value) { + if (timeSeries.length < 15) { + if (timeSeries.length > value.toInt()) { + return '${timeSeries[value.toInt()].time.month}/ ${timeSeries[value.toInt()].time.year}'; + } else + return ''; + } else { + if (value.toInt() == 0) + return '${timeSeries[value.toInt()].time.month}/ ${timeSeries[value.toInt()].time.year}'; + if (value.toInt() == timeSeries.length - 1) + return '${timeSeries[value.toInt()].time.month}/ ${timeSeries[value.toInt()].time.year}'; + if (xAxixs.contains(value.toInt())) { + return '${timeSeries[value.toInt()].time.month}/ ${timeSeries[value.toInt()].time.year}'; + } + } + return ''; + }, + ), + leftTitles: SideTitles( + showTitles: true, + getTextStyles: (value) => const TextStyle( + color: Colors.black, + fontWeight: FontWeight.bold, + fontSize: 10, + ), + getTitles: (value) { + // if (timeSeries.length < 10) { + // return '${value.toInt()}'; + // } else { + // if (value == getMinY()) + // return '${value.toInt()}'; + // if (value == getMaxY()) + // return '${value.toInt()}'; + // if (yAxixs.contains(value)) { + // return '${value.toInt()}'; + // } + // return ''; + // } + return '${value.toInt()}'; + }, + margin: 12, + ), + ), + borderData: FlBorderData( + show: true, + border: const Border( + bottom: BorderSide( + color: Colors.black, + width: 0.5, + ), + left: BorderSide( + color: Colors.black, + ), + right: BorderSide( + color: Colors.black, + ), + top: BorderSide( + color: Colors.transparent, + ), + ), + ), + minX: 0, + maxX: (timeSeries.length - 1).toDouble(), + maxY: getMaxY()+0.3, + minY: getMinY(), + lineBarsData: getData(context), + ); + } + + double getMaxY() { + double max = 0; + timeSeries.forEach((element) { + double resultValueDouble = element.sales; + if (resultValueDouble > max) max = resultValueDouble; + }); + + return max.roundToDouble() ; + } + + double getMinY() { + double min = timeSeries[0].sales; + timeSeries.forEach((element) { + double resultValueDouble = element.sales; + if (resultValueDouble < min) min = resultValueDouble; + }); + int value = min.toInt(); + + return value.toDouble(); + } + + List getData(context) { + List spots = List(); + for (int index = 0; index < timeSeries.length; index++) { + spots.add(FlSpot(index.toDouble(), timeSeries[index].sales)); + } + + final LineChartBarData lineChartBarData1 = LineChartBarData( + spots: spots, + isCurved: true, + colors: [Theme.of(context).primaryColor], + barWidth: 5, + isStrokeCapRound: true, + dotData: FlDotData( + show: false, + ), + belowBarData: BarAreaData( + show: false, + ), + ); + + return [ + lineChartBarData1, + ]; + } +} diff --git a/lib/pages/medical/vital_sign/LineChartCurvedBloodPressure.dart b/lib/pages/medical/vital_sign/LineChartCurvedBloodPressure.dart new file mode 100644 index 00000000..e8cb8b24 --- /dev/null +++ b/lib/pages/medical/vital_sign/LineChartCurvedBloodPressure.dart @@ -0,0 +1,257 @@ +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/charts/app_time_series_chart.dart'; +import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; +import 'package:fl_chart/fl_chart.dart'; +import 'package:flutter/material.dart'; + +class LineChartCurvedBloodPressure extends StatelessWidget { + final String title; + final List timeSeries1; + final List timeSeries2; + final int indexes; + + LineChartCurvedBloodPressure( + {this.title, this.timeSeries1, this.indexes, this.timeSeries2}); + + List xAxixs = List(); + List yAxixs = List(); + + @override + Widget build(BuildContext context) { + getXaxix(); + return AspectRatio( + aspectRatio: 1.1, + child: Container( + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(18)), + // color: Colors.white, + ), + child: Stack( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const SizedBox( + height: 15, + ), + Text( + title, + style: TextStyle( + color: Colors.black, fontSize: 15, letterSpacing: 2), + textAlign: TextAlign.center, + ), + SizedBox( + height: 10, + ), + Expanded( + child: Padding( + padding: + const EdgeInsets.only(right: 18.0, left: 16.0, top: 15), + child: LineChart( + sampleData1(context), + swapAnimationDuration: const Duration(milliseconds: 250), + ), + ), + ), + SizedBox( + height: 10, + ), + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Row( + children: [ + Container( + width: 20, + height: 20, + decoration: BoxDecoration( + shape: BoxShape.rectangle, + color: Theme.of(context).primaryColor), + ), + SizedBox(width: 5,), + Texts(TranslationBase.of(context).systolicLng) + ], + ), + SizedBox(width: 15,), + Row( + children: [ + Container( + width: 20, + height: 20, + decoration: BoxDecoration( + shape: BoxShape.rectangle, + color: Colors.grey), + ), + SizedBox(width: 5,), + Texts(TranslationBase.of(context).diastolicLng) + ], + ), + ], + ) + ], + ), + ], + ), + ), + ); + } + + getXaxix() { + for (int index = 0; index < timeSeries1.length; index++) { + int mIndex = indexes * index; + if (mIndex < timeSeries1.length) { + xAxixs.add(mIndex); + } + } + } + + LineChartData sampleData1(context) { + return LineChartData( + lineTouchData: LineTouchData( + touchTooltipData: LineTouchTooltipData( + tooltipBgColor: Colors.white, + ), + touchCallback: (LineTouchResponse touchResponse) {}, + handleBuiltInTouches: true, + ), + gridData: FlGridData( + show: true, drawVerticalLine: true, drawHorizontalLine: true), + titlesData: FlTitlesData( + bottomTitles: SideTitles( + showTitles: true, + getTextStyles: (value) => const TextStyle( + color: Colors.black, + fontSize: 10, + ), + rotateAngle: -65, + //rotateAngle:-65, + margin: 22, + getTitles: (value) { + if (timeSeries1.length < 15) { + if (timeSeries1.length > value.toInt()) { + return '${timeSeries1[value.toInt()].time.month}/ ${timeSeries1[value.toInt()].time.year}'; + } else + return ''; + } else { + if (value.toInt() == 0) + return '${timeSeries1[value.toInt()].time.month}/ ${timeSeries1[value.toInt()].time.year}'; + if (value.toInt() == timeSeries1.length - 1) + return '${timeSeries1[value.toInt()].time.month}/ ${timeSeries1[value.toInt()].time.year}'; + if (xAxixs.contains(value.toInt())) { + return '${timeSeries1[value.toInt()].time.month}/ ${timeSeries1[value.toInt()].time.year}'; + } + } + return ''; + }, + ), + leftTitles: SideTitles( + showTitles: true, + getTextStyles: (value) => const TextStyle( + color: Colors.black, + fontWeight: FontWeight.bold, + fontSize: 10, + ), + getTitles: (value) { + return '${value.toInt()}'; + }, + margin: 12, + ), + ), + borderData: FlBorderData( + show: true, + border: const Border( + bottom: BorderSide( + color: Colors.black, + width: 0.5, + ), + left: BorderSide( + color: Colors.black, + ), + right: BorderSide( + color: Colors.black, + ), + top: BorderSide( + color: Colors.transparent, + ), + ), + ), + minX: 0, + maxX: (timeSeries1.length - 1).toDouble(), + maxY: getMaxY() + 0.3, + minY: getMinY(), + lineBarsData: getData(context), + ); + } + + double getMaxY() { + double max = 0; + timeSeries1.forEach((element) { + double resultValueDouble = element.sales; + if (resultValueDouble > max) max = resultValueDouble; + }); + timeSeries2.forEach((element) { + double resultValueDouble = element.sales; + if (resultValueDouble > max) max = resultValueDouble; + }); + + return max.roundToDouble(); + } + + double getMinY() { + double min = timeSeries1[0].sales; + timeSeries1.forEach((element) { + double resultValueDouble = element.sales; + if (resultValueDouble < min) min = resultValueDouble; + }); + timeSeries2.forEach((element) { + double resultValueDouble = element.sales; + if (resultValueDouble < min) min = resultValueDouble; + }); + + int value = min.toInt(); + + return value.toDouble(); + } + + List getData(context) { + List spots = List(); + for (int index = 0; index < timeSeries1.length; index++) { + spots.add(FlSpot(index.toDouble(), timeSeries1[index].sales)); + } + + List spots2 = List(); + for (int index = 0; index < timeSeries2.length; index++) { + spots2.add(FlSpot(index.toDouble(), timeSeries2[index].sales)); + } + + final LineChartBarData lineChartBarData1 = LineChartBarData( + spots: spots, + isCurved: true, + colors: [Theme.of(context).primaryColor], + barWidth: 5, + isStrokeCapRound: true, + dotData: FlDotData( + show: false, + ), + belowBarData: BarAreaData( + show: false, + ), + ); + final LineChartBarData lineChartBarData2 = LineChartBarData( + spots: spots2, + isCurved: true, + colors: [Colors.grey], + barWidth: 5, + isStrokeCapRound: true, + dotData: FlDotData( + show: false, + ), + belowBarData: BarAreaData( + show: false, + ), + ); + + return [lineChartBarData1, lineChartBarData2]; + } +} diff --git a/lib/pages/medical/vital_sign/vital_sign_details_blood_pressurewideget.dart b/lib/pages/medical/vital_sign/vital_sign_details_blood_pressurewideget.dart new file mode 100644 index 00000000..e28b52e1 --- /dev/null +++ b/lib/pages/medical/vital_sign/vital_sign_details_blood_pressurewideget.dart @@ -0,0 +1,146 @@ +import 'package:diplomaticquarterapp/core/model/vital_sign/vital_sign_res_model.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:hexcolor/hexcolor.dart'; +import 'package:provider/provider.dart'; + +class VitalSignBloodPressureWidget extends StatefulWidget { + final List vitalList; + final String title1; + final String title2; + final String title3; + final String viewKey1; + final String viewKey2; + + VitalSignBloodPressureWidget( + {Key key, this.vitalList, this.title1, this.title2, this.viewKey1, this.title3, this.viewKey2}); + + @override + _VitalSignDetailsWidgetState createState() => _VitalSignDetailsWidgetState(); +} + +class _VitalSignDetailsWidgetState extends State { + @override + Widget build(BuildContext context) { + ProjectViewModel projectViewModel = Provider.of(context); + return Container( + decoration: BoxDecoration( + color: Colors.transparent, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(10.0), topRight: Radius.circular(10.0)), + border: Border.all(color: Colors.grey, width: 1), + ), + margin: EdgeInsets.all(20), + child: Container( + color: Colors.transparent, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Table( + border: TableBorder.symmetric( + inside: BorderSide(width: 2.0, color: Colors.grey[300]), + ), + children: fullData(projectViewModel), + ), + ], + ), + ), + ); + } + + List fullData(ProjectViewModel projectViewModel) { + List tableRow = []; + tableRow.add(TableRow(children: [ + Container( + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).primaryColor, + borderRadius: BorderRadius.only( + topLeft:projectViewModel.isArabic? Radius.circular(0.0):Radius.circular(10.0), + topRight: projectViewModel.isArabic? Radius.circular(10.0):Radius.circular(0.0) + ), + ), + child: Center( + child: Texts( + TranslationBase.of(context).date, + color: Colors.white, + ), + ), + height: 60, + ), + ), + Container( + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).primaryColor, + + ), + child: Center( + child: Texts(widget.title2, color: Colors.white), + ), + height: 60), + ), + Container( + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).primaryColor, + borderRadius: BorderRadius.only( + topRight: projectViewModel.isArabic? Radius.circular(0.0):Radius.circular(10.0), + topLeft: projectViewModel.isArabic? Radius.circular(10.0):Radius.circular(0.0) + ), + ), + child: Center( + child: Texts(widget.title3, color: Colors.white), + ), + height: 60), + ), + ])); + widget.vitalList.forEach((vital) { + var data = vital.toJson()[widget.viewKey1]; + if (data != 0) + tableRow.add(TableRow(children: [ + Container( + child: Container( + padding: EdgeInsets.all(10), + color: Colors.white, + child: Center( + child: Texts( + '${projectViewModel.isArabic ? DateUtil.getWeekDayArabic(vital.vitalSignDate.weekday) : DateUtil.getWeekDay(vital.vitalSignDate.weekday)}, ${vital.vitalSignDate.day} ${projectViewModel.isArabic ? DateUtil.getMonthArabic(vital.vitalSignDate.month) : DateUtil.getMonth(vital.vitalSignDate.month)}, ${vital.vitalSignDate.year} ', + textAlign: TextAlign.center, + ), + ), + ), + ), + Container( + child: Container( + padding: EdgeInsets.all(10), + color: Colors.white, + child: Center( + child: Texts( + '${vital.toJson()[widget.viewKey1]}', + textAlign: TextAlign.center, + ), + ), + ), + ), + Container( + child: Container( + padding: EdgeInsets.all(10), + color: Colors.white, + child: Center( + child: Texts( + '${vital.toJson()[widget.viewKey2]}', + textAlign: TextAlign.center, + ), + ), + ), + ), + ])); + }); + return tableRow; + } +} diff --git a/lib/pages/medical/vital_sign/vital_sign_details_screen.dart b/lib/pages/medical/vital_sign/vital_sign_details_screen.dart index c4273a09..4d141b5f 100644 --- a/lib/pages/medical/vital_sign/vital_sign_details_screen.dart +++ b/lib/pages/medical/vital_sign/vital_sign_details_screen.dart @@ -17,7 +17,8 @@ class VitalSignDetailsScreen extends StatelessWidget { int appointmentNo; int projectID; - VitalSignDetailsScreen({this.appointmentNo, this.projectID}); + bool isNotOneAppointment; + VitalSignDetailsScreen({this.appointmentNo, this.projectID,this.isNotOneAppointment=true}); List imagesInfo = List(); @@ -27,9 +28,9 @@ class VitalSignDetailsScreen extends StatelessWidget { imagesInfo.add(ImagesInfo(imageEn: 'https://hmgwebservices.com/Images/MobileApp/imges-info/my-vital-signs/en/1.png',imageAr: 'https://hmgwebservices.com/Images/MobileApp/imges-info/my-vital-signs/ar/1.png')); return BaseView( onModelReady: appointmentNo != null && projectID != null - ? (model) => model.getPatientRadOrders( + ? (model) => model.getPatientVitalSign( appointmentNo: appointmentNo, projectID: projectID) - : (model) => model.getPatientRadOrders(), + : (model) => model.getPatientVitalSign(), builder: (_, mode, widget) => AppScaffold( isShowAppBar: true, appBarTitle: TranslationBase.of(context).vitalSigns, @@ -43,7 +44,7 @@ class VitalSignDetailsScreen extends StatelessWidget { Row( children: [ InkWell( - onTap: () => Navigator.push( + onTap: () =>isNotOneAppointment? Navigator.push( context, FadePage( page: VitalSignItemDetailsScreen( @@ -52,22 +53,18 @@ class VitalSignDetailsScreen extends StatelessWidget { vitalList: mode.vitalSignResModelList, ), ), - ), + ):null, child: Container( child: VitalSignItem( des: TranslationBase.of(context).height, icon: DQIcons.height, - lastVal: mode - .vitalSignResModelList[ - mode.vitalSignResModelList.length - 1] - .heightCm - .toString(), + lastVal: mode.heightCm, unit: TranslationBase.of(context).cm, ), ), ), InkWell( - onTap: () => Navigator.push( + onTap: () => isNotOneAppointment ? Navigator.push( context, FadePage( page: VitalSignItemDetailsScreen( @@ -76,16 +73,12 @@ class VitalSignDetailsScreen extends StatelessWidget { vitalList: mode.vitalSignResModelList, ), ), - ), + ):null, child: VitalSignItem( des: TranslationBase.of(context).weight, icon: DQIcons.weight_scale, unit: TranslationBase.of(context).kg, - lastVal: mode - .vitalSignResModelList[ - mode.vitalSignResModelList.length - 1] - .weightKg - .toString(), + lastVal: mode.weightKg, ), ), ], @@ -93,7 +86,7 @@ class VitalSignDetailsScreen extends StatelessWidget { Row( children: [ InkWell( - onTap: () => Navigator.push( + onTap: () => isNotOneAppointment ? Navigator.push( context, FadePage( page: VitalSignItemDetailsScreen( @@ -103,18 +96,16 @@ class VitalSignDetailsScreen extends StatelessWidget { vitalList: mode.vitalSignResModelList, ), ), - ), + ): null, child: VitalSignItem( des: TranslationBase.of(context).body, icon: DQIcons.bmi, - lastVal: mode - .vitalSignResModelList[0].pulseBeatPerMinute - .toString(), + lastVal: mode.bodyMax, unit: TranslationBase.of(context).mass, ), ), InkWell( - onTap: () => Navigator.push( + onTap: () => isNotOneAppointment ? Navigator.push( context, FadePage( page: VitalSignItemDetailsScreen( @@ -124,14 +115,12 @@ class VitalSignDetailsScreen extends StatelessWidget { vitalList: mode.vitalSignResModelList, ), ), - ), + ):null, child: Container( child: VitalSignItem( des: TranslationBase.of(context).temperature, icon: DQIcons.thermometer, - lastVal: mode - .vitalSignResModelList[0].temperatureCelcius - .toString(), + lastVal: mode.temperatureCelcius, unit: TranslationBase.of(context).tempC, ), ), @@ -141,7 +130,7 @@ class VitalSignDetailsScreen extends StatelessWidget { Row( children: [ InkWell( - onTap: () => Navigator.push( + onTap: () => isNotOneAppointment ? Navigator.push( context, FadePage( page: VitalSignItemDetailsScreen( @@ -150,20 +139,16 @@ class VitalSignDetailsScreen extends StatelessWidget { vitalList: mode.vitalSignResModelList, ), ), - ), + ):null, child: VitalSignItem( des: TranslationBase.of(context).heart, icon: DQIcons.heart, - lastVal: mode - .vitalSignResModelList[ - mode.vitalSignResModelList.length - 1] - .pulseBeatPerMinute - .toString(), + lastVal: mode.hartRat, unit: TranslationBase.of(context).bpm, ), ), InkWell( - onTap: () => Navigator.push( + onTap: () => isNotOneAppointment ? Navigator.push( context, FadePage( page: VitalSignItemDetailsScreen( @@ -173,15 +158,11 @@ class VitalSignDetailsScreen extends StatelessWidget { vitalList: mode.vitalSignResModelList, ), ), - ), + ):null, child: VitalSignItem( des: TranslationBase.of(context).respirationRate, icon: DQIcons.outline, - lastVal: mode - .vitalSignResModelList[ - mode.vitalSignResModelList.length - 1] - .respirationBeatPerMinute - .toString(), + lastVal: mode.respirationBeatPerMinute, unit: TranslationBase.of(context).respirationSigns, ), ), @@ -191,24 +172,20 @@ class VitalSignDetailsScreen extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.center, children: [ InkWell( - onTap: () => Navigator.push( + onTap: () => isNotOneAppointment ? Navigator.push( context, FadePage( page: VitalSignItemDetailsScreen( pageKey: VitalSignDetails.BloodPressure, - pageTitle: TranslationBase.of(context).pulse, + pageTitle: TranslationBase.of(context).bloodPressure, vitalList: mode.vitalSignResModelList, ), ), - ), + ):null, child: VitalSignItem( - des: TranslationBase.of(context).pulse, + des: TranslationBase.of(context).bloodPressure, icon: DQIcons.blood_pressure, - lastVal: mode - .vitalSignResModelList[ - mode.vitalSignResModelList.length - 1] - .bloodPressure - .toString(), + lastVal: mode.bloodPressure, unit: TranslationBase.of(context).sysDias, ), ), diff --git a/lib/pages/medical/vital_sign/vital_sign_details_wideget.dart b/lib/pages/medical/vital_sign/vital_sign_details_wideget.dart index 589284a1..113e29a6 100644 --- a/lib/pages/medical/vital_sign/vital_sign_details_wideget.dart +++ b/lib/pages/medical/vital_sign/vital_sign_details_wideget.dart @@ -1,9 +1,12 @@ import 'package:diplomaticquarterapp/core/model/vital_sign/vital_sign_res_model.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:hexcolor/hexcolor.dart'; +import 'package:provider/provider.dart'; class VitalSignDetailsWidget extends StatefulWidget { final List vitalList; @@ -21,6 +24,7 @@ class VitalSignDetailsWidget extends StatefulWidget { class _VitalSignDetailsWidgetState extends State { @override Widget build(BuildContext context) { + ProjectViewModel projectViewModel = Provider.of(context); return Container( decoration: BoxDecoration( color: Colors.transparent, @@ -38,7 +42,7 @@ class _VitalSignDetailsWidgetState extends State { border: TableBorder.symmetric( inside: BorderSide(width: 2.0, color: Colors.grey[300]), ), - children: fullData(), + children: fullData(projectViewModel), ), ], ), @@ -46,20 +50,21 @@ class _VitalSignDetailsWidgetState extends State { ); } - List fullData() { + List fullData(ProjectViewModel projectViewModel) { List tableRow = []; tableRow.add(TableRow(children: [ Container( child: Container( decoration: BoxDecoration( - color: HexColor('#515B5D'), + color: Theme.of(context).primaryColor, borderRadius: BorderRadius.only( - topLeft: Radius.circular(10.0), + topLeft:projectViewModel.isArabic? Radius.circular(0.0):Radius.circular(10.0), + topRight: projectViewModel.isArabic? Radius.circular(10.0):Radius.circular(0.0) ), ), child: Center( child: Texts( - widget.title1, + TranslationBase.of(context).date, color: Colors.white, ), ), @@ -69,9 +74,10 @@ class _VitalSignDetailsWidgetState extends State { Container( child: Container( decoration: BoxDecoration( - color: HexColor('#515B5D'), + color: Theme.of(context).primaryColor, borderRadius: BorderRadius.only( - topRight: Radius.circular(10.0), + topRight: projectViewModel.isArabic? Radius.circular(0.0):Radius.circular(10.0), + topLeft: projectViewModel.isArabic? Radius.circular(10.0):Radius.circular(0.0) ), ), child: Center( @@ -81,32 +87,34 @@ class _VitalSignDetailsWidgetState extends State { ) ])); widget.vitalList.forEach((vital) { - tableRow.add(TableRow(children: [ - Container( - child: Container( - padding: EdgeInsets.all(10), - color: Colors.white, - child: Center( - child: Texts( - '${DateUtil.getWeekDay(vital.vitalSignDate.weekday)}, ${vital.vitalSignDate.day} ${DateUtil.getMonth(vital.vitalSignDate.month)}, ${vital.vitalSignDate.year} ', - textAlign: TextAlign.center, + var data = vital.toJson()[widget.viewKey]; + if (data != 0) + tableRow.add(TableRow(children: [ + Container( + child: Container( + padding: EdgeInsets.all(10), + color: Colors.white, + child: Center( + child: Texts( + '${projectViewModel.isArabic ? DateUtil.getWeekDayArabic(vital.vitalSignDate.weekday) : DateUtil.getWeekDay(vital.vitalSignDate.weekday)}, ${vital.vitalSignDate.day} ${projectViewModel.isArabic ? DateUtil.getMonthArabic(vital.vitalSignDate.month) : DateUtil.getMonth(vital.vitalSignDate.month)}, ${vital.vitalSignDate.year} ', + textAlign: TextAlign.center, + ), ), ), ), - ), - Container( - child: Container( - padding: EdgeInsets.all(10), - color: Colors.white, - child: Center( - child: Texts( - '${vital.toJson()[widget.viewKey]}', - textAlign: TextAlign.center, + Container( + child: Container( + padding: EdgeInsets.all(10), + color: Colors.white, + child: Center( + child: Texts( + '${vital.toJson()[widget.viewKey]}', + textAlign: TextAlign.center, + ), ), ), ), - ), - ])); + ])); }); return tableRow; } diff --git a/lib/pages/medical/vital_sign/vital_sign_item.dart b/lib/pages/medical/vital_sign/vital_sign_item.dart index 5304bb9b..fb44772d 100644 --- a/lib/pages/medical/vital_sign/vital_sign_item.dart +++ b/lib/pages/medical/vital_sign/vital_sign_item.dart @@ -46,7 +46,7 @@ class VitalSignItem extends StatelessWidget { des, style: TextStyle( fontSize: 1.7 * SizeConfig.textMultiplier, - color: Theme.of(context).textTheme.headline1.color, + color: HexColor('#B8382C'), fontWeight: FontWeight.bold, ), ), @@ -76,9 +76,9 @@ class VitalSignItem extends StatelessWidget { text: TextSpan( style: TextStyle(color: Colors.black), children: [ - TextSpan(text: lastVal + " "), + TextSpan(text: lastVal), TextSpan( - text: " " + unit, + text: unit, style: TextStyle( color: HexColor('#B8382C'), ), diff --git a/lib/pages/medical/vital_sign/vital_sign_item_details_screen.dart b/lib/pages/medical/vital_sign/vital_sign_item_details_screen.dart index 802aae38..6db865b6 100644 --- a/lib/pages/medical/vital_sign/vital_sign_item_details_screen.dart +++ b/lib/pages/medical/vital_sign/vital_sign_item_details_screen.dart @@ -1,8 +1,11 @@ import 'package:diplomaticquarterapp/core/enum/patient_lookup.dart'; import 'package:diplomaticquarterapp/core/model/vital_sign/vital_sign_res_model.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/pages/medical/vital_sign/vital_sing_chart_and_detials.dart'; +import 'package:diplomaticquarterapp/pages/medical/vital_sign/vital_sing_chart_blood_pressure.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; class VitalSignItemDetailsScreen extends StatelessWidget { final VitalSignDetails pageKey; @@ -15,45 +18,19 @@ class VitalSignItemDetailsScreen extends StatelessWidget { @override Widget build(BuildContext context) { + ProjectViewModel projectViewModel = Provider.of(context); switch (pageKey) { case VitalSignDetails.BodyMeasurements: VSchart = [ { - 'name': 'Height', + 'name': 'BMI', + 'nameAr': 'مؤشر الكتلة', 'title1': 'Date', - 'title2': 'Cm', - 'viewKey': 'HeightCm', - }, - { - 'name': 'Weight Kg', - 'title1': 'Date', - 'title2': 'Kg', - 'viewKey': 'WeightKg', - }, - { - 'name': 'BodyMassIndex', - 'title1': 'Date', - 'title2': 'BodyMass', + 'title2': 'BMI', + 'title2Ar': 'الكتلة', 'viewKey': 'BodyMassIndex', }, - { - 'name': 'HeadCircumCm', - 'title1': 'Date', - 'title2': 'Cm', - 'viewKey': 'HeadCircumCm', - }, - { - 'name': 'Ideal Body Weight (Lbs)', - 'title1': 'Date', - 'title2': 'Ideal Weight', - 'viewKey': 'IdealBodyWeightLbs', - }, - { - 'name': 'LeanBodyWeightLbs (Lbs)', - 'title1': 'Date', - 'title2': 'Lean Weight', - 'viewKey': 'LeanBodyWeightLbs', - } + ]; break; @@ -61,9 +38,11 @@ class VitalSignItemDetailsScreen extends StatelessWidget { case VitalSignDetails.Temperature: VSchart = [ { - 'name': 'Temperature In Celcius', + 'name': 'Temperature In Celsius', + 'nameAr': 'درجة الحرارة بالدرجة المئوية', 'title1': 'Date', 'title2': 'C', + 'title2Ar': 'ْس', 'viewKey': 'TemperatureCelcius', }, ]; @@ -73,8 +52,10 @@ class VitalSignItemDetailsScreen extends StatelessWidget { VSchart = [ { 'name': 'Pulse Beat Per Minute', + 'nameAr': 'نبضة نبضة في الدقيقة', 'title1': 'Date', 'title2': 'Minute', + 'title2Ar': 'دقيقة', 'viewKey': 'PulseBeatPerMinute', }, ]; @@ -84,8 +65,10 @@ class VitalSignItemDetailsScreen extends StatelessWidget { VSchart = [ { 'name': 'Respiration Beat Per Minute', + 'nameAr': 'ضربات التنفس في الدقيقة', 'title1': 'Date', 'title2': 'Beat Per Minute', + 'title2Ar': 'نفس في الدقيقة', 'viewKey': 'RespirationBeatPerMinute', }, ]; @@ -94,17 +77,16 @@ class VitalSignItemDetailsScreen extends StatelessWidget { case VitalSignDetails.BloodPressure: VSchart = [ { - 'name': 'Blood Pressure Higher', + 'name': 'Blood Pressure Systolic Diastolic', + 'nameAr': 'ضغط الدم الإنقباض الإنبساط', 'title1': 'Date', - 'title2': 'Minute', - 'viewKey': 'BloodPressureHigher', + 'title2': 'systolic', + 'title3': 'Diastolic', + 'title2Ar': 'الإنقباض', + 'title3Ar': 'الإنبساط', + 'viewKey': 'BloodPressure', }, - { - 'name': 'Blood Pressure Lower', - 'title1': 'Date', - 'title2': 'Minute', - 'viewKey': 'BloodPressureLower', - } + ]; break; @@ -112,8 +94,10 @@ class VitalSignItemDetailsScreen extends StatelessWidget { VSchart = [ { 'name': 'Respiration Rate', + 'nameAr': 'معدل التنفس', 'title1': 'Date', 'title2': 'bpm', + 'title2Ar': 'نفس', 'viewKey': 'RespirationBeatPerMinute', }, ]; @@ -122,9 +106,11 @@ class VitalSignItemDetailsScreen extends StatelessWidget { case VitalSignDetails.heart: VSchart = [ { - 'name': 'FIO2', + 'name': 'Heart rate', + 'nameAr': 'معدل النبض بالدقيقة', 'title1': 'Date', 'title2': 'bpm', + 'title2Ar': 'نبضة', 'viewKey': 'PulseBeatPerMinute', }, ]; @@ -134,8 +120,10 @@ class VitalSignItemDetailsScreen extends StatelessWidget { VSchart = [ { 'name': 'PainScore', + 'nameAr': 'نقاط الألم', 'title1': 'Date', 'title2': 'Cm', + 'title2Ar': 'سم', 'viewKey': 'PainScore', }, ]; @@ -145,8 +133,10 @@ class VitalSignItemDetailsScreen extends StatelessWidget { VSchart = [ { 'name': 'Weight Kg', + 'nameAr': 'الوزن كجم', 'title1': 'Date', 'title2': 'Kg', + 'title2Ar': 'كجم', 'viewKey': 'WeightKg', }, ]; @@ -157,8 +147,10 @@ class VitalSignItemDetailsScreen extends StatelessWidget { VSchart = [ { 'name': 'Height Cm', + 'nameAr': 'الطول سم', 'title1': 'Date', 'title2': 'Cm', + 'title2Ar': 'سم', 'viewKey': 'HeightCm', }, ]; @@ -174,12 +166,26 @@ class VitalSignItemDetailsScreen extends StatelessWidget { var vitalListTemp = vitalList.where( (element) => element.toJson()[chartInfo['viewKey']] != null, ); + + if(vitalListTemp.length != 0 && chartInfo['viewKey']=='BloodPressure'){ + return VitalSingChartBloodPressure( + vitalList: vitalList, + name:projectViewModel.isArabic? chartInfo['nameAr']:chartInfo['name'], + title1: chartInfo['title1'], + title2:projectViewModel.isArabic?chartInfo['title2Ar']: chartInfo['title2'], + title3:projectViewModel.isArabic?chartInfo['title3Ar']: chartInfo['title3'], + viewKey1: 'BloodPressureHigher', + viewKey2: 'BloodPressureLower', + + ); + } + return vitalListTemp.length != 0 ? VitalSingChartAndDetials( vitalList: vitalList, - name: chartInfo['name'], + name:projectViewModel.isArabic? chartInfo['nameAr']:chartInfo['name'], title1: chartInfo['title1'], - title2: chartInfo['title2'], + title2:projectViewModel.isArabic?chartInfo['title2Ar']: chartInfo['title2'], viewKey: chartInfo['viewKey']) : Container(); }).toList(), diff --git a/lib/pages/medical/vital_sign/vital_sing_chart_and_detials.dart b/lib/pages/medical/vital_sign/vital_sing_chart_and_detials.dart index 299605ef..43bc9f0a 100644 --- a/lib/pages/medical/vital_sign/vital_sing_chart_and_detials.dart +++ b/lib/pages/medical/vital_sign/vital_sing_chart_and_detials.dart @@ -6,6 +6,8 @@ import 'package:flutter/material.dart'; import 'package:charts_flutter/flutter.dart' as charts; +import 'LineChartCurved.dart'; + class VitalSingChartAndDetials extends StatelessWidget { VitalSingChartAndDetials({ Key key, @@ -21,31 +23,18 @@ class VitalSingChartAndDetials extends StatelessWidget { final String viewKey; final String title1; final String title2; - List timeSeriesData = []; + List timeSeriesData = []; @override Widget build(BuildContext context) { + generateData(); return Column( children: [ AppExpandableNotifier( - headerWidget: AppTimeSeriesChart( - seriesList: generateData(), - chartName: name, - startDate: DateTime( - vitalList[vitalList.length - 1] - .vitalSignDate - .year, - vitalList[vitalList.length - 1] - .vitalSignDate - .month + - 3, - vitalList[vitalList.length - 1] - .vitalSignDate - .day), - endDate: vitalList[0].vitalSignDate, - ), + isExpand: true, + headerWidget: LineChartCurved(title: name,timeSeries:timeSeriesData,indexes: timeSeriesData.length~/5.5,), bodyWidget: VitalSignDetailsWidget( - vitalList: vitalList.reversed.toList(), + vitalList: vitalList, title1: title1, title2: title2, viewKey: viewKey, @@ -57,26 +46,18 @@ class VitalSingChartAndDetials extends StatelessWidget { generateData() { if (vitalList.length > 0) { - vitalList.forEach( + vitalList.reversed.toList().forEach( (element) { + if( element.toJson()[viewKey]!=null && element.toJson()[viewKey]?.toInt()!=0) timeSeriesData.add( - TimeSeriesSales( - new DateTime(element.vitalSignDate.year, - element.vitalSignDate.month, element.vitalSignDate.day), - element.toJson()[viewKey]?.toInt(), + TimeSeriesSales2( + new DateTime(element.vitalSignDate.year, element.vitalSignDate.month, element.vitalSignDate.day), + element.toJson()[viewKey].toDouble(), ), ); }, ); } - return [ - new charts.Series( - id: 'Sales', - colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault, - domainFn: (TimeSeriesSales sales, _) => sales.time, - measureFn: (TimeSeriesSales sales, _) => sales.sales, - data: timeSeriesData, - ) - ]; + return timeSeriesData.reversed.toList(); } } diff --git a/lib/pages/medical/vital_sign/vital_sing_chart_blood_pressure.dart b/lib/pages/medical/vital_sign/vital_sing_chart_blood_pressure.dart new file mode 100644 index 00000000..84a2eb51 --- /dev/null +++ b/lib/pages/medical/vital_sign/vital_sing_chart_blood_pressure.dart @@ -0,0 +1,85 @@ +import 'package:diplomaticquarterapp/core/model/vital_sign/vital_sign_res_model.dart'; +import 'package:diplomaticquarterapp/pages/medical/vital_sign/vital_sign_details_blood_pressurewideget.dart'; +import 'package:diplomaticquarterapp/pages/medical/vital_sign/vital_sign_details_wideget.dart'; +import 'package:diplomaticquarterapp/widgets/charts/app_time_series_chart.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_expandable_notifier.dart'; +import 'package:flutter/material.dart'; + +import 'package:charts_flutter/flutter.dart' as charts; + +import 'LineChartCurved.dart'; +import 'LineChartCurvedBloodPressure.dart'; + +class VitalSingChartBloodPressure extends StatelessWidget { + VitalSingChartBloodPressure({ + Key key, + @required this.vitalList, + @required this.name, + @required this.viewKey1, + @required this.viewKey2, + @required this.title1, + @required this.title2, + @required this.title3, + }) : super(key: key); + + final List vitalList; + final String name; + final String viewKey1; + final String viewKey2; + final String title1; + final String title2; + final String title3; + List timeSeriesData1 = []; + List timeSeriesData2 = []; + + @override + Widget build(BuildContext context) { + generateData(); + return Column( + children: [ + AppExpandableNotifier( + isExpand: true, + headerWidget: LineChartCurvedBloodPressure( + title: name, + timeSeries1: timeSeriesData1, + timeSeries2: timeSeriesData2, + indexes: timeSeriesData1.length ~/ 5.5, + ), + bodyWidget: VitalSignBloodPressureWidget( + vitalList: vitalList, + title1: title1, + title2: title2, + title3: title3, + viewKey1: viewKey1, + viewKey2: viewKey2, + ), + ), + ], + ); + } + + generateData() { + if (vitalList.length > 0) { + vitalList.reversed.toList().forEach( + (element) { + if (element.toJson()[viewKey1]?.toInt() != 0) + timeSeriesData1.add( + TimeSeriesSales2( + new DateTime(element.vitalSignDate.year, + element.vitalSignDate.month, element.vitalSignDate.day), + element.toJson()[viewKey1].toDouble(), + ), + ); + if (element.toJson()[viewKey2]?.toInt() != 0) + timeSeriesData2.add( + TimeSeriesSales2( + new DateTime(element.vitalSignDate.year, + element.vitalSignDate.month, element.vitalSignDate.day), + element.toJson()[viewKey2].toDouble(), + ), + ); + }, + ); + } + } +} diff --git a/lib/pages/offers_categorise_page.dart b/lib/pages/offers_categorise_page.dart new file mode 100644 index 00000000..782ea018 --- /dev/null +++ b/lib/pages/offers_categorise_page.dart @@ -0,0 +1,620 @@ +import 'package:diplomaticquarterapp/config/size_config.dart'; +import 'package:diplomaticquarterapp/core/viewModels/offers_Categorise_view_model.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; +import 'package:diplomaticquarterapp/widgets/others/StarRating.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_pharmacy_widget.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:diplomaticquarterapp/widgets/others/network_base_view.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import 'base/base_view.dart'; + +class OffersCategorisePage extends StatefulWidget { + @override + _OffersCategorisePageState createState() => _OffersCategorisePageState(); +} + +class _OffersCategorisePageState extends State { + String categoriseName = "Personal Care"; + bool styleOne = true; + bool styleTwo = false; + Icon styleIcon = Icon( + Icons.widgets_sharp, + color: Colors.blue, + size: 29.0, + ); + + @override + Widget build(BuildContext context) { + ProjectViewModel projectProvider = Provider.of(context); + return BaseView( + onModelReady: (model) => model.getOffersCategorise(), + builder: (BuildContext context, OffersCategoriseViewModel model, + Widget child) => + PharmacyAppScaffold( + appBarTitle: 'Offers', + isShowAppBar: true, + backgroundColor: Colors.white, + isShowDecPage: false, + baseViewModel: model, + body: Container( + //height: MediaQuery.of(context).size.height * 0.57, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.all(10.0), + child: Container( + child: Texts( + 'Categories', + fontWeight: FontWeight.w800, + ), + ), + ), + Divider( + thickness: 1.0, + color: Colors.grey.shade400, + ), + //Expanded widget heree if nassery + Container( + height: MediaQuery.of(context).size.height * 0.20, + child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: model.categorise.length, + itemBuilder: (BuildContext context, int index) { + return Padding( + padding: EdgeInsets.all(8.0), + child: Row( + children: [ + InkWell( + child: Column( + children: [ + Container( + height: 60.0, + width: 65.0, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.orange.shade200 + .withOpacity(0.45), + ), + child: Icon( + Icons.apps_sharp, + size: 32.0, + ), + ), + Container( + width: MediaQuery.of(context) + .size + .width * + 0.2, + height: MediaQuery.of(context) + .size + .height * + 0.09, + child: Center( + child: Texts( + model.categorise[index].name, + fontWeight: FontWeight.w600, + fontSize: 13.8, + ), + ), + ), + ], + ), + onTap: () { + model.getOffersProducts( + i: model.categorise[index].id); + String ids = model.categorise[index].id; + + categoriseName = + model.categorise[index].name; + }), + ], + ), + ); + }), + ), + Divider( + thickness: 1.0, + color: Colors.grey.shade400, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: EdgeInsets.all(8.0), + child: Texts( + categoriseName, + fontWeight: FontWeight.w800, + ), + ), + Row( + children: [ + Container( + height: 44.0, + child: VerticalDivider( + color: Colors.black45, + thickness: 0.7, + //width: 0.3, + // indent: 0.0, + ), + ), + Padding( + padding: EdgeInsets.all(8.0), + child: InkWell( + child: styleIcon, + onTap: () { + setState(() { + if (styleOne == true) { + styleOne = false; + styleTwo = true; + styleIcon = Icon( + Icons.auto_awesome_mosaic, + color: Colors.blue, + size: 29.0, + ); + } else { + styleOne = true; + styleTwo = false; + styleIcon = Icon( + Icons.widgets_sharp, + color: Colors.blue, + size: 29.0, + ); + } + }); + }, + ), + ), + ], + ), + ], + ), + Divider( + thickness: 1.0, + color: Colors.grey.shade400, + ), + styleOne == true + ? Expanded( + child: Container( + height: MediaQuery.of(context).size.height * 0.50, + child: GridView.builder( + gridDelegate: + SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + crossAxisSpacing: 0.5, + mainAxisSpacing: 2.0, + childAspectRatio: 0.85, + ), + itemCount: model.products.length, + itemBuilder: (BuildContext context, int index) { + return NetworkBaseView( + baseViewModel: model, + child: Card( + color: model.products[index] + .discountName != + null + ? Color(0xffFFFF00) + : Colors.white, + elevation: 0, + shape: Border( + right: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + left: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + bottom: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + top: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + ), + margin: EdgeInsets.symmetric( + horizontal: 8, + vertical: 4, + ), + child: Container( + height: 250.0, + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(110.0), + ), + color: Colors.white, + ), + padding: EdgeInsets.symmetric( + horizontal: 0), + width: MediaQuery.of(context) + .size + .width / + 3, + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Stack( + children: [ + if (model.products[index] + .discountName != + null) + RotatedBox( + quarterTurns: 4, + child: Container( + decoration: + BoxDecoration(), + child: Padding( + padding: + EdgeInsets.only( + right: 5.0, + top: 20.0, + bottom: 5.0, + ), + child: Texts( + 'offer' + .toUpperCase(), + color: Colors.red, + fontSize: 13.0, + fontWeight: + FontWeight.w900, + ), + ), + transform: new Matrix4 + .rotationZ( + 5.837200), + ), + ), + Container( + margin: EdgeInsets.fromLTRB( + 0, 16, 0, 0), + alignment: Alignment.center, + child: Image.network( + model.products[index] + .images.isNotEmpty + ? model + .products[index] + .images[0] + .thumb + : 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/No_image_3x4.svg/1200px-No_image_3x4.svg.png', + fit: BoxFit.cover, + height: 80, + ), + ), + Container( + width: model.products[index] + .rxMessage != + null + ? MediaQuery.of(context) + .size + .width / + 5 + : 0, + padding: EdgeInsets.all(4), + decoration: BoxDecoration( + color: Color(0xffb23838), + borderRadius: + BorderRadius.only( + topLeft: Radius + .circular(6)), + ), + child: Texts( + model.products[index] + .rxMessage != + null + ? model + .products[index] + .rxMessage + : "", + color: Colors.white, + regular: true, + fontSize: 10, + fontWeight: + FontWeight.w400, + ), + ), + ], + ), + Container( + margin: EdgeInsets.symmetric( + horizontal: 6, + vertical: 0, + ), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + if (model.products[index] + .discountName != + null) + Container( + width: double.infinity, + height: 22.0, + decoration: + BoxDecoration( + color: + Color(0xff5AB145), + ), + child: Center( + child: Texts( + model + .products[index] + .discountName, + regular: true, + color: Colors.white, + fontSize: 12.0, + fontWeight: + FontWeight.w700, + ), + ), + ), + Texts( + model + .products[index].name, + regular: true, + fontSize: 12.58, + fontWeight: + FontWeight.w600, + ), + Padding( + padding: + const EdgeInsets.only( + top: 4, + bottom: 4), + child: Texts( + "SAR ${model.products[index].price}", + bold: true, + fontSize: 14, + ), + ), + Row( + children: [ + StarRating( + totalAverage: model + .products[ + index] + .approvedRatingSum > + 0 + ? (model.products[index].approvedRatingSum + .toDouble() / + model + .products[index] + .approvedRatingSum + .toDouble()) + .toDouble() + : 0, + forceStars: true), + Texts( + "(${model.products[index].approvedTotalReviews})", + regular: true, + fontSize: 10, + fontWeight: + FontWeight.w400, + ) + ], + ), + ], + ), + ), + ], + ), + ), + )); + }, + ), + ), + ) + : Expanded( + child: Container( + child: ListView.builder( + itemCount: model.products.length, + itemBuilder: + (BuildContext context, int index) { + return Card( + // color: + // model.products[index].discountName != + // null + // ? Color(0xffFFFF00) + // : Colors.white, + child: Row( + children: [ + Stack( + children: [ + Column( + children: [ + if (model.products[index] + .discountName != + null) + Container( + decoration: + BoxDecoration(), + child: Padding( + padding: + EdgeInsets.only( + left: 9.0, + top: 8.0, + right: 10.0, + ), + child: Container( + color: Colors.yellow, + height: 25.0, + width: 70.0, + child: Center( + child: Texts( + 'offer' + .toUpperCase(), + color: Colors.red, + fontSize: 13.0, + fontWeight: + FontWeight + .w900, + ), + ), + ), + ), + transform: + new Matrix4.rotationZ( + 6.15099), + ), + Container( + margin: EdgeInsets.fromLTRB( + 0, 0, 0, 0), + alignment: Alignment.center, + child: Image.network( + model.products[index] + .images.isNotEmpty + ? model + .products[index] + .images[0] + .thumb + : 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/No_image_3x4.svg/1200px-No_image_3x4.svg.png', + fit: BoxFit.cover, + height: 80, + ), + ), + ], + ), + Column( + children: [ + Container( + width: model.products[index] + .rxMessage != + null + ? MediaQuery.of(context) + .size + .width / + 5 + : 0, + padding: EdgeInsets.all(4), + decoration: BoxDecoration( + color: Color(0xffb23838), + borderRadius: + BorderRadius.only( + topLeft: Radius + .circular(6)), + ), + child: Texts( + model.products[index] + .rxMessage != + null + ? model + .products[index] + .rxMessage + : "", + color: Colors.white, + regular: true, + fontSize: 10, + fontWeight: + FontWeight.w400, + ), + ), + ], + ), + ], + ), + Container( + margin: EdgeInsets.symmetric( + horizontal: 6, + vertical: 0, + ), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + if (model.products[index] + .discountName != + null) + Container( + width: 250.0, + height: 22.5, + decoration: BoxDecoration( + color: Color(0xff5AB145), + ), + child: Padding( + padding: + EdgeInsets.symmetric( + horizontal: 5.5, + ), + child: Texts( + model.products[index] + .discountName, + regular: true, + color: Colors.white, + fontSize: 12.0, + fontWeight: + FontWeight.w700, + ), + ), + ), + SizedBox( + height: 4.0, + ), + Texts( + model.products[index].name, + regular: true, + fontSize: 14.0, + fontWeight: FontWeight.w600, + ), + SizedBox( + height: 8.0, + ), + Padding( + padding: + const EdgeInsets.only( + top: 4, bottom: 4), + child: Texts( + "SAR ${model.products[index].price}", + bold: true, + fontSize: 14, + ), + ), + Row( + children: [ + StarRating( + totalAverage: model + .products[ + index] + .approvedRatingSum > + 0 + ? (model + .products[ + index] + .approvedRatingSum + .toDouble() / + model + .products[ + index] + .approvedRatingSum + .toDouble()) + .toDouble() + : 0, + forceStars: true), + Texts( + "(${model.products[index].approvedTotalReviews})", + regular: true, + fontSize: 10, + fontWeight: + FontWeight.w500, + ) + ], + ), + ], + ), + ), + ], + ), + ); + }), + ), + ) + ], + ), + ), + )); + } +} diff --git a/lib/pages/parent_categorise_page.dart b/lib/pages/parent_categorise_page.dart new file mode 100644 index 00000000..414106b1 --- /dev/null +++ b/lib/pages/parent_categorise_page.dart @@ -0,0 +1,1074 @@ +import 'package:diplomaticquarterapp/config/size_config.dart'; +import 'package:diplomaticquarterapp/core/viewModels/pharmacy_categorise_view_model.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/pages/sub_categorise_page.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/button.dart'; +import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; +import 'package:diplomaticquarterapp/widgets/others/StarRating.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_pharmacy_widget.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:diplomaticquarterapp/widgets/others/network_base_view.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:giffy_dialog/giffy_dialog.dart'; + +import 'base/base_view.dart'; +import 'final_products_page.dart'; + +class ParentCategorisePage extends StatefulWidget { + String id; + String titleName; + ParentCategorisePage({this.id, this.titleName}); + @override + _ParentCategorisePageState createState() => + _ParentCategorisePageState(id: id, titleName: titleName); +} + +class _ParentCategorisePageState extends State { + String id; + String titleName; + _ParentCategorisePageState({this.id, this.titleName}); + Map values = {'huusam': false, 'ali': false, 'noor': false}; + bool checkedBrands = false; + bool checkedCategorise = false; + String categoriseName = "Personal Care"; + bool styleOne = true; + bool styleTwo = false; + Icon styleIcon = Icon( + Icons.widgets_sharp, + color: Colors.blue, + size: 29.0, + ); + @override + Widget build(BuildContext context) { + ProjectViewModel projectViewModel = Provider.of(context); + return BaseView( + onModelReady: (model) => model.getCategoriseParent(i: id), + builder: (BuildContext context, PharmacyCategoriseViewModel model, + Widget child) => + PharmacyAppScaffold( + appBarTitle: titleName, + isBottomBar: false, + isShowAppBar: true, + backgroundColor: Colors.white, + isShowDecPage: false, + baseViewModel: model, + body: Container( + child: ListView( + scrollDirection: Axis.vertical, + children: [ + Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + child: Image.network( + id == '1' + ? 'https://uat.hmgwebservices.com/epharmacy/content/images/thumbs/0089188_personal-care_2.png' + : id == '2' + ? 'https://uat.hmgwebservices.com/epharmacy/content/images/thumbs/0089189_skin-care_2.png' + : id == '3' + ? 'https://uat.hmgwebservices.com/epharmacy/content/images/thumbs/0089190_health-care_2.png' + : id == '4' + ? 'https://uat.hmgwebservices.com/epharmacy/content/images/thumbs/0089191_sexual-health_2.png' + : id == '5' + ? 'https://uat.hmgwebservices.com/epharmacy/content/images/thumbs/0089192_beauty_2.png' + : id == '6' + ? 'https://uat.hmgwebservices.com/epharmacy/content/images/thumbs/0089193_baby-child_2.png' + : id == '7' + ? 'https://uat.hmgwebservices.com/epharmacy/content/images/thumbs/0089194_vitamins-supplements_2.png' + : id == '8' + ? 'https://uat.hmgwebservices.com/epharmacy/content/images/thumbs/0089195_diet-nutrition_2.png' + : id == '9' + ? 'https://uat.hmgwebservices.com/epharmacy/content/images/thumbs/0089196_household_2.png' + : id == '10' + ? 'https://uat.hmgwebservices.com/epharmacy/content/images/thumbs/0089197_home-care-appliances_2.png' + : '', + fit: BoxFit.fill, + height: 160.0, + width: double.infinity), + ), + if (model.categoriseParent.length > 8) + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: EdgeInsets.all(10.0), + child: InkWell( + child: Container( + child: Texts( + 'View All Categories', + fontWeight: FontWeight.w300, + ), + ), + onTap: () { + showModalBottomSheet( + isScrollControlled: true, + context: context, + builder: (BuildContext context) { + return Container( + height: MediaQuery.of(context) + .size + .height * + 0.89, + color: Colors.white, + child: Center( + child: ListView.builder( + scrollDirection: + Axis.vertical, + itemCount: model + .categoriseParent + .length, + itemBuilder: + (BuildContext context, + int index) { + return Container( + child: Padding( + padding: + EdgeInsets.all( + 8.0), + child: InkWell( + child: Column( + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + Texts(model + .categoriseParent[ + index] + .name), + Divider( + thickness: + 0.6, + color: Colors + .black12, + ) + ], + ), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: + (context) => + SubCategorisePage( + title: model.categoriseParent[index].name, + id: model.categoriseParent[index].id, + parentId: id, + )), + ); + }, + ), + ), + ); + }), + ), + ); + }, + ); + }, + ), + ), + Icon(Icons.arrow_forward) + ], + ), + Divider( + thickness: 1.0, + color: Colors.grey.shade400, + ), + ], + ), + +//Expanded widget heree if nassery + Padding( + padding: EdgeInsets.only(top: 35.0), + child: Container( + height: MediaQuery.of(context).size.height * 0.2, + child: Center( + child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: model.categoriseParent.length > 8 + ? 8 + : model.categoriseParent.length, + itemBuilder: + (BuildContext context, int index) { + return Padding( + padding: EdgeInsets.symmetric( + horizontal: 8.0), + child: InkWell( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + Padding( + padding: EdgeInsets.symmetric( + horizontal: 13.0), + child: Container( + height: 60.0, + width: 65.0, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors + .orange.shade200 + .withOpacity(0.45), + ), + child: Center( + child: Icon( + Icons.apps_sharp, + size: 32.0, + ), + ), + ), + ), + Container( + width: MediaQuery.of(context) + .size + .width * + 0.197, + height: MediaQuery.of(context) + .size + .height * + 0.08, + child: Center( + child: Texts( + projectViewModel.isArabic + ? model + .categoriseParent[ + index] + .namen + : model + .categoriseParent[ + index] + .name, + fontSize: 13.4, + fontWeight: FontWeight.w600, + maxLines: 3, + ), + ), + ), + ], + ), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + SubCategorisePage( + title: model + .categoriseParent[ + index] + .name, + id: model + .categoriseParent[ + index] + .id, + parentId: id, + )), + ); + print(id); + }, + ), + ); + }), + ), + ), + ), + + Divider( + thickness: 1.0, + color: Colors.grey.shade400, + ), + Padding( + padding: EdgeInsets.symmetric(horizontal: 8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + InkWell( + child: Row( + children: [ + Icon( + Icons.wrap_text, + ), + SizedBox( + width: 10.0, + ), + Texts( + 'Refine', + fontWeight: FontWeight.w600, + ), + ], + ), + onTap: () { + showModalBottomSheet( + isScrollControlled: true, + context: context, + builder: (BuildContext context) { + return DraggableScrollableSheet( + initialChildSize: 0.95, + maxChildSize: 0.95, + minChildSize: 0.9, + builder: (BuildContext context, + ScrollController + scrollController) { + return SingleChildScrollView( + controller: scrollController, + child: Container( + height: MediaQuery.of(context) + .size + .height * + 1.95, + child: Column( + children: [ + Padding( + padding: + EdgeInsets.all(8.0), + child: Row( + children: [ + Icon( + Icons.wrap_text, + ), + SizedBox( + width: 10.0, + ), + Texts( + 'Refine', + fontWeight: + FontWeight + .w600, + ), + SizedBox( + width: 250.0, + ), + InkWell( + child: Texts( + 'Close', + color: + Colors.red, + fontWeight: + FontWeight + .w600, + fontSize: 15.0, + ), + onTap: () { + Navigator.pop( + context); + }, + ), + ], + ), + ), + Divider( + thickness: 1.0, + color: Colors.black12, + ), + Column( + children: [ + ExpansionTile( + title: Texts( + 'Categorise'), + children: [ + Container( + height: 350, + child: ListView + .builder( + controller: + scrollController, + scrollDirection: + Axis + .vertical, + shrinkWrap: + true, + itemCount: model + .categoriseParent + .length, + itemBuilder: + (BuildContext context, + int index) { + return CheckboxListTile( + tristate: + true, + title: + Texts(model.categoriseParent[index].name), + controlAffinity: + ListTileControlAffinity.leading, + value: + checkedCategorise, + onChanged: + (bool value) { + setState(() { + checkedCategorise = value; + }); + }, + ); + }), + ) + ], + ), + Divider( + thickness: 1.0, + color: + Colors.black12, + ), + ExpansionTile( + title: + Texts('Brands'), + children: [ + Container( + height: 350, + child: ListView + .builder( + scrollDirection: + Axis + .vertical, + shrinkWrap: + true, + itemCount: model + .brandsList + .length, + itemBuilder: + (BuildContext context, + int index) { + return CheckboxListTile( + tristate: + true, + title: + Texts(model.brandsList[index].name), + controlAffinity: + ListTileControlAffinity.leading, + value: + checkedBrands, + onChanged: + (bool value) { + setState(() { + checkedBrands = value; + }); + }, + autofocus: + true, + ); + }), + ) + ], + ), + Divider( + thickness: 1.0, + color: + Colors.black12, + ), + ExpansionTile( + title: + Texts('Price'), + children: [ + Container( + color: Color( + 0xffEEEEEE), + child: Row( + mainAxisAlignment: + MainAxisAlignment + .spaceAround, + children: [ + Column( + mainAxisAlignment: + MainAxisAlignment + .start, + children: [ + Texts( + 'Min'), + Container( + color: + Colors.white, + width: + 200, + height: + 40, + child: + TextFormField( + decoration: + InputDecoration( + border: OutlineInputBorder(), + ), + ), + ), + ], + ), + Column( + mainAxisAlignment: + MainAxisAlignment + .start, + children: [ + Texts( + 'Max'), + Container( + color: + Colors.white, + width: + 200, + height: + 40, + child: + TextFormField( + decoration: + InputDecoration( + border: OutlineInputBorder(), + ), + ), + ), + ], + ), + ], + ), + ) + ], + ), + Divider( + thickness: 1.0, + color: + Colors.black12, + ), + SizedBox( + height: MediaQuery.of( + context) + .size + .height * + 0.4, + ), + Padding( + padding: + EdgeInsets.all( + 8.0), + child: Row( + mainAxisAlignment: + MainAxisAlignment + .spaceEvenly, + children: [ + Container( + width: 100, + child: Button( + label: + 'Reset', + backgroundColor: + Colors + .red, + ), + ), + SizedBox( + width: 30, + ), + Container( + width: 200, + child: Button( + label: + 'Apply', + backgroundColor: + Colors + .green, + ), + ), + ], + ), + ), + ], + ), + ], + ), + ), + ); + }); + }, + ); + }, + ), + Row( + children: [ + Container( + height: 44.0, + child: VerticalDivider( + color: Colors.black45, + thickness: 1.0, +//width: 0.3, +// indent: 0.0, + ), + ), + Padding( + padding: EdgeInsets.all(8.0), + child: InkWell( + child: styleIcon, + onTap: () { + setState(() { + if (styleOne == true) { + styleOne = false; + styleTwo = true; + styleIcon = Icon( + Icons.auto_awesome_mosaic, + color: Colors.blue, + size: 29.0, + ); + } else { + styleOne = true; + styleTwo = false; + styleIcon = Icon( + Icons.widgets_sharp, + color: Colors.blue, + size: 29.0, + ); + } + }); + }, + ), + ), + ], + ), + ], + ), + ), + Divider( + thickness: 1.0, + color: Colors.grey.shade400, + ), + styleOne == true + ? Container( + height: SizeConfig.screenHeight * 7.8, + child: GridView.builder( + physics: NeverScrollableScrollPhysics(), + gridDelegate: + SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + crossAxisSpacing: 0.5, + mainAxisSpacing: 2.0, + childAspectRatio: 0.9, + ), + itemCount: model.parentProducts.length, + itemBuilder: + (BuildContext context, int index) { + return NetworkBaseView( + baseViewModel: model, + child: Card( + color: model.parentProducts[index] + .discountName != + null + ? Color(0xffFFFF00) + : Colors.white, + elevation: 0, + shape: Border( + right: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + left: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + bottom: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + top: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + ), + margin: EdgeInsets.symmetric( + horizontal: 8, + vertical: 4, + ), + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + topLeft: + Radius.circular(110.0), + ), + color: Colors.white, + ), + padding: EdgeInsets.symmetric( + horizontal: 0), + width: MediaQuery.of(context) + .size + .width / + 3, + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Stack( + children: [ + if (model + .parentProducts[ + index] + .discountName != + null) + RotatedBox( + quarterTurns: 4, + child: Container( + decoration: + BoxDecoration(), + child: Padding( + padding: + EdgeInsets + .only( + right: 5.0, + top: 20.0, + bottom: 5.0, + ), + child: Texts( + 'offer' + .toUpperCase(), + color: + Colors.red, + fontSize: 13.0, + fontWeight: + FontWeight + .w900, + ), + ), + transform: new Matrix4 + .rotationZ( + 5.837200), + ), + ), + Container( + margin: + EdgeInsets.fromLTRB( + 0, 16, 0, 0), + alignment: + Alignment.center, + child: Image.network( + model + .parentProducts[ + index] + .images + .isNotEmpty + ? model + .parentProducts[ + index] + .images[0] + .thumb + : 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/No_image_3x4.svg/1200px-No_image_3x4.svg.png', + fit: BoxFit.cover, + height: 80, + ), + ), + Container( + width: model + .parentProducts[ + index] + .rxMessage != + null + ? MediaQuery.of( + context) + .size + .width / + 5 + : 0, + padding: + EdgeInsets.all(4), + decoration: + BoxDecoration( + color: + Color(0xffb23838), + borderRadius: + BorderRadius.only( + topLeft: Radius + .circular( + 6)), + ), + child: Texts( + model + .parentProducts[ + index] + .rxMessage != + null + ? model + .parentProducts[ + index] + .rxMessage + : "", + color: Colors.white, + regular: true, + fontSize: 10, + fontWeight: + FontWeight.w400, + ), + ), + ], + ), + Container( + margin: + EdgeInsets.symmetric( + horizontal: 6, + vertical: 0, + ), + child: Column( + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + if (model + .parentProducts[ + index] + .discountName != + null) + Container( + width: + double.infinity, + height: 13.0, + decoration: + BoxDecoration( + color: Color( + 0xff5AB145), + ), + child: Center( + child: Texts( + model + .parentProducts[ + index] + .discountName, + regular: true, + color: Colors + .white, + fontSize: 10.4, + ), + ), + ), + Texts( + model + .parentProducts[ + index] + .name, + regular: true, + fontSize: 12, + fontWeight: + FontWeight.w700, + ), + Padding( + padding: + const EdgeInsets + .only( + top: 4, + bottom: 4), + child: Texts( + "SAR ${model.parentProducts[index].price}", + bold: true, + fontSize: 14, + ), + ), + Row( + children: [ + StarRating( + totalAverage: model + .parentProducts[ + index] + .approvedRatingSum > + 0 + ? (model.parentProducts[index].approvedRatingSum.toDouble() / + model.parentProducts[index].approvedRatingSum + .toDouble()) + .toDouble() + : 0, + forceStars: + true), + Texts( + "(${model.parentProducts[index].approvedTotalReviews})", + regular: true, + fontSize: 10, + fontWeight: + FontWeight + .w400, + ) + ], + ), + ], + ), + ), + ], + ), + ), + )); + }, + ), + ) + : Container( + height: + MediaQuery.of(context).size.height * 5.0, + child: ListView.builder( + physics: NeverScrollableScrollPhysics(), + itemCount: model.parentProducts.length, + itemBuilder: + (BuildContext context, int index) { + return Card( + child: Row( + children: [ + Stack( + children: [ + Column( + children: [ + Container( + decoration: + BoxDecoration(), + child: Padding( + padding: + EdgeInsets.only( + left: 9.0, + top: 8.0, + right: 10.0, + ), + ), + ), + Container( + margin: + EdgeInsets.fromLTRB( + 0, 0, 0, 0), + alignment: + Alignment.center, + child: Image.network( + model + .parentProducts[ + index] + .images + .isNotEmpty + ? model + .parentProducts[ + index] + .images[0] + .thumb + : 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/No_image_3x4.svg/1200px-No_image_3x4.svg.png', + fit: BoxFit.contain, + height: 80, + ), + ), + ], + ), + Column( + children: [ + Container( + width: model + .parentProducts[ + index] + .rxMessage != + null + ? MediaQuery.of( + context) + .size + .width / + 5 + : 0, + padding: + EdgeInsets.all(4), + decoration: + BoxDecoration( + color: + Color(0xffb23838), + borderRadius: + BorderRadius.only( + topLeft: Radius + .circular( + 6)), + ), + child: Texts( + model + .parentProducts[ + index] + .rxMessage != + null + ? model + .parentProducts[ + index] + .rxMessage + : "", + color: Colors.white, + regular: true, + fontSize: 10, + fontWeight: + FontWeight.w400, + ), + ), + ], + ), + ], + ), + Container( + height: 100.0, + margin: EdgeInsets.symmetric( + horizontal: 6, + vertical: 0, + ), + child: Column( + mainAxisAlignment: + MainAxisAlignment + .spaceAround, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + SizedBox( + height: 4.0, + ), + Texts( + model + .parentProducts[index] + .name, + regular: true, + fontSize: 13.2, + fontWeight: + FontWeight.w500, + maxLines: 5, + ), + SizedBox( + height: 8.0, + ), + Padding( + padding: + const EdgeInsets.only( + top: 4, + bottom: 4), + child: Texts( + "SAR ${model.parentProducts[index].price}", + bold: true, + fontSize: 14, + ), + ), + Row( + children: [ + StarRating( + totalAverage: model + .parentProducts[ + index] + .approvedRatingSum > + 0 + ? (model.parentProducts[index].approvedRatingSum + .toDouble() / + model + .parentProducts[index] + .approvedRatingSum + .toDouble()) + .toDouble() + : 0, + forceStars: true), + Texts( + "(${model.parentProducts[index].approvedTotalReviews})", + regular: true, + fontSize: 10, + fontWeight: + FontWeight.w400, + ) + ], + ), + ], + ), + ), + ], + ), + ); + }), + ) + ], + ), + ), + ], + ), + ), + )); + } +} diff --git a/lib/pages/paymentService/payment_service.dart b/lib/pages/paymentService/payment_service.dart index fb356dca..cca506ec 100644 --- a/lib/pages/paymentService/payment_service.dart +++ b/lib/pages/paymentService/payment_service.dart @@ -1,6 +1,9 @@ import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/models/Appointments/toDoCountProviderModel.dart'; +import 'package:diplomaticquarterapp/pages/ToDoList/ToDo.dart'; import 'package:diplomaticquarterapp/pages/medical/balance/advance_payment_page.dart'; import 'package:diplomaticquarterapp/pages/medical/balance/my_balance_page.dart'; +import 'package:diplomaticquarterapp/uitl/app_toast.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; @@ -11,9 +14,13 @@ import 'package:hexcolor/hexcolor.dart'; import 'package:provider/provider.dart'; class PaymentService extends StatelessWidget { + ToDoCountProviderModel model; + ProjectViewModel projectViewModel; + @override Widget build(BuildContext context) { - ProjectViewModel projectViewModel = Provider.of(context); + projectViewModel = Provider.of(context); + model = Provider.of(context); return AppScaffold( isShowAppBar: true, isShowDecPage: false, @@ -26,7 +33,6 @@ class PaymentService extends StatelessWidget { children: [ Row( children: [ - if(projectViewModel.havePrivilege(33)) Expanded( child: InkWell( onTap: () => Navigator.push( @@ -51,93 +57,67 @@ class PaymentService extends StatelessWidget { fontSize: 14, fontWeight: FontWeight.normal, ), - Image.asset( - 'assets/images/al-habib_online_payment_service_icon.png', - fit: BoxFit.fill, - height: 55, - width: double.infinity, + SizedBox( + height: 12, + ), + Container( + margin: EdgeInsets.only(left: 10, right: 10), + child: Image.asset( + 'assets/images/online_payment_icon.png', + fit: BoxFit.fill, + height: 55, + width: double.infinity, + ), ), ], ), ), ), ), - if(!projectViewModel.havePrivilege(33)) - Expanded( - child: InkWell( - onTap: () => Navigator.push( - context, FadePage(page: MyBalancePage())), - child: Container( - margin: EdgeInsets.all(5.0), - padding: EdgeInsets.all(9), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8.0), - shape: BoxShape.rectangle), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Texts( - 'My Balances', - color: HexColor('#B61422'), - bold: true, - ), - Texts( - TranslationBase.of(context).payment, - fontSize: 14, - fontWeight: FontWeight.normal, - ), - Align( - alignment: projectViewModel.isArabic - ? Alignment.centerRight - : Alignment.centerLeft, - child: Image.asset( - 'assets/images/al-habib_online_payment_service_icon.png', - height: 55, - ), - ), - ], - ), - ), - ), - ), + //if(!projectViewModel.havePrivilege(33)) Expanded( - child: Container( - margin: EdgeInsets.all(5.0), - padding: EdgeInsets.all(9), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8.0), - shape: BoxShape.rectangle), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Texts( - TranslationBase.of(context).onlineCheckIn, - color: HexColor('#B61422'), - bold: true, - ), - Texts( - TranslationBase.of(context).appointment, - fontSize: 14, - fontWeight: FontWeight.normal, - ), - Align( - alignment: projectViewModel.isArabic - ? Alignment.centerRight - : Alignment.centerLeft, - child: Image.asset( - 'assets/images/al-habib_online_payment_service_icon.png', - height: 55, + child: InkWell( + onTap: () => navigateToToDoPage(context), + child: Container( + margin: EdgeInsets.all(5.0), + padding: EdgeInsets.all(9), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8.0), + shape: BoxShape.rectangle), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Texts( + TranslationBase.of(context).onlineCheckIn, + color: HexColor('#B61422'), + bold: true, ), - ), - ], + Texts( + TranslationBase.of(context).appointment, + fontSize: 14, + fontWeight: FontWeight.normal, + ), + SizedBox( + height: 12, + ), + Align( + alignment: !projectViewModel.isArabic + ? Alignment.centerRight + : Alignment.centerLeft, + child: Image.asset( + 'assets/images/device_icon.png', + height: 55, + ), + ), + ], + ), ), ), ) ], ), - if(!projectViewModel.havePrivilege(33)) + // if(!projectViewModel.havePrivilege(33)) Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -165,12 +145,15 @@ class PaymentService extends StatelessWidget { fontSize: 14, fontWeight: FontWeight.normal, ), + SizedBox( + height: 12, + ), Align( - alignment: projectViewModel.isArabic + alignment: !projectViewModel.isArabic ? Alignment.centerRight : Alignment.centerLeft, child: Image.asset( - 'assets/images/al-habib_online_payment_service_icon.png', + 'assets/images/new-design/check-in.png', height: 55, ), ), @@ -190,4 +173,17 @@ class PaymentService extends StatelessWidget { ), ); } + + navigateToToDoPage(BuildContext context) { + if (projectViewModel.isLogin) { + if (model.count != 0) { + Navigator.push(context, FadePage(page: ToDo(isShowAppBar: true))); + } else { + AppToast.showErrorToast( + message: TranslationBase.of(context).upcomingEmpty); + } + } else { + Navigator.push(context, FadePage(page: ToDo(isShowAppBar: true))); + } + } } diff --git a/lib/pages/pharmacies/ProductCheckTypeWidget.dart b/lib/pages/pharmacies/ProductCheckTypeWidget.dart new file mode 100644 index 00000000..878544e1 --- /dev/null +++ b/lib/pages/pharmacies/ProductCheckTypeWidget.dart @@ -0,0 +1,70 @@ +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; +import 'package:diplomaticquarterapp/widgets/pharmacy/product_tile.dart'; +import 'package:flutter/material.dart'; + +AppSharedPreferences sharedPref = AppSharedPreferences(); +var languageID; +class ProductCheckTypeWidget extends StatelessWidget { + final List wishlist; + final bool isTrue; + + ProductCheckTypeWidget(this.isTrue, this.wishlist); + + + void initState() { + getLanguageID(); + } + + @override + Widget build(BuildContext context) { + return isTrue + ? ListView.builder( + itemCount: wishlist.length, + itemBuilder: (BuildContext context, int index) { + return Column( + children: [ + Container( + child: isTrue + ? productTile( + productName: languageID == 'ar' ? wishlist[index].product.namen : wishlist[index].product.name, + productPrice: wishlist[index].subtotal, + productRate: + double.parse(wishlist[index].subtotalVatRate), + productImage: wishlist[index].product.images[0].src, + showLine: isTrue, + productID: wishlist[index].product.id, + ) + : productTile( + productName: languageID == 'ar' ? wishlist[index].product.namen : wishlist[index].product.name, + productPrice: wishlist[index].subtotal, + productRate: + double.parse(wishlist[index].subtotalVatRate), + productImage: wishlist[index].product.images[0].src, + showLine: isTrue, + ), + ), + Divider(height: 1, color: Colors.grey) + ], + ); + }) + : GridView.count( + crossAxisCount: 2, + children: List.generate( + wishlist.length, + (index) => productTile( + productName: wishlist[index].product.name, + productPrice: wishlist[index].subtotal, + productRate: + double.parse(wishlist[index].subtotalVatRate), + productImage: wishlist[index].product.images[0].src, + showLine: isTrue, + )), + ); + } +} + +getLanguageID() async { + languageID = await sharedPref.getString(APP_LANGUAGE); +} + diff --git a/lib/pages/pharmacies/compare-list.dart b/lib/pages/pharmacies/compare-list.dart new file mode 100644 index 00000000..37e2fc8c --- /dev/null +++ b/lib/pages/pharmacies/compare-list.dart @@ -0,0 +1,36 @@ +import 'package:diplomaticquarterapp/uitl/app_toast.dart'; +import 'package:flutter/material.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/PharmacyProduct.dart'; + +class CompareList with ChangeNotifier { + List _product = []; + + List get productListItems => _product; + + void addItem(data) { + if (_product.length == 0) { + _product.add(data); + AppToast.showSuccessToast(message: 'You have added a product to the Compare list'); + } else { + for (int i = 0; i < _product.length; i++) { + if (_product.length <= 4 && _product[i].id != data.id) { + _product.add(data); + AppToast.showSuccessToast(message: 'You have added a product to the Compare list'); + break; + } else if(_product[i].id == data.id){ + AppToast.showErrorToast(message: 'the item is already in the list'); + } else if(_product.length == 4){ + AppToast.showErrorToast(message: 'your compare list is full'); + } + } + } + notifyListeners(); + } + + void deleteItem(data) { + for (int i = 0; i < _product.length; i++) { + if (_product[i].id == data) _product.remove(_product[i]); + } + notifyListeners(); + } +} diff --git a/lib/pages/pharmacies/compare.dart b/lib/pages/pharmacies/compare.dart new file mode 100644 index 00000000..d1872187 --- /dev/null +++ b/lib/pages/pharmacies/compare.dart @@ -0,0 +1,328 @@ +import 'package:flutter/material.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:carousel_slider/carousel_slider.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:diplomaticquarterapp/pages/pharmacies/compare-list.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/PharmacyProduct.dart'; +import 'package:provider/provider.dart'; + +int counter = 0; + +class ComparePage extends StatefulWidget { + @override + _ComparePageState createState() => _ComparePageState(); +} + +//CompareList compareItems = CompareList(); +class _ComparePageState extends State { + @override + Widget build(BuildContext context) { + return AppScaffold( + appBarTitle: 'Reviews page', + isShowAppBar: true, + isPharmacy: true, + body: Container( + child: compareList(), + ), + ); + } +} + +class compareList extends StatelessWidget { + @override + Widget build(BuildContext context) { + final productItemData = Provider.of(context); + final productItem = productItemData.productListItems; + return productItem.length == 0 + ? Container( + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Image.asset( + 'assets/images/new-design/empty_box.png', + width: 100, + height: 100, + fit: BoxFit.cover, + ), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + 'There is no data', + style: TextStyle(fontSize: 30), + ), + ) + ], + ), + ), + ) + : CarouselSlider( + options: CarouselOptions( + height: 800.0, + viewportFraction: 0.87, + enableInfiniteScroll: false), + items: productItem.map((i) { + return Builder( + builder: (BuildContext context) { + return Padding( + padding: const EdgeInsets.only(top: 8), + child: Container( + width: MediaQuery.of(context).size.width, + margin: EdgeInsets.symmetric(horizontal: 10.0), + child: productItem.length != 0 + ? slideDetail(productItem) + : Container(), + ), + ); + }, + ); + }).toList(), + ); + } +} + +class slideDetail extends StatefulWidget { + final List data; + + slideDetail(this.data); + + @override + _slideDetailState createState() => _slideDetailState(); +} + +class _slideDetailState extends State { + @override + Widget build(BuildContext context) { + return ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: widget.data.length, + itemBuilder: (BuildContext contx, int index) { + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + height: 550, + width: 150, + margin: EdgeInsets.symmetric(horizontal: 10.0), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + border: Border( + top: BorderSide(width: 0.5, color: Colors.grey), + left: BorderSide(width: 0.5, color: Colors.grey), + right: BorderSide(width: 0.5, color: Colors.grey), + bottom: BorderSide(width: 0.5, color: Colors.grey), + ), + color: Colors.white), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + Container( + child: Align( + alignment: Alignment.topRight, + child: IconButton( + icon: Icon(FontAwesomeIcons.trashAlt, size: 15), + onPressed: () { + setState(() { + Provider.of(context, listen: false) + .deleteItem(widget.data[index].id); + }); + }, + ), + ), + ), + SizedBox( + height: 20, + ), + Image.network( + widget.data[index].images[0].src.trim(), + fit: BoxFit.cover, + width: 100, + height: 60, + ), + Padding( + padding: EdgeInsets.only(top: 8.0), + child: Container( + height: 1.0, + width: 300.0, + color: Colors.grey, + ), + ), + Container( + margin: EdgeInsets.all(5), + child: Align( + alignment: Alignment.topLeft, + child: RichText( + text: TextSpan( + text: widget.data[index].name, + style: TextStyle( + fontWeight: FontWeight.bold, + color: Colors.black, + fontSize: 13), + ), + ), + ), + ), + Container( + margin: EdgeInsets.all(5), + child: Align( + alignment: Alignment.topLeft, + child: RichText( + text: TextSpan( + text: widget.data[index].price.toString(), + style: TextStyle( + color: Colors.black54, + fontSize: 15, + fontWeight: FontWeight.bold), + ), + ), + ), + ), + Padding( + padding: EdgeInsets.only(top: 8.0), + child: Container( + height: 1.0, + width: 300.0, + color: Colors.grey, + ), + ), + Container( + margin: EdgeInsets.all(5), + child: Align( + alignment: Alignment.topLeft, + child: RichText( + text: TextSpan( + text: widget.data[index].specifications[0].name, + style: TextStyle( + fontWeight: FontWeight.bold, + color: Colors.black, + fontSize: 13), + ), + ), + ), + ), + Container( + margin: EdgeInsets.all(5), + child: Align( + alignment: Alignment.topLeft, + child: RichText( + text: TextSpan( + text: widget.data[index].specifications[1].name, + style: TextStyle( + color: Colors.black54, + fontSize: 15, + fontWeight: FontWeight.bold), + ), + ), + ), + ), + Padding( + padding: EdgeInsets.only(top: 8.0), + child: Container( + height: 1.0, + width: 300.0, + color: Colors.grey, + ), + ), + Container( + margin: EdgeInsets.all(5), + child: Align( + alignment: Alignment.topLeft, + child: RichText( + text: TextSpan( + text: widget.data[index].specifications[2].name, + style: TextStyle( + fontWeight: FontWeight.bold, + color: Colors.black, + fontSize: 13), + ), + ), + ), + ), + Container( + margin: EdgeInsets.all(5), + child: Align( + alignment: Alignment.topLeft, + child: RichText( + text: TextSpan( + text: widget.data[index].specifications[3].name, + style: TextStyle( + color: Colors.black54, + fontSize: 15, + fontWeight: FontWeight.bold), + ), + ), + ), + ), + Padding( + padding: EdgeInsets.only(top: 8.0), + child: Container( + height: 1.0, + width: 300.0, + color: Colors.grey, + ), + ), + Container( + margin: EdgeInsets.all(5), + child: Align( + alignment: Alignment.topLeft, + child: RichText( + text: TextSpan( + text: widget.data[index].specifications[4].name, + style: TextStyle( + fontWeight: FontWeight.bold, + color: Colors.black, + fontSize: 13), + ), + ), + ), + ), + Container( + margin: EdgeInsets.all(5), + child: Align( + alignment: Alignment.topLeft, + child: RichText( + text: TextSpan( + text: widget.data[index].specifications[5].name, + style: TextStyle( + color: Colors.black54, + fontSize: 15, + fontWeight: FontWeight.bold), + ), + ), + ), + ), + Padding( + padding: EdgeInsets.only(top: 8.0), + child: Container( + height: 1.0, + width: 300.0, + color: Colors.grey, + ), + ), + ], + ), + ), + ), + ], + ); + }, + ); + } +} + +String returnString(data) { + for (int i = 0; i < data.length; i++) { + print(data[i]); +// if(data[i] == null){ +// if(counter == i){ +// +// } +// } + } + return "ENAD HILAL"; +} diff --git a/lib/pages/pharmacies/medicine_search_screen.dart b/lib/pages/pharmacies/medicine_search_screen.dart index 62cacb7f..7a61dabe 100644 --- a/lib/pages/pharmacies/medicine_search_screen.dart +++ b/lib/pages/pharmacies/medicine_search_screen.dart @@ -1,26 +1,28 @@ import 'package:diplomaticquarterapp/config/size_config.dart'; import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; -import 'package:diplomaticquarterapp/core/viewModels/pharmacies_view_model.dart'; -import 'package:diplomaticquarterapp/pages/pharmacies/pharmacies_list_screen.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/uitl/utils.dart'; import 'package:diplomaticquarterapp/widgets/buttons/button.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/pharmacies_model.dart'; +import 'package:diplomaticquarterapp/core/viewModels/pharmacies_view_model.dart'; +import '../base/base_view.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; -import 'package:diplomaticquarterapp/widgets/input/text_field.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:diplomaticquarterapp/widgets/input/text_field.dart'; import 'package:diplomaticquarterapp/widgets/pharmacy/drug_item.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; - -import '../base/base_view.dart'; +import 'package:diplomaticquarterapp/core/service/pharmacies_service.dart'; +import 'package:diplomaticquarterapp/pages/pharmacies/pharmacies_list_screen.dart'; class MedicineSearch extends StatelessWidget { final textController = TextEditingController(); final _formKey = GlobalKey(); - @override Widget build(BuildContext context) { return BaseView( + allowAny: true, + onModelReady: (model) => model.clearMedicineSearch(), builder: (BuildContext context, PharmacyViewModel model, Widget child) => AppScaffold( baseViewModel: model, @@ -51,13 +53,11 @@ class MedicineSearch extends StatelessWidget { controller: textController, validator: (value) { if (value.isEmpty) { - return TranslationBase.of(context) - .pleaseEnterMedicineName; - } else if (value.length < 4) { - return TranslationBase.of(context) - .searchItemError; - } else - return null; + return TranslationBase.of(context).pleaseEnterMedicineName; + }else if( value.length <4){ + return TranslationBase.of(context).searchItemError; + }else + return null; }, ), ), @@ -83,24 +83,21 @@ class MedicineSearch extends StatelessWidget { ], ), ), - if (model.pharmacy.isNotEmpty) - Container( - margin: EdgeInsets.only( - left: SizeConfig.heightMultiplier * 2), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - margin: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0), - child: Texts( - TranslationBase.of(context).youCanFind + - '${model.pharmacy == null ? '0' : model.pharmacy.length.toString()}' + - TranslationBase.of(context).itemInSearch, - ), - ), - ], - ), + if(model.pharmacy.isNotEmpty) + Container( + margin: EdgeInsets.only( + left: SizeConfig.heightMultiplier * 2), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Texts( + TranslationBase.of(context).youCanFind+ + '${model.pharmacy == null ? '0' : model.pharmacy.length.toString()}'+ + TranslationBase.of(context).itemInSearch, + ), + ], ), + ), if (model.state == ViewState.ErrorLocal) Container( child: Texts(model.error), diff --git a/lib/pages/pharmacies/my_reviews.dart b/lib/pages/pharmacies/my_reviews.dart new file mode 100644 index 00000000..7b17a359 --- /dev/null +++ b/lib/pages/pharmacies/my_reviews.dart @@ -0,0 +1,248 @@ +import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/review_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:rating_bar/rating_bar.dart'; +import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; + +class MyReviewsPage extends StatefulWidget { + @override + _MyReviewsPageState createState() => _MyReviewsPageState(); +} + +var languageID; + +class _MyReviewsPageState extends State { + void initState() { + getLanguageID(); + } + + @override + Widget build(BuildContext context) { + return BaseView( + onModelReady: (model) => model.getReviewData(), + builder: (_, model, wi) => AppScaffold( + appBarTitle: 'My Reviews', + isShowAppBar: true, + isPharmacy: true, + baseViewModel: model, + body: model.reviewListList.length == 0 + ? Container( + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Image.asset( + 'assets/images/new-design/empty_box.png', + width: 100, + height: 100, + fit: BoxFit.cover, + ), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + 'There is no data', + style: TextStyle(fontSize: 30), + ), + ) + ], + ), + ), + ) + : Container( + child: ListView.builder( + itemCount: model.reviewListList.length, + itemBuilder: (BuildContext context, int index) { + return Column( + children: [ + Container( + child: reviewDetails( + model.reviewListList[index], + double.parse(model.reviewListList[index].product + .approvedTotalReviews + .toString()), + double.parse(model.reviewListList[index].rating + .toString()), + ), + ), + Divider(height: 1, color: Colors.grey) + ], + ); + }), + ), + ), + ); + } +} + +reviewDetails(data, rate, myRate) { + return Container( + child: Padding( + padding: EdgeInsets.only(bottom: 10.0), + child: Container( + height: 200, + width: double.infinity, + color: Colors.white, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Row( + children: [ + Container( + margin: languageID == 'ar' + ? EdgeInsets.only(top: 10, right: 10) + : EdgeInsets.only(top: 10, left: 10), + child: Image.network( + data.product.images[0].src.trim(), + fit: BoxFit.cover, + width: 80, + height: 80, + ), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + margin: EdgeInsets.all(5), + child: Align( + alignment: languageID == 'ar' + ? Alignment.topRight + : Alignment.topLeft, + child: RichText( + text: TextSpan( + text: languageID == 'ar' + ? data.product.namen + : data.product.name, + style: TextStyle( + color: Colors.black54, + fontSize: languageID == 'ar' ? 7 : 13, + fontWeight: FontWeight.bold), + ), + ), + ), + ), + Column( + children: [ + Container( + margin: EdgeInsets.all(5), + child: Align( + alignment: languageID == 'ar' + ? Alignment.topRight + : Alignment.topLeft, + child: RichText( + text: TextSpan( + text: data.product.price.toString() + + " " + + data.product.currency, + style: TextStyle( + fontWeight: FontWeight.bold, + color: Colors.black, + fontSize: 13), + ), + ), + ), + ), + ], + ), + Container( + margin: EdgeInsets.all(5), + child: Align( + alignment: languageID == 'ar' + ? Alignment.topRight + : Alignment.topLeft, + child: RatingBar.readOnly( + initialRating: rate, + size: 15.0, + filledColor: Colors.yellow[700], + emptyColor: Colors.grey[500], + isHalfAllowed: true, + halfFilledIcon: Icons.star_half, + filledIcon: Icons.star, + emptyIcon: Icons.star, + ), + ), + ), + ], + ), + ], + ), + SizedBox( + height: 20, + ), + Container( + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + padding: languageID == 'ar' + ? EdgeInsets.only(right: 10) + : EdgeInsets.only(left: 10), + child: Text(data.createdOnUtc.toString())), + ], + ), + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Container( + padding: languageID == 'ar' + ? EdgeInsets.only(right: 60) + : EdgeInsets.only(left: 60), + child: RatingBar.readOnly( + initialRating: myRate, + size: 15.0, + filledColor: Colors.yellow[700], + emptyColor: Colors.grey[500], + isHalfAllowed: true, + halfFilledIcon: Icons.star_half, + filledIcon: Icons.star, + emptyIcon: Icons.star, + ), + ), + ], + ), + ), + ], + ), + ), + SizedBox( + height: 15, + ), + Expanded( + child: Container( + padding: languageID == 'ar' + ? EdgeInsets.only(right: 10) + : EdgeInsets.only(left: 10), + child: Text(fixingString(data.reviewText.toString())), + ), + ), + ], + ), + ), + ), + ); +} + +fixingString(txt) { + String stringTxt; + String newTxt; + stringTxt = txt.toString(); + newTxt = stringTxt.split('.')[1]; + + return newTxt; +} + +getLanguageID() async { + languageID = await sharedPref.getString(APP_LANGUAGE); +} diff --git a/lib/pages/pharmacies/pharmacies_list_screen.dart b/lib/pages/pharmacies/pharmacies_list_screen.dart index dc69a3e2..a35a77c9 100644 --- a/lib/pages/pharmacies/pharmacies_list_screen.dart +++ b/lib/pages/pharmacies/pharmacies_list_screen.dart @@ -24,12 +24,14 @@ class PharmaciesList extends StatelessWidget { @override Widget build(BuildContext context) { return BaseView( + allowAny: true, onModelReady: (model) => model.getPharmacies(id: medicineID), builder: (BuildContext context, PharmacyViewModel model, Widget child) => AppScaffold( appBarTitle: TranslationBase.of(context).pharmaciesList, baseViewModel: model, isShowAppBar: true, + isShowDecPage: false, body: Container( height: SizeConfig.screenHeight, child: ListView( @@ -146,7 +148,7 @@ class PharmaciesList extends StatelessWidget { child: InkWell( child: Icon( Icons.phone, - color: Colors.red, + color: Theme.of(context).primaryColor, ), onTap: () => launch("tel://" + model.pharmacyList[index].phoneNumber), @@ -157,7 +159,7 @@ class PharmaciesList extends StatelessWidget { child: InkWell( child: Icon( Icons.local_pharmacy, - color: Colors.red, + color: Theme.of(context).primaryColor, ), onTap: () { MapsLauncher.launchCoordinates( diff --git a/lib/pages/pharmacies/product-brands.dart b/lib/pages/pharmacies/product-brands.dart new file mode 100644 index 00000000..b9e6db95 --- /dev/null +++ b/lib/pages/pharmacies/product-brands.dart @@ -0,0 +1,254 @@ +import 'package:diplomaticquarterapp/config/config.dart'; +import 'package:diplomaticquarterapp/pages/login/register-info.dart'; +import 'package:diplomaticquarterapp/pages/pharmacies/search_brands_page.dart'; +import 'package:diplomaticquarterapp/pages/search_products_page.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; +import 'package:flutter/material.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/brand_view_model.dart'; +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; + +class ProductBrandsPage extends StatefulWidget { + @override + _ProductBrandsPageState createState() => _ProductBrandsPageState(); +} + +var languageID; +class _ProductBrandsPageState extends State { + + @override + void initState() { + super.initState(); + getLanguageID(); + } + + @override + Widget build(BuildContext context) { + return BaseView( + onModelReady: (model) => model.getBrandsData(), + builder: (_, model, wi) => AppScaffold( + appBarTitle: 'Brands page', + isShowAppBar: true, + isPharmacy: true, + isShowDecPage: false, + body: Container( + child: Column( + children: [ + Container( + color: Colors.white, + alignment: languageID == 'ar'? + Alignment.topRight : + Alignment.topLeft, + padding: languageID == 'ar' ? + EdgeInsets.only( + right: 10.0, + top: 10.0 + ): + EdgeInsets.only( + left: 10.0, + top: 10.0 + ), + child: Text( + TranslationBase.of(context).topBrands, + style: TextStyle( + fontWeight: FontWeight.bold, + ), + ), + ), + Container( + height: 220, + width: double.infinity, + color: Colors.white, + child: topBrand(), + ), + SizedBox( + height: 10, + ), + Container( + height: MediaQuery.of(context).size.height * 0.056, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(5.0), + color: Colors.white, + ), + child: InkWell( + child: Padding( + padding: EdgeInsets.all(8.0), + child: Row( + //crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Icon(Icons.search, size: 25.0), + SizedBox( + width: 15.0, + ), + Texts( + TranslationBase.of(context).searchProductHere, + fontSize: 13, + ) + ], + ), + ), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => SearchBrandsPage()), + ); + }, + ), + ), + SizedBox( + height: 10, + ), + Container( + height: 230, + width: double.infinity, + color: Colors.white, + child: ListView.builder( + itemCount: model.brandsListList.length, + itemBuilder: (BuildContext context, int index) { + return InkWell( + child: Container( + margin: EdgeInsets.only(top: 50, left: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + languageID == 'ar' ? Text(model.brandsListList[index].namen):Text(model.brandsListList[index].name), + SizedBox( + height: 3, + ), + Divider(height: 1, color: Colors.grey) + ], + ), + ), + onTap: (){ + print("ENAD"); + }, + ); + }), + ), + ], + ), + ), + ), + ); + } +} + + +topBrand() { + return BaseView( + onModelReady: (model) => model.getTopBrandsData(), + builder: (_, model, wi) => GridView.count( + crossAxisCount: 4, + children: List.generate( + model.topBrandsListList.length, + (index) => Column( + children: [ + InkWell( + child: Container( + margin: EdgeInsets.fromLTRB(5.0, 10.0, 5.0, 0.0), + child: Container( + child: Container( + child: Container( +// padding: EdgeInsets.only(left: 5), + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 10.0, vertical: 10.0), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + border: Border( + top: BorderSide(width: 1.0, color: Colors.grey), + left: BorderSide(width: 1.0, color: Colors.grey), + right: BorderSide(width: 1.0, color: Colors.grey), + bottom: BorderSide(width: 1.0, color: Colors.grey), + ), + color: Colors.white, + ), + child: model.topBrandsListList[index].image != null ?Image.network( + model.topBrandsListList[index].image.src, + fit: BoxFit.cover, + width: 60, + height: 40, + ): Text(model.topBrandsListList[index].name) + ), + ), + ), + ), + ), + onTap: (){ + print("ENAD"); + }, + ), + ], + ), + ), + ), + ); +} + +brandSearch() { + return Text('ENAD'); +} + +class SearchBar extends SearchDelegate { + @override + List buildActions(BuildContext context) { + return [ + IconButton( + icon: Icon(Icons.clear), + onPressed: () { + query = ""; + }, + ) + ]; + } + + @override + Widget buildLeading(BuildContext context) { + return IconButton( + icon: AnimatedIcon( + icon: AnimatedIcons.menu_arrow, + progress: transitionAnimation, + ), + onPressed: () { + close(context, null); + }, + ); + } + + @override + Widget buildResults(BuildContext context) { + return Container( + height: 100, + width: 100, + child: Card( + color: Colors.red, + child: Center( + child: Text(query), + ), + ), + ); + } + + @override + Widget buildSuggestions(BuildContext context) { + return ListView.builder( + itemCount: 5, + itemBuilder: (context, index) => ListTile( + leading: Icon(Icons.location_city), + title: Text("Enad"), + onTap: () { + showResults(context); + }, + ), + ); + } +} + +getLanguageID() async { + languageID = await sharedPref.getString(APP_LANGUAGE); +} diff --git a/lib/pages/pharmacies/product_detail.dart b/lib/pages/pharmacies/product_detail.dart new file mode 100644 index 00000000..2040db11 --- /dev/null +++ b/lib/pages/pharmacies/product_detail.dart @@ -0,0 +1,1862 @@ +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/PharmacyProduct.dart'; +import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/product_detail_view_model.dart'; +import 'package:diplomaticquarterapp/pages/base/base_view.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:diplomaticquarterapp/widgets/others/app_scafold_detail_page.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:provider/provider.dart'; +import 'package:rating_bar/rating_bar.dart'; +import 'package:diplomaticquarterapp/uitl/app_toast.dart'; +import 'screens/cart-order-page.dart'; +import 'package:diplomaticquarterapp/pages/pharmacies/compare-list.dart'; + +int price = 0; +var languageID; +bool isOverQuantity = false; +bool isInWishlit = false; +var itemID; +var product; +var customerId; +CompareList compareItems = new CompareList(); +PharmacyProduct specificationData; + +class ProductDetailPage extends StatefulWidget { + final PharmacyProduct product; + ProductDetailPage(this.product); + @override + __ProductDetailPageState createState() => __ProductDetailPageState(); +} + +class __ProductDetailPageState extends State { + bool isTrue = true; + bool isDetails = true; + bool isReviews = false; + bool isAvailabilty = false; + dynamic wishlistItems; + + void initState() { + price = 0; + specificationData = widget.product; + setState(() { + customerId = userInfo(widget.product.id, widget.product); + }); + super.initState(); + } + + Widget build(BuildContext context) { + return customerId != null + ? DetailPageScafold( + appBarTitle: 'product detail page', + isShowAppBar: true, + isPharmacy: true, + isShowDecPage: false, + body: SingleChildScrollView( + child: Column( + children: [ + Container( + width: double.infinity, + color: Colors.white, + child: Column( + children: [ + Image.network( + widget.product.images[0].src.trim(), + ), + widget.product.discountDescription != null + ? Container( + width: double.infinity, + height: 50, + color: Colors.yellowAccent, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + flex: 1, + child: Container( + alignment: Alignment.centerRight, + child: languageID == 'ar' + ? Text( + widget.product + .discountDescriptionn, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 17), + ) + : Text( + widget.product + .discountDescription, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 17), + ), + ), + ), + SizedBox( + width: 10, + ), + Expanded( + flex: 0, + child: Container( + child: Image( + image: AssetImage( + 'assets/images/offer.png'), + ), + ), + ), + ], + ), + ) + : Container(), + ], + ), + ), + SizedBox( + height: 4, + ), + Container( + width: 500, + height: 150, + color: Colors.white, + child: productNameAndPrice(context, widget.product), + ), + SizedBox( + height: 6, + ), + Container( + width: 500, + height: 120, + color: Colors.white, + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Container( + child: Text( + TranslationBase.of(context).specification, + style: TextStyle(fontWeight: FontWeight.bold), + ), + ), + ), + Divider(color: Colors.grey), + Padding( + padding: const EdgeInsets.all(8.0), + child: Container( + child: Text( + "there is no data", + ), + ), + ), + ], + ), + ), + SizedBox( + height: 6, + ), + Container( + width: 500, + margin: EdgeInsets.only(bottom: 100), +// height: 350, + color: Colors.white, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( + children: [ + FlatButton( + onPressed: () { + setState(() { + isDetails = true; + isReviews = false; + isAvailabilty = false; + }); + }, + child: Text( + TranslationBase.of(context).details, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold), + ), + color: Colors.white, + ), + isDetails + ? Container( + width: 100, + height: 5, + color: Colors.green, + ) + : Container() + ], + ), + SizedBox( + width: 20, + ), + Column( + children: [ + FlatButton( + onPressed: () { + setState(() { + isDetails = false; + isReviews = true; + isAvailabilty = false; + }); + }, + child: Text( + TranslationBase.of(context).reviews, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold), + ), + color: Colors.white, + ), + isReviews + ? Container( + width: 100, + height: 5, + color: Colors.green, + ) + : Container(), + ], + ), + SizedBox( + width: 20, + ), + Column( + children: [ + FlatButton( + onPressed: () { + setState(() { + isDetails = false; + isReviews = false; + isAvailabilty = true; + }); + }, + child: Text( + TranslationBase.of(context).availability, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold), + ), + color: Colors.white, + ), + isAvailabilty + ? Container( + width: 100, + height: 5, + color: Colors.green, + ) + : Container(), + ], + ), + ], + ), + SizedBox( + height: 10, + ), + isDetails + ? Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + child: Text( + TranslationBase.of(context).description, + style: TextStyle( + fontSize: 17, + color: Colors.grey, + fontWeight: FontWeight.w600), + ), + ), + SizedBox( + height: 10, + ), + Container( + child: Text( + languageID == 'ar' + ? widget.product.fullDescriptionn + : widget.product.fullDescription, + style: TextStyle( + fontSize: 16, + fontFamily: 'WorkSans-Regular'), + ), + ), + ], + ), + ) + : isReviews + ? BaseView( + onModelReady: (model) => + model.getProductReviewsData( + widget.product.id), + builder: (_, model, wi) => model + .productDetailService + .length != + 0 && + model.productDetailService[0] + .reviews.length != + 0 + ? ListView.builder( + physics: ScrollPhysics(), + itemCount: model + .productDetailService[0] + .reviews + .length, + scrollDirection: Axis.vertical, + shrinkWrap: true, + itemBuilder: (BuildContext context, + int index) { + return Padding( + padding: EdgeInsets.all(8.0), + child: Column( + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Container( + child: Row( + children: [ + Container( + child: Text( + model + .productDetailService[ + 0] + .reviews[ + index] + .customerId + .toString(), + style: TextStyle( + fontSize: 17, + color: Colors + .grey, + fontWeight: + FontWeight + .w600), + ), + ), + Container( + margin: + EdgeInsets.only( + left: 210), + child: RatingBar + .readOnly( + initialRating: model + .productDetailService[ + 0] + .reviews[ + index] + .rating + .toDouble(), + size: 15.0, + filledColor: + Colors.yellow[ + 700], + emptyColor: Colors + .grey[500], + isHalfAllowed: + true, + halfFilledIcon: + Icons + .star_half, + filledIcon: + Icons.star, + emptyIcon: + Icons.star, + ), + ), + ], + ), + ), + SizedBox( + height: 10, + ), + Container( + child: Text( + model + .productDetailService[ + 0] + .reviews[index] + .reviewText, + style: TextStyle( + fontSize: 20), + ), + ), + SizedBox( + height: 50, + ), + Divider( + height: 1, + color: Colors.grey), + ], + ), + ); + }, + ) + : Container( + padding: EdgeInsets.all(15), + alignment: Alignment.center, + child: Text('No Reviews Available'), + ), + ) + : isAvailabilty + ? BaseView( + onModelReady: (model) => + model.getProductLocationData(), + builder: (_, model, wi) => model + .productLocationService + .length == + 0 + ? Container( + padding: EdgeInsets.all(15), + alignment: Alignment.center, + child: Text( + 'No location Available'), + ) + : ListView.builder( + physics: ScrollPhysics(), + scrollDirection: Axis.vertical, + shrinkWrap: true, + itemCount: model + .productLocationService + .length, + itemBuilder: + (BuildContext context, + int index) { + return Padding( + padding: + EdgeInsets.all(8.0), + child: Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// mainAxisAlignment: MainAxisAlignment.start, + children: [ + Row( +// crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment + .start, + children: [ + Expanded( + flex: 1, + child: Image.network(model + .productLocationService[ + index] + .projectImageUrl), + ), + SizedBox( + width: 10, + ), + Expanded( + flex: 4, + child: Text( + model + .productLocationService[ + index] + .locationDescription + + "\n" + + fixingString(model + .productLocationService[ + 0] + .cityName + .toString()), + style: TextStyle( + fontSize: + 12), + ), + ), + Expanded( + flex: 1, + child: IconButton( + icon: Icon(Icons + .location_on), + color: + Colors.red, + onPressed: + () {}, + ), + ), + Expanded( + flex: 1, + child: IconButton( + icon: Icon(Icons + .phone), + color: + Colors.red, + onPressed: + () {}, + ), + ), + ], + ), + Divider( + height: 1.2, + color: Colors.grey) + ], + ), + ); + }, + ), + ) + : Container(), + ], + ), + ), +// ListView(scrollDirection: Axis.vertical, shrinkWrap: true, children: [Text('ENAD')]), + ], + ), + ), + bottomSheet: footerWidget( + widget.product.stockAvailability != 'Out of stock', + widget.product.orderMaximumQuantity, + widget.product.orderMinimumQuantity, + widget.product.stockQuantity, + widget.product), + ) + : AppScaffold( + appBarTitle: 'product detail page', + isShowAppBar: true, + isPharmacy: true, + isShowDecPage: false, + body: SingleChildScrollView( + child: Column( + children: [ + Container( + width: double.infinity, + color: Colors.white, + child: Column( + children: [ + Image.network( + widget.product.images[0].src.trim(), + ), + widget.product.discountDescription != null + ? Container( + width: double.infinity, + height: 50, + color: Colors.yellowAccent, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + flex: 1, + child: Container( + alignment: Alignment.centerRight, + child: languageID == 'ar' + ? Text( + widget.product + .discountDescriptionn, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 17), + ) + : Text( + widget.product + .discountDescription, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 17), + ), + ), + ), + SizedBox( + width: 10, + ), + Expanded( + flex: 0, + child: Container( + child: Image( + image: AssetImage( + 'assets/images/offer.png'), + ), + ), + ), + ], + ), + ) + : Container(), + ], + ), + ), + SizedBox( + height: 4, + ), + Container( + width: 500, + height: 150, + color: Colors.white, + child: productNameAndPrice(context, widget.product), + ), + SizedBox( + height: 6, + ), + Container( + width: 500, + height: 120, + color: Colors.white, + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Container( + child: Text( + TranslationBase.of(context).specification, + style: TextStyle(fontWeight: FontWeight.bold), + ), + ), + ), + Divider(color: Colors.grey) + ], + ), + ), + SizedBox( + height: 6, + ), + Container( + width: 500, + margin: EdgeInsets.only(bottom: 100), +// height: 350, + color: Colors.white, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( + children: [ + FlatButton( + onPressed: () { + setState(() { + isDetails = true; + isReviews = false; + isAvailabilty = false; + }); + }, + child: Text( + TranslationBase.of(context).details, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold), + ), + color: Colors.white, + ), + isDetails + ? Container( + width: 100, + height: 5, + color: Colors.green, + ) + : Container() + ], + ), + SizedBox( + width: 20, + ), + Column( + children: [ + FlatButton( + onPressed: () { + setState(() { + isDetails = false; + isReviews = true; + isAvailabilty = false; + }); + }, + child: Text( + TranslationBase.of(context).reviews, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold), + ), + color: Colors.white, + ), + isReviews + ? Container( + width: 100, + height: 5, + color: Colors.green, + ) + : Container(), + ], + ), + SizedBox( + width: 20, + ), + Column( + children: [ + FlatButton( + onPressed: () { + setState(() { + isDetails = false; + isReviews = false; + isAvailabilty = true; + }); + }, + child: Text( + TranslationBase.of(context).availability, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold), + ), + color: Colors.white, + ), + isAvailabilty + ? Container( + width: 100, + height: 5, + color: Colors.green, + ) + : Container(), + ], + ), + ], + ), + SizedBox( + height: 10, + ), + isDetails + ? Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + child: Text( + TranslationBase.of(context).description, + style: TextStyle( + fontSize: 17, + color: Colors.grey, + fontWeight: FontWeight.w600), + ), + ), + SizedBox( + height: 10, + ), + Container( + child: Text( + languageID == 'ar' + ? widget.product.fullDescriptionn + : widget.product.fullDescription, + style: TextStyle( + fontSize: 16, + fontFamily: 'WorkSans-Regular'), + ), + ), + ], + ), + ) + : isReviews + ? BaseView( + onModelReady: (model) => + model.getProductReviewsData( + widget.product.id), + builder: (_, model, wi) => model + .productDetailService + .length != + 0 && + model.productDetailService[0] + .reviews.length != + 0 + ? ListView.builder( + physics: ScrollPhysics(), + itemCount: model + .productDetailService[0] + .reviews + .length, + scrollDirection: Axis.vertical, + shrinkWrap: true, + itemBuilder: (BuildContext context, + int index) { + return Padding( + padding: EdgeInsets.all(8.0), + child: Column( + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Container( + child: Row( + children: [ + Container( + child: Text( + model + .productDetailService[ + 0] + .reviews[ + index] + .customerId + .toString(), + style: TextStyle( + fontSize: 17, + color: Colors + .grey, + fontWeight: + FontWeight + .w600), + ), + ), + Container( + margin: + EdgeInsets.only( + left: 210), + child: RatingBar + .readOnly( + initialRating: model + .productDetailService[ + 0] + .reviews[ + index] + .rating + .toDouble(), + size: 15.0, + filledColor: + Colors.yellow[ + 700], + emptyColor: Colors + .grey[500], + isHalfAllowed: + true, + halfFilledIcon: + Icons + .star_half, + filledIcon: + Icons.star, + emptyIcon: + Icons.star, + ), + ), + ], + ), + ), + SizedBox( + height: 10, + ), + Container( + child: Text( + model + .productDetailService[ + 0] + .reviews[index] + .reviewText, + style: TextStyle( + fontSize: 20), + ), + ), + SizedBox( + height: 50, + ), + Divider( + height: 1, + color: Colors.grey), + ], + ), + ); + }, + ) + : Container( + padding: EdgeInsets.all(15), + alignment: Alignment.center, + child: Text('No Reviews Available'), + ), + ) + : isAvailabilty + ? BaseView( + onModelReady: (model) => + model.getProductLocationData(), + builder: (_, model, wi) => + ListView.builder( + physics: ScrollPhysics(), + scrollDirection: Axis.vertical, + shrinkWrap: true, + itemCount: model + .productLocationService.length, + itemBuilder: (BuildContext context, + int index) { + return Padding( + padding: EdgeInsets.all(8.0), + child: Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// mainAxisAlignment: MainAxisAlignment.start, + children: [ + Row( +// crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + Expanded( + flex: 1, + child: Image.network(model + .productLocationService[ + index] + .projectImageUrl), + ), + SizedBox( + width: 10, + ), + Expanded( + flex: 4, + child: Text( + model + .productLocationService[ + index] + .locationDescription + + "\n" + + fixingString(model + .productLocationService[ + 0] + .cityName + .toString()), + style: TextStyle( + fontSize: 12), + ), + ), + Expanded( + flex: 1, + child: IconButton( + icon: Icon(Icons + .location_on), + color: Colors.red, + onPressed: () {}, + ), + ), + Expanded( + flex: 1, + child: IconButton( + icon: + Icon(Icons.phone), + color: Colors.red, + onPressed: () {}, + ), + ), + ], + ), + Divider( + height: 1.2, + color: Colors.grey) + ], + ), + ); + }, + ), + ) + : Container(), + ], + ), + ), +// ListView(scrollDirection: Axis.vertical, shrinkWrap: true, children: [Text('ENAD')]), + ], + ), + ), + bottomSheet: footerWidget( + widget.product.stockAvailability != 'Out of stock', + widget.product.orderMaximumQuantity, + widget.product.orderMinimumQuantity, + widget.product.stockQuantity, + widget.product), + ); + } +} + +class footerWidget extends StatefulWidget { + final bool isAvailble; + final int maxQuantity; + final int minQuantity; + final int quantityLimit; + final PharmacyProduct item; + footerWidget(this.isAvailble, this.maxQuantity, this.minQuantity, + this.quantityLimit, this.item); + @override + _footerWidgetState createState() => _footerWidgetState(); +} + +class _footerWidgetState extends State { + double quantityUI = 70; + bool showUI = false; + @override + Widget build(BuildContext context) { + return Container( + width: double.infinity, + height: quantityUI, + color: Colors.white, + child: Column( + children: [ + showUI + ? Container( + width: double.infinity, + height: 90, + color: Colors.white, + child: Container( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + TranslationBase.of(context).quantity, + style: TextStyle( + fontSize: 15, fontWeight: FontWeight.bold), + ), + ), +// ListView( +// scrollDirection: Axis.horizontal, +// children: [ +// itemQuantity(), +// ], +// ), + Container( +// margin: EdgeInsets.symmetric(vertical: 20.0), + height: 50.0, + child: ListView( + scrollDirection: Axis.horizontal, + children: [ + InkWell( + child: Container( + alignment: Alignment.center, + width: 50.0, + color: Colors.white, + child: Text( + '1', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 20), + ), + ), + onTap: () { + setState(() { + price = 1; + if (price >= widget.quantityLimit) { + isOverQuantity = true; + } else { + isOverQuantity = false; + return price; + } + }); + }, + ), + SizedBox( + width: 5, + ), + InkWell( + child: Container( + alignment: Alignment.center, + width: 50.0, + color: Colors.white, + child: Text( + '2', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 20), + ), + ), + onTap: () { + setState(() { + price = 2; + if (price >= widget.quantityLimit) { + isOverQuantity = true; + } else { + isOverQuantity = false; + return price; + } + }); + }, + ), + SizedBox( + width: 5, + ), + InkWell( + child: Container( + alignment: Alignment.center, + width: 50.0, + color: Colors.white, + child: Text( + '3', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 20), + ), + ), + onTap: () { + setState(() { + price = 3; + if (price >= widget.quantityLimit) { + isOverQuantity = true; + } else { + isOverQuantity = false; + return price; + } + }); + }, + ), + SizedBox( + width: 5, + ), + InkWell( + child: Container( + alignment: Alignment.center, + width: 50.0, + color: Colors.white, + child: Text( + '4', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 20), + ), + ), + onTap: () { + setState(() { + price = 4; + if (price >= widget.quantityLimit) { + isOverQuantity = true; + } else { + isOverQuantity = false; + return price; + } + }); + }, + ), + SizedBox( + width: 5, + ), + InkWell( + child: Container( + alignment: Alignment.center, + width: 50.0, + color: Colors.white, + child: Text( + '5', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 20), + ), + ), + onTap: () { + setState(() { + price = 5; + if (price >= widget.quantityLimit) { + isOverQuantity = true; + } else { + isOverQuantity = false; + return price; + } + }); + }, + ), + SizedBox( + width: 5, + ), + InkWell( + child: Container( + alignment: Alignment.center, + width: 50.0, + color: Colors.white, + child: Text( + '6', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 20), + ), + ), + onTap: () { + setState(() { + price = 6; + if (price >= widget.quantityLimit) { + isOverQuantity = true; + } else { + isOverQuantity = false; + return price; + } + }); + }, + ), + SizedBox( + width: 5, + ), + InkWell( + child: Container( + alignment: Alignment.center, + width: 50.0, + color: Colors.white, + child: Text( + '7', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 20), + ), + ), + onTap: () { + setState(() { + price = 7; + if (price >= widget.quantityLimit) { + isOverQuantity = true; + } else { + isOverQuantity = false; + return price; + } + }); + }, + ), + SizedBox( + width: 5, + ), + InkWell( + child: Container( + alignment: Alignment.center, + width: 50.0, + color: Colors.white, + child: Text( + '8', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 20), + ), + ), + onTap: () { + setState(() { + price = 8; + if (price >= widget.quantityLimit) { + isOverQuantity = true; + } else { + isOverQuantity = false; + return price; + } + }); + }, + ), + SizedBox( + width: 5, + ), + InkWell( + child: Container( + alignment: Alignment.center, + width: 50.0, + color: Colors.white, + child: Text( + '9', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 20), + ), + ), + onTap: () { + setState(() { + price = 9; + if (price >= widget.quantityLimit) { + isOverQuantity = true; + } else { + isOverQuantity = false; + return price; + } + }); + }, + ), + SizedBox( + width: 5, + ), + InkWell( + child: Container( + alignment: Alignment.center, + width: 50.0, + color: Colors.white, + child: Text( + '10', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 20), + ), + ), + onTap: () { + setState(() { + price = 10; + if (price >= widget.quantityLimit) { + isOverQuantity = true; + } else { + isOverQuantity = false; + return price; + } + }); + }, + ), + SizedBox( + width: 5, + ), + Container( + width: 50.0, + child: TextField( + decoration: + InputDecoration(labelText: 'quantity #'), + onChanged: (text) { + print(price); + print(widget.quantityLimit); + if (int.tryParse(text) == null) { + text = ''; + } else { + setState(() { + price = int.parse(text); + if (price >= widget.quantityLimit) { + isOverQuantity = true; + } else { + isOverQuantity = false; + } + }); + } + }, + ), + ), + ], + ), + ) + ], + ), + ), + ) + : Container( + height: 20, + ), + Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: 70, + height: 50, + child: FlatButton( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + flex: 4, + child: Text( + price.toString(), + style: TextStyle(fontSize: 20), + ), + ), + Expanded( + flex: 5, + child: Text( + TranslationBase.of(context).quantityShortcut, + style: TextStyle(fontSize: 16), + ), + ), + ], + ), + onPressed: () { + setState(() { + if (showUI) { + quantityUI = 70; + showUI = false; + } else { + quantityUI = 150; + showUI = true; + } + }); + }, + ), + ), + !widget.isAvailble && price > 0 || price > widget.quantityLimit + ? Container( + width: 190, + height: 46, + color: Colors.grey, + child: Align( + alignment: Alignment.center, + child: Text( + TranslationBase.of(context).addToCart, + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 15), + ), + ), + ) + : InkWell( + onTap: () { + addToCartFunction(price, widget.item.id); + }, + child: Container( + alignment: Alignment.center, + width: 190, + height: 46, + color: Colors.green, + child: Text( + TranslationBase.of(context).addToCart, + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 15), + ), + ), + ), + SizedBox( + width: 5, + ), + !widget.isAvailble && price > 0 || price > widget.quantityLimit + ? Container( + width: 120, + height: 46, + color: Colors.grey, + child: Align( + alignment: Alignment.center, + child: Text( + TranslationBase.of(context).buyNow, + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 15), + ), + ), + ) + : InkWell( + onTap: () { + print('buy now'); + addToCartFunction(price, widget.item.id); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => CartOrderPage()), + ); + }, + child: Container( + alignment: Alignment.center, + width: 120, + height: 46, + color: Colors.blue, + child: Text( + TranslationBase.of(context).buyNow, + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 15), + ), + ), + ), + ], + ), + ], + ), + ); + } +} + +class productNameAndPrice extends StatefulWidget { + BuildContext context; + PharmacyProduct item; + productNameAndPrice(this.context, this.item); + @override + _productNameAndPriceState createState() => _productNameAndPriceState(); +} + +class _productNameAndPriceState extends State { + @override + Widget build(BuildContext context) { + return Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + children: [ + Text( + widget.item.price.toString(), + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30), + ), + SizedBox( + width: 40, + ), + Text( + widget.item.stockAvailability, + style: widget.item.stockAvailability == 'Out of stock' + ? TextStyle(fontWeight: FontWeight.bold, color: Colors.red) + : TextStyle( + fontWeight: FontWeight.bold, color: Colors.green), + ), + SizedBox(width: 20), + widget.item.stockAvailability == 'Out of stock' + ? Text( + TranslationBase.of(context).notifyMe, + style: TextStyle( + color: Colors.blue, + decoration: TextDecoration.underline, + ), + ) + : Container(), + widget.item.stockAvailability == 'Out of stock' + ? Icon( + FontAwesomeIcons.bell, + color: Colors.blue, + size: 15.0, + ) + : Container(), + Container( + margin: languageID == 'ar' + ? EdgeInsets.only(right: 25) + : EdgeInsets.only(left: 25), + width: 40, + height: 40, + decoration: BoxDecoration( + color: Colors.grey, + borderRadius: BorderRadius.circular(30), + ), + child: !isInWishlit + ? IconButton( + icon: Icon(Icons.favorite_border), + color: Colors.white, + onPressed: () { + setState(() { + addToWishlistFunction(widget.item.id); + }); +// MyStatelessWidget(); + }, + ) + : IconButton( + icon: Icon(Icons.favorite), + color: Colors.red, + onPressed: () { + setState(() { + deleteFromWishlistFunction(widget.item.id); + }); +// MyStatelessWidget(); + }, + )), + ], + ), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Container( + margin: EdgeInsets.only(left: 5), + child: Align( + alignment: + languageID == 'ar' ? Alignment.topRight : Alignment.topLeft, + child: Text( + languageID == 'ar' + ? widget.item.fullDescriptionn + : widget.item.fullDescription, + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 15), + ), + ), + ), + ), + Row( + children: [ + Expanded( + flex: 2, + child: Container( + margin: EdgeInsets.only(right: 150), + child: Align( + alignment: Alignment.bottomLeft, + child: RatingBar.readOnly( + initialRating: 3, + size: 15.0, + filledColor: Colors.yellow[700], + emptyColor: Colors.grey[500], + isHalfAllowed: true, + halfFilledIcon: Icons.star_half, + filledIcon: Icons.star, + emptyIcon: Icons.star, + ), + ), + ), + ), + Expanded( + flex: 1, + child: Container( + child: widget.item.rxMessage != null + ? Text( + languageID == 'ar' + ? widget.item.rxMessagen.toString() + : widget.item.rxMessage.toString(), + style: TextStyle(color: Colors.red, fontSize: 10), + ) + : Container()), + ), + widget.item.rxMessage != null + ? Icon( + FontAwesomeIcons.questionCircle, + color: Colors.red, + size: 15.0, + ) + : Container(), + ], + ), + ], + ); + } +} + +//productNameAndPrice(BuildContext context, item) { +// return Column( +// mainAxisAlignment: MainAxisAlignment.start, +// children: [ +// Padding( +// padding: const EdgeInsets.all(8.0), +// child: Row( +// children: [ +// Text( +// item.price.toString(), +// style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30), +// ), +// SizedBox( +// width: 40, +// ), +// Text( +// item.stockAvailability, +// style: item.stockAvailability == 'Out of stock' +// ? TextStyle(fontWeight: FontWeight.bold, color: Colors.red) +// : TextStyle(fontWeight: FontWeight.bold, color: Colors.green), +// ), +// SizedBox(width: 20), +// item.stockAvailability == 'Out of stock' +// ? Text( +// TranslationBase.of(context).notifyMe, +// style: TextStyle( +// color: Colors.blue, +// decoration: TextDecoration.underline, +// ), +// ) +// : Container(), +// item.stockAvailability == 'Out of stock' +// ? Icon( +// FontAwesomeIcons.bell, +// color: Colors.blue, +// size: 15.0, +// ) +// : Container(), +// +// Container( +// margin: languageID=='ar' ? EdgeInsets.only(right: 25) : EdgeInsets.only(left: 25), +// width: 40, +// height: 40, +// decoration: BoxDecoration( +// color: Colors.grey, +// borderRadius: BorderRadius.circular(30), +// ), +// child: !isInWishlit ?IconButton( +// icon: Icon(Icons.favorite_border), +// color: Colors.white, +// onPressed: () { +// addToWishlistFunction(item.id); +//// MyStatelessWidget(); +// +// }, +// ):IconButton( +// icon: Icon(Icons.favorite), +// color: Colors.red, +// onPressed: () { +// deleteFromWishlistFunction(item.id); +//// MyStatelessWidget(); +// +// }, +// ) +// ), +// +// ], +// ), +// ), +// Padding( +// padding: const EdgeInsets.all(8.0), +// child: Container( +// margin: EdgeInsets.only(left: 5), +// child: Align( +// alignment: +// languageID == 'ar' ? Alignment.topRight : Alignment.topLeft, +// child: Text( +// languageID == 'ar' ? item.fullDescriptionn : item.fullDescription, +// style: TextStyle(fontWeight: FontWeight.bold, fontSize: 15), +// ), +// ), +// ), +// ), +// Row( +// children: [ +// Expanded( +// flex: 2, +// child: Container( +// margin: EdgeInsets.only(right: 150), +// child: Align( +// alignment: Alignment.bottomLeft, +// child: RatingBar.readOnly( +// initialRating: 3, +// size: 15.0, +// filledColor: Colors.yellow[700], +// emptyColor: Colors.grey[500], +// isHalfAllowed: true, +// halfFilledIcon: Icons.star_half, +// filledIcon: Icons.star, +// emptyIcon: Icons.star, +// ), +// ), +// ), +// ), +// Expanded( +// flex: 1, +// child: Container( +// child: item.rxMessage != null +// ? Text( +// languageID == 'ar' +// ? item.rxMessagen.toString() +// : item.rxMessage.toString(), +// style: TextStyle(color: Colors.red, fontSize: 10), +// ) +// : Container()), +// ), +// item.rxMessage != null +// ? Icon( +// FontAwesomeIcons.questionCircle, +// color: Colors.red, +// size: 15.0, +// ) +// : Container(), +// ], +// ), +// ], +// ); +//} + +slideDetail() { + return Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 14.0, vertical: 15.0), + decoration: const BoxDecoration( + border: Border( + top: BorderSide(width: 0.5, color: Colors.grey), + left: BorderSide(width: 0.5, color: Colors.grey), + right: BorderSide(width: 0.5, color: Colors.grey), + bottom: BorderSide(width: 0.5, color: Colors.grey), + ), + color: Colors.white, + ), + child: const Text('1', + textAlign: TextAlign.center, + style: TextStyle(color: Color(0xFF000000))), + ), + ) + ], + ); +} + +fixingString(txt) { + String stringTxt; + String newTxt; + stringTxt = txt.toString(); + newTxt = stringTxt.split('.')[1]; + + return newTxt; +} + +getLanguageID() async { + languageID = await sharedPref.getString(APP_LANGUAGE); +} + +getSpecificationData(itemID) async { + ProductDetailViewModel x = new ProductDetailViewModel(); + specificationData = await x.productSpecificationData(itemID); +} + +addToCartFunction(quantity, itemID) async { + ProductDetailViewModel x = new ProductDetailViewModel(); + await x.addToCartData(quantity, itemID); +} + +addToWishlistFunction(itemID) async { + ProductDetailViewModel x = new ProductDetailViewModel(); + isInWishlit = true; + await x.addToWishlistData(itemID); +} + +deleteFromWishlistFunction(itemID) async { + ProductDetailViewModel x = new ProductDetailViewModel(); + isInWishlit = false; + await x.addToWishlistData(itemID); +} + +checkWishlist() async { + ProductDetailViewModel x = new ProductDetailViewModel(); + await x.checkWishlistData(); + for (int i = 0; i < x.wishListItems.length; i++) { +// print(itemID); +// print(x.wishListItems[i].product.id); + if (itemID == x.wishListItems[i].product.id) { + isInWishlit = true; +// print('in wishlist'); + break; + } else { + isInWishlit = false; +// print('not in wishlist'); + } + } +} + +class sttingModalBottomSheet extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Container(); + } +} + +settingModalBottomSheet(context) { + showModalBottomSheet( + context: context, + builder: (BuildContext bc) { + return Container( + child: new Wrap( + children: [ + new ListTile( + leading: new Icon(Icons.shopping_cart), + title: new Text('Add to cart'), + onTap: () => { + if (price > 0) + {addToCartFunction(price, itemID)} + else + { + AppToast.showErrorToast( + message: "you should add quantity") + } + }), + new ListTile( + leading: new Icon(Icons.favorite_border), + title: new Text('Add to wishlist'), + onTap: () => {addToWishlistFunction(itemID)}, + ), + new ListTile( + leading: new Icon(Icons.compare), + title: new Text('Compare'), + onTap: () => { + Provider.of(context, listen: false) + .addItem(specificationData), + }, + ), + ], + ), + ); + }); +} + +userInfo(id, product) async { + customerId = await sharedPref.getString(PHARMACY_CUSTOMER_ID); + if (customerId != null) { + itemID = id; + product = product; + checkWishlist(); + } + return customerId; +// getSpecificationData(itemID); +} diff --git a/lib/pages/pharmacies/screens/address-select-page.dart b/lib/pages/pharmacies/screens/address-select-page.dart new file mode 100644 index 00000000..6c39ba3f --- /dev/null +++ b/lib/pages/pharmacies/screens/address-select-page.dart @@ -0,0 +1,34 @@ +import 'package:diplomaticquarterapp/core/model/pharmacies/Addresses.dart'; +import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/OrderPreviewViewModel.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:flutter/material.dart'; + +class AddressSelectPageTest extends StatelessWidget { + final List addresses; + + AddressSelectPageTest(this.addresses); + + @override + Widget build(BuildContext context) { + return AppScaffold( + title: "test", + isShowAppBar: true, + isShowDecPage: false, + body: Column( + children: [ + Container( + child: RaisedButton( + onPressed: () => {Navigator.pop(context, addresses[0])}, + child: new Text( + "Set address", + style: new TextStyle(color: Colors.white, fontSize: 14), + ), + color: Colors.blueAccent, + disabledColor: Colors.blueAccent, + ), + ), + ], + ), + ); + } +} diff --git a/lib/pages/pharmacies/screens/cart-order-page.dart b/lib/pages/pharmacies/screens/cart-order-page.dart new file mode 100644 index 00000000..cca6c1df --- /dev/null +++ b/lib/pages/pharmacies/screens/cart-order-page.dart @@ -0,0 +1,382 @@ +import 'package:diplomaticquarterapp/core/model/pharmacies/Addresses.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/ShoppingCartResponse.dart'; +import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/OrderPreviewViewModel.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/pages/pharmacies/screens/cart-order-preview.dart'; +import 'package:diplomaticquarterapp/pages/pharmacies/screens/pharmacy-terms-conditions-page.dart'; +import 'package:diplomaticquarterapp/pages/pharmacies/widgets/ProductOrderItem.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/GestureIconButton.dart'; +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'; + +class CartOrderPage extends StatelessWidget { + @override + Widget build(BuildContext context) { + final mediaQuery = MediaQuery.of(context); + + final height = mediaQuery.size.height - 60 - mediaQuery.padding.top; + + return BaseView( + onModelReady: (model) => model.getOrderPreviewData(), + builder: (_, model, wi) => ChangeNotifierProvider.value( + value: model.cartResponse, + child: AppScaffold( + appBarTitle: TranslationBase.of(context).shoppingCart, + isShowAppBar: true, + isPharmacy: true, + baseViewModel: model, + backgroundColor: Colors.white, + body: !(model.cartResponse.shoppingCarts == null || + model.cartResponse.shoppingCarts.length == 0) + ? Container( + height: height * 0.85, + width: double.infinity, + child: Consumer( + builder: (ctx, cart, _) => Container( + child: SingleChildScrollView( + child: Container( + margin: EdgeInsets.all(10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + GestureIconButton( + TranslationBase.of(context).deleteAllItems, + Icon( + Icons.delete_outline_sharp, + color: Colors.grey.shade700, + ), + onTap: () => {model.deleteShoppingCart()}, + ), + const Divider( + color: Color(0xFFD6D6D6), + height: 20, + thickness: 1, + indent: 0, + endIndent: 0, + ), + Container( + child: Column( + children: [ + ...List.generate( + cart.shoppingCarts != null + ? cart.shoppingCarts.length + : 0, + (index) => ProductOrderItem( + cart.shoppingCarts[index], () { + print(cart.shoppingCarts[index] + .quantity); + model.changeProductQuantity( + cart.shoppingCarts[index]); + }, + () => model.deleteProduct( + cart.shoppingCarts[index]))) + ], + ), + ), + const Divider( + color: Color(0xFFD6D6D6), + height: 20, + thickness: 2, + indent: 0, + endIndent: 0, + ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Texts( + TranslationBase.of(context).subtotal, + fontSize: 14, + color: Colors.black, + fontWeight: FontWeight.w500, + ), + Texts( + "${TranslationBase.of(context).sar} ${(cart.subtotal).toStringAsFixed(2)}", + fontSize: 14, + color: Colors.black, + fontWeight: FontWeight.w500, + ), + ], + ), + const Divider( + color: Color(0xFFD6D6D6), + height: 20, + thickness: 1, + indent: 0, + endIndent: 0, + ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Texts( + "${TranslationBase.of(context).vat}", + fontSize: 14, + color: Colors.black, + fontWeight: FontWeight.w500, + ), + Texts( + "${TranslationBase.of(context).sar} ${(cart.subtotalVatAmount).toStringAsFixed(2)}", + fontSize: 14, + color: Colors.black, + fontWeight: FontWeight.w500, + ), + ], + ), + const Divider( + color: Color(0xFFD6D6D6), + height: 20, + thickness: 1, + indent: 0, + endIndent: 0, + ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Texts( + TranslationBase.of(context).total, + fontSize: 14, + color: Colors.black, + fontWeight: FontWeight.bold, + ), + Texts( + "${TranslationBase.of(context).sar} ${(cart.subtotal).toStringAsFixed(2)}", + fontSize: 14, + color: Colors.black, + fontWeight: FontWeight.bold, + ), + ], + ), + const Divider( + color: Color(0xFFD6D6D6), + height: 20, + thickness: 1, + indent: 0, + endIndent: 0, + ), + Image.asset( + "assets/images/pharmacy_module/payment_image.png", + width: mediaQuery.size.width - 20, + height: 30.0, + fit: BoxFit.scaleDown, + ) + ], + ), + ), + ), + ), + ), + ) + : Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Image.asset( + 'assets/images/new-design/empty_box.png', + width: 100, + height: 100, + fit: BoxFit.cover, + ), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + 'There is no data', + style: TextStyle(fontSize: 30), + ), + ) + ], + ), + ), + bottomSheet: Container( + height: !(model.cartResponse.shoppingCarts == null || + model.cartResponse.shoppingCarts.length == 0) + ? height * 0.15 + : 0, + color: Colors.white, + child: OrderBottomWidget(model.addresses, height), + ), + ), + ), + ); + } +} + +class OrderBottomWidget extends StatefulWidget { + final List addresses; + final double height; + + OrderBottomWidget(this.addresses, this.height); + + @override + _OrderBottomWidgetState createState() => _OrderBottomWidgetState(); +} + +class _OrderBottomWidgetState extends State { + bool isAgree = false; + + @override + Widget build(BuildContext context) { + ProjectViewModel projectProvider = Provider.of(context); + + return Container( + margin: EdgeInsets.symmetric(horizontal: 10, vertical: 0), + child: Consumer( + builder: (ctx, cart, _) => !(cart.shoppingCarts == null || + cart.shoppingCarts.length == 0) + ? Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Divider( + color: Color(0xFFD6D6D6), + height: 1, + thickness: 1, + indent: 0, + endIndent: 0, + ), + Container( + height: widget.height * 0.070, + color: Color(0xffe6ffe0), + padding: EdgeInsets.symmetric(horizontal: 4), + child: Expanded( + child: Row( + children: [ + InkWell( + onTap: () { + setState(() { + isAgree = !isAgree; + }); + }, + child: Container( + width: 25.0, + height: widget.height * 0.070, + decoration: new BoxDecoration( + color: !isAgree + ? Color(0xffeeeeee) + : Colors.green, + shape: BoxShape.circle, + ), + child: !isAgree + ? null + : Padding( + padding: const EdgeInsets.all(0.0), + child: Icon( + Icons.check, + color: Colors.white, + size: 25, + ), + ), + ), + ), + Expanded( + child: Container( + padding: EdgeInsets.symmetric(horizontal: 4), + margin: const EdgeInsets.symmetric(vertical: 4), + child: Texts( + TranslationBase.of(context) + .pharmacyServiceTermsCondition, + fontSize: 13, + color: Colors.grey.shade800, + fontWeight: FontWeight.normal, + ), + ), + ), + InkWell( + onTap: () => { + Navigator.push(context, + FadePage(page: PharmacyTermsConditions())) + }, + child: Container( + child: Icon( + Icons.info, + size: 25, + color: Color(0xff005aff), + ), + ), + ), + ], + ), + ), + ), + Container( + height: widget.height * 0.065, + margin: EdgeInsets.symmetric(vertical: 2), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + margin: EdgeInsets.symmetric( + horizontal: 0, vertical: 0), + child: Row( + children: [ + Texts( + "${TranslationBase.of(context).sar} ${(cart.subtotal).toStringAsFixed(2)}", + fontSize: + projectProvider.isArabic ? 12 : 14, + fontWeight: FontWeight.bold, + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 4), + child: Texts( + "${TranslationBase.of(context).inclusiveVat}", + fontSize: 8, + color: Colors.grey, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + Texts( + "${cart.quantityCount} ${TranslationBase.of(context).items}", + fontSize: 10, + color: Colors.grey, + fontWeight: FontWeight.bold, + ), + ], + ), + ), + RaisedButton( + onPressed: isAgree + ? () => { + Navigator.push( + context, + FadePage( + page: OrderPreviewPage( + widget.addresses))) + } + : null, + child: new Text( + "${TranslationBase.of(context).checkOut}", + style: new TextStyle( + color: isAgree + ? Colors.white + : Colors.grey.shade300, + fontSize: 14), + ), + color: Color(0xff005aff), + disabledColor: Color(0xff005aff), + ), + ], + ), + ), + ], + ) + : Container(), + )); + } +} diff --git a/lib/pages/pharmacies/screens/cart-order-preview.dart b/lib/pages/pharmacies/screens/cart-order-preview.dart new file mode 100644 index 00000000..9d819c1c --- /dev/null +++ b/lib/pages/pharmacies/screens/cart-order-preview.dart @@ -0,0 +1,832 @@ +import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/Addresses.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/payment-checkout-data.dart'; +import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/OrderPreviewViewModel.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/pages/pharmacies/screens/address-select-page.dart'; +import 'package:diplomaticquarterapp/pages/pharmacies/screens/payment-method-select-page.dart'; +import 'package:diplomaticquarterapp/pages/pharmacies/screens/pharmacy_module_page.dart'; +import 'package:diplomaticquarterapp/pages/pharmacies/widgets/ProductOrderPreviewItem.dart'; +import 'package:diplomaticquarterapp/pages/pharmacy/pharmacyAddresses/PharmacyAddresses.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +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 'package:flutter/scheduler.dart'; + +class OrderPreviewPage extends StatelessWidget { + final List addresses; + + OrderPreviewPage(this.addresses); + + @override + Widget build(BuildContext context) { + final mediaQuery = MediaQuery.of(context); + final height = mediaQuery.size.height - + 60 - + mediaQuery.padding.top; + + return BaseView( + onModelReady: (model) => model.getShoppingCart(), + builder: (_, model, wi) => ChangeNotifierProvider.value( + value: model.paymentCheckoutData, + child: AppScaffold( + appBarTitle: "${TranslationBase.of(context).checkOut}", + isShowAppBar: true, + isPharmacy: true, + isShowDecPage: false, + backgroundColor: Colors.white, + baseViewModel: model, + body: Container( + height: height * 0.90, + child: SingleChildScrollView( + child: Container( + color: Color(0xFFF1F1F1), + child: Column( + children: [ + SelectAddressWidget(model, addresses), + SizedBox( + height: 10, + ), + SelectPaymentOptionWidget(model), + SizedBox( + height: 10, + ), + Consumer( + builder: (ctx, paymentData, _) => + paymentData.lacumInformation != null + ? Container( + child: Column( + children: [ + LakumWidget(model), + SizedBox( + height: 10, + ), + ], + ), + ) + : Container()), + Container( + color: Colors.white, + width: double.infinity, + padding: EdgeInsets.all(8), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Texts( + TranslationBase.of(context).reviewOrder, + fontSize: 14, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ...List.generate( + model.cartResponse.shoppingCarts != null + ? model.cartResponse.shoppingCarts.length + : 0, + (index) => ProductOrderPreviewItem( + model.cartResponse.shoppingCarts[index]), + ), + ], + ), + ), + Container( + width: double.infinity, + padding: EdgeInsets.all(8), + child: model.cartResponse.subtotal != null + ? Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Texts( + TranslationBase.of(context) + .orderSummary, + fontSize: 14, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + SizedBox( + height: 20, + ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Texts( + "${TranslationBase.of(context).subtotal}", + fontSize: 14, + color: Colors.black, + fontWeight: FontWeight.w500, + ), + Texts( + "${TranslationBase.of(context).sar} ${(model.cartResponse.subtotal).toStringAsFixed(2)}", + fontSize: 14, + color: Colors.black, + fontWeight: FontWeight.w500, + ), + ], + ), + const Divider( + color: Color(0xFFD6D6D6), + height: 20, + thickness: 1, + indent: 0, + endIndent: 0, + ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Texts( + "${TranslationBase.of(context).shipping}", + fontSize: 14, + color: Colors.black, + fontWeight: FontWeight.w500, + ), + Texts( + "${TranslationBase.of(context).sar} ${(model.totalAdditionalShippingCharge).toStringAsFixed(2)}", + fontSize: 14, + color: Colors.black, + fontWeight: FontWeight.w500, + ), + ], + ), + const Divider( + color: Color(0xFFD6D6D6), + height: 20, + thickness: 1, + indent: 0, + endIndent: 0, + ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Texts( + "${TranslationBase.of(context).vat}", + fontSize: 14, + color: Colors.black, + fontWeight: FontWeight.w500, + ), + Texts( + "${TranslationBase.of(context).sar} ${(model.cartResponse.subtotalVatAmount).toStringAsFixed(2)}", + fontSize: 14, + color: Colors.black, + fontWeight: FontWeight.w500, + ), + ], + ), + const Divider( + color: Color(0xFFD6D6D6), + height: 20, + thickness: 1, + indent: 0, + endIndent: 0, + ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Texts( + TranslationBase.of(context).total, + fontSize: 14, + color: Colors.black, + fontWeight: FontWeight.bold, + ), + Texts( + "${TranslationBase.of(context).sar} ${(model.cartResponse.subtotal).toStringAsFixed(2)}", + fontSize: 14, + color: Colors.black, + fontWeight: FontWeight.bold, + ), + ], + ), + SizedBox( + height: 10, + ), + ], + ) + : Container(), + ) + ], + ), + ), + ), + ), + bottomSheet: Container( + height: model.cartResponse.shoppingCarts != null + ? height * 0.10 + : 0, + color: Colors.white, + child: PaymentBottomWidget(model), + ), + ), + )); + } +} + +class SelectAddressWidget extends StatefulWidget { + final OrderPreviewViewModel model; + final List addresses; + + SelectAddressWidget(this.model, this.addresses); + + @override + _SelectAddressWidgetState createState() => _SelectAddressWidgetState(); +} + +class _SelectAddressWidgetState extends State { + Addresses address; + + _navigateToAddressPage() { + Navigator.push(context, FadePage(page: PharmacyAddressesPage())) + .then((result) { + if (result != null) { + address = result; + widget.model.paymentCheckoutData.address = address; + widget.model.getInformationsByAddress(); + } + + /* setState(() { + if (result != null) { + address = result; + widget.model.paymentCheckoutData.address = address; + widget.model.getInformationsByAddress(); + } + })*/ + }); + } + + @override + void initState() { + if (widget.model.paymentCheckoutData.address != null) { + address = widget.model.paymentCheckoutData.address; + } + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Consumer( + builder: (ctx, paymentData, _) => Container( + color: Colors.white, + child: address == null + ? InkWell( + onTap: () => {_navigateToAddressPage()}, + child: Container( + margin: EdgeInsets.symmetric(vertical: 12, horizontal: 12), + child: Row( + children: [ + Image.asset( + "assets/images/pharmacy_module/ic_shipping_address.png", + width: 30.0, + height: 30.0, + fit: BoxFit.scaleDown, + ), + Expanded( + child: Container( + padding: + EdgeInsets.symmetric(vertical: 0, horizontal: 6), + child: Texts( + TranslationBase.of(context).selectAddress, + fontSize: 14, + fontWeight: FontWeight.bold, + color: Color(0xff0000ff), + ), + ), + ), + Icon( + Icons.arrow_forward_ios, + size: 20, + color: Colors.grey.shade400, + ), + ], + ), + ), + ) + : Container( + child: Container( + margin: EdgeInsets.symmetric(vertical: 12, horizontal: 12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Image.asset( + "assets/images/pharmacy_module/ic_shipping_mark.png", + width: 30.0, + height: 30.0, + fit: BoxFit.scaleDown, + ), + Expanded( + child: Container( + padding: EdgeInsets.symmetric( + vertical: 0, horizontal: 6), + child: Texts( + TranslationBase.of(context).shippingAddress, + fontSize: 14, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + ), + InkWell( + onTap: () => {_navigateToAddressPage()}, + child: Texts( + TranslationBase.of(context).changeAddress, + fontSize: 12, + fontWeight: FontWeight.normal, + color: Color(0xff0000ff), + ), + ), + ], + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Texts( + "${address.firstName} ${address.lastName}", + fontSize: 14, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Texts( + "${address.address1} ${address.address2} ${address.address2},, ${address.city}, ${address.country} ${address.zipPostalCode}", + fontSize: 12, + fontWeight: FontWeight.normal, + color: Colors.grey.shade500, + ), + ), + Row( + children: [ + Container( + margin: const EdgeInsets.only(right: 8), + child: Icon( + Icons.phone, + size: 20, + color: Colors.black, + ), + ), + Texts( + "${address.phoneNumber}", + fontSize: 14, + fontWeight: FontWeight.bold, + color: Colors.grey, + ), + ], + ), + Container( + margin: EdgeInsets.symmetric(vertical: 8), + child: SizedBox( + height: 2, + width: double.infinity, + child: Container( + color: Color(0xffefefef), + ), + ), + ), + Row( + children: [ + Image.asset( + "assets/images/pharmacy_module/ic_shipping_truck.png", + width: 30.0, + height: 30.0, + fit: BoxFit.scaleDown, + ), + Container( + padding: EdgeInsets.symmetric( + vertical: 0, horizontal: 6), + child: Texts( + "${TranslationBase.of(context).shipBy}", + fontSize: 12, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + Container( + child: Image.asset( + paymentData.shippingOption + .shippingRateComputationMethodSystemName == + "Shipping.FixedOrByWeight" + ? "assets/images/pharmacy_module/payment/hmg_shipping_logo.png" + : "assets/images/pharmacy_module/payment/aramex_shipping_logo.png", + fit: BoxFit.contain, + ), + margin: EdgeInsets.symmetric(horizontal: 8), + ), + ], + ), + ], + ), + ), + ), // ic_shipping_mark.png + ), + ); + } +} + +class SelectPaymentOptionWidget extends StatefulWidget { + final OrderPreviewViewModel model; + + SelectPaymentOptionWidget(this.model); + + @override + _SelectPaymentOptionWidgetState createState() => + _SelectPaymentOptionWidgetState(); +} + +class _SelectPaymentOptionWidgetState extends State { + PaymentOption paymentOption; + + _navigateToPaymentOption() { + Navigator.push(context, FadePage(page: PaymentMethodSelectPage())) + .then((result) => { + setState(() { + if (result != null) { + paymentOption = result; + widget.model.paymentCheckoutData.paymentOption = + paymentOption; + widget.model.paymentCheckoutData.updateData(); + } + }) + }); + } + + @override + void initState() { + if (widget.model.paymentCheckoutData.paymentOption != null) { + paymentOption = widget.model.paymentCheckoutData.paymentOption; + } + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Container( + color: Colors.white, + child: paymentOption == null + ? InkWell( + onTap: () => {_navigateToPaymentOption()}, + child: Container( + margin: EdgeInsets.symmetric(vertical: 12, horizontal: 12), + child: Row( + children: [ + Image.asset( + "assets/images/pharmacy_module/ic_payment_option.png", + width: 30.0, + height: 30.0, + fit: BoxFit.scaleDown, + ), + Expanded( + child: Container( + padding: + EdgeInsets.symmetric(vertical: 0, horizontal: 6), + child: Texts( + TranslationBase.of(context).selectPaymentOption, + fontSize: 14, + fontWeight: FontWeight.bold, + color: Color(0xff0000ff), + ), + ), + ), + Icon( + Icons.arrow_forward_ios, + size: 20, + color: Colors.grey.shade400, + ), + ], + ), + ), + ) + : Container( + margin: EdgeInsets.symmetric(vertical: 12, horizontal: 12), + child: Row( + children: [ + Image.asset( + "assets/images/pharmacy_module/ic_payment_option.png", + width: 30.0, + height: 30.0, + fit: BoxFit.scaleDown, + ), + Container( + margin: EdgeInsets.symmetric(horizontal: 8), + padding: EdgeInsets.symmetric(horizontal: 4, vertical: 0), + decoration: new BoxDecoration( + color: Colors.grey.shade100, + shape: BoxShape.rectangle, + ), + child: Image.asset( + widget.model.getPaymentOptionImage(paymentOption), + width: 30.0, + height: 30.0, + fit: BoxFit.scaleDown, + ), + ), + Expanded( + child: Container( + padding: EdgeInsets.symmetric(vertical: 0, horizontal: 6), + child: Texts( + widget.model.getPaymentOptionName(paymentOption), + fontSize: 14, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + ), + InkWell( + onTap: () => {_navigateToPaymentOption()}, + child: Texts( + TranslationBase.of(context).changeMethod, + fontSize: 12, + fontWeight: FontWeight.normal, + color: Color(0xff0000ff), + ), + ), + ], + ), + ), + ); + } +} + +class LakumWidget extends StatefulWidget { + final OrderPreviewViewModel model; + + LakumWidget(this.model); + + @override + _LakumWidgetState createState() => _LakumWidgetState(); +} + +class _LakumWidgetState extends State { + TextEditingController _pointsController = new TextEditingController(); + + @override + Widget build(BuildContext context) { + ProjectViewModel projectProvider = Provider.of(context); + + return Container( + color: Colors.white, + padding: EdgeInsets.symmetric(vertical: 12, horizontal: 12), + child: Row( + children: [ + Image.asset( + "assets/images/pharmacy_module/lakum/lakum_checkout.png", + width: 30.0, + fit: BoxFit.scaleDown, + ), + Container( + decoration: BoxDecoration(color: Color(0x99ffffff)), + padding: const EdgeInsets.symmetric(horizontal: 8), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Texts( + "${TranslationBase.of(context).lakumPoints}", + fontSize: 12, + fontWeight: FontWeight.bold, + ), + Texts( + "${widget.model.paymentCheckoutData.lacumInformation.lakumInquiryInformationObjVersion.pointsBalanceAmount}", + fontSize: 12, + fontWeight: FontWeight.normal, + ), + ], + ), + ), + Expanded( + child: Container( + decoration: BoxDecoration(color: Color(0x99ffffff)), + padding: const EdgeInsets.symmetric(horizontal: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Texts( + "${TranslationBase.of(context).riyal}", + fontSize: 12, + fontWeight: FontWeight.bold, + ), + Container( + margin: projectProvider.isArabic + ? EdgeInsets.only(right: 4) + : EdgeInsets.only(left: 4), + width: 60, + height: 50, + child: TextField( + decoration: InputDecoration( + border: OutlineInputBorder( + borderSide: + BorderSide(color: Colors.black, width: 0.2), + gapPadding: 0, + borderRadius: projectProvider.isArabic + ? BorderRadius.only( + topRight: Radius.circular(8), + bottomRight: Radius.circular(8)) + : BorderRadius.only( + topLeft: Radius.circular(8), + bottomLeft: Radius.circular(8)), + ), + disabledBorder: OutlineInputBorder( + borderSide: + BorderSide(color: Colors.black, width: 0.4), + gapPadding: 0, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(8), + bottomLeft: Radius.circular(8)), + ), + ), + controller: _pointsController, + keyboardType: TextInputType.number, + style: TextStyle( + fontSize: 14, + color: widget + .model + .paymentCheckoutData + .lacumInformation + .lakumInquiryInformationObjVersion + .pointsBalanceAmount > + 0 + ? Colors.black + : Colors.grey, + ), + enabled: widget + .model + .paymentCheckoutData + .lacumInformation + .lakumInquiryInformationObjVersion + .pointsBalanceAmount == + 0 + ? false + : true, + onChanged: (val) { + var value = int.tryParse(val); + if (value != null && + value <= + widget + .model + .paymentCheckoutData + .lacumInformation + .lakumInquiryInformationObjVersion + .pointsBalanceAmount) { + widget.model.paymentCheckoutData.usedLakumPoints = + value; + } else { + widget.model.paymentCheckoutData.usedLakumPoints = 0; + } + _pointsController.text = + "${widget.model.paymentCheckoutData.usedLakumPoints}"; + }, + ), + ), + Container( + height: 50, + padding: EdgeInsets.symmetric(horizontal: 8, vertical: 12), + decoration: new BoxDecoration( + color: Color(0xff3666E0), + shape: BoxShape.rectangle, + borderRadius: projectProvider.isArabic + ? BorderRadius.only( + topLeft: Radius.circular(6), + bottomLeft: Radius.circular(6)) + : BorderRadius.only( + topRight: Radius.circular(6), + bottomRight: Radius.circular(6)), + border: Border.fromBorderSide(BorderSide( + color: Color(0xff3666E0), + width: 0.8, + )), + ), + child: Texts( + "${TranslationBase.of(context).use}", + fontSize: 12, + color: Colors.white, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + ), + ], + ), + ); + } +} + +class PaymentBottomWidget extends StatelessWidget { + final OrderPreviewViewModel model; + + PaymentBottomWidget(this.model); + + @override + Widget build(BuildContext context) { + final scaffold = Scaffold.of(context); + + return Container( + margin: EdgeInsets.symmetric(horizontal: 10, vertical: 0), + child: Consumer( + builder: (ctx, paymentData, _) => paymentData.cartDataVisible + ? Container( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Container( + margin: + EdgeInsets.symmetric(horizontal: 0, vertical: 4), + child: Row( + children: [ + Texts( + "${TranslationBase.of(context).sar} ${(model.cartResponse.subtotal).toStringAsFixed(2)}", + fontSize: 14, + fontWeight: FontWeight.bold, + color: Color(0xff929295), + ), + Padding( + padding: + const EdgeInsets.symmetric(horizontal: 4), + child: Texts( + "${TranslationBase.of(context).inclusiveVat}", + fontSize: 8, + color: Color(0xff929295), + fontWeight: FontWeight.w600, + ), + ), + ], + ), + ), + Texts( + "${model.cartResponse.quantityCount} ${TranslationBase.of(context).items}", + fontSize: 10, + color: Colors.grey, + fontWeight: FontWeight.bold, + ), + ], + ), + Container( + child: RaisedButton( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + side: BorderSide( + color: Color(0xff929295), + width: 1, + ), + ), + onPressed: (paymentData.address != null && + paymentData.paymentOption != null) + ? () => { + model.makeOrder().then((_) { + if (model.state != ViewState.Idle) { + SnackBar snackBar = SnackBar( + content: Text( + 'Order has been placed successfully!!')); + scaffold.showSnackBar(snackBar); + } + + // Navigator.pushAndRemoveUntil( + // context, + // MaterialPageRoute( + // builder: (context) => + // PharmacyPage()), + // (Route r) => false); + }) + } + : null, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 16), + child: new Text( + "${TranslationBase.of(context).proceedPay}", + style: new TextStyle( + color: (paymentData.address != null && + paymentData.paymentOption != null) + ? Colors.white + : Colors.grey.shade400, + fontWeight: FontWeight.bold, + fontSize: 12), + ), + ), + color: (paymentData.address != null && + paymentData.paymentOption != null) + ? Colors.green + : Color(0xff929295), + disabledColor: (paymentData.address != null && + paymentData.paymentOption != null) + ? Colors.green + : Color(0xff929295), + ), + ), + ], + ), + ) + : Container(), + ), + ); + } +} diff --git a/lib/pages/pharmacies/screens/lacum-activitaion-vida-page.dart b/lib/pages/pharmacies/screens/lacum-activitaion-vida-page.dart new file mode 100644 index 00000000..fc1270c0 --- /dev/null +++ b/lib/pages/pharmacies/screens/lacum-activitaion-vida-page.dart @@ -0,0 +1,101 @@ +import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; +import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/lacum-registration-viewModel.dart'; +import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +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:diplomaticquarterapp/widgets/transitions/fade_page.dart'; +import 'package:flutter/material.dart'; + +import 'lacum-registration-page.dart'; + +class LakumActivationVidaPage extends StatelessWidget { + TextEditingController _identificationNumberController = + new TextEditingController(); + + @override + Widget build(BuildContext context) { + final mediaQuery = MediaQuery.of(context); + + return BaseView( + builder: (_, model, wi) => AppScaffold( + title: "Acount Activation", + isShowAppBar: true, + isShowDecPage: false, + backgroundColor: Colors.white, + baseViewModel: model, + body: Container( + margin: EdgeInsets.symmetric(vertical: 16, horizontal: 12), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Texts( + " This service allows you to activate your LAKUM account after registering through the Vida system. ", + fontSize: 14, + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: TextField( + controller: _identificationNumberController, + decoration: new InputDecoration( + hintText: 'Enter Identification Number', + ), + style: TextStyle( + fontSize: 16, + color: Colors.grey.shade700, + ), + ), + ), + ], + ), + Container( + margin: EdgeInsets.only(top: 4), + child: BorderedButton( + TranslationBase.of(context).accountActivation, + backgroundColor: + _identificationNumberController.text != null && + _identificationNumberController.text != "" + ? Color(0xff60686b) + : Color(0xffb0b4b5), + textColor: Colors.white, + fontSize: 16, + hPadding: 8, + vPadding: 12, + handler: _identificationNumberController.text != null && + _identificationNumberController.text != "" + ? () { + model + .checkLacumAccountActivation( + _identificationNumberController.text) + .then((_) => { + if (model.state == ViewState.Idle) + { + Navigator.push( + context, + FadePage( + page: LakumRegistrationPage( + _identificationNumberController + .text))) + .then((status) => { + if (status == 200) + {Navigator.pop(context, "")} + // back to previous page + }) + } + }); + } + : null, + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/pages/pharmacies/screens/lacum-registration-page.dart b/lib/pages/pharmacies/screens/lacum-registration-page.dart new file mode 100644 index 00000000..c40771b8 --- /dev/null +++ b/lib/pages/pharmacies/screens/lacum-registration-page.dart @@ -0,0 +1,234 @@ +import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/lacum-registration-viewModel.dart'; +import 'package:diplomaticquarterapp/models/id-name-pair.dart'; +import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/borderedButton.dart'; +import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; +import 'package:diplomaticquarterapp/widgets/dialogs/radio-group-dialog.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; +import 'package:flutter/material.dart'; + +import 'lakum-terms-conditions-page.dart'; + +class LakumRegistrationPage extends StatefulWidget { + final String patientIdentificationNo; + + LakumRegistrationPage(this.patientIdentificationNo); + + @override + _LakumRegistrationPageState createState() => _LakumRegistrationPageState(); +} + +class _LakumRegistrationPageState extends State { + final TextEditingController _firstNameController = TextEditingController(); + + final TextEditingController _lastNameController = TextEditingController(); + + final TextEditingController _mobileNumberController = TextEditingController(); + + List languages = List(); + + IdNamePair selectedLanguage; + + @override + Widget build(BuildContext context) { + final mediaQuery = MediaQuery.of(context); + languages.clear(); + languages.add(IdNamePair(1, TranslationBase.of(context).arabic)); + languages.add(IdNamePair(2, TranslationBase.of(context).english)); + + bool canSubmit = _firstNameController.text != null && + _firstNameController.text != "" && + _lastNameController.text != null && + _lastNameController.text != "" && + _mobileNumberController.text != null && + _mobileNumberController.text != "" && + selectedLanguage != null; + + return BaseView( + builder: (_, model, wi) => AppScaffold( + appBarTitle: + "${TranslationBase.of(context).register} ${TranslationBase.of(context).lakum}", + isShowAppBar: true, + isShowDecPage: false, + backgroundColor: Colors.white, + baseViewModel: model, + body: Container( + width: double.infinity, + child: SingleChildScrollView( + child: SizedBox( + height: + mediaQuery.size.height - 60 - mediaQuery.padding.top, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisSize: MainAxisSize.max, + children: [ + Column( + children: [ + Image.asset( + "assets/images/pharmacy_module/lakum/lakum_card_front_bg.png", + fit: BoxFit.fill, + height: 150, + width: mediaQuery.size.width, + ), + Container( + margin: EdgeInsets.symmetric(horizontal: 8), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + height: 10, + ), + Texts( + TranslationBase.of(context).firstName, + fontSize: 13, + fontWeight: FontWeight.normal, + color: Color(0xff8a8a8a), + ), + TextField( + controller: _firstNameController, + style: TextStyle( + fontSize: 16, + color: Colors.black, + ), + ), + SizedBox( + height: 10, + ), + Texts( + TranslationBase.of(context).lastName, + fontSize: 13, + fontWeight: FontWeight.normal, + color: Color(0xff8a8a8a), + ), + TextField( + controller: _lastNameController, + style: TextStyle( + fontSize: 16, + color: Colors.black, + ), + ), + SizedBox( + height: 10, + ), + Texts( + TranslationBase.of(context).mobileNumber, + fontSize: 13, + fontWeight: FontWeight.normal, + color: Color(0xff8a8a8a), + ), + TextField( + controller: _mobileNumberController, + style: TextStyle( + fontSize: 16, + color: Colors.black, + ), + ), + SizedBox( + height: 10, + ), + Texts( + TranslationBase.of(context) + .prefferedLanguage, + fontSize: 13, + fontWeight: FontWeight.normal, + color: Color(0xff8a8a8a), + ), + InkWell( + onTap: () { + RadioGroupDialog dialog = + new RadioGroupDialog( + context: context, + title: TranslationBase.of(context) + .prefferedLanguage, + okText: + TranslationBase.of(context) + .confirm, + cancelText: + TranslationBase.of(context) + .cancel_nocaps, + list: languages, + okFunction: (selectedValue) { + setState(() { + selectedLanguage = + selectedValue; + }); + print( + "selectedLanguage = ${selectedValue.name}"); + }, + cancelFunction: () => {}); + showDialog( + barrierDismissible: false, + context: context, + builder: (BuildContext context) { + return dialog; + }, + ); + }, + child: TextField( + enabled: false, + decoration: InputDecoration( + suffixIcon: + Icon(Icons.arrow_drop_down), + hintText: selectedLanguage == null + ? "${TranslationBase.of(context).prefferedLanguage}" + : "${selectedLanguage.name}", + hintStyle: TextStyle( + fontSize: 16, + color: Colors.black, + )), + style: TextStyle( + fontSize: 16, + color: Colors.grey.shade700, + ), + ), + ), + ], + ), + ), + ], + ), + Container( + color: Colors.green, + margin: EdgeInsets.all(8), + child: BorderedButton( + TranslationBase.of(context).register, + backgroundColor: canSubmit + ? Color(0xff339933) + : Color(0xff99cc99), + textColor: Colors.white, + fontSize: 16, + hPadding: 8, + vPadding: 12, + handler: canSubmit + ? () { + Navigator.push( + context, + FadePage( + page: LakumTermsConditions( + widget + .patientIdentificationNo, + _firstNameController.text, + _lastNameController.text, + _mobileNumberController + .text, + selectedLanguage.id))) + .then((status) => { + if (status == 200) + {Navigator.pop(context, "")} + // back to previous page + }); + } + : null, + ), + ), + ], + ), + ), + ), + ), + )); + } +} diff --git a/lib/pages/pharmacies/screens/lacum-setting-page.dart b/lib/pages/pharmacies/screens/lacum-setting-page.dart new file mode 100644 index 00000000..861279f3 --- /dev/null +++ b/lib/pages/pharmacies/screens/lacum-setting-page.dart @@ -0,0 +1,238 @@ +import 'package:diplomaticquarterapp/core/model/pharmacies/LacumAccountInformation.dart'; +import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/lacum-viewmodel.dart'; +import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/pages/pharmacies/widgets/lacum-banner-widget.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +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'; + +class LakumSettingPage extends StatefulWidget { + final LacumAccountInformation lacumInformation; + final LacumAccountInformation lacumGroupInformation; + + LakumSettingPage(this.lacumInformation, this.lacumGroupInformation); + + @override + _LakumSettingPageState createState() => _LakumSettingPageState(); +} + +class _LakumSettingPageState extends State { + bool _lakumAccountActivated = false; + TextEditingController _nameController = new TextEditingController(); + TextEditingController _phoneController = new TextEditingController(); + + @override + void initState() { + _lakumAccountActivated = widget.lacumGroupInformation + .lakumInquiryInformationObjVersion.accountStatus == + "Active"; + super.initState(); + _nameController.text = widget.lacumGroupInformation.lakumInquiryInformationObjVersion.memberName; + _phoneController.text = widget.lacumGroupInformation.lakumInquiryInformationObjVersion.mobileNumber; + } + + @override + Widget build(BuildContext context) { + final mediaQuery = MediaQuery.of(context); + + return BaseView( + onModelReady: (model) => model.setLakumData( + widget.lacumInformation, widget.lacumGroupInformation), + builder: (_, model, wi) => AppScaffold( + appBarTitle: "${TranslationBase.of(context).lakum}", + isShowAppBar: true, + isShowDecPage: false, + backgroundColor: Colors.white, + baseViewModel: model, + body: Container( + width: double.infinity, + child: SingleChildScrollView( + child: SizedBox( + height: mediaQuery.size.height - + 60 - + mediaQuery.padding.top, + child: _buildSettingScreen(mediaQuery, model), + ), + ), + ), + ), + ); + } + + _buildSettingScreen(MediaQueryData mediaQuery, LacumViewModel model) { + bool canUpdate = (_nameController.text != "" && + _phoneController.text != "" && + (_nameController.text != widget.lacumGroupInformation.lakumInquiryInformationObjVersion.memberName || + _phoneController.text != widget.lacumGroupInformation.lakumInquiryInformationObjVersion.mobileNumber)); + + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisSize: MainAxisSize.max, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Stack( + children: [ + Container( + height: mediaQuery.size.height * 0.15, + color: Colors.green, + ), + Column( + children: [ + SizedBox( + height: mediaQuery.size.height * 0.05, + ), + Container( + width: mediaQuery.size.width * 1, + child: LakumBannerWidget(model, mediaQuery, false)), + ], + ) + ], + ), + SizedBox( + height: 20, + ), + SizedBox( + height: 1, + width: double.infinity, + child: Container( + color: Color(0xffefefef), + ), + ), + Container( + margin: EdgeInsets.symmetric(horizontal: 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Texts( + "Activate LAKUM Account", + fontSize: 16, + fontWeight: FontWeight.normal, + color: Colors.black, + ), + Switch.adaptive( + activeColor: Color.fromRGBO(51, 153, 51, 1), + inactiveThumbColor: Colors.red, + activeTrackColor: Colors.grey, + inactiveTrackColor: Colors.grey, + value: _lakumAccountActivated, + onChanged: (val) { + if (_lakumAccountActivated) { + model.makeAccountDeactivate(); + } else { + model.makeAccountActivate(); + } + setState(() { + _lakumAccountActivated = val; + }); + }, + ), + ], + ), + ), + SizedBox( + height: 30, + ), + Container( + margin: EdgeInsets.symmetric(horizontal: 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Texts( + TranslationBase.of(context).name, + fontSize: 13, + fontWeight: _lakumAccountActivated + ? FontWeight.bold + : FontWeight.normal, + color: Colors.grey.shade400, + ), + _lakumAccountActivated + ? TextField( + controller: _nameController, + enabled: _lakumAccountActivated ? true : false, + style: TextStyle( + fontSize: 16, + color: _lakumAccountActivated + ? Colors.black + : Colors.white38, + ), + ) + : Texts( + _nameController.text, + fontSize: 16, + color: Colors.grey.shade600, + ), + SizedBox( + height: 10, + ), + Texts( + TranslationBase.of(context).mobileNumber, + fontSize: 13, + fontWeight: _lakumAccountActivated + ? FontWeight.bold + : FontWeight.normal, + color: Colors.grey.shade400, + ), + _lakumAccountActivated + ? TextField( + controller: _phoneController, + enabled: _lakumAccountActivated ? true : false, + keyboardType: TextInputType.phone, + style: TextStyle( + fontSize: 16, + color: _lakumAccountActivated + ? Colors.black + : Colors.white38, + ), + ) + : Texts( + _phoneController.text, + fontSize: 16, + color: Colors.grey.shade600, + ), + ], + ), + ), + ], + ), + Container( + child: Column( + children: [ + SizedBox( + height: 2, + width: double.infinity, + child: Container( + color: Color(0xffefefef), + ), + ), + Container( + margin: EdgeInsets.all(8), + child: BorderedButton( + TranslationBase.of(context).save, + backgroundColor: + canUpdate ? Color(0xff60686b) : Color(0xffb0b4b5), + textColor: Colors.white, + fontSize: 16, + hPadding: 8, + vPadding: 12, + handler: canUpdate + ? () { + model.createLakumAccount(_nameController.text, _phoneController.text).then((status) => { + if (status == 200) {Navigator.pop(context, "")} + // back to previous page + }); + } + : null, + ), + ) + ], + ), + ), + ], + ); + } +} diff --git a/lib/pages/pharmacies/screens/lacum-transfer-page.dart b/lib/pages/pharmacies/screens/lacum-transfer-page.dart new file mode 100644 index 00000000..9103b646 --- /dev/null +++ b/lib/pages/pharmacies/screens/lacum-transfer-page.dart @@ -0,0 +1,315 @@ +import 'package:diplomaticquarterapp/core/model/pharmacies/LacumAccountInformation.dart'; +import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/lacum-trasnfer-viewModel.dart'; +import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +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'; + +class LacumTransferPage extends StatefulWidget { + final LacumAccountInformation lacumInformation; + final LacumAccountInformation lacumGroupInformation; + + LacumTransferPage(this.lacumInformation, this.lacumGroupInformation); + + @override + _LacumTransferPageState createState() => _LacumTransferPageState(); +} + +class _LacumTransferPageState extends State { + TextEditingController _beneficieryAccountController = + new TextEditingController(); + TextEditingController _transferPointsController = new TextEditingController(); + + @override + void initState() { + super.initState(); + _beneficieryAccountController.text = ""; + _transferPointsController.text = "0"; + } + + @override + Widget build(BuildContext context) { + final mediaQuery = MediaQuery.of(context); + + return BaseView( + onModelReady: (model) => model.setLakumData( + widget.lacumInformation, widget.lacumGroupInformation), + builder: (_, model, wi) => AppScaffold( + appBarTitle: "${TranslationBase.of(context).lakum}", + isShowAppBar: true, + isShowDecPage: false, + backgroundColor: Colors.white, + baseViewModel: model, + body: Container( + width: double.infinity, + child: SingleChildScrollView( + child: SizedBox( + height: + mediaQuery.size.height - 58 - mediaQuery.padding.top, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + children: [ + Row( + children: [ + Container( + height: 100, + width: mediaQuery.size.width / 2 - 26, + padding: EdgeInsets.only( + top: 12, left: 8, right: 8, bottom: 4), + decoration: BoxDecoration( + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(8), + border: Border.fromBorderSide(BorderSide( + color: Color(0xffe1e1e1), + width: 0.4, + )), + color: Color(0xff6294ed), + ), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Column( + children: [ + Container( + child: Texts( + "Point Balance", + fontSize: 14, + fontWeight: FontWeight.bold, + color: Colors.white, + ), + ), + ], + ), + ), + Expanded( + child: Container( + padding: EdgeInsets.symmetric( + vertical: 8), + child: Column( + mainAxisAlignment: + MainAxisAlignment.end, + crossAxisAlignment: + CrossAxisAlignment.end, + children: [ + Texts( + "0", + fontSize: 14, + fontWeight: FontWeight.bold, + color: Colors.white, + ), + ], + ), + ), + ) + ], + ), + ), + SizedBox( + width: 20, + ), + Container( + height: 100, + width: mediaQuery.size.width / 2 - 26, + padding: EdgeInsets.only( + top: 12, left: 8, right: 8, bottom: 4), + decoration: BoxDecoration( + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(8), + border: Border.fromBorderSide(BorderSide( + color: Color(0xffe1e1e1), + width: 0.4, + )), + color: Color(0xff339933), + ), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Column( + children: [ + Container( + child: Texts( + "Riyal Balance", + fontSize: 14, + fontWeight: FontWeight.bold, + color: Colors.white, + ), + ), + ], + ), + ), + Expanded( + child: Container( + padding: EdgeInsets.symmetric( + vertical: 8), + child: Column( + mainAxisAlignment: + MainAxisAlignment.end, + crossAxisAlignment: + CrossAxisAlignment.end, + children: [ + Texts( + "0", + fontSize: 14, + fontWeight: FontWeight.bold, + color: Colors.white, + ), + ], + ), + ), + ) + ], + ), + ), + ], + ), + Container( + margin: EdgeInsets.only(top: 16), + child: TextField( + controller: _beneficieryAccountController, + decoration: new InputDecoration( + hintText: 'Enter Beneficiary Account No.', + ), + style: TextStyle( + fontSize: 16, + color: Colors.grey.shade700, + ), + ), + ), + Container( + margin: EdgeInsets.only(top: 4), + child: BorderedButton( + TranslationBase.of(context).checkBeneficiary, + backgroundColor: + _beneficieryAccountController.text != "" + ? Color(0xff60686b) + : Color(0xffb0b4b5), + textColor: Colors.white, + fontSize: 16, + hPadding: 8, + vPadding: 12, + handler: + _beneficieryAccountController.text != "" + ? () { + model.getLacumGroupDataBuAccountId( + _beneficieryAccountController + .text); + } + : null, + ), + ), + (model.lacumReceiverInformation != null && + model.lacumReceiverInformation + .lakumInquiryInformationObjVersion != + null) + ? Container( + margin: EdgeInsets.only(top: 8), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Texts( + TranslationBase.of(context) + .beneficiaryName, + color: Colors.black, + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 8), + child: TextField( + enabled: false, + decoration: new InputDecoration( + hintText: + "${model.lacumReceiverInformation.lakumInquiryInformationObjVersion.memberName}", + hintStyle: TextStyle( + fontSize: 16, + color: Colors.grey.shade600, + )), + style: TextStyle( + fontSize: 16, + color: Colors.grey.shade700, + ), + ), + ), + SizedBox( + height: 10, + width: double.infinity, + ), + Texts( + "Point's to Transfer :", + color: Colors.black, + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 8), + child: TextField( + controller: + _transferPointsController, + decoration: new InputDecoration( + focusColor: Colors.green, + hintStyle: TextStyle( + fontSize: 16, + color: Colors.grey.shade600, + )), + style: TextStyle( + fontSize: 16, + color: Colors.grey.shade700, + ), + ), + ), + ], + ), + ) + : Container() + ], + ), + if (model.lacumReceiverInformation != null && + model.lacumReceiverInformation + .lakumInquiryInformationObjVersion != + null) + Container( + margin: EdgeInsets.all(8), + child: BorderedButton( + "LACUM TRANSFER", + backgroundColor: Color(0xff339933), + textColor: Colors.white, + fontSize: 18, + hPadding: 8, + radius: 12, + vPadding: 16, + fontWeight: FontWeight.w600, + handler: () { + model + .transferYaHalaLoyaltyPoints( + _transferPointsController.text) + .then((status) => { + if (status == 200) + {Navigator.pop(context, "")} + // back to previous page + }); + }, + ), + ) + ], + ), + ), + ), + ), + ), + )); + } +} diff --git a/lib/pages/pharmacies/screens/lakum-main-page.dart b/lib/pages/pharmacies/screens/lakum-main-page.dart new file mode 100644 index 00000000..adbb07c2 --- /dev/null +++ b/lib/pages/pharmacies/screens/lakum-main-page.dart @@ -0,0 +1,555 @@ +import 'package:diplomaticquarterapp/config/config.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/PointsAmountPerYear.dart'; +import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/lacum-viewmodel.dart'; +import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/pages/pharmacies/screens/lacum-setting-page.dart'; +import 'package:diplomaticquarterapp/pages/pharmacies/screens/lacum-transfer-page.dart'; +import 'package:diplomaticquarterapp/pages/pharmacies/screens/lakum-points-year-page.dart'; +import 'package:diplomaticquarterapp/pages/pharmacies/widgets/lacum-banner-widget.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +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 'lacum-activitaion-vida-page.dart'; + +class LakumMainPage extends StatelessWidget { + @override + Widget build(BuildContext context) { + final mediaQuery = MediaQuery.of(context); + + return BaseView( + onModelReady: (model) => model.getLacumData(), + builder: (_, model, wi) => AppScaffold( + title: "Lakum", + isShowAppBar: true, + isPharmacy: true, + isShowDecPage: false, + backgroundColor: Colors.white, + baseViewModel: model, + appBarIcons: _buildAppBarICons(context, model), + // preferredSize: mediaQuery.size.height * 0.20, + body: Container( + width: double.infinity, + child: SingleChildScrollView( + child: (model.lacumGroupInformation != null && + model.lacumGroupInformation + .lakumInquiryInformationObjVersion != + null) + ? Column( + children: [ + Stack( + children: [ + Container( + height: mediaQuery.size.height * 0.15, + color: Colors.green, + ), + Column( + children: [ + SizedBox( + height: mediaQuery.size.height * 0.05, + ), + Container( + width: mediaQuery.size.width * 1, + child: LakumBannerWidget( + model, mediaQuery, true)), + ], + ) + ], + ), + SizedBox( + height: 20, + ), + LakumHomeButtons(mediaQuery, model), + SizedBox( + height: 20, + ), + Container( + height: 100, + margin: EdgeInsets.symmetric(horizontal: 16), + child: ListView( + scrollDirection: Axis.horizontal, + children: [ + LacumPointsWidget( + mediaQuery, + 1, + TranslationBase.of(context).balance, + model + .lacumGroupInformation + .lakumInquiryInformationObjVersion + .pointsBalanceAmount, + model + .lacumGroupInformation + .lakumInquiryInformationObjVersion + .pointsBalance, + null), + SizedBox( + width: 8, + ), + LacumPointsWidget( + mediaQuery, + 2, + TranslationBase.of(context).gained, + model + .lacumGroupInformation + .lakumInquiryInformationObjVersion + .pointsBalanceAmount, + model + .lacumGroupInformation + .lakumInquiryInformationObjVersion + .gainedPoints, + model + .lacumGroupInformation + .lakumInquiryInformationObjVersion + .gainedPointsAmountPerYear), + SizedBox( + width: 8, + ), + LacumPointsWidget( + mediaQuery, + 3, + TranslationBase.of(context).consumed, + model + .lacumGroupInformation + .lakumInquiryInformationObjVersion + .consumedPointsAmount != + null + ? int.parse(model + .lacumGroupInformation + .lakumInquiryInformationObjVersion + .consumedPointsAmount) + : 0, + model + .lacumGroupInformation + .lakumInquiryInformationObjVersion + .consumedPoints, + model + .lacumGroupInformation + .lakumInquiryInformationObjVersion + .consumedPointsAmountPerYear), + SizedBox( + width: 8, + ), + LacumPointsWidget( + mediaQuery, + 4, + TranslationBase.of(context).transferred, + 0, + model + .lacumGroupInformation + .lakumInquiryInformationObjVersion + .transferPoints, + model + .lacumGroupInformation + .lakumInquiryInformationObjVersion + .transferPointsAmountPerYear), + ], + ), + ), + SizedBox( + height: 20, + ), + SizedBox( + height: 8, + width: double.infinity, + child: Container( + color: Color(0xffefefef), + ), + ), + Container( + margin: EdgeInsets.symmetric( + vertical: 16, horizontal: 8), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Image.asset( + "assets/images/pharmacy_module/lakum/expired_icon.png", + fit: BoxFit.fill, + width: 25, + height: 25, + ), + Padding( + padding: + EdgeInsets.symmetric(horizontal: 8), + child: Texts( + "Expired", + fontSize: 14, + ), + ) + ], + ), + Texts( + "${model.lacumGroupInformation.lakumInquiryInformationObjVersion.expiredPoints} Points", + fontWeight: FontWeight.bold, + fontSize: 14, + ), + ], + ), + ), + SizedBox( + height: 2, + width: double.infinity, + child: Container( + color: Color(0xffefefef), + ), + ), + Container( + margin: EdgeInsets.symmetric( + vertical: 16, horizontal: 8), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Image.asset( + "assets/images/pharmacy_module/lakum/waiting_gained_icon.png", + fit: BoxFit.fill, + width: 20, + height: 25, + ), + Padding( + padding: + EdgeInsets.symmetric(horizontal: 8), + child: Texts( + "Waiting gained", + fontSize: 14, + ), + ) + ], + ), + Texts( + "${model.lacumGroupInformation.lakumInquiryInformationObjVersion.waitingPoints} Points", + fontWeight: FontWeight.bold, + fontSize: 14, + ), + ], + ), + ), + SizedBox( + height: 2, + width: double.infinity, + child: Container( + color: Color(0xffefefef), + ), + ), + Container( + margin: EdgeInsets.symmetric( + vertical: 16, horizontal: 8), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Image.asset( + "assets/images/pharmacy_module/lakum/will_be_expired_icon.png", + fit: BoxFit.fill, + width: 25, + height: 25, + ), + Padding( + padding: + EdgeInsets.symmetric(horizontal: 8), + child: Texts( + "Will Be Expired", + fontSize: 14, + ), + ) + ], + ), + Texts( + "${model.lacumGroupInformation.lakumInquiryInformationObjVersion.pointsWillBeExpired} Points", + fontWeight: FontWeight.bold, + fontSize: 14, + ), + ], + ), + ), + SizedBox( + height: 2, + width: double.infinity, + child: Container( + color: Color(0xffefefef), + ), + ), + ], + ) + : Container(), + ), + ), + )); + } +} + +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()}); + }, + ), + ]; +} + +class LakumHomeButtons extends StatelessWidget { + final MediaQueryData mediaQuery; + final LacumViewModel model; + + LakumHomeButtons(this.mediaQuery, this.model); + + @override + Widget build(BuildContext context) { + return Container( + margin: EdgeInsets.symmetric(horizontal: 16), + child: Row( + children: [ + Expanded( + child: InkWell( + onTap: () { + print("Account activate click"); + Navigator.push( + context, FadePage(page: LakumActivationVidaPage())) + .then((result) => {model.getLacumGroupData()}); + }, + child: Container( + padding: EdgeInsets.symmetric(horizontal: 8), + decoration: BoxDecoration( + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(8), + border: Border.fromBorderSide(BorderSide( + color: Color(0xffe1e1e1), + width: 0.4, + )), + color: Color(0xffe1e1e1)), + height: mediaQuery.size.height * 0.08, + child: Row( + children: [ + Image.asset( + "assets/images/pharmacy_module/lakum/Account_activation_icon.png", + fit: BoxFit.fill, + width: 30, + height: 30, + ), + Expanded( + child: Container( + padding: EdgeInsets.symmetric(horizontal: 16), + child: Texts( + "Account Activation", + fontSize: 14, + fontWeight: FontWeight.bold, + ), + ), + ) + ], + ), + ), + ), + ), + SizedBox( + width: 8, + ), + Expanded( + child: InkWell( + onTap: () { + print("Lacum transfer click"); + Navigator.push( + context, + FadePage( + page: LacumTransferPage(model.lacumInformation, + model.lacumGroupInformation))) + .then((result) => {model.getLacumGroupData()}); + }, + child: Container( + padding: EdgeInsets.symmetric(horizontal: 8), + decoration: BoxDecoration( + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(8), + border: Border.fromBorderSide(BorderSide( + color: Color(0xffe1e1e1), + width: 0.4, + )), + color: Color(0xffe1e1e1)), + height: mediaQuery.size.height * 0.08, + child: Row( + children: [ + Image.asset( + "assets/images/pharmacy_module/lakum/Lakum_transfer_icon.png", + fit: BoxFit.fill, + width: 35, + height: 30, + ), + Expanded( + child: Container( + padding: EdgeInsets.symmetric(horizontal: 16), + child: Texts( + "Lakum Transfer", + fontSize: 14, + fontWeight: FontWeight.bold, + ), + ), + ) + ], + ), + ), + ), + ), + ], + ), + ); + } +} + +class LacumPointsWidget extends StatelessWidget { + final MediaQueryData mediaQuery; + final int pointType; // 1. balance, 2. gained, 3. consume, 4. transfer + final String title; + final int riyal; + final int point; + Color titleColor; + final List pointsAmountPerYear; + + LacumPointsWidget(this.mediaQuery, this.pointType, this.title, this.riyal, + this.point, this.pointsAmountPerYear) { + if (pointType == 1) { + titleColor = Color(0xffefefef); + } else if (pointType == 2) { + titleColor = Color(0xff004bcc); + } else if (pointType == 3) { + titleColor = Color(0xff339933); + } else { + titleColor = Color(0xffffa500); + } + } + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: () { + if (pointType != 1) { + if (pointsAmountPerYear != null && pointsAmountPerYear.length > 0) { + Navigator.push(context, + FadePage(page: LakumPointsYearPage(pointsAmountPerYear))); + } else { + // show snackBar No Details Points are there + } + } + }, + child: Container( + width: mediaQuery.size.width / 2 - 16, + padding: EdgeInsets.only(top: 12, left: 8, right: 8, bottom: 4), + decoration: BoxDecoration( + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(8), + border: Border.fromBorderSide(BorderSide( + color: Color(0xffe1e1e1), + width: 0.4, + )), + color: pointType == 1 ? Color(0xff004bcc) : Color(0xffefefef), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + child: Texts( + title, + fontSize: 14, + fontWeight: FontWeight.bold, + color: titleColor, + ), + ), + if (pointType != 1) + Icon( + Icons.arrow_forward, + color: titleColor, + ) + ], + ), + ], + ), + ), + Expanded( + child: Row( + children: [ + if (pointType != 4) + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Texts( + "RIYAL", + fontSize: 13, + fontWeight: FontWeight.bold, + color: pointType == 1 ? Colors.white : Colors.black, + ), + SizedBox( + height: 4, + ), + Texts( + "$riyal", + fontSize: 13, + fontWeight: FontWeight.bold, + color: pointType == 1 ? Colors.white : Colors.black, + ), + ], + ), + ), + if (pointType != 4) + SizedBox( + child: Container( + color: pointType == 1 ? Colors.white : Colors.grey, + ), + width: 1, + ), + Expanded( + child: Container( + margin: EdgeInsets.only(left: 4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Texts( + "POINT", + fontSize: 12, + fontWeight: FontWeight.bold, + color: pointType == 1 ? Colors.white : Colors.black, + ), + SizedBox( + height: 4, + ), + Texts( + "$point", + fontSize: 12, + fontWeight: FontWeight.bold, + color: pointType == 1 ? Colors.white : Colors.black, + ), + ], + ), + ), + ), + ], + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/pages/pharmacies/screens/lakum-points-month-page.dart b/lib/pages/pharmacies/screens/lakum-points-month-page.dart new file mode 100644 index 00000000..47270eee --- /dev/null +++ b/lib/pages/pharmacies/screens/lakum-points-month-page.dart @@ -0,0 +1,271 @@ +import 'package:diplomaticquarterapp/core/model/pharmacies/PointsAmountPerMonth.dart'; +import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/lacum-viewmodel.dart'; +import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/pages/pharmacies/widgets/lakum-point-table-row-widget.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +class LakumPointMonthPage extends StatefulWidget { + final PointsAmountPerMonth pointsAmountPerMonth; + final int year; + int expandedItemIndex = -1; + + LakumPointMonthPage(this.pointsAmountPerMonth, this.year); + + @override + _LakumPointsMonthPageState createState() => _LakumPointsMonthPageState(); +} + +class _LakumPointsMonthPageState extends State { + @override + Widget build(BuildContext context) { + final mediaQuery = MediaQuery.of(context); + + return BaseView( + builder: (_, model, wi) => AppScaffold( + title: "Lakum points", + isShowAppBar: true, + isShowDecPage: false, + backgroundColor: Colors.white, + baseViewModel: model, + body: Container( + width: double.infinity, + child: SingleChildScrollView( + child: Column( + children: [ + Container( + height: mediaQuery.size.height * 0.25, + child: Stack( + children: [ + Image.asset( + "assets/images/pharmacy_module/lakum/lakum_card_front_bg.png", + fit: BoxFit.fill, + width: mediaQuery.size.width * 1.0, + ), + Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Container( + height: mediaQuery.size.height * 0.06, + margin: EdgeInsets.symmetric( + vertical: 16, horizontal: 24), + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Texts( + TranslationBase.of(context).month, + color: Colors.grey.shade600, + fontSize: 16, + ), + Texts( + "${widget.pointsAmountPerMonth.month}, ${widget.year}", + color: Colors.grey.shade700, + fontWeight: FontWeight.bold, + fontSize: 16, + ), + ], + ), + ), + Expanded( + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + child: Column( + mainAxisAlignment: + MainAxisAlignment.end, + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + Texts( + TranslationBase.of(context).point, + color: Colors.grey.shade600, + fontSize: 16, + ), + Texts( + "${widget.pointsAmountPerMonth.pointsPerMonth}", + color: Colors.grey.shade700, + fontWeight: FontWeight.bold, + fontSize: 16, + ), + ], + ), + ), + SizedBox( + child: Container( + color: Colors.grey, + ), + width: 1, + ), + Expanded( + child: Column( + mainAxisAlignment: + MainAxisAlignment.end, + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + Texts( + TranslationBase.of(context).riyal, + color: Colors.grey.shade600, + fontSize: 16, + ), + Texts( + "${widget.pointsAmountPerMonth.amountPerMonth}", + color: Colors.grey.shade700, + fontWeight: FontWeight.bold, + fontSize: 16, + ), + ], + ), + ), + ], + ), + ), + ], + ), + ), + ], + ), + ], + ), + ), + SizedBox( + height: 10, + ), + LakumPointTableRowWidget(true, "DAY", 0, 0, null, 0), + ...List.generate( + widget.pointsAmountPerMonth.pointsAmountPerday.length, + (index) => LakumPointTableRowWidget( + false, + widget.pointsAmountPerMonth.pointsAmountPerday[index].day, + widget.pointsAmountPerMonth.pointsAmountPerday[index] + .pointsPerDay, + widget.pointsAmountPerMonth.pointsAmountPerday[index] + .amountPerDay, + () { + setState(() { + if (widget.expandedItemIndex == index) { + widget.expandedItemIndex = -1; + } else { + widget.expandedItemIndex = index; + } + }); + }, + index, + expandFlag: widget.expandedItemIndex == index, + collapsed: Column( + children: [ + ...List.generate( + widget.pointsAmountPerMonth.pointsAmountPerday[index] + .pointsDetails.length, + (index) => DayPointsDetailWidget( + widget + .pointsAmountPerMonth + .pointsAmountPerday[index] + .pointsDetails[index] + .subTransactionTypeDescription, + widget + .pointsAmountPerMonth + .pointsAmountPerday[index] + .pointsDetails[index].purchasePoints, + widget + .pointsAmountPerMonth + .pointsAmountPerday[index] + .pointsDetails[index].amount), + ), + ], + ), + ), + ), + ], + ), + ), + ), + ), + ); + } +} + +class DayPointsDetailWidget extends StatelessWidget { + final String rowTitle; + final double points; + final double riyal; + + DayPointsDetailWidget(this.rowTitle, this.points, this.riyal); + + @override + Widget build(BuildContext context) { + return Container( + color: Color(0xffe4e4e4), + padding: EdgeInsets.symmetric(vertical: 0, horizontal: 12), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Row( + children: [ + Expanded( + child: Container( + child: Column( + children: [ + Texts( + "TYPE", + fontSize: 12, + fontWeight: FontWeight.bold, + ), + SizedBox( + height: 4, + ), + Texts( + rowTitle, + fontSize: 14, + fontWeight: FontWeight.normal, + ), + ], + crossAxisAlignment: CrossAxisAlignment.start, + ), + )), + Expanded( + + child: Container( + child: Texts( + "$points", + fontSize: 14, + fontWeight: FontWeight.normal, + ), + )), + Expanded( + child: Container( + child: Texts( + "$riyal", + fontSize: 14, + fontWeight: FontWeight.normal, + ), + )), + Expanded(child: Container()), + ], + ), + ), + const Divider( + color: Color(0xFFD6D6D6), + height: 1, + thickness: 1, + indent: 0, + endIndent: 0, + ), + ], + ), + ); + } +} diff --git a/lib/pages/pharmacies/screens/lakum-points-year-page.dart b/lib/pages/pharmacies/screens/lakum-points-year-page.dart new file mode 100644 index 00000000..f7b6d9e6 --- /dev/null +++ b/lib/pages/pharmacies/screens/lakum-points-year-page.dart @@ -0,0 +1,201 @@ +import 'package:diplomaticquarterapp/core/model/pharmacies/PointsAmountPerYear.dart'; +import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/lacum-viewmodel.dart'; +import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/pages/pharmacies/widgets/lakum-point-table-row-widget.dart'; +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 'lakum-points-month-page.dart'; + +class LakumPointsYearPage extends StatefulWidget { + final List pointsAmountPerYear; + int selectedIndexYear = 0; + + LakumPointsYearPage(this.pointsAmountPerYear); + + @override + _LakumPointsYearPageState createState() => _LakumPointsYearPageState(); +} + +class _LakumPointsYearPageState extends State { + @override + Widget build(BuildContext context) { + final mediaQuery = MediaQuery.of(context); + + return BaseView( + builder: (_, model, wi) => AppScaffold( + title: "Lakum points", + isShowAppBar: true, + isShowDecPage: false, + backgroundColor: Colors.white, + baseViewModel: model, + body: Container( + width: double.infinity, + child: SingleChildScrollView( + child: Column( + children: [ + Container( + height: 100, + margin: EdgeInsets.symmetric(horizontal: 16, vertical: 16), + child: ListView( + scrollDirection: Axis.horizontal, + children: [ + ...List.generate( + widget.pointsAmountPerYear.length, + (index) => LacumPointsYearWidget( + mediaQuery, + widget.selectedIndexYear == index, + widget.pointsAmountPerYear[index], () { + setState(() { + widget.selectedIndexYear = index; + }); + })), + ], + ), + ), + SizedBox( + height: 0, + ), + LakumPointTableRowWidget(true, "MONTH", 0, 0, null, 0), + ...List.generate( + widget.pointsAmountPerYear[widget.selectedIndexYear] + .pointsAmountPerMonth.length, + (index) => LakumPointTableRowWidget( + false, + widget.pointsAmountPerYear[widget.selectedIndexYear] + .pointsAmountPerMonth[index].month, + widget.pointsAmountPerYear[widget.selectedIndexYear] + .pointsAmountPerMonth[index].pointsPerMonth, + widget.pointsAmountPerYear[widget.selectedIndexYear] + .pointsAmountPerMonth[index].amountPerMonth, + (){ + Navigator.push(context, + FadePage(page: LakumPointMonthPage(widget.pointsAmountPerYear[widget.selectedIndexYear] + .pointsAmountPerMonth[index], widget.pointsAmountPerYear[widget.selectedIndexYear].year))); + }, + index), + ), + ], + ), + ), + ), + ), + ); + } +} + +class LacumPointsYearWidget extends StatelessWidget { + final MediaQueryData mediaQuery; + final bool isSelected; + final PointsAmountPerYear yearPoints; + final Function yearOnTap; + + LacumPointsYearWidget( + this.mediaQuery, this.isSelected, this.yearPoints, this.yearOnTap); + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: yearOnTap, + child: Container( + width: mediaQuery.size.width / 2 - 16, + padding: EdgeInsets.only(top: 12, left: 8, right: 8, bottom: 4), + decoration: BoxDecoration( + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(8), + border: Border.fromBorderSide(BorderSide( + color: Color(0xffe1e1e1), + width: 0.4, + )), + color: isSelected ? Color(0xff004bcc) : Color(0xffefefef), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + child: Texts( + "YEAR: ${yearPoints.year}", + fontSize: 14, + fontWeight: FontWeight.bold, + color: isSelected ? Colors.white : Colors.black, + ), + ), + ], + ), + ], + ), + ), + Expanded( + child: Row( + children: [ + Expanded( + child: Container( + margin: EdgeInsets.only(left: 4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Texts( + "POINT", + fontSize: 12, + fontWeight: FontWeight.bold, + color: isSelected ? Colors.white : Colors.black, + ), + SizedBox( + height: 4, + ), + Texts( + "${yearPoints.pointsPerYear}", + fontSize: 12, + fontWeight: FontWeight.bold, + color: isSelected ? Colors.white : Colors.black, + ), + ], + ), + ), + ), + SizedBox( + child: Container( + color: isSelected ? Colors.white : Colors.grey, + ), + width: 1, + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Texts( + "RIYAL", + fontSize: 13, + fontWeight: FontWeight.bold, + color: isSelected ? Colors.white : Colors.black, + ), + SizedBox( + height: 4, + ), + Texts( + "${yearPoints.amountPerYear}", + fontSize: 13, + fontWeight: FontWeight.bold, + color: isSelected ? Colors.white : Colors.black, + ), + ], + ), + ), + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/pages/pharmacies/screens/lakum-terms-conditions-page.dart b/lib/pages/pharmacies/screens/lakum-terms-conditions-page.dart new file mode 100644 index 00000000..228b0874 --- /dev/null +++ b/lib/pages/pharmacies/screens/lakum-terms-conditions-page.dart @@ -0,0 +1,77 @@ +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'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_html/flutter_html.dart'; +import 'package:provider/provider.dart'; + +class LakumTermsConditions extends StatelessWidget { + final String firstName, lastName, mobileNo, identificationNo; + final int languageId; + + LakumTermsConditions(this.identificationNo, this.firstName, this.lastName, + this.mobileNo, this.languageId); + + @override + Widget build(BuildContext context) { + ProjectViewModel projectProvider = Provider.of(context); + + return BaseView( + onModelReady: (model) => model.getUserTermsAndConditionsForEPharmcy(), + builder: (_, model, wi) => AppScaffold( + appBarTitle: "${TranslationBase.of(context).register} ${TranslationBase.of(context).lakum}", + isShowAppBar: true, + isShowDecPage: false, + backgroundColor: Colors.white, + baseViewModel: model, + body: Container( + margin: EdgeInsets.all(8), + width: double.infinity, + child: Stack( + children: [ + SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (model.listUserAgreement != null && + model.listUserAgreement.userAgreementLAKUM != + null) + Html( + data: projectProvider.isArabic + ? model.listUserAgreement.userAgreementLAKUMn + : model.listUserAgreement.userAgreementLAKUM, + ), + ], + ), + ), + Align( + alignment: Alignment.bottomCenter, + child: Container( + height: 50, + margin: EdgeInsets.all(8), + child: BorderedButton( + TranslationBase.of(context).acceptLbl, + backgroundColor: Color(0xff60686b), + textColor: Colors.white, + fontSize: 16, + hPadding: 8, + vPadding: 12, + handler: () { + model.createNewLakumAccount("$firstName $lastName", mobileNo, identificationNo, languageId).then((status) => { + if (status == 200) {Navigator.pop(context, "")} + // back to previous page + }); + }, + ), + ), + ), + ], + ), + ), + )); + } +} diff --git a/lib/pages/pharmacies/screens/payment-method-select-page.dart b/lib/pages/pharmacies/screens/payment-method-select-page.dart new file mode 100644 index 00000000..8cdbaf3c --- /dev/null +++ b/lib/pages/pharmacies/screens/payment-method-select-page.dart @@ -0,0 +1,202 @@ +import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/OrderPreviewViewModel.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +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'; + +class PaymentMethodSelectPage extends StatefulWidget { + @override + _PaymentMethodSelectPageState createState() => + _PaymentMethodSelectPageState(); +} + +class _PaymentMethodSelectPageState extends State { + PaymentOption selectedPaymentOption; + + @override + Widget build(BuildContext context) { + Size screenSize = MediaQuery.of(context).size; + double cardWidth = screenSize.width / 2 - 32; + + return AppScaffold( + title: "Payment method", + isShowAppBar: true, + isShowDecPage: false, + body: Container( + width: double.infinity, + margin: EdgeInsets.symmetric(horizontal: 0, vertical: 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Center( + child: Texts( + TranslationBase.of(context).selectPaymentOption, + fontSize: 20, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + Container( + margin: EdgeInsets.symmetric(horizontal: 0, vertical: 16), + child: Column( + children: [ + Row( + children: [ + PaymentMethodCard( + cardWidth, + selectedPaymentOption, + PaymentOption.meda, + () => { + setState(() { + selectedPaymentOption = PaymentOption.meda; + }) + }), + PaymentMethodCard( + cardWidth, + selectedPaymentOption, + PaymentOption.sadad, + () => { + setState(() { + selectedPaymentOption = PaymentOption.sadad; + }) + }), + ], + ), + Row( + children: [ + PaymentMethodCard( + cardWidth, + selectedPaymentOption, + PaymentOption.visa, + () => { + setState(() { + selectedPaymentOption = PaymentOption.visa; + }) + }), + PaymentMethodCard( + cardWidth, + selectedPaymentOption, + PaymentOption.mastercard, + () => { + setState(() { + selectedPaymentOption = + PaymentOption.mastercard; + }) + }), + ], + ), + PaymentMethodCard( + (cardWidth * 2 + 32), + selectedPaymentOption, + PaymentOption.installments, + () => { + setState(() { + selectedPaymentOption = + PaymentOption.installments; + }) + }), + ], + ), + ), + ], + ), + ), + bottomSheet: Container( + height: screenSize.height * 0.08, + margin: EdgeInsets.symmetric(horizontal: 16, vertical: 8), + child: BorderedButton( + TranslationBase.of(context).next, + backgroundColor: Color(0xff5AB154), + textColor: Colors.white, + fontSize: 16, + hPadding: 8, + vPadding: 12, + handler: selectedPaymentOption != null + ? () => {Navigator.pop(context, selectedPaymentOption)} + : null, + ), + ), + ); + } +} + +class PaymentMethodCard extends StatelessWidget { + final double cardWidth; + final PaymentOption selectedPaymentOption; + final PaymentOption paymentOption; + final Function selectMethod; + + PaymentMethodCard(this.cardWidth, this.selectedPaymentOption, + this.paymentOption, this.selectMethod); + + @override + Widget build(BuildContext context) { + bool isSelected = false; + if (selectedPaymentOption != null && + selectedPaymentOption == paymentOption) { + isSelected = true; + } + + return InkWell( + onTap: selectMethod, + child: Container( + margin: EdgeInsets.symmetric(horizontal: 2, vertical: 0), + child: Stack( + children: [ + Container( + padding: EdgeInsets.symmetric(horizontal: 8, vertical: 8), + margin: EdgeInsets.symmetric(horizontal: 14, vertical: 8), + decoration: new BoxDecoration( + color: Colors.grey.shade100, + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(8), + border: Border.fromBorderSide(BorderSide( + color: isSelected ? Color(0xff20BC11) : Colors.grey.shade300, + width: 0.8, + )), + ), + width: cardWidth, + child: Image.asset( + getPaymentOptionImage(paymentOption), + fit: BoxFit.cover, + ), + ), + if (isSelected) + Positioned( + right: 1, + child: Icon( + Icons.check_circle, + color: Color(0xff20BC11), + size: 30, + ), + ), + ], + ), + ), + ); + } + + String getPaymentOptionImage(PaymentOption paymentOption) { + String assetFile = "assets/images/pharmacy_module/payment/"; + switch (paymentOption.index) { + case 0: + return "${assetFile}mada.png"; + break; + case 1: + return "${assetFile}sadad.png"; + break; + case 2: + return "${assetFile}visa.png"; + break; + case 3: + return "${assetFile}mastercard.png"; + break; + case 4: + return "${assetFile}installment.png"; + break; + default: + return ""; + } + } +} diff --git a/lib/pages/pharmacies/screens/pharmacy-terms-conditions-page.dart b/lib/pages/pharmacies/screens/pharmacy-terms-conditions-page.dart new file mode 100644 index 00000000..87c1b97c --- /dev/null +++ b/lib/pages/pharmacies/screens/pharmacy-terms-conditions-page.dart @@ -0,0 +1,51 @@ +import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/tems-condition-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'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_html/flutter_html.dart'; +import 'package:provider/provider.dart'; + +class PharmacyTermsConditions extends StatelessWidget { + @override + Widget build(BuildContext context) { + ProjectViewModel projectProvider = Provider.of(context); + + return BaseView( + onModelReady: (model) => model.getUserTermsAndConditionsForEPharmcy(), + builder: (_, model, wi) => AppScaffold( + appBarTitle: TranslationBase.of(context).termOfService, + isShowAppBar: true, + isShowDecPage: false, + isPharmacy: true, + backgroundColor: Colors.white, + baseViewModel: model, + body: Container( + margin: EdgeInsets.all(8), + width: double.infinity, + child: Stack( + children: [ + SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + if (model.listUserAgreement != null && + model.listUserAgreement.userAgreementLAKUM != + null) + Html( + data: projectProvider.isArabic + ? model.listUserAgreement.userAgreementTxtn + : model.listUserAgreement.userAgreementTxt, + ), + ], + ), + ), + ], + ), + ), + )); + } +} diff --git a/lib/pages/pharmacies/screens/pharmacy_module_page.dart b/lib/pages/pharmacies/screens/pharmacy_module_page.dart index 2ae2be65..fd51d6ef 100644 --- a/lib/pages/pharmacies/screens/pharmacy_module_page.dart +++ b/lib/pages/pharmacies/screens/pharmacy_module_page.dart @@ -2,27 +2,32 @@ import 'package:diplomaticquarterapp/config/size_config.dart'; import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/pharmacy_module_view_model.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; import 'package:diplomaticquarterapp/pages/landing/home_page.dart'; -import 'package:diplomaticquarterapp/pages/pharmacies/screens/order-preview-page.dart'; +import 'package:diplomaticquarterapp/pages/offers_categorise_page.dart'; +import 'package:diplomaticquarterapp/pages/pharmacies/screens/cart-order-page.dart'; +import 'package:diplomaticquarterapp/pages/pharmacies/screens/lakum-main-page.dart'; import 'package:diplomaticquarterapp/pages/pharmacies/widgets/BannerPager.dart'; import 'package:diplomaticquarterapp/pages/pharmacies/widgets/ProductTileItem.dart'; import 'package:diplomaticquarterapp/pages/pharmacies/widgets/manufacturerItem.dart'; +import 'package:diplomaticquarterapp/pages/pharmacy/pharmacyAddresses/PharmacyAddresses.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; 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:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/material.dart'; +import 'package:diplomaticquarterapp/pages/pharmacies/product-brands.dart'; -class PharmacyPage extends StatelessWidget { +import 'lacum-activitaion-vida-page.dart'; +class PharmacyPage extends StatelessWidget { @override Widget build(BuildContext context) { return BaseView( - // onModelReady: (model) => model.getPharmacyHomeData(), onModelReady: (model) => model.getPharmacyHomeData(), + allowAny: true, builder: (_, model, wi) => AppScaffold( title: "", - isShowAppBar: true, + isShowAppBar: false, isShowDecPage: false, baseViewModel: model, backgroundColor: Colors.white, @@ -33,8 +38,7 @@ class PharmacyPage extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ BannerPager(model), - GridViewButtons(), - /*BannerPager(model.getBannerImagesUrl()),*/ + GridViewButtons(model), Container( margin: EdgeInsets.fromLTRB(10, 0, 10, 0), child: Row( @@ -48,9 +52,12 @@ class PharmacyPage extends StatelessWidget { TranslationBase.of(context).viewAll, hasBorder: true, vPadding: 6, + hPadding: 4, borderColor: Colors.green, - color: Colors.green, - handler: () {}, + textColor: Colors.green, + handler: () =>{ + Navigator.push(context,FadePage(page: ProductBrandsPage())), + }, ), ], ), @@ -77,15 +84,18 @@ class PharmacyPage extends StatelessWidget { TranslationBase.of(context).viewAll, hasBorder: true, vPadding: 6, + hPadding: 4, borderColor: Colors.green, - color: Colors.green, + textColor: Colors.green, handler: () {}, ), ], ), ), Container( - height: model.lastVisitedProducts.length > 0 ? MediaQuery.of(context).size.height / 4 : 0, + height: model.lastVisitedProducts.length > 0 + ? MediaQuery.of(context).size.height / 4 + 20 + : 0, child: ListView.builder( itemBuilder: (ctx, i) => ProductTileItem(model.lastVisitedProducts[i]), @@ -106,15 +116,18 @@ class PharmacyPage extends StatelessWidget { TranslationBase.of(context).viewAll, hasBorder: true, borderColor: Colors.green, - color: Colors.green, + textColor: Colors.green, vPadding: 6, - handler: () {}, + hPadding: 4, + handler: () =>{ + Navigator.push(context,FadePage(page: ProductBrandsPage())), + }, ), ], ), ), Container( - height: MediaQuery.of(context).size.height / 4, + height: MediaQuery.of(context).size.height / 4 + 20, child: ListView.builder( itemBuilder: (ctx, i) => ProductTileItem(model.bestSellerProduct[i]), @@ -132,6 +145,10 @@ class PharmacyPage extends StatelessWidget { } class GridViewButtons extends StatelessWidget { + final PharmacyModuleViewModel model; + + GridViewButtons(this.model); + @override Widget build(BuildContext context) { final gridHeight = (MediaQuery.of(context).size.width * 0.3) * 1.8; @@ -153,24 +170,34 @@ class GridViewButtons extends StatelessWidget { opacity: 0.8, child: GridViewCard( TranslationBase.of(context).offersAndPromotions, - 'assets/images/pharmacy_module/offer_icon.png', - () { - Navigator.push(context, FadePage(page: OrderPreviewPage())); - }), + 'assets/images/pharmacy_module/offer_icon.png', () { + Navigator.push(context, FadePage(page: OffersCategorisePage())); + }), ), DashboardItem( imageName: 'pharmacy_module/bg_2.png', opacity: 0, hasColorFilter: false, child: GridViewCard(TranslationBase.of(context).medicationRefill, - 'assets/images/pharmacy_module/medication_icon.png', () {}), + 'assets/images/pharmacy_module/medication_icon.png', () { + model.checkUserIsActivated().then((isActivated) { + if (isActivated) { + Navigator.push(context, FadePage(page: LakumMainPage())); + } else { + Navigator.push( + context, FadePage(page: LakumActivationVidaPage())); + } + }); + }), ), DashboardItem( imageName: 'pharmacy_module/bg_3.png', opacity: 0, hasColorFilter: false, child: GridViewCard(TranslationBase.of(context).myPrescriptions, - 'assets/images/pharmacy_module/prescription_icon.png', () {}), + 'assets/images/pharmacy_module/prescription_icon.png', () { + Navigator.push(context, FadePage(page: PharmacyAddressesPage())); + }), ), DashboardItem( imageName: 'pharmacy_module/bg_4.png', @@ -179,7 +206,7 @@ class GridViewButtons extends StatelessWidget { child: GridViewCard( TranslationBase.of(context).searchAndScanMedication, 'assets/images/pharmacy_module/search_scan_icon.png', - () {}), + () {}), ), ], ), @@ -219,11 +246,16 @@ class GridViewCard extends StatelessWidget { ), ), ), - Expanded( - child: BorderedButton( - TranslationBase.of(context).viewAll, - handler: handler, - ), + Row( + children: [ + BorderedButton( + TranslationBase.of(context).viewAll, + handler: handler, + tPadding: 0, + bPadding: 0, + ), + Expanded(child: Container()), + ], ), ], ), diff --git a/lib/pages/pharmacies/search_brands_page.dart b/lib/pages/pharmacies/search_brands_page.dart new file mode 100644 index 00000000..8f771490 --- /dev/null +++ b/lib/pages/pharmacies/search_brands_page.dart @@ -0,0 +1,145 @@ +import 'package:diplomaticquarterapp/config/size_config.dart'; +import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; +import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/brand_view_model.dart'; +import 'package:diplomaticquarterapp/core/viewModels/pharmacy_categorise_view_model.dart'; +import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/uitl/utils.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/button.dart'; +import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; +import 'package:diplomaticquarterapp/widgets/input/text_field.dart'; +import 'package:diplomaticquarterapp/widgets/others/StarRating.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_pharmacy_widget.dart'; +import 'package:diplomaticquarterapp/widgets/others/network_base_view.dart'; +import 'package:flutter/material.dart'; + +class SearchBrandsPage extends StatefulWidget { + @override + _SearchBrandsPageState createState() => _SearchBrandsPageState(); +} + +class _SearchBrandsPageState extends State { + final textController = TextEditingController(); + final _formKey = GlobalKey(); + String msg = ''; + + @override + Widget build(BuildContext context) { + return BaseView( + onModelReady: (model) => model.searchProducts(), + builder: (BuildContext context, model, Widget child) => + PharmacyAppScaffold( + appBarTitle: 'Search', + isBottomBar: false, + isShowAppBar: true, + backgroundColor: Colors.white, + isShowDecPage: false, + //baseViewModel: model, + body: SingleChildScrollView( + child: Container( + height: SizeConfig.screenHeight, + child: Column( + children: [ + Padding( + padding: EdgeInsets.all(8.0), + child: Row( + children: [ + Container( + width: MediaQuery.of(context).size.width * 0.79, + child: Form( + key: _formKey, + child: TextFields( + autoFocus: true, + hintText: 'Search', + fontSize: 19.0, + prefixIcon: Icon(Icons.search), + inputAction: TextInputAction.search, + onSaved: (value) { + //searchMedicine(model, context); + }, + onSubmit: (value) { + searchMedicine(model, context); + msg = 'No Result Found'; + }, + controller: textController, + validator: (value) { + if (value.isEmpty) { + return 'please Enter Product Name'; + } + return null; + }, + ), + ), + ), + SizedBox( + width: 10.0, + ), + InkWell( + child: Texts( + 'Cancel', + fontSize: 17.0, + fontWeight: FontWeight.w500, + ), + onTap: () { + Navigator.pop(context); + }, + ), + + // child: Container( + // child: Button( + // backgroundColor: Colors.green, + // loading: model.state == ViewState.BusyLocal, + // label: 'Search', + // onTap: () { + // searchMedicine(model, context); + // }), + // width: MediaQuery.of(context).size.width * 0.09, + // ), + ], + ), + ), + model.searchList.length == 0 + ? Container( + child: Text( + 'no data' + model.searchList.length.toString()), + ) + : Expanded( + child: Container( + child: ListView.builder( + itemCount: model.searchList.length, + itemBuilder: (BuildContext ctx, index) { + return Padding( + padding:EdgeInsets.all(8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Container( + child: Text( + model.searchList[index].name, + style: TextStyle(fontSize: 20), + ), + ), + ), + Divider(height: 1, color: Colors.grey) + ],), + ); + }, + ), + ), + ), + ], + ), + ), + ), + ), + ); + } + + searchMedicine(model, BuildContext context) { + Utils.hideKeyboard(context); + if (_formKey.currentState.validate()) + model.searchProducts(productName: textController.text); + } +} diff --git a/lib/pages/pharmacies/widgets/ProductOrderItem.dart b/lib/pages/pharmacies/widgets/ProductOrderItem.dart index 81b6068a..92e2c39d 100644 --- a/lib/pages/pharmacies/widgets/ProductOrderItem.dart +++ b/lib/pages/pharmacies/widgets/ProductOrderItem.dart @@ -1,13 +1,239 @@ +import 'package:diplomaticquarterapp/core/model/pharmacies/ShoppingCart.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class ProductOrderItem extends StatefulWidget { + final ShoppingCart item; + final VoidCallback changeCartItems; + final VoidCallback deleteCartItems; + + ProductOrderItem(this.item, this.changeCartItems, this.deleteCartItems); + + @override + _ProductOrderItemState createState() => _ProductOrderItemState(); +} + +class _ProductOrderItemState extends State { + TextEditingController _quantityController = new TextEditingController(); + String _totalPrice = "0"; + + @override + void initState() { + _quantityController.text = "${widget.item.quantity}"; + _totalPrice = + "${(widget.item.product.price * widget.item.quantity).toStringAsFixed(2)}"; + super.initState(); + } -class ProductOrderItem extends StatelessWidget { @override Widget build(BuildContext context) { - return ListTile( - leading: Icon( - Icons.delete_outline_sharp, - color: Colors.grey.shade800, - ), + ProjectViewModel projectProvider = Provider.of(context); + + return Column( + children: [ + ListTile( + leading: InkWell( + onTap: () => {widget.deleteCartItems()}, + child: Icon( + Icons.delete_outline_sharp, + color: Colors.grey.shade700, + ), + ), + title: Container( + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: [ + (widget.item.product.images != null && widget.item.product.images.length > 0) + ? Image.network( + widget.item.product.images[0].src, + fit: BoxFit.cover, + height: 80, + ) + : Image.asset( + "assets/images/no_image.png", + fit: BoxFit.cover, + height: 80, + ), + Expanded( + child: Container( + margin: + const EdgeInsets.symmetric(vertical: 8, horizontal: 8), + child: Container( + child: Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + child: Texts( + projectProvider.isArabic + ? widget.item.product.namen + : widget.item.product.name, + regular: true, + textAlign: TextAlign.justify, + fontSize: 12, + fontWeight: FontWeight.w400, + ), + margin: const EdgeInsets.only(bottom: 4), + ), + Container( + child: Texts( + "${(widget.item.product.price).toStringAsFixed(2)} ${projectProvider.isArabic ? widget.item.currencyn : widget.item.currency}", + fontSize: 14, + fontWeight: FontWeight.bold, + ), + margin: const EdgeInsets.only(bottom: 4), + ), + Row( + children: [ + InkWell( + onTap: () => + {_quantityOnChangeClick(Operation.dec)}, + child: Container( + width: 25, + height: 25, + child: Center( + child: Texts( + "-", + color: Colors.grey.shade400, + )), + decoration: BoxDecoration( + border: Border.all( + color: Colors.grey.shade400, + width: 1.0, + ), + ), + ), + ), + Container( + margin: + const EdgeInsets.symmetric(horizontal: 4), + width: 25, + height: 25, + color: Colors.grey.shade300, + child: Center( + child: TextField( + cursorColor: Colors.black, + keyboardType: TextInputType.number, + controller: _quantityController, + textAlign: TextAlign.center, + onChanged: (text) { + setState(() { + var value = int.tryParse(text); + if (value == null) { + widget.item.quantity = 0; + } else { + widget.item.quantity = int.parse(text); + } + _totalPrice = + "${(widget.item.product.price * widget.item.quantity).toStringAsFixed(2)}"; + }); + }, + )), + ), + InkWell( + onTap: () => + {_quantityOnChangeClick(Operation.inc)}, + child: Container( + width: 25, + height: 25, + child: Center( + child: Texts( + "+", + color: Colors.grey.shade400, + )), + decoration: BoxDecoration( + border: Border.all( + color: Colors.grey.shade400, + width: 1.0, + ), + ), + ), + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Texts( + TranslationBase.of(context).total, + color: Colors.grey.shade500, + fontWeight: FontWeight.bold, + fontSize: 12, + ), + Texts( + "$_totalPrice ${projectProvider.isArabic ? widget.item.currencyn : widget.item.currency}", + fontSize: 12, + fontWeight: FontWeight.bold, + ) + ], + ), + ) + ], + ) + ], + ), + ), + ), + ) + ], + ), + ), + ), + const Divider( + color: Color(0xFFD6D6D6), + height: 15, + thickness: 1, + indent: 0, + endIndent: 0, + ), + ], ); } + + _quantityOnChangeClick(Operation operation) { + int newValue = 0; + setState(() { + switch (operation) { + case Operation.inc: + { + newValue = widget.item.quantity + 1; + } + break; + + case Operation.dec: + { + newValue = widget.item.quantity - 1; + } + break; + default: + { + //statements; + } + break; + } + if (newValue > 0) { + widget.item.quantity = newValue; + _quantityController.text = "${widget.item.quantity}"; + _totalPrice = + "${(widget.item.product.price * widget.item.quantity).toStringAsFixed(2)}"; + } + }); + if (newValue > 0) { + widget.changeCartItems(); + } + } + + @override + void dispose() { + // Clean up the controller when the widget is removed from the + // widget tree. + _quantityController.dispose(); + super.dispose(); + } } + +enum Operation { inc, dec } diff --git a/lib/pages/pharmacies/widgets/ProductOrderPreviewItem.dart b/lib/pages/pharmacies/widgets/ProductOrderPreviewItem.dart new file mode 100644 index 00000000..d38f437c --- /dev/null +++ b/lib/pages/pharmacies/widgets/ProductOrderPreviewItem.dart @@ -0,0 +1,111 @@ +import 'package:diplomaticquarterapp/core/model/pharmacies/ShoppingCart.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class ProductOrderPreviewItem extends StatelessWidget { + final ShoppingCart item; + + ProductOrderPreviewItem(this.item); + + @override + Widget build(BuildContext context) { + ProjectViewModel projectProvider = Provider.of(context); + + return Container( + margin: EdgeInsets.only(top: 16), + child: Column( + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: [ + (item.product.images != null && item.product.images.length > 0) + ? Image.network( + item.product.images[0].src, + fit: BoxFit.cover, + height: 80, + ) + : Image.asset( + "assets/images/no_image.png", + fit: BoxFit.cover, + height: 80, + ), + Expanded( + child: Container( + margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 8), + child: Container( + child: Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + child: Texts( + projectProvider.isArabic + ? item.product.namen + : item.product.name, + regular: true, + textAlign: TextAlign.justify, + fontSize: 12, + fontWeight: FontWeight.w400, + ), + margin: const EdgeInsets.only(bottom: 4), + ), + Container( + child: Texts( + "${(item.product.price).toStringAsFixed(2)} ${projectProvider.isArabic ? item.currencyn : item.currency}", + fontSize: 14, + fontWeight: FontWeight.bold, + ), + margin: const EdgeInsets.only(bottom: 4), + ), + Container( + width: double.infinity, + alignment: Alignment.centerRight, + child: Texts( + TranslationBase.of(context).total, + color: Colors.grey.shade700, + fontWeight: FontWeight.bold, + fontSize: 13, + ), + ), + Row( + children: [ + Texts( + "QTY: ${item.quantity}", + color: Colors.grey.shade500, + fontWeight: FontWeight.bold, + fontSize: 12, + ), + Expanded( + child: Container( + alignment: Alignment.centerRight, + child: Texts( + "${(item.product.price * item.quantity).toStringAsFixed(2)} ${projectProvider.isArabic ? item.currencyn : item.currency}", + fontSize: 14, + fontWeight: FontWeight.bold, + ), + ), + ) + ], + ), + ], + ), + ), + )), + ], + ), + const Divider( + color: Color(0xFFD6D6D6), + height: 0, + thickness: 1, + indent: 0, + endIndent: 0, + ), + ], + ), + ); + } +} diff --git a/lib/pages/pharmacies/widgets/ProductTileItem.dart b/lib/pages/pharmacies/widgets/ProductTileItem.dart index 62493387..20d6b730 100644 --- a/lib/pages/pharmacies/widgets/ProductTileItem.dart +++ b/lib/pages/pharmacies/widgets/ProductTileItem.dart @@ -1,6 +1,7 @@ import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/core/model/pharmacies/PharmacyProduct.dart'; import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/pages/pharmacies/product_detail.dart'; import 'package:diplomaticquarterapp/pages/pharmacies/screens/phramacy-product-detail-page.dart'; import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; @@ -17,7 +18,7 @@ class ProductTileItem extends StatelessWidget { void productOnClick(BuildContext ctx) { _saveLastVisitProducts(); - Navigator.push(ctx, FadePage(page: ProductDetailScreen(item))); + Navigator.push(ctx, FadePage(page: ProductDetailPage(item))); } void _saveLastVisitProducts() async { @@ -69,11 +70,17 @@ class ProductTileItem extends StatelessWidget { Container( margin: EdgeInsets.fromLTRB(0, 16, 0, 0), alignment: Alignment.center, - child: Image.network( - item.images[0].src, - fit: BoxFit.cover, - height: 80, - ), + child: (item.images != null && item.images.length > 0) + ? Image.network( + item.images[0].src, + fit: BoxFit.cover, + height: 80, + ) + : Image.asset( + "assets/images/no_image.png", + fit: BoxFit.cover, + height: 80, + ), ), Container( width: item.rxMessage != null @@ -104,7 +111,7 @@ class ProductTileItem extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Texts( - projectProvider.isArabic ? item.name : item.namen, + projectProvider.isArabic ? item.namen : item.name, regular: true, fontSize: 12, fontWeight: FontWeight.w400, @@ -119,19 +126,21 @@ class ProductTileItem extends StatelessWidget { ), Row( children: [ - StarRating( - totalAverage: item.approvedTotalReviews > 0 - ? (item.approvedRatingSum.toDouble() / - item.approvedTotalReviews.toDouble()) - .toDouble() - : 0, - forceStars: true), - Texts( + Expanded( + child: StarRating( + totalAverage: item.approvedTotalReviews > 0 + ? (item.approvedRatingSum.toDouble() / + item.approvedTotalReviews.toDouble()) + .toDouble() + : 0, + forceStars: true), + ), + /*Texts( "(${item.approvedTotalReviews})", regular: true, fontSize: 10, fontWeight: FontWeight.w400, - ) + ),*/ ], ), ], diff --git a/lib/pages/pharmacies/widgets/lacum-banner-widget.dart b/lib/pages/pharmacies/widgets/lacum-banner-widget.dart new file mode 100644 index 00000000..14a53e72 --- /dev/null +++ b/lib/pages/pharmacies/widgets/lacum-banner-widget.dart @@ -0,0 +1,289 @@ +import 'package:carousel_slider/carousel_slider.dart'; +import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/lacum-viewmodel.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/borderedButton.dart'; +import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; +import 'package:flutter/material.dart'; + +class LakumBannerWidget extends StatefulWidget { + final LacumViewModel model; + final MediaQueryData mediaQuery; + final bool isLacumHomePage; + + LakumBannerWidget(this.model, this.mediaQuery, this.isLacumHomePage); + + @override + _LakumBannerWidgetState createState() => _LakumBannerWidgetState(); +} + +class _LakumBannerWidgetState extends State { + int _current = 0; + + @override + Widget build(BuildContext context) { + return Container( + child: Stack( + children: [ + CarouselSlider( + options: CarouselOptions( + enableInfiniteScroll: false, + enlargeCenterPage: false, + viewportFraction: 1.0, + scrollPhysics: widget.isLacumHomePage + ? ScrollPhysics() + : NeverScrollableScrollPhysics(), + initialPage: 0, + onPageChanged: (index, reason) { + setState(() { + _current = index; + }); + }, + ), + items: [ + Container( + decoration: BoxDecoration( + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(4), + border: Border.fromBorderSide(BorderSide( + color: Colors.grey, + width: 0.4, + )), + ), + margin: EdgeInsets.symmetric(horizontal: 16), + child: Stack( + children: [ + Image.asset( + "assets/images/pharmacy_module/lakum/lakum_card_front_bg.png", + fit: BoxFit.fill, + width: widget.mediaQuery.size.width * 1.0, + height: widget.mediaQuery.size.width * 1.0, + ), + Container( + margin: EdgeInsets.fromLTRB(12, 70, 12, 4), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Texts( + widget.model.lacumGroupInformation.lakumInquiryInformationObjVersion.memberName, + fontSize: 14, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + Texts( + "${widget.model.lacumInformation.yahalaAccountNo}", + fontSize: 16, + fontWeight: FontWeight.normal, + color: Colors.black, + ), + ], + ), + BorderedButton( + widget.model.lacumGroupInformation.lakumInquiryInformationObjVersion.accountStatus == "Active" + ? TranslationBase.of(context).active + : TranslationBase.of(context).inactive, + textColor: widget.model.lacumInformation + .accountStatus == + 1 + ? Colors.green + : Colors.red, + hasBorder: true, + borderColor: widget.model.lacumInformation + .accountStatus == + 1 + ? Colors.green + : Colors.red, + radius: 16, + rPadding: 16, + icon: widget.model.lacumInformation + .accountStatus == + 1 + ? Icon( + Icons.check_circle, + size: 25, + color: Colors.green, + ) + : Image.asset( + "assets/images/pharmacy_module/lakum/inactive_cross.png", + fit: BoxFit.fill, + width: 25, + height: 25, + ), + ), + ], + ), + SizedBox( + height: 10, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Texts( + "IDENTIFICATION #", + fontSize: 14, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + Texts( + widget.model.lacumInformation + .identificationNo, + fontSize: 16, + fontWeight: FontWeight.normal, + color: Colors.black, + ), + ], + ), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Texts( + "MEMBER SINCE", + fontSize: 14, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + Texts( + widget.model.formatCreatedDateToString(), + fontSize: 16, + fontWeight: FontWeight.normal, + color: Colors.black, + ), + ], + ), + ], + ), + SizedBox( + height: 10, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Texts( + "MOBILE #", + fontSize: 14, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + Texts( + widget.model.lacumGroupInformation.lakumInquiryInformationObjVersion.mobileNumber, + fontSize: 16, + fontWeight: FontWeight.normal, + color: Colors.black, + ), + ], + ), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Texts( + TranslationBase.of(context).language, + fontSize: 14, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + Texts( + widget.model.lacumInformation.prefLang == + "1" + ? TranslationBase.of(context).lanEnglish + : TranslationBase.of(context).lanArabic, + fontSize: 16, + fontWeight: FontWeight.normal, + color: Colors.black, + ), + ], + ), + ], + ), + ], + ), + ), + ], + ), + ), + widget.isLacumHomePage + ? Container( + decoration: BoxDecoration( + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(4), + border: Border.fromBorderSide(BorderSide( + color: Colors.grey, + width: 0.4, + )), + ), + margin: EdgeInsets.symmetric(horizontal: 16), + child: Stack( + children: [ + Image.asset( + "assets/images/pharmacy_module/lakum/lakum_card_front_bg.png", + fit: BoxFit.fill, + width: widget.mediaQuery.size.width * 1.0, + height: widget.mediaQuery.size.width * 1.0, + ), + Container( + margin: EdgeInsets.fromLTRB(12, 70, 12, 4), + child: widget.model.convertBase64ToBarCodeImage() != + null + ? Image.memory( + widget.model.convertBase64ToBarCodeImage()) + : Container(), + ), + ], + ), + ) + : Container(), + ], + ), + widget.isLacumHomePage + ? Positioned( + bottom: 1, + left: 1, + right: 1, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + width: _current == 0 ? 12.0 : 8.0, + height: 4.0, + margin: EdgeInsets.symmetric( + vertical: 0.0, horizontal: 2.0), + decoration: BoxDecoration( + shape: BoxShape.rectangle, + color: _current == 0 + ? Color(0xff5ab145) + : Color.fromRGBO(0, 0, 0, 0.4), + ), + ), + Container( + width: _current == 1 ? 12.0 : 8.0, + height: 4.0, + margin: EdgeInsets.symmetric( + vertical: 0.0, horizontal: 2.0), + decoration: BoxDecoration( + shape: BoxShape.rectangle, + color: _current == 1 + ? Color(0xff5ab145) + : Color.fromRGBO(0, 0, 0, 0.4), + ), + ), + ], + ), + ), + ) + : Container(), + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/pages/pharmacies/widgets/lakum-banner-widget.dart b/lib/pages/pharmacies/widgets/lakum-banner-widget.dart new file mode 100644 index 00000000..14a53e72 --- /dev/null +++ b/lib/pages/pharmacies/widgets/lakum-banner-widget.dart @@ -0,0 +1,289 @@ +import 'package:carousel_slider/carousel_slider.dart'; +import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/lacum-viewmodel.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/borderedButton.dart'; +import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; +import 'package:flutter/material.dart'; + +class LakumBannerWidget extends StatefulWidget { + final LacumViewModel model; + final MediaQueryData mediaQuery; + final bool isLacumHomePage; + + LakumBannerWidget(this.model, this.mediaQuery, this.isLacumHomePage); + + @override + _LakumBannerWidgetState createState() => _LakumBannerWidgetState(); +} + +class _LakumBannerWidgetState extends State { + int _current = 0; + + @override + Widget build(BuildContext context) { + return Container( + child: Stack( + children: [ + CarouselSlider( + options: CarouselOptions( + enableInfiniteScroll: false, + enlargeCenterPage: false, + viewportFraction: 1.0, + scrollPhysics: widget.isLacumHomePage + ? ScrollPhysics() + : NeverScrollableScrollPhysics(), + initialPage: 0, + onPageChanged: (index, reason) { + setState(() { + _current = index; + }); + }, + ), + items: [ + Container( + decoration: BoxDecoration( + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(4), + border: Border.fromBorderSide(BorderSide( + color: Colors.grey, + width: 0.4, + )), + ), + margin: EdgeInsets.symmetric(horizontal: 16), + child: Stack( + children: [ + Image.asset( + "assets/images/pharmacy_module/lakum/lakum_card_front_bg.png", + fit: BoxFit.fill, + width: widget.mediaQuery.size.width * 1.0, + height: widget.mediaQuery.size.width * 1.0, + ), + Container( + margin: EdgeInsets.fromLTRB(12, 70, 12, 4), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Texts( + widget.model.lacumGroupInformation.lakumInquiryInformationObjVersion.memberName, + fontSize: 14, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + Texts( + "${widget.model.lacumInformation.yahalaAccountNo}", + fontSize: 16, + fontWeight: FontWeight.normal, + color: Colors.black, + ), + ], + ), + BorderedButton( + widget.model.lacumGroupInformation.lakumInquiryInformationObjVersion.accountStatus == "Active" + ? TranslationBase.of(context).active + : TranslationBase.of(context).inactive, + textColor: widget.model.lacumInformation + .accountStatus == + 1 + ? Colors.green + : Colors.red, + hasBorder: true, + borderColor: widget.model.lacumInformation + .accountStatus == + 1 + ? Colors.green + : Colors.red, + radius: 16, + rPadding: 16, + icon: widget.model.lacumInformation + .accountStatus == + 1 + ? Icon( + Icons.check_circle, + size: 25, + color: Colors.green, + ) + : Image.asset( + "assets/images/pharmacy_module/lakum/inactive_cross.png", + fit: BoxFit.fill, + width: 25, + height: 25, + ), + ), + ], + ), + SizedBox( + height: 10, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Texts( + "IDENTIFICATION #", + fontSize: 14, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + Texts( + widget.model.lacumInformation + .identificationNo, + fontSize: 16, + fontWeight: FontWeight.normal, + color: Colors.black, + ), + ], + ), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Texts( + "MEMBER SINCE", + fontSize: 14, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + Texts( + widget.model.formatCreatedDateToString(), + fontSize: 16, + fontWeight: FontWeight.normal, + color: Colors.black, + ), + ], + ), + ], + ), + SizedBox( + height: 10, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Texts( + "MOBILE #", + fontSize: 14, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + Texts( + widget.model.lacumGroupInformation.lakumInquiryInformationObjVersion.mobileNumber, + fontSize: 16, + fontWeight: FontWeight.normal, + color: Colors.black, + ), + ], + ), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Texts( + TranslationBase.of(context).language, + fontSize: 14, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + Texts( + widget.model.lacumInformation.prefLang == + "1" + ? TranslationBase.of(context).lanEnglish + : TranslationBase.of(context).lanArabic, + fontSize: 16, + fontWeight: FontWeight.normal, + color: Colors.black, + ), + ], + ), + ], + ), + ], + ), + ), + ], + ), + ), + widget.isLacumHomePage + ? Container( + decoration: BoxDecoration( + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(4), + border: Border.fromBorderSide(BorderSide( + color: Colors.grey, + width: 0.4, + )), + ), + margin: EdgeInsets.symmetric(horizontal: 16), + child: Stack( + children: [ + Image.asset( + "assets/images/pharmacy_module/lakum/lakum_card_front_bg.png", + fit: BoxFit.fill, + width: widget.mediaQuery.size.width * 1.0, + height: widget.mediaQuery.size.width * 1.0, + ), + Container( + margin: EdgeInsets.fromLTRB(12, 70, 12, 4), + child: widget.model.convertBase64ToBarCodeImage() != + null + ? Image.memory( + widget.model.convertBase64ToBarCodeImage()) + : Container(), + ), + ], + ), + ) + : Container(), + ], + ), + widget.isLacumHomePage + ? Positioned( + bottom: 1, + left: 1, + right: 1, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + width: _current == 0 ? 12.0 : 8.0, + height: 4.0, + margin: EdgeInsets.symmetric( + vertical: 0.0, horizontal: 2.0), + decoration: BoxDecoration( + shape: BoxShape.rectangle, + color: _current == 0 + ? Color(0xff5ab145) + : Color.fromRGBO(0, 0, 0, 0.4), + ), + ), + Container( + width: _current == 1 ? 12.0 : 8.0, + height: 4.0, + margin: EdgeInsets.symmetric( + vertical: 0.0, horizontal: 2.0), + decoration: BoxDecoration( + shape: BoxShape.rectangle, + color: _current == 1 + ? Color(0xff5ab145) + : Color.fromRGBO(0, 0, 0, 0.4), + ), + ), + ], + ), + ), + ) + : Container(), + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/pages/pharmacies/widgets/lakum-point-table-row-widget.dart b/lib/pages/pharmacies/widgets/lakum-point-table-row-widget.dart new file mode 100644 index 00000000..6e4e2309 --- /dev/null +++ b/lib/pages/pharmacies/widgets/lakum-point-table-row-widget.dart @@ -0,0 +1,116 @@ +import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_expandable_notifier.dart'; +import 'package:diplomaticquarterapp/widgets/others/points-expandable-notifier.dart'; +import 'package:expandable/expandable.dart'; +import 'package:flutter/material.dart'; + +class LakumPointTableRowWidget extends StatefulWidget { + final bool isTableTitle; // true : title , false: row + final String rowTitle; + final double points; + final double riyal; + final Function onTap; + final int rowIndex; + final Widget collapsed; + final bool expandFlag; + + LakumPointTableRowWidget(this.isTableTitle, this.rowTitle, this.points, + this.riyal, this.onTap, this.rowIndex, + {this.collapsed, this.expandFlag = false}); + + @override + _LakumPointTableRowWidgetState createState() => + _LakumPointTableRowWidgetState(); +} + +class _LakumPointTableRowWidgetState extends State { + @override + Widget build(BuildContext context) { + return InkWell( + onTap: widget.onTap, + child: Column( + children: [ + Column( + children: [ + widget.collapsed != null + ? PointsExpandableNotifier( + headerWidget: buildPointRowBody(), + // bodyWidget: widget.collapsed != null ? widget.collapsed : null, + bodyWidget: widget.collapsed, + isExpand: widget.expandFlag, + ) + : buildPointRowBody(), + ], + ), + const Divider( + color: Color(0xFFD6D6D6), + height: 1, + thickness: 1, + indent: 0, + endIndent: 0, + ), + ], + ), + ); + } + + Widget buildPointRowBody() { + bool isEven = widget.rowIndex % 2 == 0; + return Container( + padding: EdgeInsets.symmetric(vertical: 12, horizontal: 12), + color: widget.expandFlag ? Color(0xffe4e4e4) : isEven && !widget.isTableTitle ? Color(0xffefefef) : Colors.white, + child: Column( + children: [ + Row( + children: [ + Expanded( + child: Container( + child: Texts( + widget.rowTitle, + fontSize: 14, + fontWeight: + widget.isTableTitle ? FontWeight.bold : FontWeight.normal, + ), + )), + Expanded( + child: Container( + child: Texts( + widget.isTableTitle ? "POINTS" : "${widget.points}", + fontSize: 14, + fontWeight: + widget.isTableTitle ? FontWeight.bold : FontWeight.normal, + ), + )), + Expanded( + child: Container( + child: Texts( + widget.isTableTitle ? "RIYAL" : "${widget.riyal}", + fontSize: 14, + fontWeight: + widget.isTableTitle ? FontWeight.bold : FontWeight.normal, + ), + )), + Expanded( + child: widget.isTableTitle + ? Container() + : Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Icon( + widget.collapsed == null + ? Icons.keyboard_arrow_right + : widget.expandFlag + ? Icons.keyboard_arrow_up + : Icons.keyboard_arrow_down, + size: 25, + color: Colors.grey.shade700, + ), + ], + )), + ], + ), + ], + ), + ); + } +} diff --git a/lib/pages/pharmacies/widgets/lakum_point_table_row_widget.dart b/lib/pages/pharmacies/widgets/lakum_point_table_row_widget.dart new file mode 100644 index 00000000..bddd2e3b --- /dev/null +++ b/lib/pages/pharmacies/widgets/lakum_point_table_row_widget.dart @@ -0,0 +1,116 @@ +import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_expandable_notifier.dart'; +import 'package:diplomaticquarterapp/widgets/others/points-expandable-notifier.dart'; +import 'package:expandable/expandable.dart'; +import 'package:flutter/material.dart'; + +class LakumPointTableRowWidget extends StatefulWidget { + final bool isTableTitle; // true : title , false: row + final String rowTitle; + final double points; + final double riyal; + final Function onTap; + final int rowIndex; + final Widget collapsed; + final bool expandFlag; + + LakumPointTableRowWidget(this.isTableTitle, this.rowTitle, this.points, + this.riyal, this.onTap, this.rowIndex, + {this.collapsed, this.expandFlag = false}); + + @override + _LakumPointTableRowWidgetState createState() => + _LakumPointTableRowWidgetState(); +} + +class _LakumPointTableRowWidgetState extends State { + @override + Widget build(BuildContext context) { + return InkWell( + onTap: widget.onTap, + child: Column( + children: [ + Column( + children: [ + widget.collapsed != null + ? PointsExpandableNotifier( + headerWidget: buildPointRowBody(), + // bodyWidget: widget.collapsed != null ? widget.collapsed : null, + bodyWidget: widget.collapsed, + isExpand: widget.expandFlag, + ) + : buildPointRowBody(), + ], + ), + const Divider( + color: Color(0xFFD6D6D6), + height: 1, + thickness: 1, + indent: 0, + endIndent: 0, + ), + ], + ), + ); + } + + Widget buildPointRowBody() { + bool isEven = widget.rowIndex % 2 == 0; + return Container( + padding: EdgeInsets.symmetric(vertical: 12, horizontal: 12), + color: widget.expandFlag ? Color(0xffe4e4e4) : isEven && !widget.isTableTitle ? Color(0xffefefef) : Colors.white, + child: Column( + children: [ + Row( + children: [ + Expanded( + child: Container( + child: Texts( + widget.rowTitle, + fontSize: 14, + fontWeight: + widget.isTableTitle ? FontWeight.bold : FontWeight.normal, + ), + )), + Expanded( + child: Container( + child: Texts( + widget.isTableTitle ? "POINTS" : "${widget.points}", + fontSize: 14, + fontWeight: + widget.isTableTitle ? FontWeight.bold : FontWeight.normal, + ), + )), + Expanded( + child: Container( + child: Texts( + widget.isTableTitle ? "RIYAL" : "${widget.riyal}", + fontSize: 14, + fontWeight: + widget.isTableTitle ? FontWeight.bold : FontWeight.normal, + ), + )), + Expanded( + child: widget.isTableTitle + ? Container() + : Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Icon( + widget.collapsed == null + ? Icons.keyboard_arrow_right + : widget.expandFlag + ? Icons.keyboard_arrow_up + : Icons.keyboard_arrow_down, + size: 25, + color: Colors.grey.shade700, + ), + ], + )), + ], + ), + ], + ), + ); + } +} diff --git a/lib/pages/pharmacies/wishlist.dart b/lib/pages/pharmacies/wishlist.dart new file mode 100644 index 00000000..822dfe89 --- /dev/null +++ b/lib/pages/pharmacies/wishlist.dart @@ -0,0 +1,69 @@ +import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/wishlist_view_model.dart'; +import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/pages/pharmacies/ProductCheckTypeWidget.dart'; +import 'package:flutter/material.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; + +class WishlistPage extends StatefulWidget { + @override + _WishlistPageState createState() => _WishlistPageState(); +} + +class _WishlistPageState extends State { + bool isTrue = true; + + Widget build(BuildContext context) { + return BaseView( + onModelReady: (model) => model.getWishlistData(), + builder: (_, model, wi) => AppScaffold( + appBarTitle: 'Wishlist page', + isShowAppBar: false, + isShowDecPage: false, + isPharmacy: false, + baseViewModel: model, + body: model.wishListList.length == 0 + ? Container( + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Image.asset( + 'assets/images/new-design/empty_box.png', + width: 100, + height: 100, + fit: BoxFit.cover, + ), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + 'There is no data', + style: TextStyle(fontSize: 30), + ), + ) + ], + ), + ), + ) + : Container( + child: Column( + children: [ + Expanded( + flex: 20, + child: Container( + width: double.infinity, + height: + MediaQuery.of(context).size.height * 0.85, //250, + child: + ProductCheckTypeWidget(isTrue, model.wishListList), + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/pages/pharmacy/order/Order.dart b/lib/pages/pharmacy/order/Order.dart new file mode 100644 index 00000000..576bf2a0 --- /dev/null +++ b/lib/pages/pharmacy/order/Order.dart @@ -0,0 +1,1148 @@ +import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/order_model_view_model.dart'; +import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:flutter/material.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:diplomaticquarterapp/config/config.dart'; +import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; +import 'package:diplomaticquarterapp/services/pharmacy_services/order_service.dart'; +import 'package:diplomaticquarterapp/pages/pharmacy/order/OrderDetails.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/order_model.dart'; +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/pages/base/base_view.dart'; + +dynamic languageID; +class OrderPage extends StatefulWidget { + +// orderList({this.customerId, this.pageId}); + + String customerID; + + OrderPage({@required this.customerID}); + + @override + _OrderPageState createState() => _OrderPageState(); +} + +class _OrderPageState extends State with SingleTickerProviderStateMixin{ + + String pageID= "1"; + String customerId = ""; + String order =""; + + List orderList = [] ; + List deliveredOrderList = [] ; + List processingOrderList = []; + List cancelledOrderList = []; + List pendingOrderList = []; + + TabController _tabController; +// AppSharedPreferences sharedPref = AppSharedPreferences(); + getLanguageID() async { + languageID = await sharedPref.getString(APP_LANGUAGE); + } + + @override + void initState() { + getLanguageID(); + super.initState(); + + + _tabController = new TabController(length: 4, vsync: this,); + } + + @override + Widget build(BuildContext context) { + print( "customerID" + widget.customerID); + return BaseView( + onModelReady: (model) => model.getOrder(widget.customerID, pageID), + builder: (_,model, wi )=> AppScaffold( + appBarTitle:TranslationBase.of(context).order, + baseViewModel: model, + isShowAppBar: true, + isPharmacy:true , + body: Container( + child: Column( + children: [ + TabBar( + tabs: [ + Tab(text: TranslationBase.of(context).delivered), + Tab(text: TranslationBase.of(context).processing), + Tab(text: TranslationBase.of(context).pending), + Tab(text: TranslationBase.of(context).cancelled), + ], + controller: _tabController, + ), + Divider( + color: Colors.grey[350], + height: 10, + thickness: 6, + indent: 0, + endIndent: 0, + ), + Expanded( + child: new TabBarView( + physics: NeverScrollableScrollPhysics(), + children: [ + getDeliveredOrder(model), + getProcessingOrder(model), + getPendingOrder(model), + getCancelledOrder(model), + ], + controller: _tabController, + ), + ), + ], + ), + ), + ), + ); + } + + + + Widget getDeliveredOrder(OrderModelViewModel model){ + for(int i=0 ; i< model.order.length; i++){ + if( model.order[i].orderStatusId == 30 || model.order[i].orderStatusId == 997 + || model.order[i].orderStatusId == 994 + ){ + deliveredOrderList.add(model.order[i]); + } + } + return Container( + width: MediaQuery.of(context).size.width, + child: model.order.length != 0 + ? SingleChildScrollView( + child: Column( + children: [ + ListView.builder( + scrollDirection: Axis.vertical, + shrinkWrap: true, + physics: ScrollPhysics(), + itemCount: deliveredOrderList.length, + itemBuilder: (context, index){ + return Container( + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + margin: EdgeInsets.all(8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Container( + margin: EdgeInsets.only(right: 5), + child: Text(TranslationBase.of(context).orderNumber, + style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold, + ), + ), + ), + Container( + child: Text(deliveredOrderList[index].id.toString(), + style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + SizedBox( + height: 5,), + Row( + children: [ + Container( + margin: EdgeInsets.only(right: 5), + child: Text(TranslationBase.of(context).orderDate, + style: TextStyle(fontSize: 14.0, + ), + ), + ), + Container( + child: Text(deliveredOrderList[index].createdOnUtc.toString().substring(0,11), + style: TextStyle(fontSize: 14.0, + ), + ), + ), + ], + ), + ], + ), + ), + Container( + margin: EdgeInsets.all(8.0), + child: InkWell( + onTap: () { + Navigator.push(context, + MaterialPageRoute(builder: (context) => OrderDetailsPage(orderModel:deliveredOrderList[index]))); + }, + child: SvgPicture.asset( + languageID == "ar" + ? 'assets/images/pharmacy/arrow_left.svg' + :'assets/images/pharmacy/arrow_right.svg', + height: 20, + width: 20,), + ), + ), + ], + ), + Divider( + color: Colors.grey[350], + height: 20, + thickness: 1, + indent: 0, + endIndent: 0, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + margin: EdgeInsets.only(left: 8, right: 8, top: 1, bottom: 8), + padding: EdgeInsets.only(left: 13.0, right: 13.0), + decoration: BoxDecoration( + border: Border.all( + color: Colors.blue[700], + style: BorderStyle.solid, + width: 5.0, + ), + color: Colors.blue[700], + borderRadius: BorderRadius.circular(30.0) + ), + child: deliveredOrderList[index].orderStatusId == 30 + ? Text( +// deliveredOrderList[0].orderStatus.toString().substring(12), + TranslationBase.of(context).deliveredOrder, + style: TextStyle( + color: Colors.white, + fontSize: 15.0, + fontWeight: FontWeight.bold, + ), + ) + : Text( + languageID == "ar" + ? deliveredOrderList[index].orderStatusn.toString(): + deliveredOrderList[index].orderStatus.toString(), + style: TextStyle( + color: Colors.white, + fontSize: 15.0, + fontWeight: FontWeight.bold, + ), + ) + ), + Container( + margin: EdgeInsets.only(left: 8, right: 8, top: 1, bottom: 8), + child: Column( +// crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Row( + children: [ + Container( + margin: EdgeInsets.only(left: 5), + child: Text(deliveredOrderList[index].orderTotal.toString(), + style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold, + ), + ), + ), + Container( + margin: EdgeInsets.only(left: 5), + child: Text(TranslationBase.of(context).sar, + style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + SizedBox( + height: 5,), + Row( + children: [ + Container( + child: Text(deliveredOrderList[index].orderItems.length.toString(), + style: TextStyle(fontSize: 14.0, + ), + ), + ), + Container( + margin: EdgeInsets.only(left: 5), + child: Text(TranslationBase.of(context).itemsNo, + style: TextStyle(fontSize: 14.0, + ), + ), + ), + ], + ), + ], + ), + ), + ], + ), + Divider( + color: Colors.grey[350], + height: 20, + thickness: 8, + indent: 0, + endIndent: 0, + ), + ], + ), + ); + } + ) + ], + ), + ) + : Container( + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SvgPicture.asset( + 'assets/images/pharmacy/empty_box.svg'), + Container( + margin: EdgeInsets.only(top: 10.0), + child: Text(TranslationBase.of(context).noOrder, + style: TextStyle( + fontSize: 16.0, + )), + ), + ], + ), + ), + ), + ); + } + + Widget getProcessingOrder(OrderModelViewModel model){ + for(int i=0 ; i< model.order.length; i++){ + if( model.order[i].orderStatusId == 20 || model.order[i].orderStatusId == 995 || + model.order[i].orderStatusId == 998 || model.order[i].orderStatusId == 999){ + processingOrderList.add(model.order[i]); + } + } + return Container( + width: MediaQuery.of(context).size.width, + child: model.order.length != 0 + ? SingleChildScrollView( + child: Column( + children: [ + ListView.builder( + scrollDirection: Axis.vertical, + shrinkWrap: true, + physics: ScrollPhysics(), + itemCount: processingOrderList.length, + itemBuilder: (context, index){ + return Container( + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + margin: EdgeInsets.all(8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Container( + margin: EdgeInsets.only(right: 5), + child: Text(TranslationBase.of(context).orderNumber, + style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold, + ), + ), + ), + Container( + child: Text(processingOrderList[index].id.toString(), + style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + SizedBox( + height: 5,), + Row( + children: [ + Container( + margin: EdgeInsets.only(right: 5), + child: Text(TranslationBase.of(context).orderDate, + style: TextStyle(fontSize: 14.0, + ), + ), + ), + Container( + child: Text(processingOrderList[index].createdOnUtc.toString().substring(0,11), + style: TextStyle(fontSize: 14.0, + ), + ), + ), + ], + ), + ], + ), + ), + Container( + margin: EdgeInsets.all(8.0), + child: InkWell( + onTap: () { + Navigator.push(context, + MaterialPageRoute(builder: (context) => OrderDetailsPage(orderModel:processingOrderList[index]))); + }, + child: SvgPicture.asset( + languageID == "ar" + ? 'assets/images/pharmacy/arrow_left.svg' + :'assets/images/pharmacy/arrow_right.svg', + height: 20, + width: 20,), + ), + ), + ], + ), + Divider( + color: Colors.grey[350], + height: 20, + thickness: 1, + indent: 0, + endIndent: 0, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + margin: EdgeInsets.only(left: 8, right: 8, top: 1, bottom: 8), + padding: EdgeInsets.only(left: 13.0, right: 13.0), + decoration: BoxDecoration( + border: Border.all( + color: Colors.green, + style: BorderStyle.solid, + width: 5.0, + ), + color: Colors.green, + borderRadius: BorderRadius.circular(30.0) + ), + child: processingOrderList[index].orderStatusId == 20 + ? Text( +// deliveredOrderList[0].orderStatus.toString().substring(12), + TranslationBase.of(context).processingOrder, + style: TextStyle( + color: Colors.white, + fontSize: 15.0, + fontWeight: FontWeight.bold, + ), + ) + : Text( + languageID == "ar" + ? processingOrderList[index].orderStatusn.toString(): + processingOrderList[index].orderStatus.toString(), + style: TextStyle( + color: Colors.white, + fontSize: 15.0, + fontWeight: FontWeight.bold, + ), + ) + ), + Container( + margin: EdgeInsets.only(left: 8, right: 8, top: 1, bottom: 8), + child: Column( +// crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Row( + children: [ + Container( + margin: EdgeInsets.only(left: 5), + child: Text(processingOrderList[index].orderTotal.toString(), + style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold, + ), + ), + ), + Container( + margin: EdgeInsets.only(left: 5), + child: Text(TranslationBase.of(context).sar, + style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + SizedBox( + height: 5,), + Row( + children: [ + Container( + child: Text(processingOrderList[index].orderItems.length.toString(), + style: TextStyle(fontSize: 14.0, + ), + ), + ), + Container( + margin: EdgeInsets.only(left: 5), + child: Text(TranslationBase.of(context).itemsNo, + style: TextStyle(fontSize: 14.0, + ), + ), + ), + ], + ), + ], + ), + ), + ], + ), + Divider( + color: Colors.grey[350], + height: 20, + thickness: 8, + indent: 0, + endIndent: 0, + ), + ], + ), + ); + } + ) + ], + ), + ) + : Container( + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SvgPicture.asset( + 'assets/images/pharmacy/empty_box.svg'), + Container( + margin: EdgeInsets.only(top: 10.0), + child: Text(TranslationBase.of(context).noOrder, + style: TextStyle( + fontSize: 16.0, + )), + ), + ], + ), + ), + ), + ); +// return Container( +// child: model.order.length != 0 +// ? SingleChildScrollView( +// child: Column( +// children: [ +// ListView.builder( +// child: Row( +// mainAxisAlignment: MainAxisAlignment.spaceBetween, +// children: [ +// Container( +// margin: EdgeInsets.all(8), +// child: Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// Row( +// children: [ +// Container( +// margin: EdgeInsets.only(right: 5), +// child: Text(TranslationBase.of(context).orderNumber, +// style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold, +// ), +// ), +// ), +// Container( +// child: Text(processingOrderList[0].id.toString(), +// style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold, +// ), +// ), +// ), +// ], +// ), +// SizedBox( +// height: 5,), +// Row( +// children: [ +// Container( +// margin: EdgeInsets.only(right: 5), +// child: Text(TranslationBase.of(context).orderDate, +// style: TextStyle(fontSize: 14.0, +// ), +// ), +// ), +// Container( +// child: Text(processingOrderList[0].createdOnUtc.toString().substring(0,11), +// style: TextStyle(fontSize: 14.0, +// ), +// ), +// ), +// ], +// ), +// ], +// ), +// ), +// Container( +// margin: EdgeInsets.all(8), +// child: InkWell( +// onTap: () { +// Navigator.push(context, +// MaterialPageRoute(builder: (context) => OrderDetailsPage(orderModel:processingOrderList[0]))); +// }, +// child: SvgPicture.asset( +// 'assets/images/pharmacy/arrow_right.svg', +// height: 20, +// width: 20,), +// ), +// ), +// ], +// ), +// ), +// Divider( +// color: Colors.grey[350], +// height: 20, +// thickness: 1, +// indent: 0, +// endIndent: 0, +// ), +// Row( +// mainAxisAlignment: MainAxisAlignment.spaceBetween, +// children: [ +// Container( +// margin: EdgeInsets.only(left: 8, right: 8, top: 1, bottom: 8), +// padding: EdgeInsets.only(left: 13.0, right: 13.0), +// decoration: BoxDecoration( +// border: Border.all( +// color: Colors.green, +// style: BorderStyle.solid, +// width: 5.0, +// ), +// color: Colors.green, +// borderRadius: BorderRadius.circular(30.0) +// ), +// child: Text( widget.languageID == "ar" +// ? processingOrderList[0].orderStatusn.toString() +// : processingOrderList[0].orderStatus.toString().substring(12), +//// TranslationBase.of(context).processing, +// style: TextStyle( +// color: Colors.white, +// fontSize: 15.0, +// fontWeight: FontWeight.bold, +// ), +// ), +// ), +// Container( +// margin: EdgeInsets.only(left: 8, right: 8, top: 1, bottom: 8), +// child: Column( +//// crossAxisAlignment: CrossAxisAlignment.end, +// children: [ +// Row( +// children: [ +// Container( +// margin: EdgeInsets.only(left: 5), +// child: Text(processingOrderList[0].orderTotal.toString(), +// style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold, +// ), +// ), +// ), +// Container( +// margin: EdgeInsets.only(left: 5), +// child: Text(TranslationBase.of(context).sar, +// style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold, +// ), +// ), +// ), +// ], +// ), +// SizedBox( +// height: 5,), +// Row( +// children: [ +// Container( +// child: Text(processingOrderList[0].orderItems[0].quantity.toString(), +// style: TextStyle(fontSize: 14.0, +// ), +// ), +// ), +// Container( +// margin: EdgeInsets.only(left: 5), +// child: Text(TranslationBase.of(context).itemsNo, +// style: TextStyle(fontSize: 14.0, +// ), +// ), +// ), +// ], +// ), +// ], +// ), +// ), +// ], +// ), +// Divider( +// color: Colors.grey[350], +// height: 20, +// thickness: 8, +// indent: 0, +// endIndent: 0, +// ), +// ], +// ), +// ) +// : Container( +// child: Center( +// child: Column( +// mainAxisAlignment: MainAxisAlignment.center, +// crossAxisAlignment: CrossAxisAlignment.center, +// children: [ +// SvgPicture.asset( +// 'assets/images/pharmacy/empty_box.svg'), +// Container( +// margin: EdgeInsets.only(top: 10.0), +// child: Text(TranslationBase.of(context).noOrder, +// style: TextStyle( +// fontSize: 16.0, +// )), +// ), +// ], +// ), +// ), +// ), +// ); + } + + Widget getPendingOrder(OrderModelViewModel model){ + for(int i=0 ; i< model.order.length; i++){ + if( model.order[i].orderStatusId == 10){ + pendingOrderList.add(model.order[i]); + } + } + return Container( + child: model.order.length != 0 + ? SingleChildScrollView( + child: Column( + children: [ + ListView.builder( + scrollDirection: Axis.vertical, + shrinkWrap: true, + physics: ScrollPhysics(), + itemCount: pendingOrderList.length , + itemBuilder: (context, index){ + return Container( + child: SingleChildScrollView( + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + margin: EdgeInsets.all(8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Container( + margin: EdgeInsets.only(right: 5), + child: Text(TranslationBase.of(context).orderNumber, + style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold, + ), + ), + ), + Container( + child: Text(pendingOrderList[index].id.toString(), + style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + SizedBox( + height: 5,), + Row( + children: [ + Container( + margin: EdgeInsets.only(right: 5), + child: Text(TranslationBase.of(context).orderDate, + style: TextStyle(fontSize: 14.0, + ), + ), + ), + Container( + child: Text(pendingOrderList[index].createdOnUtc.toString().substring(0,11), + style: TextStyle(fontSize: 14.0, + ), + ), + ), + ], + ), + ], + ), + ), + Container( + margin: EdgeInsets.all( 8.0), + child: InkWell( + onTap: () { + Navigator.push(context, + MaterialPageRoute(builder: (context) => OrderDetailsPage(orderModel:pendingOrderList[index]))); + }, + child: SvgPicture.asset( + languageID == "ar" + ? 'assets/images/pharmacy/arrow_left.svg' + :'assets/images/pharmacy/arrow_right.svg', + height: 20, + width: 20,), + ), + ), + ], + ), + Divider( + color: Colors.grey[350], + height: 20, + thickness: 1, + indent: 0, + endIndent: 0, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + margin: EdgeInsets.all(8.0), + padding: EdgeInsets.only(left: 13.0, right: 13.0), + decoration: BoxDecoration( + border: Border.all( + color: Colors.orange[300], + style: BorderStyle.solid, + width: 5.0, + ), + color: Colors.orange[300], + borderRadius: BorderRadius.circular(30.0) + ), + child: pendingOrderList[index].orderStatusId == 10 + ? Text( +// deliveredOrderList[0].orderStatus.toString().substring(12), + TranslationBase.of(context).pendingOrder, + style: TextStyle( + color: Colors.white, + fontSize: 15.0, + fontWeight: FontWeight.bold, + ), + ) + : Text( + languageID == "ar" + ? pendingOrderList[index].orderStatusn.toString(): + pendingOrderList[index].orderStatus.toString(), + style: TextStyle( + color: Colors.white, + fontSize: 15.0, + fontWeight: FontWeight.bold, + ), + ) + ), + Container( + margin: EdgeInsets.all(8.0), + child: Column( +// crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Row( + children: [ + Container( + margin: EdgeInsets.only(left: 5), + child: Text(pendingOrderList[index].orderTotal.toString(), + style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold, + ), + ), + ), + Container( + margin: EdgeInsets.only(left: 5), + child: Text(TranslationBase.of(context).sar, + style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + SizedBox( + height: 5,), + Row( + children: [ + Container( + child: Text(pendingOrderList[index].orderItems.length.toString(), + style: TextStyle(fontSize: 14.0, + ), + ), + ), + Container( + margin: EdgeInsets.only(left: 5), + child: Text(TranslationBase.of(context).itemsNo, + style: TextStyle(fontSize: 14.0, + ), + ), + ), + ], + ), + ], + ), + ), + ], + ), + Divider( + color: Colors.grey[350], + height: 20, + thickness: 8, + indent: 0, + endIndent: 0, + ), + ], + ), + ), + + ); + } + ) + ], + ), + ) + : Container( + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SvgPicture.asset( + 'assets/images/pharmacy/empty_box.svg'), + Container( + margin: EdgeInsets.only(top: 10.0), + child: Text(TranslationBase.of(context).noOrder, + style: TextStyle( + fontSize: 16.0, + )), + ), + ], + ), + ), + ), + + ); + } + + Widget getCancelledOrder(OrderModelViewModel model){ + for(int i=0 ; i< model.order.length; i++){ + if( model.order[i].orderStatusId == 40 || model.order[i].orderStatusId == 996 + || model.order[i].orderStatusId == 200){ + cancelledOrderList.add(model.order[i]); + } + } + return Container( + child: model.order.length != 0 + ? SingleChildScrollView( + child: Column( + children: [ + ListView.builder( + scrollDirection: Axis.vertical, + shrinkWrap: true, + physics: ScrollPhysics(), + itemCount: cancelledOrderList.length, + itemBuilder: (context, index){ + return Container( + child: SingleChildScrollView( + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + margin: EdgeInsets.all( 8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Container( + margin: EdgeInsets.only(right: 5), + child: Text(TranslationBase.of(context).orderNumber, + style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold, + ), + ), + ), + Container( + child: Text(cancelledOrderList[index].id.toString(), + style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + SizedBox( + height: 5,), + Row( + children: [ + Container( + margin: EdgeInsets.only(right: 5), + child: Text(TranslationBase.of(context).orderDate, + style: TextStyle(fontSize: 14.0, + ), + ), + ), + Container( + child: Text(cancelledOrderList[index].createdOnUtc.toString().substring(0,11), + style: TextStyle(fontSize: 14.0, + ), + ), + ), + ], + ), + ], + ), + ), + Container( + margin: EdgeInsets.all(8.0), + child: InkWell( + onTap: () { + Navigator.push(context, + MaterialPageRoute(builder: (context) => OrderDetailsPage(orderModel:cancelledOrderList[index]))); + }, + child: SvgPicture.asset( + languageID == "ar" + ? 'assets/images/pharmacy/arrow_left.svg' + :'assets/images/pharmacy/arrow_right.svg', + height: 20, + width: 20,), + ), + ), + ], + ), + Divider( + color: Colors.grey[350], + height: 20, + thickness: 1, + indent: 0, + endIndent: 0, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + margin: EdgeInsets.only(left: 8, right: 8, top: 1, bottom: 8), + padding: EdgeInsets.only(left: 10.0, right: 10.0), + decoration: BoxDecoration( + border: Border.all( + color: Colors.red[900], + style: BorderStyle.solid, + width: 5.0, + ), + color: Colors.red[900], + borderRadius: BorderRadius.circular(30.0) + ), + child: cancelledOrderList[index].orderStatusId == 40 + ? Text( +// deliveredOrderList[0].orderStatus.toString().substring(12), + TranslationBase.of(context).cancelledOrder, + style: TextStyle( + color: Colors.white, + fontSize: 15.0, + fontWeight: FontWeight.bold, + ), + ) + : Text( + languageID == "ar" + ? cancelledOrderList[index].orderStatusn.toString(): + cancelledOrderList[index].orderStatus.toString(), + style: TextStyle( + color: Colors.white, + fontSize: 15.0, + fontWeight: FontWeight.bold, + ), + ) + ), + Container( + margin: EdgeInsets.only(left: 8, right: 8, top: 1, bottom: 8), + child: Column( +// crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Row( + children: [ + Container( + margin: EdgeInsets.only(left: 5), + child: Text(cancelledOrderList[index].orderTotal.toString(), + style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold, + ), + ), + ), + Container( + margin: EdgeInsets.only(left: 5), + child: Text(TranslationBase.of(context).sar, + style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + SizedBox( + height: 5,), + Row( + children: [ + Container( + child: Text(cancelledOrderList[index].orderItems.length.toString(), + style: TextStyle(fontSize: 14.0, + ), + ), + ), + Container( + margin: EdgeInsets.only(left: 5), + child: Text(TranslationBase.of(context).itemsNo, + style: TextStyle(fontSize: 14.0, + ), + ), + ), + ], + ), + ], + ), + ), + ], + ), + Divider( + color: Colors.grey[350], + height: 20, + thickness: 8, + indent: 0, + endIndent: 0, + ), + ], + ), + ), + + ); + } + ) + ], + ), + ) + : Container( + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SvgPicture.asset( + 'assets/images/pharmacy/empty_box.svg'), + Container( + margin: EdgeInsets.only(top: 10.0), + child: Text(TranslationBase.of(context).noOrder, + style: TextStyle( + fontSize: 16.0, + )), + ), + ], + ), + ), + ), + ); + } + + +} + + + + + + diff --git a/lib/pages/pharmacy/order/OrderDetails.dart b/lib/pages/pharmacy/order/OrderDetails.dart new file mode 100644 index 00000000..5438663d --- /dev/null +++ b/lib/pages/pharmacy/order/OrderDetails.dart @@ -0,0 +1,650 @@ +import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/order_model_view_model.dart'; +import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/pages/pharmacy/order/Order.dart'; +import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; +import 'package:diplomaticquarterapp/widgets/dialogs/confirm_dialog.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:diplomaticquarterapp/widgets//pharmacy/product_tile.dart'; +import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/order_model.dart'; +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:flutter/src/widgets/image.dart' as flutterImage; + +import 'package:diplomaticquarterapp/widgets/dialogs/confirm_dialog.dart'; +import 'package:diplomaticquarterapp/uitl/app_toast.dart'; +import 'package:provider/provider.dart'; + + + + +dynamic languageID; +class OrderDetailsPage extends StatefulWidget { + OrderModel orderModel; + + OrderDetailsPage({@required this.orderModel}); + + @override + _OrderDetailsPageState createState() => _OrderDetailsPageState(); +} + +class _OrderDetailsPageState extends State { + getLanguageID() async { + languageID = await sharedPref.getString(APP_LANGUAGE); + } + +// AppSharedPreferences sharedPref = AppSharedPreferences(); + String orderId = ""; + String customerId; + List orderList = []; + + List cancelledOrderList = []; + +// String orderId="3516"; + var model; + var isCancel = false; + var isRefund = false; + var dataIsCancel; + var dataIsRefund; + + @override + void initState() { + getLanguageID(); + super.initState(); + print(widget.orderModel.orderItems.length); + getCancelOrder(widget.orderModel.id); +// cancelOrderDetail(order) + } + + @override + Widget build(BuildContext context) { + return BaseView( + onModelReady: (model) => model.getOrderDetails(widget.orderModel.id), + builder: (_, model, wi) => AppScaffold( + appBarTitle: TranslationBase.of(context).orderDetail, + isShowAppBar: true, + isPharmacy: true, + body: Container( + color: Colors.white, + child: SingleChildScrollView( + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + margin: EdgeInsets.fromLTRB(10.0, 15.0, 1.0, 5.0), + child: Row( + children: [ + SvgPicture.asset( + 'assets/images/pharmacy/shipping_mark_icon.svg', + width: 28, + height: 28, + ), + Text( + TranslationBase.of(context).shippingAddress, + style: TextStyle( + fontSize: 13.0, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + Container( + margin: EdgeInsets.only(top: 15.0, right: 10.0), + padding: EdgeInsets.only(left: 11.0, right: 11.0), + decoration: BoxDecoration( + border: Border.all( + color: getStatusBackgroundColor(), + style: BorderStyle.solid, + width: 5.0, + ), + color: getStatusBackgroundColor(), + borderRadius: BorderRadius.circular(30.0)), + child: Text( + languageID == "ar" + ? widget.orderModel.orderStatusn.toString(): + widget.orderModel.orderStatus.toString().substring(12) , +// TranslationBase.of(context).delivered, + style: TextStyle( + color: Colors.white, + fontSize: 13.0, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + Container( + margin: EdgeInsets.only(left: 10.0, top: 13.0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + widget.orderModel.shippingAddress.firstName + .toString() + .substring(10) + + ' ' + + widget.orderModel.shippingAddress.lastName + .toString() + .substring(9), + style: TextStyle( + fontSize: 15.0, + fontWeight: FontWeight.bold, + ), + ), + ]), + ), + Container( + margin: EdgeInsets.fromLTRB(10.0, 5.0, 1.0, 5.0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + widget.orderModel.shippingAddress.address1 + .toString() + .substring(9), + style: TextStyle( + fontSize: 10.0, + fontWeight: FontWeight.bold, + color: Colors.grey, + ), + ),] + ), + ), + Container( + margin: EdgeInsets.fromLTRB(10.0, 5.0, 1.0, 5.0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + widget.orderModel.shippingAddress.address2 + .toString() + .substring(9) + + ' ' + + widget.orderModel.shippingAddress.country + .toString() + + ' ' + + widget.orderModel.shippingAddress.zipPostalCode + .toString(), + style: TextStyle( + fontSize: 10.0, + fontWeight: FontWeight.bold, + color: Colors.grey, + ), + ), + ]), + ), + Container( + child: Row( + children: [ + Container( + margin: EdgeInsets.fromLTRB(10.0, 5.0, 8.0, 5.0), + child: SvgPicture.asset( + 'assets/images/pharmacy/mobile_number_icon.svg', + height: 13, + ), + ), + Container( + margin: EdgeInsets.only(top: 5.0, bottom: 5.0), + child: Text( + widget.orderModel.shippingAddress.phoneNumber + .toString(), + style: TextStyle( + fontSize: 15.0, + ), + ), + ), + ], + ), + ), + Divider( + color: Colors.grey[350], + height: 20, + thickness: 1, + indent: 0, + endIndent: 0, + ), + Row( + children: [ + Container( + margin: EdgeInsets.fromLTRB(10.0, 10.0, 5.0, 10.0), + child: SvgPicture.asset( + 'assets/images/pharmacy/shipping_truck_icon.svg', + height: 20, + width: 20, + ), + ), + Container( + margin: EdgeInsets.all(10.0), + child: Text( + TranslationBase.of(context).shippedMethod, + style: TextStyle( + fontSize: 13.0, + fontWeight: FontWeight.bold, + ), + ), + ), + Container( + child: flutterImage.Image.asset( + widget.orderModel.shippingRateComputationMethodSystemName != + "Shipping.Aramex" + ? "assets/images/pharmacy_module/payment/LogoParmacyGreen.png" + : "assets/images/pharmacy_module/payment/aramex_shipping_logo.png", + fit: BoxFit.contain, +// height: 100, + width: 100, + ), + ), +// Container( +// child: widget.orderModel +// .shippingRateComputationMethodSystemName == +// "Shipping.FixedOrByWeight" +// ? Container( +// margin: EdgeInsets.only(bottom: 10.0, top: 10.0), +// child: SvgPicture.asset( +// 'assets/images/pharmacy_module/payment/hmg_shipping_logo.png', +// height: 25, +// width: 25, +// ), +// ) +// : Container( +// margin: EdgeInsets.only(bottom: 10.0, top: 10.0), +// child: SvgPicture.asset( +// 'assets/images/pharmacy_module/payment/aramex_shipping_logo.png', +// height: 25, +// width: 25, +// ), +// ), +// ), + ], + ), + Divider( + color: Colors.grey[350], + height: 20, + thickness: 8, + indent: 0, + endIndent: 0, + ), + Row( + children: [ + Container( + margin: EdgeInsets.all(10.0), + child: SvgPicture.asset( + 'assets/images/pharmacy/credit_card_icon.svg', + height: 20, + width: 20, + ), + ), + Container( + margin: EdgeInsets.only(bottom: 10.0, top: 10.0), + child: Text( + widget.orderModel.paymentName.toString().substring(12), + style: TextStyle( + fontSize: 13.0, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + Divider( + color: Colors.grey[350], + height: 20, + thickness: 8, + indent: 0, + endIndent: 0, + ), + Container( + padding: EdgeInsets.only(bottom: 15.0), + margin: EdgeInsets.only(left: 10.0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationBase.of(context).orderDetail, + style: TextStyle( + fontSize: 15.0, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + ListView.builder( + scrollDirection: Axis.vertical, + shrinkWrap: true, + physics: ScrollPhysics(), + itemCount:widget.orderModel.orderItems.length, + itemBuilder: (context, index){ + return Container( + child: productTile(productName: widget.orderModel.orderItems[index].product.name.toString(), + productPrice: widget.orderModel.orderItems[index].product.price.toString(), + productRate: widget.orderModel.orderItems[index].product.approvedRatingSum.toDouble(), + productReviews:widget.orderModel.orderItems[index].product.approvedTotalReviews, + totalPrice: "${(widget.orderModel.orderItems[index].product.price + * widget.orderModel.orderItems[index].quantity).toStringAsFixed(2)}", + qyt: widget.orderModel.orderItems[index].quantity.toString(), + isOrderDetails:true, + imgs: widget.orderModel.orderItems[index].product.images != null && + widget.orderModel.orderItems[index].product.images.length != 0 + ? widget.orderModel.orderItems[index].product.images [0].src.toString() + : null, + status: widget.orderModel.orderStatusId, + product: widget.orderModel.orderItems[index].product, + ), + ); + }), + + Container( + padding: EdgeInsets.only(bottom: 10.0), + margin: EdgeInsets.only(left: 10.0, top: 5.0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationBase.of(context).orderSummary, + style: TextStyle( + fontSize: 15.0, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + padding: EdgeInsets.only(bottom: 10.0), + margin: EdgeInsets.only(top: 5.0, left: 10.0), + child: Text( + TranslationBase.of(context).subtotal, + style: TextStyle( + fontSize: 13.0, + ), + ), + ), + Container( + padding: EdgeInsets.only(bottom: 10.0), + margin: EdgeInsets.fromLTRB(10.0, 5.0, 5.0, 5.0), + child: Row( + children: [ + Container( + margin: EdgeInsets.only(right: 5.0), + child: Text( + TranslationBase.of(context).sar, + style: TextStyle( + fontSize: 13.0, + ), + ), + ), + Text( + widget.orderModel.orderSubtotalExclTax.toString(), + style: TextStyle( + fontSize: 13.0, + ), + ), + ], + ), + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + padding: EdgeInsets.only(bottom: 10.0), + margin: EdgeInsets.only(top: 5.0, left: 10.0), + child: Text( + TranslationBase.of(context).shipping, + style: TextStyle( + fontSize: 13.0, + ), + ), + ), + Container( + padding: EdgeInsets.only(bottom: 10.0), + margin: EdgeInsets.fromLTRB(10.0, 5.0, 5.0, 5.0), + child: Row( + children: [ + Container( + margin: EdgeInsets.only(right: 5.0), + child: Text( + TranslationBase.of(context).sar, + style: TextStyle( + fontSize: 13.0, + ), + ), + ), + Text( + widget.orderModel.orderShippingExclTax.toString(), + style: TextStyle( + fontSize: 13.0, + ), + ), + ], + ), + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + padding: EdgeInsets.only(bottom: 10.0), + margin: EdgeInsets.only(top: 5.0, left: 10.0), + child: Text( + TranslationBase.of(context).vat, + style: TextStyle( + fontSize: 13.0, + ), + ), + ), + Container( + padding: EdgeInsets.only(bottom: 10.0), + margin: EdgeInsets.fromLTRB(10.0, 5.0, 5.0, 5.0), + child: Row( + children: [ + Container( + margin: EdgeInsets.only(right: 5.0), + child: Text( + TranslationBase.of(context).sar, + style: TextStyle( + fontSize: 13.0, + ), + ), + ), + Text( + widget.orderModel.orderTax.toString(), + style: TextStyle( + fontSize: 13.0, + ), + ), + ], + ), + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + margin: EdgeInsets.only(top: 5.0, left: 10.0), + child: Text( + TranslationBase.of(context).total, + style: TextStyle( + fontSize: 15.0, + fontWeight: FontWeight.bold, + ), + ), + ), + Container( + margin: EdgeInsets.fromLTRB(10.0, 5.0, 5.0, 5.0), + child: Row( + children: [ + Container( + margin: EdgeInsets.only(right: 5.0), + child: Text( + TranslationBase.of(context).sar, + style: TextStyle( + fontSize: 15.0, + fontWeight: FontWeight.bold, + ), + ), + ), + Text( + widget.orderModel.orderTotal.toString(), + style: TextStyle( + fontSize: 15.0, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + ], + ), + widget.orderModel.orderStatusId == 10 + ? InkWell( + onTap: () { + model.makeOrder(); + }, + child: Container( +// margin: EdgeInsets.only(top: 20.0), + height: 50.0, + color: Colors.transparent, + child: Container( + padding: EdgeInsets.only(left: 130.0, right: 130.0), + decoration: BoxDecoration( + border: Border.all( + color: Colors.green, + style: BorderStyle.solid, + width: 4.0), + color: Colors.green, + borderRadius: BorderRadius.circular(5.0)), + child: Center( + child: Text( + TranslationBase.of(context).payOnline, + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ), + ) + : Container(), +// getCancelOrder(canCancel, canRefund), + isCancel + ? InkWell( + onTap: () { + presentConfirmDialog(model, + widget.orderModel.id); //(widget.orderModel.id)); +// + }, + child: Container( +// padding: EdgeInsets.only(left: 13.0, right: 13.0, top: 5.0), + height: 50.0, + color: Colors.transparent, + child: Center( + child: Text( + TranslationBase.of(context).cancelOrder, + style: TextStyle( + color: Colors.red[900], + fontWeight: FontWeight.bold, + decoration: TextDecoration.underline), + ), + ), + ), + ) + : Container(), + ], + ), + ), + ), + ), + ); + } + + Color getStatusBackgroundColor() { + print(widget.orderModel.orderStatusId); +// if(orderStatus == 'delivered') + if (widget.orderModel.orderStatusId == 30 || + widget.orderModel.orderStatusId == 997 || + widget.orderModel.orderStatusId == 994) + return Colors.blue[700]; + else if (widget.orderModel.orderStatusId == 20 || + widget.orderModel.orderStatusId == 995 || + widget.orderModel.orderStatusId == 998 || + widget.orderModel.orderStatusId == 999) + return Colors.green; + else if (widget.orderModel.orderStatusId == 10) + return Colors.orange[300]; + else if (widget.orderModel.orderStatusId == 40 || + widget.orderModel.orderStatusId == 996 || + widget.orderModel.orderStatusId == 200) return Colors.red[900]; + } + + getCancelOrder(dataIsCancel) { + if (widget.orderModel.canCancel && widget.orderModel.canRefund) { + setState(() { + isCancel = true; + isRefund = false; + }); + } else if (widget.orderModel.canCancel) { + setState(() { + isCancel = true; + isRefund = false; + }); + } else if (widget.orderModel.canRefund) { + setState(() { + isCancel = false; + isRefund = true; + }); + } else { + setState(() { + isCancel = false; + isRefund = false; + }); + } + } + +// .getCanceledOrder + presentConfirmDialog(cancelFunction, id) { + ConfirmDialog dialog = new ConfirmDialog( + context: context, + confirmMessage: TranslationBase.of(context).confirmCancellation, + okText: TranslationBase.of(context).confirm, + cancelText: TranslationBase.of(context).cancel_nocaps, + okFunction: () => + cancelFunction.getCanceledOrder(id, context).then((value) { + print(":D"); + print(value); +// Navigator.pop(context); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => OrderPage( + customerID: widget.orderModel.customerId.toString())), + ); + }), + cancelFunction: () => {}); + dialog.showAlertDialog(context); + } + + getCanceledOrder(order) { + Navigator.pop(context); + if (widget.orderModel.canCancel && widget.orderModel.canRefund == false) { +// getCanceledOrder(order); +// AppToast.showSuccessToast(message: "Request Sent Successfully"); +// Navigator.push(context, +// MaterialPageRoute(builder: (context) => OrderPage())); + + } + } +} diff --git a/lib/pages/pharmacy/order/ProductReview.dart b/lib/pages/pharmacy/order/ProductReview.dart new file mode 100644 index 00000000..4d09191c --- /dev/null +++ b/lib/pages/pharmacy/order/ProductReview.dart @@ -0,0 +1,367 @@ +import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/order_model_view_model.dart'; +import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/pages/pharmacy/profile/profile.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:diplomaticquarterapp/core/model/pharmacies/order_model.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:intl/intl.dart'; +import 'package:rating_bar/rating_bar.dart'; +import 'package:flutter/src/widgets/image.dart' as flutterImage; + +class ProductReviewPage extends StatefulWidget { + final Product product; + + ProductReviewPage(this.product); + + @override + _ProductReviewPageState createState() => _ProductReviewPageState(); +} + +class _ProductReviewPageState extends State { + AppSharedPreferences sharedPref = AppSharedPreferences(); + double currentRating = 0; + String reviewText = ""; + TextEditingController _reviewController = new TextEditingController(); + bool finishReview = false; + + @override + Widget build(BuildContext context) { + double ratingValue = double.parse("${widget.product.approvedRatingSum}"); + return BaseView( + builder: (_, model, wi) => AppScaffold( + appBarTitle: TranslationBase.of(context).writeReview, + isShowAppBar: true, + isPharmacy: true, + body: Container( + color: Colors.white, + child: !finishReview ? SingleChildScrollView( + child: Column( + children: [ + Container( + margin: EdgeInsets.symmetric(vertical: 8, horizontal: 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + widget.product.images != null + ? flutterImage.Image.network( + widget.product.images[0].src, + fit: BoxFit.cover, + height: 80, + ) + : flutterImage.Image.asset( + "assets/images/no_image.png", + fit: BoxFit.cover, + height: 80, + ), + Expanded( + child: Container( + child: Column( + children: [ + Container( + margin: EdgeInsets.all(5), + child: Align( + alignment: Alignment.topLeft, + child: RichText( + text: TextSpan( + text: widget.product.name, + style: TextStyle( + color: Colors.black, + fontSize: 14, + fontWeight: FontWeight.normal), + ), + ), + ), + ), + Container( + margin: EdgeInsets.all(5), + child: Align( + alignment: Alignment.topLeft, + child: RichText( + text: TextSpan( + text: + '${widget.product.price} ${TranslationBase.of(context).sar}', + style: TextStyle( + fontWeight: FontWeight.bold, + color: Colors.black, + fontSize: 13), + ), + ), + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + child: Align( + alignment: Alignment.topLeft, + child: RatingBar.readOnly( + initialRating: ratingValue, + size: 15.0, + filledColor: Colors.yellow[700], + emptyColor: Colors.grey[500], + isHalfAllowed: true, + halfFilledIcon: Icons.star_half, + filledIcon: Icons.star, + emptyIcon: Icons.star, + ), + ), + ), + SizedBox( + width: 20, + ), + Container( + child: Align( + child: RichText( + text: TextSpan( + text: + '(${widget.product.approvedTotalReviews} reviews)', + style: TextStyle( + fontWeight: FontWeight.bold, + color: Colors.grey, + fontSize: 13), + ), + ), + ), + ), + ], + ), + ], + ), + ), + ), + ]), + ), + Divider( + color: Colors.grey[350], + height: 20, + thickness: 8, + indent: 0, + endIndent: 0, + ), + Container( + margin: EdgeInsets.only(top: 12.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisSize: MainAxisSize.max, + children: [ + RatingBar( + size: 40.0, + filledColor: Colors.yellow[700], + emptyColor: Colors.grey[500], + isHalfAllowed: true, + halfFilledIcon: Icons.star_half, + filledIcon: Icons.star, + emptyIcon: Icons.star, + onRatingChanged: (rating) { + currentRating = rating; + }, + ), + ], + ), + ), + Container( + padding: EdgeInsets.symmetric(horizontal: 16, vertical: 16), + child: Column( + children: [ + TextFormField( + controller: _reviewController, + maxLines: 6, + minLines: 4, + decoration: InputDecoration( + border: InputBorder.none, + hintText: 'Tell us more about product!', + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(5.0), + borderSide: + BorderSide(width: 1, color: Colors.grey[400]), + ), + enabledBorder: OutlineInputBorder( + borderRadius: + BorderRadius.all(Radius.circular(5.0)), + borderSide: + BorderSide(color: Colors.grey[400], width: 1), + ), + ), + onChanged: (value) { + setState(() { + reviewText = value; + }); + }, + textAlign: TextAlign.start, + textAlignVertical: TextAlignVertical.top, + ), + ], + ), + ), + InkWell( + onTap: reviewText != null && reviewText != "" + ? () { + model + .makeReview( + widget.product, ratingValue, reviewText) + .then((value) { + setState(() { + finishReview = true; + }); + }); + } + : null, + child: Container( + margin: EdgeInsets.symmetric(vertical: 8, horizontal: 16), + height: 50.0, + width: 400.0, + color: Colors.transparent, + child: Container( + decoration: BoxDecoration( + border: Border.all( + color: _reviewController.value.text != null && + _reviewController.value.text != "" + ? Colors.yellow[700] + : Color(0xFFf5d69c), + style: BorderStyle.solid, + width: 1.0), + color: _reviewController.value.text != null && + _reviewController.value.text != "" + ? Colors.yellow[700] + : Color(0xFFf5d69c), + borderRadius: BorderRadius.circular(5.0)), + child: Center( + child: Text( + TranslationBase.of(context).shareReview, + style: TextStyle( + color: Colors.white, + fontSize: 16.0, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ), + ), + ], + ), + ) : getReviewedProduct(), + ), + ), + ); + } + + //new screen is showing after submitting the review + Widget getReviewedProduct() { + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset( + 'assets/images/pharmacy/check_icon.svg', + width: 28, + height: 28, + ), + Container( + margin: EdgeInsets.symmetric(horizontal: 8), + child: Text( + TranslationBase.of(context).reviewSuccessful, + style: TextStyle( + fontSize: 20.0, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + Container( + margin: EdgeInsets.symmetric(horizontal: 8, vertical: 8), + child: Text( + TranslationBase.of(context).reviewShared, + style: TextStyle( + fontSize: 15.0, + ), + ), + ), + Container( + margin: EdgeInsets.only(bottom: 30.0, top: 30.0), + child: SvgPicture.asset( + 'assets/images/pharmacy/success_review_icon.svg', + width: 100, + height: 100, + ), + ), + Container( + margin: EdgeInsets.symmetric(horizontal: 16), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + SvgPicture.asset( + 'assets/images/pharmacy/quote_start.svg', + width: 15, + height: 15, + ), + ], + ), + Text( + TranslationBase.of(context).reviewComment, + style: TextStyle( + fontSize: 15.0, + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + SvgPicture.asset( + 'assets/images/pharmacy/quote_end.svg', + width: 15, + height: 15, + ), + ], + ), + ], + ), + ), + Container( + margin: EdgeInsets.only(top: 20.0), + child: InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute(builder: (context) { + return PharmacyProfilePage(); + }), + ); + }, + child: Container( + height: 50.0, + color: Colors.transparent, + child: Container( + decoration: BoxDecoration( + border: Border.all( + color: Colors.orange, + style: BorderStyle.solid, + width: 1.0), + color: Colors.transparent, + borderRadius: BorderRadius.circular(5.0)), + child: Center( + child: Text( + TranslationBase.of(context).backMyAccount, + style: TextStyle( + color: Colors.orange, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ), + ), + ), + ], + ); + } + +} diff --git a/lib/pages/pharmacy/pharmacyAddresses/AddAddress.dart b/lib/pages/pharmacy/pharmacyAddresses/AddAddress.dart new file mode 100644 index 00000000..7569ed43 --- /dev/null +++ b/lib/pages/pharmacy/pharmacyAddresses/AddAddress.dart @@ -0,0 +1,79 @@ +import 'package:diplomaticquarterapp/core/model/pharmacies/Addresses.dart'; +import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/PharmacyAddressesViewModel.dart'; +import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/borderedButton.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:diplomaticquarterapp/widgets/pickupLocation/PickupLocationFromMap.dart'; +import 'package:flutter/material.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:geolocator/geolocator.dart'; +import 'package:google_maps_place_picker/google_maps_place_picker.dart'; + +class AddAddressPage extends StatefulWidget { + final Addresses editedAddress; + final Function(PickResult) onPick; + + AddAddressPage(this.editedAddress, this.onPick); + + @override + _AddAddressPageState createState() => _AddAddressPageState(); +} + +class _AddAddressPageState extends State { + double _latitude; + double _longitude; + + @override + void initState() { + super.initState(); + if (widget.editedAddress != null && + widget.editedAddress.latLong != null && + widget.editedAddress.latLong != "") { + List latLng = widget.editedAddress.latLong.split(","); + _latitude = double.parse(latLng[0]); + _longitude = double.parse(latLng[1]); + } else { + _getCurrentLocation(); + } + } + + _getCurrentLocation() async { + await Geolocator.getLastKnownPosition().then((value) { + _latitude = value.latitude; + _longitude = value.longitude; + }).catchError((e) { + _longitude = 0; + _latitude = 0; + }); + } + + @override + Widget build(BuildContext context) { + final mediaQuery = MediaQuery.of(context); + final height = mediaQuery.size.height - + 60 - + mediaQuery.padding.top; + + return BaseView( + builder: (_, model, wi) => AppScaffold( + appBarTitle: TranslationBase.of(context).changeAddress, + isShowAppBar: true, + isPharmacy: true, + backgroundColor: Colors.white, + body: Container( + height: height * 1, + child: PickupLocationFromMap( + latitude: _latitude, + longitude: _longitude, + isWithAppBar: false, + buttonColor: Color(0xFF5AB145), + buttonLabel: TranslationBase.of(context).save, + onPick: (value) { + widget.onPick(value); + }, + ), + ), + ), + ); + } +} diff --git a/lib/pages/pharmacy/pharmacyAddresses/PharmacyAddresses.dart b/lib/pages/pharmacy/pharmacyAddresses/PharmacyAddresses.dart new file mode 100644 index 00000000..340e2bd8 --- /dev/null +++ b/lib/pages/pharmacy/pharmacyAddresses/PharmacyAddresses.dart @@ -0,0 +1,313 @@ +import 'package:diplomaticquarterapp/core/model/pharmacies/Addresses.dart'; +import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/PharmacyAddressesViewModel.dart'; +import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/uitl/app_toast.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/borderedButton.dart'; +import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; +import 'package:diplomaticquarterapp/widgets/dialogs/confirm_dialog.dart'; +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:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/pages/pharmacy/pharmacyAddresses/AddAddress.dart'; + +class PharmacyAddressesPage extends StatefulWidget { + @override + _PharmacyAddressesState createState() => _PharmacyAddressesState(); +} + +class _PharmacyAddressesState extends State { + void navigateToAddressPage( + BuildContext ctx, PharmacyAddressesViewModel model, Addresses address) { + Navigator.push( + ctx, + FadePage( + page: AddAddressPage(address, (pickResult) { + model.addEditAddress(pickResult, address); + }))); + } + + Widget build(BuildContext context) { + final mediaQuery = MediaQuery.of(context); + final height = mediaQuery.size.height - 60 - mediaQuery.padding.top; + + return BaseView( + onModelReady: (model) => model.getAddressesList(), + builder: (_, model, wi) => AppScaffold( + appBarTitle: TranslationBase.of(context).changeAddress, + isShowAppBar: true, + isPharmacy: true, + baseViewModel: model, + backgroundColor: Colors.white, + body: Container( + height: height * 0.90, + child: SingleChildScrollView( + child: Column( + children: [ + ...List.generate( + model.addresses != null ? model.addresses.length : 0, + (index) => AddressItemWidget( + model, + model.addresses[index], + () { + setState(() { + model.setSelectedAddressIndex(index); + }); + }, + model.selectedAddressIndex == index, + (address) { + navigateToAddressPage(context, model, address); + }), + ), + Container( + color: Colors.white, + margin: EdgeInsets.all(8), + child: BorderedButton( + TranslationBase.of(context).addAddress, + hasBorder: true, + borderColor: Color(0xFF0fca6d), + textColor: Color(0xFF0fca6d), + fontWeight: FontWeight.bold, + backgroundColor: Colors.white, + fontSize: 14, + vPadding: 12, + hasShadow: true, + handler: () { + navigateToAddressPage(context, model, null); + }, + ), + ), + ], + ), + ), + ), + bottomSheet: Container( + height: height * 0.10, + color: Colors.white, + child: Column( + children: [ + Divider( + color: Colors.grey.shade300, + height: 1, + thickness: 1, + indent: 0, + endIndent: 0, + ), + Container( + padding: EdgeInsets.symmetric(horizontal: 12, vertical: 8), + child: BorderedButton( + TranslationBase.of(context).confirmAddress, + hasBorder: true, + borderColor: Color(0xFF5AB145), + textColor: Colors.white, + fontWeight: FontWeight.bold, + backgroundColor: Color(0xFF5AB145), + fontSize: 14, + vPadding: 12, + handler: () { + model.saveSelectedAddressLocally( + model.addresses[model.selectedAddressIndex]); + Navigator.pop( + context, model.addresses[model.selectedAddressIndex]); + }, + ), + ), + ], + ), + ), + ), + ); + } +} + +class AddressItemWidget extends StatelessWidget { + final PharmacyAddressesViewModel model; + final Addresses address; + final Function selectAddress; + final bool isSelected; + final Function(Addresses) onTabEditAddress; + + AddressItemWidget(this.model, this.address, this.selectAddress, + this.isSelected, this.onTabEditAddress); + + @override + Widget build(BuildContext context) { + return Container( + color: Colors.white, + child: Padding( + padding: EdgeInsets.symmetric(vertical: 8, horizontal: 0), + child: Column( + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + InkWell( + onTap: selectAddress, + child: Container( + margin: EdgeInsets.only(left: 16, right: 16), + child: Padding( + padding: const EdgeInsets.all(5.0), + child: Container( + decoration: new BoxDecoration( + color: !isSelected ? Colors.white : Colors.green, + shape: BoxShape.circle, + border: Border.all( + color: Colors.grey, + style: BorderStyle.solid, + width: 1.0), + ), + child: Padding( + padding: const EdgeInsets.all(0.0), + child: Icon( + Icons.check, + color: isSelected + ? Colors.white + : Colors.transparent, + size: 25, + ), + ), + ), + ), + ), + ), + ], + ), + Expanded( + child: Container( + child: Container( + margin: + EdgeInsets.symmetric(vertical: 12, horizontal: 12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 0), + child: Texts( + "${address.firstName} ${address.lastName}", + fontSize: 14, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 4), + child: Texts( + "${address.address1} ${address.address2} ${address.address2},, ${address.city}, ${address.country} ${address.zipPostalCode}", + fontSize: 12, + fontWeight: FontWeight.normal, + color: Colors.grey.shade500, + ), + ), + Row( + children: [ + Container( + margin: const EdgeInsets.only(right: 8), + child: Icon( + Icons.phone, + size: 20, + color: Colors.black, + ), + ), + Texts( + "${address.phoneNumber}", + fontSize: 14, + fontWeight: FontWeight.bold, + color: Colors.grey, + ), + ], + ), + SizedBox( + height: 10, + ), + Container( + height: 25, + child: Row( + children: [ + BorderedButton( + TranslationBase.of(context).edit, + backgroundColor: Colors.transparent, + hasBorder: true, + borderColor: Colors.transparent, + textColor: Color(0x990000FF), + handler: () { + onTabEditAddress(address); + }, + icon: Icon( + Icons.edit, + size: 15, + color: Color(0x990000FF), + ), + ), + Padding( + padding: + const EdgeInsets.symmetric(horizontal: 8), + child: SizedBox( + child: Container( + width: 1, + color: Colors.grey.shade400, + ), + ), + ), + BorderedButton( + TranslationBase.of(context).delete, + backgroundColor: Colors.transparent, + hasBorder: true, + borderColor: Colors.transparent, + textColor: Color(0x99FF0000), + handler: () { + ConfirmDialog dialog = new ConfirmDialog( + context: context, + title: "Are you sure want to delete", + confirmMessage: + "${address.address1} ${address.address2}", + okText: + TranslationBase.of(context).delete, + cancelText: TranslationBase.of(context) + .cancel_nocaps, + okFunction: () => { + model + .deleteAddresses(address) + .then((_) { + ConfirmDialog.closeAlertDialog( + context); + AppToast.showErrorToast( + message: + "Address has been deleted"); + }) + }, + cancelFunction: () => {}); + dialog.showAlertDialog(context); + }, + icon: Icon( + Icons.delete, + size: 15, + color: Color(0x99FF0000), + ), + ), + ], + ), + ), + ], + ), + ), + ), + ), + ], + ), + Divider( + color: Colors.grey.shade200, + height: 10, + thickness: 10, + indent: 0, + endIndent: 0, + ), + ], + ), + ), + ); + } +} diff --git a/lib/pages/pharmacy/profile/profile.dart b/lib/pages/pharmacy/profile/profile.dart new file mode 100644 index 00000000..ba742179 --- /dev/null +++ b/lib/pages/pharmacy/profile/profile.dart @@ -0,0 +1,626 @@ +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/order_model_view_model.dart'; +import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; +import 'package:diplomaticquarterapp/pages/ContactUs/LiveChat/livechat_page.dart'; +import 'package:diplomaticquarterapp/pages/ContactUs/findus/findus_page.dart'; +import 'package:diplomaticquarterapp/pages/DrawerPages/family/my-family.dart'; +import 'package:diplomaticquarterapp/pages/login/welcome.dart'; +import 'package:diplomaticquarterapp/pages/medical/prescriptions/prescriptions_home_page.dart'; +import 'package:diplomaticquarterapp/pages/pharmacies/screens/lakum-main-page.dart'; +import 'package:diplomaticquarterapp/pages/pharmacies/screens/lakum-terms-conditions-page.dart'; +import 'package:diplomaticquarterapp/pages/pharmacies/screens/pharmacy-terms-conditions-page.dart'; +import 'package:diplomaticquarterapp/pages/pharmacies/wishlist.dart'; +import 'package:diplomaticquarterapp/pages/pharmacy/order/Order.dart'; +import 'package:diplomaticquarterapp/pages/pharmacy/pharmacyAddresses/PharmacyAddresses.dart'; +import 'package:diplomaticquarterapp/uitl/app_toast.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/avatar/large_avatar.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:diplomaticquarterapp/pages/base/base_view.dart'; + +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:diplomaticquarterapp/config/config.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/order_model.dart'; +import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; +import 'package:diplomaticquarterapp/pages/pharmacies/my_reviews.dart'; +import 'package:diplomaticquarterapp/pages/pharmacies/compare.dart'; + +dynamic languageID ; +class PharmacyProfilePage extends StatefulWidget { + @override + _ProfilePageState createState() => _ProfilePageState(); +} + +class _ProfilePageState extends State { + AppSharedPreferences sharedPref = AppSharedPreferences(); + String page_id = ""; + + AuthenticatedUser user; + bool isLogin = false; + String firstName; + String customerId; + String lastName, mobileNo, identificationNo; + int languageId; + + _ProfilePageState({this.customerId }); + + getLanguageID() async { + languageID = await sharedPref.getString(APP_LANGUAGE); + } + getCustomer() async { + String custID; + custID = await sharedPref.getString(PHARMACY_CUSTOMER_ID); + setState(() { + customerId = custID; + }); + print("customer Id is"+ customerId); + return customerId; + } + + getUser() async { + var userData = await sharedPref.getObject(USER_PROFILE); + if (userData != null){ user = AuthenticatedUser.fromJson(userData); + setState(() { + firstName = user.firstName.toString(); + print("this is user" + user.firstName.toString()); + print("this is user" + user.firstNameN.toString()); + }); + } else{ + if(userData == null){ + Navigator.push(context, + MaterialPageRoute(builder: (context) => + WelcomeLogin()), + ); + } + } + +// this.isLogin = user != null; + } + void initState() { + getCustomer(); + getLanguageID(); + super.initState(); + getUser(); + } + + @override + Widget build(BuildContext context) { + return BaseView( + onModelReady: (model) => model.getOrder(customerId, page_id), + builder: (_, model, wi) => AppScaffold( + appBarTitle: TranslationBase.of(context).myAccount, + isShowAppBar:false, + isShowDecPage: false, + isPharmacy: true, + body: user != null ? Container( + child: SingleChildScrollView( + child: Column( + children: [ + Container( + child: Row( + children: [ + Container( + padding: EdgeInsets.only( + top: 20.0, + left: 10.0, + right: 10.0, + bottom: 10.0, + ), + child: LargeAvatar( + name: "profile", + url: '', + ), + ), + Container( + child: Column( + children: [ + Text( + TranslationBase.of(context).welcome, + style: TextStyle(fontSize: 14.0, + fontWeight: FontWeight.bold, + color:Colors.grey + ), + ), + Text( + languageID == "ar" + ? user.firstNameN.toString()+ " " + user.lastNameN.toString() + : user.firstName.toString()+ " " + user.lastName.toString(), + style: TextStyle( + fontSize: 14.0, fontWeight: FontWeight.bold), + ), + ], + ), + + ) + ], + ), + ), + Divider( + color: Colors.grey[350], + height: 20, + thickness: 5, + indent: 0, + endIndent: 0, + ), + SizedBox( + height: 15, + ), + Container( + child: Row( + children: [ + Expanded( + child: InkWell( + onTap: () { + if(customerId == null){ + AppToast.showErrorToast(message: "Customer not found"); + return; + } + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => OrderPage(customerID: customerId))); + }, + child: Column( + children: [ +// Image(image: AssetImage('assets/images/pharmacy/orders_icon.svg')), + SvgPicture.asset( + 'assets/images/pharmacy/orders_icon.svg', + width: 50, + height: 50, + ), + SizedBox( + height: 5, + ), + Text( + TranslationBase.of(context).orders, + style: TextStyle( + fontSize: 13.0, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + ), + Expanded( + child: InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => LakumMainPage())); + }, + child: Column( + children: [ + SvgPicture.asset( + 'assets/images/pharmacy/lakum_icon.svg', + width: 50, + height: 50, + ), + SizedBox( + height: 5, + ), + Text( + TranslationBase.of(context).lakum, + style: TextStyle( + fontSize: 13.0, fontWeight: FontWeight.bold), + ), + ], + ), + ), + ), + Expanded( + child: InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => WishlistPage())); + }, + child: Column( + children: [ + SvgPicture.asset( + 'assets/images/pharmacy/wishlist_icon.svg', + width: 50, + height: 50, + + ),SizedBox( + height: 5, + ), + Text( + TranslationBase.of(context).wishlist, + style: TextStyle( + fontSize: 13.0, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + ), + Expanded( + child: InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => MyReviewsPage())); + },child: Column( + children: [ + SvgPicture.asset( + 'assets/images/pharmacy/review_icon.svg', + width: 50, + height: 50, + ), + SizedBox( + height: 5, + ), + Text( + TranslationBase.of(context).reviews, + style: TextStyle( + fontSize: 13.0, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + ), + ], + )), + SizedBox( + height: 15, + ), + Divider( + color: Colors.grey[350], + height: 20, + thickness: 5, + indent: 0, + endIndent: 0, + ), + SizedBox( + height: 10, + ), + Container( + padding: EdgeInsets.only(left: 10.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationBase.of(context).myAccount, + style: TextStyle( + fontSize: 16.0, fontWeight: FontWeight.bold), + ), + SizedBox( + height: 10, + ), + Divider( + color: Colors.grey, + height: 20, + ), + InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => HomePrescriptionsPage())); + }, + child: Row( + children: [ + SvgPicture.asset( + 'assets/images/pharmacy/my_prescription_icon.svg', + width: 28, + height: 28, + ), + SizedBox( + width: 15, + ), + Text( + TranslationBase.of(context).myPrescription, + style: TextStyle( + fontSize: 13.0, + ), + ), + ], + ), + ), + SizedBox( + height: 5, + ), + Divider( + color: Colors.grey, + height: 20, + ), + InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => ComparePage())); + }, + child: Row( + children: [ + Image.asset('assets/images/pharmacy/compare.png', + width: 35, height: 35), + SizedBox( + width: 15, + ), + Text( + TranslationBase.of(context).compare, + style: TextStyle( + fontSize: 13.0, + ), + ), + ], + ), + ), + SizedBox( + height: 5, + ), + Divider( + color: Colors.grey, + height: 20, + ), + InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => HomePrescriptionsPage())); + }, + child: Row( + children: [ + SvgPicture.asset( + 'assets/images/pharmacy/medication_refill_icon.svg', + width: 30, + height: 30, + ), + SizedBox( + width: 20, + ), + Text( + TranslationBase.of(context).medicationsRefill, + style: TextStyle( + fontSize: 13.0, + ), + ), + ], + ), + ), + SizedBox( + height: 5, + ), + Divider( + color: Colors.grey, + height: 20, + ), + InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => MyFamily())); + }, + child: Row( + children: [ + SvgPicture.asset( + 'assets/images/pharmacy/my_family_icon.svg', + width: 20, + height: 20, + ), + SizedBox( + width: 20, + ), + Text( + TranslationBase.of(context).family, + style: TextStyle( + fontSize: 13.0, + ), + ), + ], + ), + ), + SizedBox( + height: 5, + ), + Divider( + color: Colors.grey, + height: 20, + ), + InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => PharmacyAddressesPage())); + }, + child: Row( + children: [ + SvgPicture.asset( + 'assets/images/pharmacy/shipping_addresses_icon.svg', + width: 30, + height: 30, + ), + SizedBox( + width: 20, + ), + Text( + TranslationBase.of(context).shippingAddresses, + style: TextStyle( + fontSize: 13.0, + ), + ), + ], + ), + ), + SizedBox( + height: 5, + ), + Divider( + color: Colors.grey, + height: 20, + ), + InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => PharmacyTermsConditions())); + }, + child: Row( + children: [ + Image.asset('assets/images/pharmacy/terms.png', + width: 25, + height: 25, + ), + + SizedBox( + width: 10, + ), + Text( + TranslationBase.of(context).conditionsHMG, + style: TextStyle( + fontSize: 13.0, + ), + ), + ], + ), + ), + SizedBox( + height: 5, + ), + Divider( + color: Colors.grey, + height: 20, + ), + InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => LakumTermsConditions(this.identificationNo, this.firstName, this.lastName, + this.mobileNo, this.languageId))); + }, + child: Row( + children: [ + Image.asset('assets/images/pharmacy/terms.png', + width: 25, + height: 25, + ), +// IconButton(icon: Icon(Icons.error_outline), iconSize: 30, +// color: Colors.black,), + SizedBox( + width: 10, + ), + Text( + TranslationBase.of(context).conditions, + style: TextStyle( + fontSize: 13.0, + ), + ), + ], + ), + ), + ], + ), + ), + SizedBox( + height: 10, + ), + Divider( + color: Colors.grey[350], + height: 20, + thickness: 5, + indent: 0, + endIndent: 0, + ), + SizedBox( + height: 10, + ), + Container( + padding: EdgeInsets.only(left: 10.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationBase.of(context).reachUs, + style: TextStyle( + fontSize: 16.0, fontWeight: FontWeight.bold), + ), + SizedBox( + height: 5, + ), + Divider( + color: Colors.grey, + height: 20, + ), + InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => LiveChatPage())); + }, + child: Row( + children: [ + SvgPicture.asset( + 'assets/images/pharmacy/contact_us_icon.svg', + width: 20, + height: 20, + ), + SizedBox( + width: 20, + ), + Text( + TranslationBase.of(context).contactUs, + style: TextStyle(fontSize: 13.0), + ), + ], + ), + ), + SizedBox( + height: 5, + ), + Divider( + color: Colors.grey, + height: 20, + ), + InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => FindUsPage())); + }, + child: Row( + children: [ + SvgPicture.asset( + 'assets/images/pharmacy/our_locations_icon.svg', + width: 30, + height: 30, + ), + SizedBox( + width: 20, + ), + Text( + TranslationBase.of(context).ourLocations, + style: TextStyle(fontSize: 13.0), + ), + ], + ), + ) + ], + ), + ) + ], + ), + ), + ) : Container(), + )); + }} + + + + diff --git a/lib/pages/pharmacy_categorise.dart b/lib/pages/pharmacy_categorise.dart new file mode 100644 index 00000000..06bba8c3 --- /dev/null +++ b/lib/pages/pharmacy_categorise.dart @@ -0,0 +1,239 @@ +import 'dart:convert'; + +import 'package:barcode_scan_fix/barcode_scan.dart'; +import 'package:charts_flutter/flutter.dart'; +import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; +import 'package:diplomaticquarterapp/core/viewModels/pharmacy_categorise_view_model.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/pages/landing/landing_page_pharmcy.dart'; +import 'package:diplomaticquarterapp/pages/parent_categorise_page.dart'; +import 'package:diplomaticquarterapp/uitl/app_toast.dart'; +import 'package:diplomaticquarterapp/uitl/utils.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'; +import 'base/base_view.dart'; +import 'final_products_page.dart'; + +class PharmacyCategorisePage extends StatefulWidget { + @override + _PharmacyCategorisePageState createState() => _PharmacyCategorisePageState(); +} + +class _PharmacyCategorisePageState extends State { + String idCategorise; + + @override + Widget build(BuildContext context) { + ProjectViewModel projectViewModel = Provider.of(context); + return BaseView( + onModelReady: (model) => model.getCategorise(), + builder: (BuildContext context, PharmacyCategoriseViewModel model, + Widget child) => + AppScaffold( + isShowDecPage: false, + baseViewModel: model, + body: Column( + children: [ + Container( + height: 400, + margin: EdgeInsets.only(bottom: 22), + child: GridView.builder( + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + crossAxisSpacing: 0.5, + mainAxisSpacing: 1.0, + childAspectRatio: 3.2, + ), + itemCount: model.categorise.length, + itemBuilder: (BuildContext context, int index) { + return Padding( + padding: EdgeInsets.all(4.0), + child: InkWell( + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(5), + color: Colors.grey.withOpacity(0.24), + ), + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 10.0), + child: Texts( + projectViewModel.isArabic + ? model.categorise[index].namen + : model.categorise[index].name, + fontWeight: FontWeight.w600, + ), + ), + ), + onTap: () => { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + model.categorise[index].id != '12' + ? ParentCategorisePage( + id: model.categorise[index].id, + titleName: model.categorise[index].name, + ) + : FinalProductsPage( + id: model.categorise[index].id, + ), + ), + ), + }, + ), + ); + }, + ), + ), + Container( + height: 140, + child: Column( + children: [ + Divider( + height: 2.0, + thickness: 1.0, + color: Colors.black12.withOpacity(0.14)), + SizedBox( + height: 10.0, + ), + Row( + children: [ + Expanded( + child: Padding( + padding: EdgeInsets.all(4.0), + child: Container( + height: 50.0, + width: 55.0, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(5.0), + color: Colors.green.shade300.withOpacity(0.34), + ), + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 10.0), + child: Texts( + projectViewModel.isArabic + ? 'الاكثر مبيعا' + : 'Best Sellers', + fontWeight: FontWeight.w600, + ), + ), + ), + ), + ), + Expanded( + child: Padding( + padding: EdgeInsets.all(4.0), + child: Container( + height: 50.0, + width: 55.0, + decoration: BoxDecoration( + color: Colors.orangeAccent.shade200 + .withOpacity(0.34), + borderRadius: BorderRadius.circular(5.0), + ), + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 10.0), + child: Texts( + projectViewModel.isArabic + ? 'الاكثر مشاهدة' + : 'Most Viewed', + fontWeight: FontWeight.w600, + ), + ), + ), + ), + ), + ], + ), + Row( + children: [ + Expanded( + child: Padding( + padding: EdgeInsets.all(4.0), + child: Container( + height: 50.0, + width: 55.0, + decoration: BoxDecoration( + color: Colors.blue.shade200.withOpacity(0.34), + borderRadius: BorderRadius.circular(5.0), + ), + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 10.0), + child: Texts( + projectViewModel.isArabic + ? 'منتجات جديدة' + : 'New Products', + fontWeight: FontWeight.w600, + ), + ), + ), + ), + ), + Expanded( + child: Padding( + padding: EdgeInsets.all(4.0), + child: InkWell( + onTap: () { + _scanQrAndGetPatient(context, model); + }, + child: Container( + height: 50.0, + width: 55.0, + decoration: BoxDecoration( + color: + Colors.purple.shade200.withOpacity(0.34), + borderRadius: BorderRadius.circular(5.0), + ), + child: Padding( + padding: + EdgeInsets.symmetric(horizontal: 10.0), + child: Texts( + projectViewModel.isArabic + ? 'شوهد مؤخرا' + : 'Recently Viewed', + fontWeight: FontWeight.w600, + ), + ), + ), + ), + ), + ), + ], + ), + ], + )), + ], + ), + ), + ); + } + + _scanQrAndGetPatient( + BuildContext context, + PharmacyCategoriseViewModel model, + ) async { + //TODO fix it + /// When give qr we will change this method to get data + /// var result = await BarcodeScanner.scan(); + /// int patientID = get from qr result + String result = await BarcodeScanner.scan(); + var data = json.decode(result); + if (data!=null) { + var qRParkingID = data['QRParkingID']; + await model.scanQr(); + if (model.state == ViewState.ErrorLocal) { + Utils.showErrorToast(model.error); + } else { + AppToast.showSuccessToast(message: model.scanList[0].id); + { + Navigator.push( + context, + MaterialPageRoute(builder: (context) => LandingPagePharmacy()), + ); + } + } + } + } +} diff --git a/lib/pages/rateAppointment/rate_appointment_clinic.dart b/lib/pages/rateAppointment/rate_appointment_clinic.dart index 38fdd008..bf0f4b4e 100644 --- a/lib/pages/rateAppointment/rate_appointment_clinic.dart +++ b/lib/pages/rateAppointment/rate_appointment_clinic.dart @@ -5,6 +5,7 @@ import 'package:diplomaticquarterapp/core/viewModels/appointment_rate_view_model import 'package:diplomaticquarterapp/pages/base/base_view.dart'; import 'package:diplomaticquarterapp/pages/landing/landing_page.dart'; import 'package:diplomaticquarterapp/uitl/app_toast.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/avatar/large_avatar.dart'; import 'package:diplomaticquarterapp/widgets/buttons/button.dart'; import 'package:diplomaticquarterapp/widgets/buttons/secondary_button.dart'; @@ -72,7 +73,7 @@ class _RateAppointmentClinicState extends State { height: 25, ), Texts( - 'How would you rate your last visit to the Clinic', + TranslationBase.of(context).lastAppointment, bold: true, color: Colors.black, ), @@ -122,7 +123,7 @@ class _RateAppointmentClinicState extends State { ), Center( child: Texts( - 'Please rate the Clinic', + TranslationBase.of(context).rateClinic, textAlign: TextAlign.center, )), SizedBox( @@ -145,7 +146,7 @@ class _RateAppointmentClinicState extends State { child: Container( key: ValueKey(rating), child: IconButton( - iconSize: 55.0, + iconSize: 45.0, onPressed: () { setState(() { rating = index + 1; @@ -206,9 +207,9 @@ class _RateAppointmentClinicState extends State { message: 'please rate the clinic'); } }, - label: "Rate", - disabled: model.state == ViewState.BusyLocal, - loading: model.state == ViewState.BusyLocal, + label: TranslationBase.of(context).submit, + disabled: (model.state == ViewState.Busy || rating==0), + // loading: model.state == ViewState.BusyLocal, textColor: Theme.of(context).backgroundColor), ), SizedBox( @@ -224,7 +225,7 @@ class _RateAppointmentClinicState extends State { ); }, child: Texts( - 'Later', + TranslationBase.of(context).later, decoration: TextDecoration.underline, color: HexColor('#151DFE'), fontSize: 18, diff --git a/lib/pages/rateAppointment/rate_appointment_doctor.dart b/lib/pages/rateAppointment/rate_appointment_doctor.dart index b79911ef..71aacae2 100644 --- a/lib/pages/rateAppointment/rate_appointment_doctor.dart +++ b/lib/pages/rateAppointment/rate_appointment_doctor.dart @@ -40,7 +40,7 @@ class _RateAppointmentDoctorState extends State { headline6: TextStyle(color: Colors.white, fontWeight: FontWeight.bold), ), - title: Text('Rate'), + title: Text(TranslationBase.of(context).rate), leading: Builder( builder: (BuildContext context) { return IconButton( @@ -61,10 +61,10 @@ class _RateAppointmentDoctorState extends State { child: Column( children: [ SizedBox( - height: 25, + height: 25, //5598 ), Texts( - 'How would you rate your last visit to the doctor', + TranslationBase.of(context).lastVisit, bold: true, color: Colors.black, ), @@ -94,7 +94,7 @@ class _RateAppointmentDoctorState extends State { height: 22, ), Texts( - model.appointmentDetails.doctorName, + TranslationBase.of(context).dr + " " + model.appointmentDetails.doctorName, bold: true, ), SizedBox( @@ -115,7 +115,7 @@ class _RateAppointmentDoctorState extends State { ), Center( child: Texts( - 'Please rate the doctor', + TranslationBase.of(context).tapTitle, textAlign: TextAlign.center, )), SizedBox( @@ -138,7 +138,7 @@ class _RateAppointmentDoctorState extends State { child: Container( key: ValueKey(rating), child: IconButton( - iconSize: 55.0, + iconSize: 45.0, onPressed: () { setState(() { rating = index + 1; @@ -162,15 +162,15 @@ class _RateAppointmentDoctorState extends State { Form( key: formKey, child: TextFields( - hintText: "Notes", + hintText: TranslationBase.of(context).notes, minLines: 4, maxLines: 4, - validator: (value) { - if (value.isEmpty) - return 'Please enter your note'; - else if (rating == 0) return 'Rating cannot be \"0\"'; - return null; - }, + // validator: (value) { + // if (value.isEmpty) + // return 'Please enter your note'; + // else if (rating == 0) return 'Rating cannot be \"0\"'; + // return null; + // }, onChanged: (value) { setState(() { note = value; @@ -190,7 +190,7 @@ class _RateAppointmentDoctorState extends State { child: SecondaryButton( onTap: () async { final form = formKey.currentState; - if (form.validate()) { + if (form.validate() && rating>0 ) { form.save(); Navigator.push( context, @@ -206,7 +206,7 @@ class _RateAppointmentDoctorState extends State { } }, label: TranslationBase.of(context).next, - disabled: model.state == ViewState.BusyLocal, + disabled: (model.state == ViewState.BusyLocal || rating==0), loading: model.state == ViewState.BusyLocal, textColor: Theme.of(context).backgroundColor), ), @@ -223,7 +223,7 @@ class _RateAppointmentDoctorState extends State { ); }, child: Texts( - 'Later', + TranslationBase.of(context).later, decoration: TextDecoration.underline, color: HexColor('#151DFE'), fontSize: 18, diff --git a/lib/pages/search_products_page.dart b/lib/pages/search_products_page.dart new file mode 100644 index 00000000..45cafd35 --- /dev/null +++ b/lib/pages/search_products_page.dart @@ -0,0 +1,287 @@ +import 'package:diplomaticquarterapp/config/size_config.dart'; +import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; +import 'package:diplomaticquarterapp/core/viewModels/pharmacy_categorise_view_model.dart'; +import 'package:diplomaticquarterapp/uitl/utils.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/button.dart'; +import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; +import 'package:diplomaticquarterapp/widgets/input/text_field.dart'; +import 'package:diplomaticquarterapp/widgets/others/StarRating.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_pharmacy_widget.dart'; +import 'package:diplomaticquarterapp/widgets/others/network_base_view.dart'; +import 'package:flutter/material.dart'; + +import 'base/base_view.dart'; + +class SearchProductsPage extends StatefulWidget { + @override + _SearchProductsPageState createState() => _SearchProductsPageState(); +} + +class _SearchProductsPageState extends State { + final textController = TextEditingController(); + final _formKey = GlobalKey(); + String msg = ''; + + @override + Widget build(BuildContext context) { + return BaseView( + onModelReady: (model) => model.clearSearchList(), + builder: (BuildContext context, PharmacyCategoriseViewModel model, + Widget child) => + PharmacyAppScaffold( + appBarTitle: 'Search', + isBottomBar: false, + isShowAppBar: true, + backgroundColor: Colors.white, + isShowDecPage: false, + //baseViewModel: model, + body: SingleChildScrollView( + child: Container( + height: SizeConfig.screenHeight, + child: Column( + children: [ + Padding( + padding: EdgeInsets.all(8.0), + child: Row( + children: [ + Container( + width: MediaQuery.of(context).size.width * 0.79, + child: Form( + key: _formKey, + child: TextFields( + autoFocus: true, + hintText: 'Search', + fontSize: 19.0, + prefixIcon: Icon(Icons.search), + inputAction: TextInputAction.search, + onSaved: (value) { + //searchMedicine(model, context); + }, + onSubmit: (value) { + searchMedicine(model, context); + msg = 'No Result Found'; + }, + controller: textController, + validator: (value) { + if (value.isEmpty) { + return 'please Enter Product Name'; + } + return null; + }, + ), + ), + ), + SizedBox( + width: 10.0, + ), + InkWell( + child: Texts( + 'Cancel', + fontSize: 17.0, + fontWeight: FontWeight.w500, + ), + onTap: () { + Navigator.pop(context); + }, + ), + + // child: Container( + // child: Button( + // backgroundColor: Colors.green, + // loading: model.state == ViewState.BusyLocal, + // label: 'Search', + // onTap: () { + // searchMedicine(model, context); + // }), + // width: MediaQuery.of(context).size.width * 0.09, + // ), + ], + ), + ), + Center( + child: NetworkBaseView( + baseViewModel: model, + child: model.searchList.isNotEmpty + ? Container( + height: MediaQuery.of(context).size.height * 0.80, + child: GridView.builder( + //physics: NeverScrollableScrollPhysics(), + gridDelegate: + SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + crossAxisSpacing: 0.5, + mainAxisSpacing: 2.0, + childAspectRatio: 1.0, + ), + itemCount: model.searchList.length, + itemBuilder: (BuildContext context, int index) { + return Card( + color: model.searchList[index].discountName != + null + ? Color(0xffFFFF00) + : Colors.white, + elevation: 0, + shape: Border( + right: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + left: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + bottom: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + top: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + ), + margin: EdgeInsets.symmetric( + horizontal: 8, + vertical: 4, + ), + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(110.0), + ), + color: Colors.white, + ), + padding: + EdgeInsets.symmetric(horizontal: 0), + width: + MediaQuery.of(context).size.width / 3, + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Stack( + children: [ + Container( + margin: EdgeInsets.fromLTRB( + 0, 16, 0, 0), + alignment: Alignment.center, + child: Image.network( + model.searchList[index].images + .isNotEmpty + ? model.searchList[index] + .images[0].thumb + : 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/No_image_3x4.svg/1200px-No_image_3x4.svg.png', + fit: BoxFit.cover, + height: 80, + ), + ), + Container( + width: model.searchList[index] + .rxMessage != + null + ? MediaQuery.of(context) + .size + .width / + 5 + : 0, + padding: EdgeInsets.all(4), + decoration: BoxDecoration( + color: Color(0xffb23838), + borderRadius: BorderRadius.only( + topLeft: + Radius.circular(6)), + ), + child: Texts( + model.searchList[index] + .rxMessage != + null + ? model.searchList[index] + .rxMessage + : "", + color: Colors.white, + regular: true, + fontSize: 10, + fontWeight: FontWeight.w400, + ), + ), + ], + ), + Container( + margin: EdgeInsets.symmetric( + horizontal: 6, + vertical: 0, + ), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Texts( + model.searchList[index].name, + regular: true, + fontSize: 12, + fontWeight: FontWeight.w400, + ), + Padding( + padding: const EdgeInsets.only( + top: 4, bottom: 4), + child: Texts( + "SAR ${model.searchList[index].price}", + bold: true, + fontSize: 14, + ), + ), + Row( + children: [ + StarRating( + totalAverage: model + .searchList[ + index] + .approvedRatingSum > + 0 + ? (model + .searchList[ + index] + .approvedRatingSum + .toDouble() / + model + .searchList[ + index] + .approvedRatingSum + .toDouble()) + .toDouble() + : 0, + forceStars: true), + Texts( + "(${model.searchList[index].approvedTotalReviews})", + regular: true, + fontSize: 10, + fontWeight: FontWeight.w400, + ) + ], + ), + ], + ), + ), + ], + ), + ), + ); + }, + ), + ) + : Texts(msg), + ), + ) + ], + ), + ), + ), + ), + ); + } + + searchMedicine(PharmacyCategoriseViewModel model, BuildContext context) { + Utils.hideKeyboard(context); + if (_formKey.currentState.validate()) + model.searchProducts(productName: textController.text); + } +} diff --git a/lib/pages/settings/general_setting.dart b/lib/pages/settings/general_setting.dart index 86167b7d..7085150a 100644 --- a/lib/pages/settings/general_setting.dart +++ b/lib/pages/settings/general_setting.dart @@ -19,14 +19,14 @@ class GeneralSettings extends StatefulWidget { class _GeneralSettings extends State with TickerProviderStateMixin { var themeNotifier; - var mediaQueryData; int blindValue = 0; - bool vibration =false; - bool accsibility =false; - bool camera =false; - bool location =false; + bool vibration =false; + bool accsibility =false; + bool camera =false; + bool location =false; var sharedPref = new AppSharedPreferences(); var permission = new PermissionService(); + var mediaQueryData; @override void initState() { getValues(); @@ -81,104 +81,104 @@ class _GeneralSettings extends State setState(() { accsibility = value; }); - permission.openSettings(); + //setAccisibility(value); }, activeTrackColor: Colors.lightGreenAccent, activeColor: Colors.green, ) ], )), - // Container( - // padding: EdgeInsets.all(10), - // child: AppText( - // TranslationBase.of(context).blindMode, - // color: Colors.black, - // fontWeight: FontWeight.bold, - // ), - // ), - // new Container( - // color: Colors.white, - // padding: EdgeInsets.all(8.0), - // child: new Column( - // mainAxisAlignment: MainAxisAlignment.center, - // children: [ - // new Column( - // mainAxisAlignment: MainAxisAlignment.center, - // children: [ - // Row( - // mainAxisAlignment: MainAxisAlignment.spaceBetween, - // children: [ - // new Text( - // TranslationBase.of(context).offTheme, - // style: new TextStyle(fontSize: 16.0), - // ), - // Radio( - // value: 0, - // groupValue: blindValue, - // onChanged: (value) { - // setState(() => {this.blindValue = value}); - // setTheme(value); - // }, - // ), - // ], - // ), - // Row( - // mainAxisAlignment: MainAxisAlignment.spaceBetween, - // children: [ - // new Text( - // TranslationBase.of(context).invertTheme, - // style: new TextStyle( - // fontSize: 16.0, - // ), - // ), - // new Radio( - // value: 1, - // groupValue: blindValue, - // onChanged: (value) { - // setState(() => {this.blindValue = value}); - // setTheme(value); - // }, - // ) - // ], - // ), - // Row( - // mainAxisAlignment: MainAxisAlignment.spaceBetween, - // children: [ - // new Text( - // TranslationBase.of(context).dimTheme, - // style: new TextStyle(fontSize: 16.0), - // ), - // new Radio( - // value: 2, - // groupValue: blindValue, - // onChanged: (value) { - // setState(() => {this.blindValue = value}); - // setTheme(value); - // }, - // ), - // ], - // ), - // Row( - // mainAxisAlignment: MainAxisAlignment.spaceBetween, - // children: [ - // new Text( - // TranslationBase.of(context).bwTheme, - // style: new TextStyle(fontSize: 16.0), - // ), - // new Radio( - // value: 3, - // groupValue: blindValue, - // onChanged: (value) { - // setState(() => {this.blindValue = value}); - // - // setTheme(value); - // }, - // ), - // ], - // ), - // ], - // ) - // ])), + Container( + padding: EdgeInsets.all(10), + child: AppText( + TranslationBase.of(context).blindMode, + color: Colors.black, + fontWeight: FontWeight.bold, + ), + ), + new Container( + color: Colors.white, + padding: EdgeInsets.all(8.0), + child: new Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + new Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + new Text( + TranslationBase.of(context).offTheme, + style: new TextStyle(fontSize: 16.0), + ), + Radio( + value: 0, + groupValue: blindValue, + onChanged: (value) { + setState(() => {this.blindValue = value}); + setTheme(value); + }, + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + new Text( + TranslationBase.of(context).invertTheme, + style: new TextStyle( + fontSize: 16.0, + ), + ), + new Radio( + value: 1, + groupValue: blindValue, + onChanged: (value) { + setState(() => {this.blindValue = value}); + setTheme(value); + }, + ) + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + new Text( + TranslationBase.of(context).dimTheme, + style: new TextStyle(fontSize: 16.0), + ), + new Radio( + value: 2, + groupValue: blindValue, + onChanged: (value) { + setState(() => {this.blindValue = value}); + setTheme(value); + }, + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + new Text( + TranslationBase.of(context).bwTheme, + style: new TextStyle(fontSize: 16.0), + ), + new Radio( + value: 3, + groupValue: blindValue, + onChanged: (value) { + setState(() => {this.blindValue = value}); + + setTheme(value); + }, + ), + ], + ), + ], + ) + ])), Container( padding: EdgeInsets.all(10), child: AppText( @@ -200,7 +200,6 @@ class _GeneralSettings extends State setState(() { camera = value; }); - permission.setCameraLocationPermission(context); }, activeTrackColor: Colors.lightGreenAccent, activeColor: Colors.green, @@ -220,7 +219,6 @@ class _GeneralSettings extends State setState(() { location = value; }); - permission.setCameraLocationPermission(context); }, activeTrackColor: Colors.lightGreenAccent, activeColor: Colors.green, @@ -240,7 +238,43 @@ class _GeneralSettings extends State break; case 1: { - themeNotifier.setTheme(await getTheme(value)); + themeNotifier.setTheme(ThemeData( + fontFamily: await sharedPref.getString(APP_LANGUAGE) == 'ar' ? 'Cairo' : 'WorkSans', + primarySwatch: Colors.grey, + visualDensity: VisualDensity.adaptivePlatformDensity, + brightness: Brightness.light, + pageTransitionsTheme: const PageTransitionsTheme( + builders: { + TargetPlatform.android: ZoomPageTransitionsBuilder(), + TargetPlatform.iOS: CupertinoPageTransitionsBuilder(), + }, + ), + hintColor: Colors.grey[400], + cardColor: Colors.black, + buttonColor: Colors.grey[400], + disabledColor: Colors.grey[300], + errorColor: Color.fromRGBO(235, 80, 60, 1.0), + scaffoldBackgroundColor: Colors.grey, + textSelectionColor: Color.fromRGBO(80, 100, 253, 0.5), + textSelectionHandleColor: Colors.grey, + canvasColor: Colors.white, + backgroundColor: Colors.grey, + highlightColor: Colors.grey[100].withOpacity(0.4), + splashColor: Colors.transparent, + primaryColor: Colors.grey, + bottomSheetTheme: BottomSheetThemeData(backgroundColor: Color(0xffE0E0E0)), + cursorColor: Colors.grey, + + iconTheme: IconThemeData(), + appBarTheme: AppBarTheme( + color: Colors.grey, + brightness: Brightness.dark, + elevation: 10.0, + actionsIconTheme: IconThemeData( + color: Colors.grey, + ), + ), + )); Screen.setBrightness(1.0); } break; @@ -261,31 +295,28 @@ class _GeneralSettings extends State } break; } - permission.setTheme(value); + //permission.setTheme(value); } setVibration(value){ permission.setVibrationPermission(value); } + setAccisibility(){ + if(!accsibility){ + + } + // permission.setVibrationPermission(value); + } getValues() async{ - blindValue= permission.isThemeEnabled() == null ? 0 : permission.isThemeEnabled(); - vibration = permission.isVibrationEnabled() ==null ? false : permission.isVibrationEnabled(); - camera = await permission.isCameraEnabled(); - location = await permission.isLocationEnabled(); - setState(() { - location =location; - camera = camera; - vibration = vibration; - blindValue =blindValue; - accsibility = mediaQueryData.accessibleNavigation; - }); + blindValue= permission.isThemeEnabled() == null ? 0 : permission.isThemeEnabled(); + vibration = permission.isVibrationEnabled() ==null ? false : permission.isVibrationEnabled(); + accsibility =mediaQueryData.accessibleNavigation; } getTheme(value) async{ - if(value ==1){ return ThemeData( - fontFamily: await sharedPref.getString(APP_LANGUAGE) == 'en' ? 'WorkSans' : 'Cairo', + fontFamily: await sharedPref.getString(APP_LANGUAGE) == 'ar' ? 'Cairo' : 'WorkSans', primarySwatch: Colors.grey, visualDensity: VisualDensity.adaptivePlatformDensity, brightness: Brightness.light, @@ -324,7 +355,7 @@ class _GeneralSettings extends State }else if(value ==3){ return ThemeData( - fontFamily: await sharedPref.getString(APP_LANGUAGE) == 'en' ? 'WorkSans' : 'Cairo', + fontFamily: await sharedPref.getString(APP_LANGUAGE) == 'ar' ? 'Cairo' : 'WorkSans', primarySwatch: Colors.grey, visualDensity: VisualDensity.adaptivePlatformDensity, brightness: Brightness.light, @@ -363,7 +394,7 @@ class _GeneralSettings extends State }else { return ThemeData( - fontFamily: await sharedPref.getString(APP_LANGUAGE) == 'en' ? 'WorkSans' : 'Cairo', + fontFamily: await sharedPref.getString(APP_LANGUAGE) == 'ar' ? 'Cairo' : 'WorkSans', primarySwatch: Colors.blue, visualDensity: VisualDensity.adaptivePlatformDensity, brightness: Brightness.light, diff --git a/lib/pages/settings/profile_setting.dart b/lib/pages/settings/profile_setting.dart index c9089351..dcfdb8a8 100644 --- a/lib/pages/settings/profile_setting.dart +++ b/lib/pages/settings/profile_setting.dart @@ -1,5 +1,6 @@ import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/core/viewModels/dashboard_view_model.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; import 'package:diplomaticquarterapp/services/authentication/auth_provider.dart'; import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; @@ -9,6 +10,8 @@ import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:diplomaticquarterapp/widgets/text/app_texts_widget.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:diplomaticquarterapp/uitl/app_toast.dart'; +import 'package:provider/provider.dart'; class ProfileSettings extends StatefulWidget { @@ -28,203 +31,210 @@ class _ProfileSettings extends State @override void initState() { Future.delayed(new Duration(seconds: 0), () { - getSettings(context); + ProjectViewModel projectProvider; + projectProvider = Provider.of(context); + if (projectProvider.isLogin == true) getSettings(context); }); super.initState(); } - Widget build(BuildContext context) { + Widget build(BuildContext context) { return BaseView( - onModelReady: (model) =>{}, + onModelReady: (model) => {}, builder: (_, model, wi) => Container( - child: - ListView(scrollDirection: Axis.vertical, children: [ - Container( - padding: EdgeInsets.all(15), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - AppText( - TranslationBase.of(context).fileNo, - color: Colors.black, + child: model.user != null + ? ListView(scrollDirection: Axis.vertical, children: [ + Container( + padding: EdgeInsets.all(15), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + AppText( + TranslationBase.of(context).fileNo, + color: Colors.black, + ), + AppText( + model.user.patientID.toString(), + color: Colors.black, + ), + ], + ), ), - AppText( - model.user.patientID.toString(), - color: Colors.black, + SizedBox( + height: 1, + width: MediaQuery.of(context).size.width, + child: Container( + color: Colors.grey[300], + ), ), - ], - ), - ), - SizedBox( - height: 1, - width: MediaQuery.of(context).size.width, - child: Container( - color: Colors.grey[300], - ), - ), - Padding( - child: AppText(TranslationBase.of(context).languageSetting, - fontWeight: FontWeight.bold), - padding: EdgeInsets.all(10), - ), - Container( - color: Colors.white, - padding: - EdgeInsets.only(top: 0, left: 10, right: 10, bottom: 0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - AppText(TranslationBase.of(context).english), - new Radio( - value: 2, - groupValue: language, - onChanged: (value) { - setState(() { - language = value; - }); - - }, - ) - ], - )), - Container( - color: Colors.white, - padding: - EdgeInsets.only(top: 0, left: 10, right: 10, bottom: 0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - AppText(TranslationBase.of(context).arabic), - new Radio( - value: 1, - groupValue: language, - onChanged: (value) { - setState(() { - language = value; - }); - - }, - ) - ], - )), - Padding( - child: AppText(TranslationBase.of(context).alert), - padding: EdgeInsets.all(10), - ), - Container( - color: Colors.white, - padding: - EdgeInsets.only(top: 0, left: 10, right: 10, bottom: 0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - AppText(TranslationBase.of(context).emailAlert), - Switch( - value: emailAlert, - onChanged: (value) { - setState(() { - emailAlert = value; - }); - }, - activeTrackColor: Colors.lightGreenAccent, - activeColor: Colors.green, - ) - ], - )), - Container( - color: Colors.white, - padding: - EdgeInsets.only(top: 0, left: 10, right: 10, bottom: 0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - AppText(TranslationBase.of(context).smsAlert), - Switch( - value: smsAlert, - onChanged: (value) { - setState(() { - smsAlert = value; - }); - }, - activeTrackColor: Colors.lightGreenAccent, - activeColor: Colors.green, - ) - ], - )), - Padding( - child: AppText(TranslationBase.of(context).contactInfo), - padding: EdgeInsets.all(10), - ), - Container( - color: Colors.white, - padding: - EdgeInsets.only(top: 0, left: 10, right: 10, bottom: 0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - AppText(TranslationBase.of(context).email), - TextField( - controller: emailController, - decoration: InputDecoration( - suffixIcon: Icon(Icons.edit), - )) - ], - )), - Container( - color: Colors.white, - padding: - EdgeInsets.only(top: 0, left: 10, right: 10, bottom: 0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - AppText(TranslationBase.of(context).emergencyName), - TextField( - controller: emergencyContactName, - decoration: InputDecoration( - suffixIcon: Icon(Icons.edit), - )) - ], - )), - Container( - color: Colors.white, - padding: - EdgeInsets.only(top: 0, left: 10, right: 10, bottom: 0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - AppText(TranslationBase.of(context).emergencyContact), - TextField( - controller: emergencyContact, - decoration: InputDecoration( - suffixIcon: Icon(Icons.edit), - ), - ) - ], - )), - Container( - padding: EdgeInsets.all(10), - child: Row( - children: [ - Expanded( - child: DefaultButton( - TranslationBase.of(context).submit, - () { - saveSettings(); - }, - )), - ], - )) - ]))); + Padding( + child: AppText( + TranslationBase.of(context).languageSetting, + fontWeight: FontWeight.bold), + padding: EdgeInsets.all(10), + ), + Container( + color: Colors.white, + padding: EdgeInsets.only( + top: 0, left: 10, right: 10, bottom: 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + AppText(TranslationBase.of(context).english), + new Radio( + value: 2, + groupValue: language, + onChanged: (value) { + setState(() { + language = value; + }); + }, + ) + ], + )), + Container( + color: Colors.white, + padding: EdgeInsets.only( + top: 0, left: 10, right: 10, bottom: 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + AppText(TranslationBase.of(context).arabic), + new Radio( + value: 1, + groupValue: language, + onChanged: (value) { + setState(() { + language = value; + }); + }, + ) + ], + )), + Padding( + child: AppText(TranslationBase.of(context).alert), + padding: EdgeInsets.all(10), + ), + Container( + color: Colors.white, + padding: EdgeInsets.only( + top: 0, left: 10, right: 10, bottom: 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + AppText(TranslationBase.of(context).emailAlert), + Switch( + value: emailAlert, + onChanged: (value) { + setState(() { + emailAlert = value; + }); + }, + activeTrackColor: Colors.lightGreenAccent, + activeColor: Colors.green, + ) + ], + )), + Container( + color: Colors.white, + padding: EdgeInsets.only( + top: 0, left: 10, right: 10, bottom: 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + AppText(TranslationBase.of(context).smsAlert), + Switch( + value: smsAlert, + onChanged: (value) { + setState(() { + smsAlert = value; + }); + }, + activeTrackColor: Colors.lightGreenAccent, + activeColor: Colors.green, + ) + ], + )), + Padding( + child: AppText(TranslationBase.of(context).contactInfo), + padding: EdgeInsets.all(10), + ), + Container( + color: Colors.white, + padding: EdgeInsets.only( + top: 0, left: 10, right: 10, bottom: 0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + AppText(TranslationBase.of(context).email), + TextField( + controller: emailController, + decoration: InputDecoration( + suffixIcon: Icon(Icons.edit), + )) + ], + )), + Container( + color: Colors.white, + padding: EdgeInsets.only( + top: 0, left: 10, right: 10, bottom: 0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + AppText(TranslationBase.of(context).emergencyName), + TextField( + controller: emergencyContactName, + decoration: InputDecoration( + suffixIcon: Icon(Icons.edit), + )) + ], + )), + Container( + color: Colors.white, + padding: EdgeInsets.only( + top: 0, left: 10, right: 10, bottom: 0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + AppText( + TranslationBase.of(context).emergencyContact), + TextField( + controller: emergencyContact, + decoration: InputDecoration( + suffixIcon: Icon(Icons.edit), + ), + ) + ], + )), + Container( + padding: EdgeInsets.all(10), + child: Row( + children: [ + Expanded( + child: DefaultButton( + TranslationBase.of(context).save, + () { + saveSettings(); + }, + )), + ], + )) + ]) + : Center( + child: + AppText(TranslationBase.of(context).loginToUseService), + ))); } - getSettings(context){ + getSettings(context) { GifLoaderDialogUtils.showMyDialog(context); - authService.getSettings().then((result)=>{ - GifLoaderDialogUtils.hideDialog(context), - setValue(result["PateintInfoForUpdateList"][0]) - }); + authService.getSettings().then((result) => { + GifLoaderDialogUtils.hideDialog(context), + setValue(result["PateintInfoForUpdateList"][0]) + }); } - setValue(value){ + + setValue(value) { setState(() { this.language = int.parse(value["PreferredLanguage"]); this.emailAlert = value["IsEmailAlertRequired"]; @@ -233,20 +243,21 @@ class _ProfileSettings extends State this.emergencyContact.text = value["EmergencyContactNo"]; this.emergencyContactName.text = value["EmergencyContactName"]; }); - } - saveSettings(){ + + saveSettings() { GifLoaderDialogUtils.showMyDialog(context); Map request = {}; - request["EmailAddress"] =this.emailController.text; + request["EmailAddress"] = this.emailController.text; request["EmergencyContactName"] = this.emergencyContactName.text; request["EmergencyContactNo"] = this.emergencyContact.text; request["IsEmailAlertRequired"] = this.emailAlert; request["IsSMSAlertRequired"] = this.smsAlert; request["PreferredLanguage"] = this.language.toString(); - authService.saveSettings(request).then((result)=>{ - print(result), - GifLoaderDialogUtils.hideDialog(context) - }); + authService.saveSettings(request).then((result) => { + AppToast.showSuccessToast( + message: TranslationBase.of(context).profileUpdate), + GifLoaderDialogUtils.hideDialog(context) + }); } } diff --git a/lib/pages/settings/settings.dart b/lib/pages/settings/settings.dart index abdac118..0c63b900 100644 --- a/lib/pages/settings/settings.dart +++ b/lib/pages/settings/settings.dart @@ -21,6 +21,10 @@ class _Settings extends State with TickerProviderStateMixin { _tabController = new TabController(length: 2, vsync: this, initialIndex: widget.type); + if(widget.type==1){ + _tabController.animateTo(1); + } + super.initState(); } @@ -30,6 +34,14 @@ class _Settings extends State with TickerProviderStateMixin { return Scaffold( appBar: AppBar( bottom: TabBar( + // isScrollable: true, + + indicatorWeight: 5.0, + //indicatorSize: TabBarIndicatorSize.label, + // indicatorSize: TabBarIndicatorSize.tab, + + indicatorColor: Theme.of(context).primaryColor, + // labelColor: Theme.of(context).primaryColor, tabs: [ Tab(text: TranslationBase.of(context).general), Tab( diff --git a/lib/pages/sub_categorise_page.dart b/lib/pages/sub_categorise_page.dart new file mode 100644 index 00000000..45c9fd6c --- /dev/null +++ b/lib/pages/sub_categorise_page.dart @@ -0,0 +1,944 @@ +import 'package:diplomaticquarterapp/core/viewModels/pharmacy_categorise_view_model.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/button.dart'; +import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; +import 'package:diplomaticquarterapp/widgets/others/StarRating.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_pharmacy_widget.dart'; +import 'package:diplomaticquarterapp/widgets/others/network_base_view.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import 'base/base_view.dart'; +import 'final_products_page.dart'; + +class SubCategorisePage extends StatefulWidget { + String id; + String title; + String parentId; + + SubCategorisePage({this.id, this.parentId, this.title}); + @override + _SubCategorisePageState createState() => + _SubCategorisePageState(id: id, title: title, parentId: parentId); +} + +class _SubCategorisePageState extends State { + bool checkedBrands = false; + bool checkedCategorise = false; + String id; + String title; + String parentId; + _SubCategorisePageState({this.title, this.parentId, this.id}); + String categoriseName = "Personal Care"; + bool styleOne = true; + bool styleTwo = false; + Icon styleIcon = Icon( + Icons.widgets_sharp, + color: Colors.blue, + size: 29.0, + ); + @override + Widget build(BuildContext context) { + return BaseView( + onModelReady: (model) => model.getSubCategorise(i: id), + builder: (BuildContext context, PharmacyCategoriseViewModel model, + Widget child) => + PharmacyAppScaffold( + appBarTitle: title, + isBottomBar: false, + isShowAppBar: true, + backgroundColor: Colors.white, + isShowDecPage: false, + baseViewModel: model, + body: SingleChildScrollView( + child: Container( + height: MediaQuery.of(context).size.height * 5.97, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + child: Image.network( + parentId == '1' + ? 'https://uat.hmgwebservices.com/epharmacy/content/images/thumbs/0089188_personal-care_2.png' + : parentId == '2' + ? 'https://uat.hmgwebservices.com/epharmacy/content/images/thumbs/0089189_skin-care_2.png' + : parentId == '3' + ? 'https://uat.hmgwebservices.com/epharmacy/content/images/thumbs/0089190_health-care_2.png' + : parentId == '4' + ? 'https://uat.hmgwebservices.com/epharmacy/content/images/thumbs/0089191_sexual-health_2.png' + : parentId == '5' + ? 'https://uat.hmgwebservices.com/epharmacy/content/images/thumbs/0089192_beauty_2.png' + : parentId == '6' + ? 'https://uat.hmgwebservices.com/epharmacy/content/images/thumbs/0089193_baby-child_2.png' + : parentId == '7' + ? 'https://uat.hmgwebservices.com/epharmacy/content/images/thumbs/0089194_vitamins-supplements_2.png' + : parentId == '8' + ? 'https://uat.hmgwebservices.com/epharmacy/content/images/thumbs/0089195_diet-nutrition_2.png' + : parentId == '9' + ? 'https://uat.hmgwebservices.com/epharmacy/content/images/thumbs/0089196_household_2.png' + : parentId == + '10' + ? 'https://uat.hmgwebservices.com/epharmacy/content/images/thumbs/0089197_home-care-appliances_2.png' + : '', + fit: BoxFit.fill, + height: 160.0, + width: double.infinity), + ), + if (model.subCategorise.length > 8) + Column( + children: [ + InkWell( + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: EdgeInsets.all(10.0), + child: Container( + child: Texts('View All Categories'), + ), + ), + Icon(Icons.arrow_forward) + ], + ), + onTap: () { + showModalBottomSheet( + isScrollControlled: true, + context: context, + builder: (BuildContext context) { + return Container( + height: + MediaQuery.of(context).size.height * + 0.89, + color: Colors.white, + child: Center( + child: ListView.builder( + scrollDirection: Axis.vertical, + itemCount: + model.subCategorise.length, + itemBuilder: (BuildContext context, + int index) { + return Container( + child: Padding( + padding: EdgeInsets.all(8.0), + child: InkWell( + child: Column( + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + Texts(model + .subCategorise[ + index] + .name), + Divider( + thickness: 0.6, + color: Colors.black12, + ) + ], + ), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + FinalProductsPage( + id: model + .subCategorise[ + index] + .id, + ), + ), + ); + }, + ), + ), + ); + }), + ), + ); + }, + ); + }, + ), + Divider( + thickness: 1.0, + color: Colors.grey.shade400, + ), + ], + ), + +//Expanded widget heree if nassery + Padding( + padding: EdgeInsets.only(top: 35.0), + child: Container( + height: MediaQuery.of(context).size.height * 0.2, + child: Center( + child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: model.subCategorise.length, + itemBuilder: (BuildContext context, int index) { + return Padding( + padding: + EdgeInsets.symmetric(horizontal: 8.0), + child: InkWell( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + Padding( + padding: EdgeInsets.symmetric( + horizontal: 13.0), + child: Container( + height: 60.0, + width: 65.0, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.orange.shade200 + .withOpacity(0.45), + ), + child: Center( + child: Icon( + Icons.apps_sharp, + size: 32.0, + ), + ), + ), + ), + Container( + width: MediaQuery.of(context) + .size + .width * + 0.17, + height: MediaQuery.of(context) + .size + .height * + 0.10, + child: Center( + child: Texts( + model.subCategorise[index].name, + fontSize: 14, + fontWeight: FontWeight.w600, + maxLines: 2, + ), + ), + ), + ], + ), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + FinalProductsPage( + id: model.subCategorise[index].id, + ), + ), + ); + }, + ), + ); + }), + ), + ), + ), + + Divider( + thickness: 1.0, + color: Colors.grey.shade400, + ), + Padding( + padding: EdgeInsets.symmetric(horizontal: 8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + InkWell( + child: Row( + children: [ + Icon(Icons.wrap_text), + SizedBox( + width: 10.0, + ), + Texts( + 'Refine', + fontWeight: FontWeight.w600, + ), + ], + ), + onTap: () { + showModalBottomSheet( + isScrollControlled: true, + context: context, + builder: (BuildContext context) { + return DraggableScrollableSheet( + initialChildSize: 0.95, + maxChildSize: 0.95, + minChildSize: 0.9, + builder: (BuildContext context, + ScrollController scrollController) { + return SingleChildScrollView( + controller: scrollController, + child: Container( + height: MediaQuery.of(context) + .size + .height * + 1.95, + child: Column( + children: [ + Padding( + padding: + EdgeInsets.all(8.0), + child: Row( + children: [ + Icon( + Icons.wrap_text, + ), + SizedBox( + width: 10.0, + ), + Texts( + 'Refine', + fontWeight: + FontWeight.w600, + ), + SizedBox( + width: 250.0, + ), + InkWell( + child: Texts( + 'Close', + color: Colors.red, + fontWeight: + FontWeight.w600, + fontSize: 15.0, + ), + onTap: () { + Navigator.pop( + context); + }, + ), + ], + ), + ), + Divider( + thickness: 1.0, + color: Colors.black12, + ), + Column( + children: [ + ExpansionTile( + title: + Texts('Categorise'), + children: [ + Container( + height: 350, + child: ListView + .builder( + controller: + scrollController, + scrollDirection: + Axis + .vertical, + shrinkWrap: + true, + itemCount: model + .categoriseParent + .length, + itemBuilder: + (BuildContext + context, + int index) { + return CheckboxListTile( + tristate: + true, + title: Texts(model + .categoriseParent[index] + .name), + controlAffinity: + ListTileControlAffinity.leading, + value: + checkedCategorise, + onChanged: + (bool + value) { + setState( + () { + checkedCategorise = + value; + }); + }, + ); + }), + ) + ], + ), + Divider( + thickness: 1.0, + color: Colors.black12, + ), + ExpansionTile( + title: Texts('Brands'), + children: [ + Container( + height: 350, + child: ListView + .builder( + scrollDirection: + Axis + .vertical, + shrinkWrap: + true, + itemCount: model + .brandsList + .length, + itemBuilder: + (BuildContext + context, + int index) { + return CheckboxListTile( + tristate: + true, + title: Texts(model + .brandsList[index] + .name), + controlAffinity: + ListTileControlAffinity.leading, + value: + checkedBrands, + onChanged: + (bool + value) { + setState( + () { + checkedBrands = + value; + }); + }, + autofocus: + true, + ); + }), + ) + ], + ), + Divider( + thickness: 1.0, + color: Colors.black12, + ), + ExpansionTile( + title: Texts('Price'), + children: [ + Container( + color: Color( + 0xffEEEEEE), + child: Row( + mainAxisAlignment: + MainAxisAlignment + .spaceAround, + children: [ + Column( + mainAxisAlignment: + MainAxisAlignment + .start, + children: [ + Texts( + 'Min'), + Container( + color: Colors + .white, + width: + 200, + height: + 40, + child: + TextFormField( + decoration: + InputDecoration( + border: + OutlineInputBorder(), + ), + ), + ), + ], + ), + Column( + mainAxisAlignment: + MainAxisAlignment + .start, + children: [ + Texts( + 'Max'), + Container( + color: Colors + .white, + width: + 200, + height: + 40, + child: + TextFormField( + decoration: + InputDecoration( + border: + OutlineInputBorder(), + ), + ), + ), + ], + ), + ], + ), + ) + ], + ), + Divider( + thickness: 1.0, + color: Colors.black12, + ), + SizedBox( + height: MediaQuery.of( + context) + .size + .height * + 0.4, + ), + Padding( + padding: + EdgeInsets.all(8.0), + child: Row( + mainAxisAlignment: + MainAxisAlignment + .spaceEvenly, + children: [ + Container( + width: 100, + child: Button( + label: 'Reset', + backgroundColor: + Colors.red, + ), + ), + SizedBox( + width: 30, + ), + Container( + width: 200, + child: Button( + label: 'Apply', + backgroundColor: + Colors + .green, + ), + ), + ], + ), + ), + ], + ), + ], + ), + ), + ); + }); + }, + ); + }, + ), + Row( + children: [ + Container( + height: 44.0, + child: VerticalDivider( + color: Colors.black45, + thickness: 1.0, + //width: 0.3, + // indent: 0.0, + ), + ), + Padding( + padding: EdgeInsets.all(8.0), + child: InkWell( + child: styleIcon, + onTap: () { + setState(() { + if (styleOne == true) { + styleOne = false; + styleTwo = true; + styleIcon = Icon( + Icons.auto_awesome_mosaic, + color: Colors.blue, + size: 29.0, + ); + } else { + styleOne = true; + styleTwo = false; + styleIcon = Icon( + Icons.widgets_sharp, + color: Colors.blue, + size: 29.0, + ); + } + }); + }, + ), + ), + ], + ), + ], + ), + ), + Divider( + thickness: 1.0, + color: Colors.grey.shade400, + ), + styleOne == true + ? Container( + height: MediaQuery.of(context).size.height * 3.85, + child: GridView.builder( + physics: NeverScrollableScrollPhysics(), + gridDelegate: + SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + crossAxisSpacing: 0.5, + mainAxisSpacing: 2.0, + childAspectRatio: 1.0, + ), + itemCount: model.subProducts.length, + itemBuilder: (BuildContext context, int index) { + return NetworkBaseView( + baseViewModel: model, + child: Card( + color: model.subProducts[index] + .discountName != + null + ? Color(0xffFFFF00) + : Colors.white, + elevation: 0, + shape: Border( + right: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + left: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + bottom: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + top: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + ), + margin: EdgeInsets.symmetric( + horizontal: 8, + vertical: 4, + ), + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(110.0), + ), + color: Colors.white, + ), + padding: EdgeInsets.symmetric( + horizontal: 0), + width: MediaQuery.of(context) + .size + .width / + 3, + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Stack( + children: [ + Container( + margin: EdgeInsets.fromLTRB( + 0, 16, 0, 0), + alignment: Alignment.center, + child: Image.network( + model.subProducts[index] + .images.isNotEmpty + ? model + .subProducts[ + index] + .images[0] + .thumb + : 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/No_image_3x4.svg/1200px-No_image_3x4.svg.png', + fit: BoxFit.cover, + height: 80, + ), + ), + Container( + width: model + .subProducts[ + index] + .rxMessage != + null + ? MediaQuery.of(context) + .size + .width / + 5 + : 0, + padding: EdgeInsets.all(4), + decoration: BoxDecoration( + color: Color(0xffb23838), + borderRadius: + BorderRadius.only( + topLeft: Radius + .circular(6)), + ), + child: Texts( + model.subProducts[index] + .rxMessage != + null + ? model + .subProducts[ + index] + .rxMessage + : "", + color: Colors.white, + regular: true, + fontSize: 10, + fontWeight: + FontWeight.w400, + ), + ), + ], + ), + Container( + margin: EdgeInsets.symmetric( + horizontal: 6, + vertical: 0, + ), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Texts( + model.subProducts[index] + .name, + regular: true, + fontSize: 12, + fontWeight: + FontWeight.w400, + ), + Padding( + padding: + const EdgeInsets.only( + top: 4, + bottom: 4), + child: Texts( + "SAR ${model.subProducts[index].price}", + bold: true, + fontSize: 14, + ), + ), + Row( + children: [ + StarRating( + totalAverage: model + .subProducts[ + index] + .approvedRatingSum > + 0 + ? (model.subProducts[index].approvedRatingSum + .toDouble() / + model + .subProducts[index] + .approvedRatingSum + .toDouble()) + .toDouble() + : 0, + forceStars: true), + Texts( + "(${model.subProducts[index].approvedTotalReviews})", + regular: true, + fontSize: 10, + fontWeight: + FontWeight.w400, + ) + ], + ), + ], + ), + ), + ], + ), + ), + )); + }, + ), + ) + : Container( + height: MediaQuery.of(context).size.height * 5.0, + child: ListView.builder( + physics: NeverScrollableScrollPhysics(), + itemCount: model.subProducts.length, + itemBuilder: + (BuildContext context, int index) { + return Card( + child: Row( + children: [ + Stack( + children: [ + Column( + children: [ + Container( + decoration: BoxDecoration(), + child: Padding( + padding: EdgeInsets.only( + left: 9.0, + top: 8.0, + right: 10.0, + ), + ), + ), + Container( + margin: EdgeInsets.fromLTRB( + 0, 0, 0, 0), + alignment: Alignment.center, + child: Image.network( + model.subProducts[index] + .images.isNotEmpty + ? model + .subProducts[ + index] + .images[0] + .thumb + : 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/No_image_3x4.svg/1200px-No_image_3x4.svg.png', + fit: BoxFit.contain, + height: 80, + ), + ), + ], + ), + Column( + children: [ + Container( + width: model + .subProducts[ + index] + .rxMessage != + null + ? MediaQuery.of(context) + .size + .width / + 5 + : 0, + padding: EdgeInsets.all(4), + decoration: BoxDecoration( + color: Color(0xffb23838), + borderRadius: + BorderRadius.only( + topLeft: Radius + .circular(6)), + ), + child: Texts( + model.subProducts[index] + .rxMessage != + null + ? model + .subProducts[ + index] + .rxMessage + : "", + color: Colors.white, + regular: true, + fontSize: 10, + fontWeight: + FontWeight.w400, + ), + ), + ], + ), + ], + ), + Container( + height: 100.0, + margin: EdgeInsets.symmetric( + horizontal: 6, + vertical: 0, + ), + child: Column( + mainAxisAlignment: + MainAxisAlignment.spaceAround, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + SizedBox( + height: 4.0, + ), + Container( + height: 35.0, + width: 250.0, + child: Texts( + model.subProducts[index] + .name, + regular: true, + fontSize: 13.2, + fontWeight: FontWeight.w500, + maxLines: 2, + ), + ), + SizedBox( + height: 8.0, + ), + Padding( + padding: + const EdgeInsets.only( + top: 4, bottom: 4), + child: Texts( + "SAR ${model.subProducts[index].price}", + bold: true, + fontSize: 14, + ), + ), + Row( + children: [ + StarRating( + totalAverage: model + .subProducts[ + index] + .approvedRatingSum > + 0 + ? (model + .subProducts[ + index] + .approvedRatingSum + .toDouble() / + model + .parentProducts[ + index] + .approvedRatingSum + .toDouble()) + .toDouble() + : 0, + forceStars: true), + Texts( + "(${model.subProducts[index].approvedTotalReviews})", + regular: true, + fontSize: 10, + fontWeight: + FontWeight.w400, + ) + ], + ), + ], + ), + ), + ], + ), + ); + }), + ) + ], + ), + ), + ), + )); + } +} diff --git a/lib/pages/vaccine/my_vaccines_screen.dart b/lib/pages/vaccine/my_vaccines_screen.dart index 3e81c41c..169e5cd5 100644 --- a/lib/pages/vaccine/my_vaccines_screen.dart +++ b/lib/pages/vaccine/my_vaccines_screen.dart @@ -16,6 +16,7 @@ import 'package:popup_box/popup_box.dart'; import 'my_vaccines_item_screen.dart'; +//TODO fix by jammal we have a static data class MyVaccines extends StatefulWidget { @override _MyVaccinesState createState() => _MyVaccinesState(); diff --git a/lib/routes.dart b/lib/routes.dart index 24069e15..97d506c5 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -38,7 +38,7 @@ const String SYMPTOM_CHECKER_INFO = 'symptom-checker-info'; const String SELECT_GENDER = 'select-gender'; const String SETTINGS = 'settings'; const String HEALTH_WEATHER = 'health-weather'; -const String APP_UPDATE = 'app_update'; +const APP_UPDATE = 'app-update'; var routes = { SPLASH: (_) => SplashScreen(), HOME: (_) => LandingPage(), @@ -60,5 +60,4 @@ var routes = { HEALTH_WEATHER: (_) => HealthWeatherIndicator(), APP_UPDATE: (_) => AppUpdatePage(), SETTINGS: (_) => Settings(), - HEALTH_WEATHER: (_) => HealthWeatherIndicator() }; diff --git a/lib/services/appointment_services/GetDoctorsList.dart b/lib/services/appointment_services/GetDoctorsList.dart index a320cf6b..d26c74ad 100644 --- a/lib/services/appointment_services/GetDoctorsList.dart +++ b/lib/services/appointment_services/GetDoctorsList.dart @@ -1087,6 +1087,44 @@ class DoctorsListService extends BaseService { return Future.value(localRes); } + Future getPatientLabOrdersByAppoNo(dynamic appoNo, dynamic projID, dynamic clinicID, 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 = { + "AppointmentNo": appoNo, + "ProjectID": projID, + "ClinicID": clinicID, + "VersionID": req.VersionID, + "Channel": req.Channel, + "LanguageID": languageID == 'ar' ? 1 : 2, + "IPAdress": req.IPAdress, + "generalid": req.generalid, + "PatientOutSA": authUser.outSA, + "SessionID": "YckwoXhUmWBsnHKEKig", + "isDentalAllowedBackend": false, + "DeviceTypeID": req.DeviceTypeID, + "PatientID": authUser.patientID, + "TokenID": "@dm!n", + "PatientTypeID": authUser.patientType, + "PatientType": authUser.patientType + }; + + dynamic localRes; + await baseAppClient.post(GET_PATIENT_LAB_ORDERS_BY_APPOINTMENT, + onSuccess: (response, statusCode) async { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request); + return Future.value(localRes); + } + Future getPatientPrescriptionReports( AppoitmentAllHistoryResultList appo, BuildContext context) async { Map request; diff --git a/lib/services/authentication/auth_provider.dart b/lib/services/authentication/auth_provider.dart index 59f51bfc..8f0ea470 100644 --- a/lib/services/authentication/auth_provider.dart +++ b/lib/services/authentication/auth_provider.dart @@ -160,8 +160,7 @@ class AuthProvider with ChangeNotifier { }, body: request); return Future.value(localRes); } catch (error) { - print(error); - //throw error; + return Future.value(null); } } @@ -173,15 +172,19 @@ class AuthProvider with ChangeNotifier { request.generalid = GENERAL_ID; request.languageID = LANGUAGE_ID; request.patientOutSA = request.zipCode == '966' ? 0 : 1; - - dynamic localRes; - await new BaseAppClient().post(CHECK_PATIENT_AUTH, - onSuccess: (dynamic response, int statusCode) { - localRes = response; - }, onFailure: (String error, int statusCode) { + try { + dynamic localRes; + await new BaseAppClient().post(CHECK_PATIENT_AUTH, + onSuccess: (dynamic response, int statusCode) { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request.toJson()); + return Future.value(localRes); + } catch (error) { throw error; - }, body: request.toJson()); - return Future.value(localRes); + //throw error; + } } Future getLoginInfo(request) async { @@ -252,9 +255,10 @@ class AuthProvider with ChangeNotifier { return Future.value(error); // throw error; }, body: neRequest.toJson()); + sharedPref.setString(BLOOD_TYPE, localRes['PatientBloodType']); return Future.value(localRes); } catch (error) { - throw error; + throw localRes; //return Future.value(error); } } diff --git a/lib/services/family_files/family_files_provider.dart b/lib/services/family_files/family_files_provider.dart index 0b0c1ef5..7a2dec81 100644 --- a/lib/services/family_files/family_files_provider.dart +++ b/lib/services/family_files/family_files_provider.dart @@ -299,7 +299,7 @@ class FamilyFilesProvider with ChangeNotifier { AppToast.showErrorToast(message: error); throw error; }, body: request); - + sharedPref.setString(BLOOD_TYPE, localRes['PatientBloodType']); return Future.value(localRes); } catch (error) { print(error); diff --git a/lib/services/permission/permission_service.dart b/lib/services/permission/permission_service.dart index 2d618f34..ea408ce2 100644 --- a/lib/services/permission/permission_service.dart +++ b/lib/services/permission/permission_service.dart @@ -1,4 +1,3 @@ -import 'package:android_intent/android_intent.dart'; import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/core/service/base_service.dart'; @@ -35,7 +34,6 @@ class PermissionService extends BaseService { }else{ callback(); } - } diff --git a/lib/services/pharmacy_services/brands_service.dart b/lib/services/pharmacy_services/brands_service.dart new file mode 100644 index 00000000..32024f2f --- /dev/null +++ b/lib/services/pharmacy_services/brands_service.dart @@ -0,0 +1,73 @@ +import 'package:diplomaticquarterapp/config/config.dart'; +import 'package:diplomaticquarterapp/core/service/base_service.dart'; +import 'package:diplomaticquarterapp/models/pharmacy/brandModel.dart'; +import 'package:diplomaticquarterapp/models/pharmacy/topBrandsModel.dart'; +import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; + +class BrandsService extends BaseService { + AppSharedPreferences sharedPref = AppSharedPreferences(); + bool isLogin = false; + + List _brandsList = List(); + List get brandsList => _brandsList; + + List _topBrandsList = List(); + List get topBrandsList => _topBrandsList; + + List _searchList = List(); + List get searchList => _searchList; + + clearSearchList() { + _searchList.clear(); + } + + Future getBrands() async { + hasError = false; + await baseAppClient.getPharmacy(GET_BRANDS, + onSuccess: (dynamic response, int statusCode) { + _brandsList.clear(); + response['manufacturer'].forEach((item) { + _brandsList.add(Brand.fromJson(item)); + }); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }); + } + + Future getTopBrands() async { + hasError = false; + await baseAppClient.getPharmacy(GET_TOP_BRANDS, + onSuccess: (dynamic response, int statusCode) { + _topBrandsList.clear(); + response['manufacturer'].forEach((item) { + _topBrandsList.add(TopBrand.fromJson(item)); + }); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }); + } + + Future searchProducts({String productName}) async { + RegExp exp = new RegExp(productName.toUpperCase()); + hasError = false; + _searchList.clear(); + await baseAppClient.getPharmacy( + GET_BRANDS, + onSuccess: (dynamic response, int statusCode) { + response['manufacturer'].forEach((item) { + if(exp.hasMatch(item['name'])){ + _searchList.add(Brand.fromJson(item)); + }else{ + } + }); + }, + onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, + ); + } + +} diff --git a/lib/services/pharmacy_services/cancelOrder_service.dart b/lib/services/pharmacy_services/cancelOrder_service.dart new file mode 100644 index 00000000..f848c2ff --- /dev/null +++ b/lib/services/pharmacy_services/cancelOrder_service.dart @@ -0,0 +1,44 @@ + +import 'package:diplomaticquarterapp/config/config.dart'; +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/order_model.dart'; +import 'package:diplomaticquarterapp/core/service/base_service.dart'; +import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; +import 'package:diplomaticquarterapp/services/authentication/auth_provider.dart'; +import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; +import 'package:flutter/material.dart'; + + +class CancelOrderService extends BaseService{ + AppSharedPreferences sharedPref = AppSharedPreferences(); + AppGlobal appGlobal = new AppGlobal(); + + AuthenticatedUser authUser = new AuthenticatedUser(); + AuthProvider authProvider = new AuthProvider(); + + List _cancelOrderList = List(); + List get cancelOrderList => _cancelOrderList; + String url =""; + + + Future getCanceledOrder(order) async { + print("step 1"); + hasError = false; + + dynamic res; + + await baseAppClient.getPharmacy(GET_Cancel_ORDER+order, + onSuccess: (dynamic response, int statusCode) { + res = response; + print(res); +// _cancelOrderList.clear(); +// response['success'].forEach((item) { +// _cancelOrderList.add(OrderModel.fromJson(item)); +// }); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }); + return res; + } +} \ No newline at end of file diff --git a/lib/services/pharmacy_services/orderDetails_service.dart b/lib/services/pharmacy_services/orderDetails_service.dart new file mode 100644 index 00000000..a3bb9976 --- /dev/null +++ b/lib/services/pharmacy_services/orderDetails_service.dart @@ -0,0 +1,75 @@ + +import 'package:diplomaticquarterapp/config/config.dart'; +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/order_model.dart'; +import 'package:diplomaticquarterapp/core/service/base_service.dart'; +import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; +import 'package:diplomaticquarterapp/services/authentication/auth_provider.dart'; +import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; +import 'package:flutter/material.dart'; + + +class OrderDetailsService extends BaseService{ + + AppSharedPreferences sharedPref = AppSharedPreferences(); + AppGlobal appGlobal = new AppGlobal(); + + AuthenticatedUser authUser = new AuthenticatedUser(); + AuthProvider authProvider = new AuthProvider(); + + List get orderDetails => orderDetails; + List _orderList = List(); + List get orderList => _orderList; + + + Future getOrderDetails(orderId) async { + print("step 2" + orderId); + hasError = false; + await baseAppClient.getPharmacy(GET_ORDER_DETAILS+orderId, + onSuccess: (dynamic response, int statusCode) { + _orderList.clear(); + response['orders'].forEach((item) { + _orderList.add(OrderModel.fromJson(item)); + }); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }); + } + + Future makeReview(Product product, double rating, String reviewText) async { + hasError = false; + super.error = ""; + + var customerId = await sharedPref.getString(PHARMACY_CUSTOMER_ID); + + + Map body = Map(); + Map reviewBody = Map(); + reviewBody["created_on_utc"] = DateTime.now().toString(); + reviewBody["customer_id"] = customerId; + reviewBody["helpful_no_total"] = 0; + reviewBody["helpful_yes_total"] = 0; + reviewBody["id"] = 0; + reviewBody["is_approved"] = false; + reviewBody["position"] = 0; + reviewBody["product_id"] = product.id; + reviewBody["rating"] = rating; + reviewBody["reply_text"] = reviewText; + reviewBody["store_id"] = 2; + reviewBody["title"] = ""; + body['review'] = reviewBody; + await baseAppClient.post("$PHARMACY_MAKE_REVIEW", + onSuccess: (response, statusCode) async { + /* + "success": { + "SuccessEndUserMsg": "Your request has been completed successfuly.", + "SuccessEndUserMsgN": "تمت العملية بنجاح" + } + */ + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body: body); + } +} \ No newline at end of file diff --git a/lib/services/pharmacy_services/order_service.dart b/lib/services/pharmacy_services/order_service.dart new file mode 100644 index 00000000..e426b801 --- /dev/null +++ b/lib/services/pharmacy_services/order_service.dart @@ -0,0 +1,81 @@ +import 'package:diplomaticquarterapp/config/config.dart'; +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/services/authentication/auth_provider.dart'; +import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; +import 'package:flutter/material.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/order_model.dart'; + + +class OrderService extends BaseService{ + AppSharedPreferences sharedPref = AppSharedPreferences(); + AppGlobal appGlobal = new AppGlobal(); + AuthenticatedUser authUser = new AuthenticatedUser(); + AuthProvider authProvider = new AuthProvider(); + + List _orderList = List(); + List get orderList => _orderList; + String url =""; + + Future getOrder(customerId, pageId) async { + hasError = false; + // url =GET_ORDER+"customer=1,fields=id,order_total,order_status,order_statusn,order_status_id,created_on_utc&page=1&limit=200&customer_id=1367368"; + url =GET_ORDER+"customer=1,fields=id,order_total,order_status,order_statusn,order_status_id,created_on_utc&page=$pageId&limit=200&customer_id=$customerId"; + print(url); + + await baseAppClient.getPharmacy(url, + onSuccess: (dynamic response, int statusCode) { + _orderList.clear(); + response['orders'].forEach((item) { + _orderList.add(OrderModel.fromJson(item)); + }); + print(_orderList.length); + print(response); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }); + } + + + Future getProductReview(orderId) async { + print("step 1"); + hasError = false; + url =GET_ORDER+"customer=1,fields=id,order_total,order_status,order_statusn,order_status_id,created_on_utc&page=1&limit=200&customer_id=1367368"; +// url =GET_ORDER+"customer=1,fields=id,order_total,order_status,order_statusn,order_status_id,created_on_utc&page=$page_id&limit=200&customer_id=$custmerId"; + print(url); + await baseAppClient.getPharmacy(url, + onSuccess: (dynamic response, int statusCode) { + _orderList.clear(); + response['orders'].forEach((item) { + _orderList.add(OrderModel.fromJson(item)); + }); + print(_orderList.length); + print(response); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }); + } +// Future getOrder(BuildContext context ) async { +// +// if (await this.sharedPref.getObject(USER_PROFILE) != null) { +// var data = AuthenticatedUser.fromJson( +// await this.sharedPref.getObject(USER_PROFILE)); +// authUser = data; +// } +// +// dynamic localRes; +// String URL; +// URL = GET_ORDER; +// +// await baseAppClient.get(URL, +// onSuccess: (response, statusCode) async { +// localRes = response; +// }, onFailure: (String error, int statusCode) { +// throw error; +// }); +// return Future.value(localRes); +// } +} \ No newline at end of file diff --git a/lib/services/pharmacy_services/pharmacyAddress_service.dart b/lib/services/pharmacy_services/pharmacyAddress_service.dart new file mode 100644 index 00000000..1bb6571c --- /dev/null +++ b/lib/services/pharmacy_services/pharmacyAddress_service.dart @@ -0,0 +1,102 @@ +import 'package:diplomaticquarterapp/config/config.dart'; +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/Addresses.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/Country.dart'; +import 'package:diplomaticquarterapp/core/service/base_service.dart'; +import 'package:diplomaticquarterapp/services/authentication/auth_provider.dart'; + +class PharmacyAddressService extends BaseService { + List addresses = List(); + CountryData country; + int selectedAddressIndex = 0; + + Future getAddresses() async { + var customerId = await sharedPref.getString(PHARMACY_CUSTOMER_ID); + Map queryParams = {'fields': 'addresses'}; + hasError = false; + Addresses selectedAddress; + try { + await baseAppClient.get("$GET_CUSTOMERS_ADDRESSES$customerId", + onSuccess: (dynamic response, int statusCode) async { + addresses.clear(); + var savedAddress = + await sharedPref.getObject(PHARMACY_SELECTED_ADDRESS); + if (savedAddress != null) { + selectedAddress = Addresses.fromJson(savedAddress); + } + int index = 0; + response['customers'][0]['addresses'].forEach((item) { + Addresses address = Addresses.fromJson(item); + if (selectedAddress != null && selectedAddress.id == item["id"]) { + selectedAddressIndex = index; + } + addresses.add(address); + index++; + }); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, queryParams: queryParams); + } catch (error) { + throw error; + } + } + + Future getCountries(String countryName) async { + hasError = false; + try { + await baseAppClient.get("$PHARMACY_GET_COUNTRY", + onSuccess: (dynamic response, int statusCode) { + // countries.clear(); + response['countries'].forEach((item) { + if (CountryData.fromJson(item).name == countryName || + CountryData.fromJson(item).namen == countryName) { + country = CountryData.fromJson(item); + } + // countries.add(CountryData.fromJson(item)); + }); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }); + } catch (error) { + throw error; + } + } + + Future addCustomerAddress(Addresses address) async { + makeCustomerAddress(address, ADD_CUSTOMER_ADDRESS); + } + + Future editCustomerAddress(Addresses address) async { + makeCustomerAddress(address, EDIT_CUSTOMER_ADDRESS); + } + + Future deleteCustomerAddress(Addresses address) async { + makeCustomerAddress(address, DELETE_CUSTOMER_ADDRESS); + } + + Future makeCustomerAddress(Addresses address, String url) async { + var customerId = await sharedPref.getString(PHARMACY_CUSTOMER_ID); + hasError = false; + super.error = ""; + + Map customerObject = Map(); + customerObject["addresses"] = [address]; + customerObject["id"] = customerId; + customerObject["email"] = address.email; + customerObject["role_ids"] = [3]; + Map body = Map(); + body["customer"] = customerObject; + + await baseAppClient.post("$url", onSuccess: (response, statusCode) async { + addresses.clear(); + response['customers'][0]['addresses'].forEach((item) { + addresses.add(Addresses.fromJson(item)); + }); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body: body); + } +} diff --git a/lib/services/pharmacy_services/product_detail_service.dart b/lib/services/pharmacy_services/product_detail_service.dart new file mode 100644 index 00000000..7a2947b0 --- /dev/null +++ b/lib/services/pharmacy_services/product_detail_service.dart @@ -0,0 +1,178 @@ +import 'package:diplomaticquarterapp/config/config.dart'; +import 'package:diplomaticquarterapp/core/service/base_service.dart'; +import 'package:diplomaticquarterapp/models/pharmacy/Wishlist.dart'; +import 'package:diplomaticquarterapp/models/pharmacy/addToCartModel.dart'; +import 'package:diplomaticquarterapp/models/pharmacy/locationModel.dart'; +import 'package:diplomaticquarterapp/models/pharmacy/productDetailModel.dart'; +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/uitl/app_toast.dart'; +import 'package:diplomaticquarterapp/models/pharmacy/specification.dart'; + +class ProductDetailService extends BaseService { + bool isLogin = false; + + List _productDetailList = List(); + List get productDetailList => _productDetailList; + + List _productLocationList = List(); + List get productLocationList => _productLocationList; + + List _addToCartModel = List(); + List get addToCartModel => _addToCartModel; + + List _wishListProducts = List(); + List get wishListProducts => _wishListProducts; + + List _productSpecification = List(); + List get productSpecification => _productSpecification; + + + + Future getProductReviews(productID) async { + hasError = false; + await baseAppClient.getPharmacy(GET_PRODUCT_DETAIL+productID+"?fields=reviews", + onSuccess: (dynamic response, int statusCode) { + _productDetailList.clear(); + response['products'].forEach((item) { + _productDetailList.add(ProductDetail.fromJson(item)); + print(response); + }); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }); + } + + Future getProductAvailabiltyDetail() async { + hasError = false; + Map request; + + request = { + "Channel": 3, + "DeviceTypeID": 2, + "IPAdress": "10.20.10.20", + "LanguageID": 2, + "PatientOutSA": 0, + "SKU": "6720020025", + "SessionID": null, + "VersionID": 5.6, + "generalid": "Cs2020@2016\$2958", + "isDentalAllowedBackend": false + }; + await baseAppClient.post(GET_LOCATION, + onSuccess: (dynamic response, int statusCode) { + _productLocationList.clear(); + response['PharmList'].forEach((item) { + _productLocationList.add(LocationModel.fromJson(item)); + print(_productLocationList); + print(response); + }); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body: request); + } + + Future addToCart(quantity, itemID) async { + var customerId = await sharedPref.getString(PHARMACY_CUSTOMER_ID); + hasError = false; + Map request; + + request = { + "shopping_cart_item": + { + "quantity": quantity, + "shopping_cart_type": "1", + "product_id": itemID, + "customer_id": customerId, + "language_id": 1 + } + }; + await baseAppClient.post(GET_SHOPPING_CART, + onSuccess: (dynamic response, int statusCode) { + _addToCartModel.clear(); + response['shopping_carts'].forEach((item) { + _addToCartModel.add(Wishlist.fromJson(item)); + }); + AppToast.showSuccessToast(message: 'You have added a product to the cart'); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + AppToast.showErrorToast(message: 'something went wrong please try again'); + }, body: request); + } + + Future addToWishlist(itemID) async { + var customerId = await sharedPref.getString(PHARMACY_CUSTOMER_ID); + hasError = false; + Map request; + + request = { + "shopping_cart_item": + { + "quantity": 1, + "shopping_cart_type": "Wishlist", + "product_id": itemID, + "customer_id": customerId, + "language_id": 1 + } + }; + await baseAppClient.post(GET_SHOPPING_CART, + onSuccess: (dynamic response, int statusCode) { + _wishListProducts.clear(); + response['shopping_carts'].forEach((item) { + _wishListProducts.add(Wishlist.fromJson(item)); + AppToast.showSuccessToast(message: 'You have added a product to the Wishlist'); + }); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + AppToast.showErrorToast(message: 'something went wrong please try again'); + }, body: request); + } + + Future getWishlistItems() async { + var customerId = await sharedPref.getString(PHARMACY_CUSTOMER_ID); + hasError = false; + await baseAppClient.getPharmacy(GET_WISHLIST+customerId+"?shopping_cart_type=2", + onSuccess: (dynamic response, int statusCode) { + _wishListProducts.clear(); + response['shopping_carts'].forEach((item) { + _wishListProducts.add(Wishlist.fromJson(item)); + }); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }); + } + Future delteItemFromWishlist(itemID) async { + var customerId = await sharedPref.getString(PHARMACY_CUSTOMER_ID); + hasError = false; + await baseAppClient.getPharmacy(DELETE_WISHLIST+customerId+"+&product_id="+itemID+"&cart_type=Wishlist", + onSuccess: (dynamic response, int statusCode) { + _wishListProducts.clear(); + response['shopping_carts'].forEach((item) { + _wishListProducts.add(Wishlist.fromJson(item)); + }); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }); + } + + Future productSpecificationData(itemID) async { + hasError = false; + + await baseAppClient.getPharmacy(GET_SPECIFICATION+itemID, + onSuccess: (dynamic response, int statusCode) { + _productSpecification.clear(); + response['specification'].forEach((item) { + _productSpecification.add(SpecificationModel.fromJson(item)); + }); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }); + } + +} diff --git a/lib/services/pharmacy_services/review_service.dart b/lib/services/pharmacy_services/review_service.dart new file mode 100644 index 00000000..44839955 --- /dev/null +++ b/lib/services/pharmacy_services/review_service.dart @@ -0,0 +1,38 @@ +import 'package:diplomaticquarterapp/config/config.dart'; +import 'package:diplomaticquarterapp/core/service/base_service.dart'; +import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; +import 'package:diplomaticquarterapp/models/pharmacy/reviewModel.dart'; +import 'package:diplomaticquarterapp/services/authentication/auth_provider.dart'; +import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; + + +class ReviewService extends BaseService { + AppSharedPreferences sharedPref = AppSharedPreferences(); + + AuthenticatedUser authUser = new AuthenticatedUser(); + AuthProvider authProvider = new AuthProvider(); + + bool isLogin = false; + List _reviewList = List(); + List get reviewList => _reviewList; + + + Future getReview() async { + + var customerId = await sharedPref.getString(PHARMACY_CUSTOMER_ID); + + hasError = false; + await baseAppClient.getPharmacy(GET_REVIEW+customerId, + onSuccess: (dynamic response, int statusCode) { + _reviewList.clear(); + response['reviews'].forEach((item) { + _reviewList.add(Review.fromJson(item)); + }); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }); + } + +} diff --git a/lib/services/pharmacy_services/wishList_service.dart b/lib/services/pharmacy_services/wishList_service.dart new file mode 100644 index 00000000..5404a2bd --- /dev/null +++ b/lib/services/pharmacy_services/wishList_service.dart @@ -0,0 +1,72 @@ +import 'package:diplomaticquarterapp/config/config.dart'; +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/pharmacy/Wishlist.dart'; +import 'package:diplomaticquarterapp/models/pharmacy/products.dart'; +import 'package:diplomaticquarterapp/services/authentication/auth_provider.dart'; +import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; +import 'package:flutter/material.dart'; + + +class WishListService extends BaseService { + AppSharedPreferences sharedPref = AppSharedPreferences(); + bool isLogin = false; + List _wishListProducts = List(); + List get wishListProducts => _wishListProducts; + +// Future getWishlist() async { +// var isLogin = await sharedPref.getString(LOGIN_TOKEN_ID); +// this.isLogin = isLogin != null; +//// if (!isLogin) { +//// // if not login +//// } else { +//// try { +//// await baseAppClient.get( +//// GET_WISHLIST +'/productsbyids/5308,3608,2316,963,5045,2714,1480,',//+ "272843" + "?shopping_cart_type=2", +//// onSuccess: (dynamic response, int statusCode) { +//// wishListProducts.clear(); +//// response['shopping_carts'].forEach((item) { +//// wishListProducts.add(Product.fromJson(item)); +//// }); +//// }, onFailure: (String error, int statusCode) { +//// hasError = true; +//// super.error = error; +//// }); +//// } catch (error) { +//// throw error; +//// } +//// } +// hasError = false; +// try { +// await baseAppClient.getPharmacy(GET_WISHLIST+"1367368?shopping_cart_type=2", +// onSuccess: (dynamic response, int statusCode) { +// wishListProducts.clear(); +// response.forEach((item) { +// wishListProducts.add(Wishlist.fromJson(response)); +// }); +// }, onFailure: (String error, int statusCode) { +// hasError = true; +// super.error = error; +// }); +// } catch (error) { +// throw error; +// } +// } + + Future getWishlist() async { + var customerId = await sharedPref.getString(PHARMACY_CUSTOMER_ID); + hasError = false; + await baseAppClient.getPharmacy(GET_WISHLIST+customerId+"?shopping_cart_type=2", + onSuccess: (dynamic response, int statusCode) { + _wishListProducts.clear(); + response['shopping_carts'].forEach((item) { + _wishListProducts.add(Wishlist.fromJson(item)); + }); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }); + } + +} diff --git a/lib/services/pharmacy_services/writeReview_service.dart b/lib/services/pharmacy_services/writeReview_service.dart new file mode 100644 index 00000000..573095eb --- /dev/null +++ b/lib/services/pharmacy_services/writeReview_service.dart @@ -0,0 +1,40 @@ + +import 'package:diplomaticquarterapp/config/config.dart'; +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/core/model/pharmacies/order_model.dart'; +import 'package:diplomaticquarterapp/core/service/base_service.dart'; +import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; +import 'package:diplomaticquarterapp/services/authentication/auth_provider.dart'; +import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; +import 'package:flutter/material.dart'; + + +class writeReviewService extends BaseService{ + + + + AppSharedPreferences sharedPref = AppSharedPreferences(); + AppGlobal appGlobal = new AppGlobal(); + + AuthenticatedUser authUser = new AuthenticatedUser(); + AuthProvider authProvider = new AuthProvider(); + + List get writeReview => writeReview; + List _writeReviewList = List(); + List get orderList => _writeReviewList; + + + Future getProductReview() async { + hasError = false; + await baseAppClient.getPharmacy(WRITE_REVIEW, + onSuccess: (dynamic response, int statusCode) { + _writeReviewList.clear(); + response[''].forEach((item) { + _writeReviewList.add(OrderModel.fromJson(item)); + }); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }); + } +} \ No newline at end of file diff --git a/lib/splashPage.dart b/lib/splashPage.dart index aaffcbbd..20da2ba6 100644 --- a/lib/splashPage.dart +++ b/lib/splashPage.dart @@ -1,15 +1,19 @@ import 'dart:async'; -import 'package:diplomaticquarterapp/core/service/privilege_service.dart'; import 'package:diplomaticquarterapp/pages/landing/landing_page.dart'; import 'package:diplomaticquarterapp/uitl/app_shared_preferences.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 'config/shared_pref_kay.dart'; +import 'config/size_config.dart'; import 'core/service/AuthenticatedUserObject.dart'; +import 'core/service/privilege_service.dart'; import 'core/viewModels/project_view_model.dart'; import 'locator.dart'; import 'models/Authentication/authenticated_user.dart'; +import 'widgets/transitions/slide_up_page.dart'; AppSharedPreferences sharedPref = new AppSharedPreferences(); AuthenticatedUserObject authenticatedUserObject = @@ -22,26 +26,24 @@ class SplashScreen extends StatefulWidget { class _SplashScreenState extends State { PrivilegeService _privilegeService = locator(); - - //Provider.of(context, listen: false).isLogin @override void initState() { super.initState(); Timer( Duration(seconds: 1, milliseconds: 500), - () { - loadPrivilege().then((value) { - Navigator.of(context).pushReplacement( - MaterialPageRoute( - builder: (BuildContext context) => LandingPage(), - ), - ); - }); + () { + loadPrivilege().then((value) { + Navigator.of(context).pushReplacement( + MaterialPageRoute( + builder: (BuildContext context) => LandingPage(), + ), + ); + }); + }, ); } - /// load the Privilege from service Future loadPrivilege() async { await _privilegeService.getPrivilege(); @@ -52,12 +54,7 @@ class _SplashScreenState extends State { Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, - body: Center( - child: Padding( - padding: const EdgeInsets.all(12.0), - child: Image.asset('assets/images/DQ/DQ_logo.png'), - ), - ), + body: Image.asset('assets/images/powerd-by.jpg',fit: BoxFit.fitWidth,width: MediaQuery.of(context).size.width,), ); } } diff --git a/lib/theme/theme_value.dart b/lib/theme/theme_value.dart index aedd0fbf..d19e13b2 100644 --- a/lib/theme/theme_value.dart +++ b/lib/theme/theme_value.dart @@ -53,7 +53,7 @@ final blueBackground = Color(0xFFFFFFFF); ), ); - var defaultTheme = ThemeData( + final defaultTheme = ThemeData( //fontFamily: ProjectViewModel().isArabic? 'Cairo' : 'WorkSans', primarySwatch: Colors.blue, visualDensity: VisualDensity.adaptivePlatformDensity, @@ -65,7 +65,6 @@ final blueBackground = Color(0xFFFFFFFF); }, ), hintColor: Colors.grey[400], - accentColor: Color(0xffB8382C), disabledColor: Colors.grey[300], errorColor: Color.fromRGBO(235, 80, 60, 1.0), scaffoldBackgroundColor: Color(0xffEEEEEE), diff --git a/lib/uitl/HMGNetworkConnectivity.dart b/lib/uitl/HMGNetworkConnectivity.dart new file mode 100644 index 00000000..228edf93 --- /dev/null +++ b/lib/uitl/HMGNetworkConnectivity.dart @@ -0,0 +1,120 @@ +import 'dart:developer'; +import 'dart:io'; + +import 'package:diplomaticquarterapp/config/config.dart'; +import 'package:diplomaticquarterapp/core/service/client/base_app_client.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/uitl/PlatformBridge.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/uitl/utils.dart'; +import 'package:diplomaticquarterapp/widgets/dialogs/alert_dialog.dart'; +import 'package:diplomaticquarterapp/widgets/dialogs/confirm_dialog.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:wifi/wifi.dart'; + +import 'gif_loader_dialog_utils.dart'; + +class HMGNetworkConnectivity { + final BuildContext context; + final Function callBack; + + final String SSID = "HMG-MobileApp"; + + HMGNetworkConnectivity(this.context, this.callBack); + + void checkAndConnectIfNoInternet() async { + String pingUrl = "$BASE_URL$PING_SERVICE"; + // pingUrl = "https://captive.apple.com"; + + String ssid = await Wifi.ssid.catchError((error) { + log(error.toString()); + }); + + bool alreadyConnected = ssid == SSID; + + BaseAppClient().simpleGet(pingUrl, onSuccess: (dynamic response, int statusCode) { + log("Having internet with status code: $statusCode"); + }, onFailure: (String error, int statusCode) { + if (alreadyConnected) + showFailDailog(TranslationBase.of(context).failedToAccessHmgServices); + else { + confirmFromUser(); + } + }); + } + + void confirmFromUser() { + TranslationBase translator = TranslationBase.of(context); + ConfirmDialog( + context: context, + confirmMessage: translator.wantToConnectWithHmgNetwork, + okText: translator.yes, + okFunction: () { + ConfirmDialog.closeAlertDialog(context); + callBack(); + }, + cancelText: translator.no, + cancelFunction: () { + ConfirmDialog.closeAlertDialog(context); + }).showAlertDialog(context); + } + + void showFailDailog(String message) { + TranslationBase translator = TranslationBase.of(context); + AlertDialogBox( + context: context, + okText: translator.ok, + confirmMessage: message, + okFunction: () { + AlertDialogBox.closeAlertDialog(context); + }).showAlertDialog(context); + } + + // void next() { + // if (Platform.isIOS) { + // confirmFromUser_iOS(); + // } else if (Platform.isAndroid) { + // confirmFromUser(); + // } + // } + + // void confirmFromUser_iOS() { + // String message = "You don't have internet access, Do you want to connect with HMG Network to use App.\n\nMake sure you are in HMG Network range"; + // ConfirmDialog( + // context: context, + // confirmMessage: message, + // okText: "Yes", + // okFunction: () { + // ConfirmDialog.closeAlertDialog(context); + // callBack(); + // }, + // cancelText: "No", + // cancelFunction: () { + // ConfirmDialog.closeAlertDialog(context); + // }).showAlertDialog(context); + // } + + // void connect_Android() { + // // enable the Wifi if its off + // PlatformBridge() + // .enableWifiIfNot() + // .then((value) => { + // if (value == true) + // { + // callBack() + // // Wifi.list(SSID) + // // .then((value1) => { + // // if (value1.length > 0) {callBack()} else {log("No HMG network in range")} + // // }) + // // .catchError((e) { + // // log(e); + // // }) + // } + // }) + // .catchError((error) { + // showFailDailog(error); + // }); + // } +} diff --git a/lib/uitl/HMG_Geofence.dart b/lib/uitl/HMG_Geofence.dart new file mode 100644 index 00000000..54c789ba --- /dev/null +++ b/lib/uitl/HMG_Geofence.dart @@ -0,0 +1,189 @@ +// import 'dart:convert'; +// import 'dart:core'; +// import 'dart:io'; +// import 'dart:isolate'; +// import 'dart:math'; +// import 'dart:ui'; +// +// import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +// import 'package:diplomaticquarterapp/core/model/geofencing/requests/GeoZonesRequestModel.dart'; +// import 'package:diplomaticquarterapp/core/model/geofencing/requests/LogGeoZoneRequestModel.dart'; +// import 'package:diplomaticquarterapp/core/model/geofencing/responses/GeoZonesResponseModel.dart'; +// import 'package:diplomaticquarterapp/core/service/geofencing/GeofencingServices.dart'; +// import 'package:diplomaticquarterapp/locator.dart'; +// import 'package:diplomaticquarterapp/uitl/LocalNotification.dart'; +// import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; +// import 'package:flutter/cupertino.dart'; +// import 'package:flutter/foundation.dart'; +// import 'package:geofencing/geofencing.dart'; +// +// class HMG_Geofencing { +// var _testTrigger = false; +// static var _isolatePortName = "hmg_geofencing_send_port"; +// +// List _zones; +// List registeredGeofences = []; +// +// final AndroidGeofencingSettings androidSettings = AndroidGeofencingSettings(initialTrigger: [GeofenceEvent.enter, GeofenceEvent.exit, GeofenceEvent.dwell], loiteringDelay: 1000 * 60); +// +// final BuildContext context; +// final List triggers = List(); +// +// HMG_Geofencing(this.context) { +// triggers.add(GeofenceEvent.enter); +// triggers.add(GeofenceEvent.exit); +// // triggers.add(GeofenceEvent.dwell); +// } +// +// Future loadZones() async{ +// _zones = await locator().getAllGeoZones(GeoZonesRequestModel()); +// return this; +// } +// +// void init() async { +// // debug check (Testing Geo Zones) +// if (kDebugMode) { +// addTestingGeofences(); +// } +// _saveZones(); +// await GeofencingManager.initialize(); +// await Future.delayed(Duration(seconds: 2)); +// _registerIsolatePort(); +// _registerGeofences().then((value) { +// debugPrint(value.toString()); +// if(_testTrigger) { +// var events = [GeofenceEvent.enter,GeofenceEvent.exit]; +// events.shuffle(); +// transitionTrigger(value, null, events.first); +// } +// }); +// +// } +// +// void _saveZones() { +// var list = List(); +// _zones.forEach((element) { +// list.add(element.toJson()); +// }); +// +// var jsonString = jsonEncode(list); +// AppSharedPreferences pref = AppSharedPreferences(); +// pref.setString(HMG_GEOFENCES, jsonString); +// } +// +// Future> _registerGeofences() async { +// registeredGeofences = await GeofencingManager.getRegisteredGeofenceIds(); +// +// var maxLimit = Platform.isIOS ? 20 : 100; +// +// if (registeredGeofences.length < maxLimit) { +// var notRegistered = _zones.where((element) => !(registeredGeofences.contains(element.geofenceId()))).toList(); +// for (int i = 0; i < notRegistered.length; i++) { +// var zone = notRegistered.elementAt(i); +// var lat = double.tryParse(zone.latitude); +// var lon = double.tryParse(zone.longitude); +// var rad = double.tryParse(zone.radius.toString()); +// +// if (lat != null || lon != null || rad != null) { +// await GeofencingManager.registerGeofence(GeofenceRegion(zone.geofenceId(), lat, lon, rad, triggers), transitionTrigger); +// registeredGeofences.add(zone.geofenceId()); +// if (registeredGeofences.length >= maxLimit) { +// break; +// } +// await Future.delayed(Duration(milliseconds: 100)); +// debugPrint("Geofence: ${zone.description} registered"); +// } else { +// debugPrint("Geofence: ${zone.description} registered"); +// } +// } +// } +// return registeredGeofences; +// } +// +// void addTestingGeofences() { +// _zones.add(GeoZonesResponseModel.get("24.777577,46.652675", 150, "msH")); +// _zones.add(GeoZonesResponseModel.get("24.691136,46.650116", 150, "zkH")); +// _zones.add(GeoZonesResponseModel.get("24.7087913,46.6656461", 150, "csO")); +// } +// +// static void transitionTrigger(List id, Location location, GeofenceEvent event) { +// var dataToSend = id.map((element) => {"event": event, "geofence_id": element}).toList() ?? []; +// final SendPort send = IsolateNameServer.lookupPortByName(_isolatePortName); +// send?.send(dataToSend); +// } +// +// ReceivePort _port = ReceivePort(); +// void _registerIsolatePort() async{ +// IsolateNameServer.registerPortWithName(_port.sendPort, _isolatePortName); +// _port.listen((dynamic data) { +// +// Future result = AppSharedPreferences().getStringWithDefaultValue(HMG_GEOFENCES,"[]"); +// result.then((jsonString){ +// +// List jsonList = json.decode(jsonString) ?? []; +// List geoList = jsonList.map((e) => GeoZonesResponseModel().fromJson(e)).toList() ?? []; +// +// (data as List).forEach((element) async { +// GeofenceEvent geofenceEvent = element["event"]; +// String geofence_id = element["geofence_id"]; +// +// GeoZonesResponseModel geoZone = _findByGeofenceFrom(geoList, by: geofence_id); +// if(geoZone != null) { +// LocalNotification.getInstance().showNow( +// title: "GeofenceEvent: ${_nameOf(geofenceEvent)}", +// subtitle: geoZone.description, +// payload: json.encode(geoZone.toJson())); +// +// _logGeoZoneToServer(zoneId: geoZone.geofId, transition: _idOf(geofenceEvent)); +// } +// +// await Future.delayed(Duration(milliseconds: 700)); +// +// }); +// +// }); +// }); +// } +// +// _logGeoZoneToServer({int zoneId, int transition}){ +// locator() +// .logGeoZone(LogGeoZoneRequestModel(GeoType: transition, PointsID: zoneId ?? 1)) +// .then((response){ +// +// }).catchError((error){ +// +// }); +// +// } +// +// GeoZonesResponseModel _findByGeofenceFrom(List list, { String by}) { +// var have = list.where((element) => element.geofenceId() == by).toList().first; +// return have; +// } +// +// String _nameOf(GeofenceEvent event) { +// switch (event) { +// case GeofenceEvent.enter: +// return "Enter"; +// case GeofenceEvent.exit: +// return "Exit"; +// case GeofenceEvent.dwell: +// return "dWell"; +// default: +// return event.toString(); +// } +// } +// +// int _idOf(GeofenceEvent event){ +// switch (event) { +// case GeofenceEvent.enter: +// return 1; +// case GeofenceEvent.exit: +// return 2; +// case GeofenceEvent.dwell: +// return 3; +// default: +// return -1; +// } +// } +// } diff --git a/lib/uitl/LocalNotification.dart b/lib/uitl/LocalNotification.dart index 5b826f00..e0367ba3 100644 --- a/lib/uitl/LocalNotification.dart +++ b/lib/uitl/LocalNotification.dart @@ -1,17 +1,63 @@ +import 'dart:math'; import 'dart:typed_data'; import 'dart:ui'; import 'package:flutter/cupertino.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; -final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = - FlutterLocalNotificationsPlugin(); +final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); class LocalNotification { - static Future scheduleNotification( - {@required DateTime scheduledNotificationDateTime, - @required String title, - @required String description}) async { + Function(String payload) _onNotificationClick; + static LocalNotification _instance; + static LocalNotification getInstance(){ + return _instance; + } + static init({Function(String payload) onNotificationClick}){ + if(_instance == null){ + _instance = LocalNotification(); + _instance._onNotificationClick = onNotificationClick; + _instance._initialize(); + }else{ + // assert(false,(){ + // //TODO fix it + // "LocalNotification Already Initialized"; + // }); + } + } + + _initialize(){ + var initializationSettingsAndroid = new AndroidInitializationSettings('app_icon'); + var initializationSettingsIOS = IOSInitializationSettings(onDidReceiveLocalNotification: null); + var initializationSettings = InitializationSettings(initializationSettingsAndroid, initializationSettingsIOS); + flutterLocalNotificationsPlugin.initialize(initializationSettings, onSelectNotification: _onNotificationClick); + } + + var _random = new Random(); + _randomNumber({int from = 100000}){ + return _random.nextInt(from); + } + + _vibrationPattern(){ + var vibrationPattern = Int64List(4); + vibrationPattern[0] = 0; + vibrationPattern[1] = 1000; + vibrationPattern[2] = 5000; + vibrationPattern[3] = 2000; + + return vibrationPattern; + } + + Future showNow({@required String title, @required String subtitle, String payload}) { + Future.delayed(Duration(seconds: 1)).then((result) async { + var androidPlatformChannelSpecifics = AndroidNotificationDetails('com.hmg.local_notification', 'HMG', 'HMG', importance: Importance.Max, priority: Priority.High, ticker: 'ticker', vibrationPattern: _vibrationPattern()); + var iOSPlatformChannelSpecifics = IOSNotificationDetails(); + var platformChannelSpecifics = NotificationDetails(androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics); + await flutterLocalNotificationsPlugin.show(_randomNumber(), title, subtitle, platformChannelSpecifics, payload: payload); + }); + } + + Future scheduleNotification({@required DateTime scheduledNotificationDateTime, @required String title, @required String description}) async { ///vibrationPattern var vibrationPattern = Int64List(4); vibrationPattern[0] = 0; @@ -19,10 +65,7 @@ class LocalNotification { vibrationPattern[2] = 5000; vibrationPattern[3] = 2000; - var androidPlatformChannelSpecifics = AndroidNotificationDetails( - 'active-prescriptions', - 'ActivePrescriptions', - 'ActivePrescriptionsDescription', + var androidPlatformChannelSpecifics = AndroidNotificationDetails('active-prescriptions', 'ActivePrescriptions', 'ActivePrescriptionsDescription', // icon: 'secondary_icon', sound: RawResourceAndroidNotificationSound('slow_spring_board'), @@ -34,8 +77,7 @@ class LocalNotification { ledColor: const Color.fromARGB(255, 255, 0, 0), ledOnMs: 1000, ledOffMs: 500); - var iOSPlatformChannelSpecifics = - IOSNotificationDetails(sound: 'slow_spring_board.aiff'); + var iOSPlatformChannelSpecifics = IOSNotificationDetails(sound: 'slow_spring_board.aiff'); ///change it to be as ionic // var platformChannelSpecifics = NotificationDetails( @@ -45,12 +87,9 @@ class LocalNotification { } ///Repeat notification every day at approximately 10:00:00 am - static Future showDailyAtTime() async { + Future showDailyAtTime() async { var time = Time(10, 0, 0); - var androidPlatformChannelSpecifics = AndroidNotificationDetails( - 'repeatDailyAtTime channel id', - 'repeatDailyAtTime channel name', - 'repeatDailyAtTime description'); + var androidPlatformChannelSpecifics = AndroidNotificationDetails('repeatDailyAtTime channel id', 'repeatDailyAtTime channel name', 'repeatDailyAtTime description'); var iOSPlatformChannelSpecifics = IOSNotificationDetails(); // var platformChannelSpecifics = NotificationDetails( // androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics); @@ -63,12 +102,9 @@ class LocalNotification { } ///Repeat notification weekly on Monday at approximately 10:00:00 am - static Future showWeeklyAtDayAndTime() async { + Future showWeeklyAtDayAndTime() async { var time = Time(10, 0, 0); - var androidPlatformChannelSpecifics = AndroidNotificationDetails( - 'show weekly channel id', - 'show weekly channel name', - 'show weekly description'); + var androidPlatformChannelSpecifics = AndroidNotificationDetails('show weekly channel id', 'show weekly channel name', 'show weekly description'); var iOSPlatformChannelSpecifics = IOSNotificationDetails(); // var platformChannelSpecifics = NotificationDetails( // androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics); @@ -81,15 +117,15 @@ class LocalNotification { // platformChannelSpecifics); } - static String _toTwoDigitString(int value) { + String _toTwoDigitString(int value) { return value.toString().padLeft(2, '0'); } - static Future cancelNotification() async { + Future cancelNotification() async { await flutterLocalNotificationsPlugin.cancel(0); } - static Future cancelAllNotifications() async { + Future cancelAllNotifications() async { await flutterLocalNotificationsPlugin.cancelAll(); } } diff --git a/lib/uitl/PlatformBridge.dart b/lib/uitl/PlatformBridge.dart new file mode 100644 index 00000000..3ad91cdd --- /dev/null +++ b/lib/uitl/PlatformBridge.dart @@ -0,0 +1,152 @@ +import 'dart:developer'; + +import 'package:diplomaticquarterapp/config/config.dart'; +import 'package:diplomaticquarterapp/config/localized_values.dart'; +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/core/service/client/base_app_client.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/services.dart'; + +class PlatformBridge { + static const platform = const MethodChannel("HMG-Platform-Bridge"); + static PlatformBridge _shared; + static BuildContext _context; + + // // Singleton + // static final PlatformBridge _singleton = PlatformBridge._internal(); + // factory PlatformBridge() { + // return _singleton; + // } + // PlatformBridge._internal(); + + static PlatformBridge shared() { + if (_shared == null) { + assert(true, "PlatformBridge is not initialized, (Initialized it by calling 'PlatformBridge.init(BuildContext))'."); + } + return _shared; + } + + static void init(BuildContext context) { + _context = context; + _shared = PlatformBridge(); + + Future incoming(MethodCall methodCall) async { + switch (methodCall.method) { + case 'localizedValue': + String key = methodCall.arguments.toString(); + return localizedValue(key); + + case 'getGeoZones': + return getGeoZones(); + + case 'getLogGeofenceFullUrl': + return getLogGeofenceFullUrl(); + + case 'getDefaultHttpParameters': + return getDefaultHttpParameters(); + + default: + throw MissingPluginException('notImplemented'); + } + } + + platform.setMethodCallHandler(incoming); + } + + //--------------------------------- + // Incoming below + //--------------------------------- + static Future localizedValue(String forKey) async { + String currentLanguage = await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar'); + Object localized = platformLocalizedValues[forKey][currentLanguage]; + return (localized != null || (localized is String)) ? localized : forKey; + } + + static Future getGeoZones() async { + var res = await sharedPref.getStringWithDefaultValue(HMG_GEOFENCES, "[]"); + return res; + } + + static Future getLogGeofenceFullUrl() async { + var res = BASE_URL + LOG_GEO_ZONES; + return res; + } + + static Future getDefaultHttpParameters() async { + return BaseAppClient.defaultHttpParameters(); + } + + //--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--// + //--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--// + + //--------------------------------- + // Outgoing below + //--------------------------------- + // Method Names + static const hmg_internet_wifi_connect_method = "connectHMGInternetWifi"; + static const hmg_guest_wifi_connect_method = "connectHMGGuestWifi"; + static const is_hmg_network_available_method = "isHMGNetworkAvailable"; + static const enable_wifi_if_not = "enableWifiIfNot"; + static const show_loading_method = "loading"; + static const register_Hmg_Geofences = "registerHmgGeofences"; + static const un_register_Hmg_Geofences = "unRegisterHmgGeofences"; + + Future connectHMGInternetWifi(String patientId) { + print("Invoking platform method: $hmg_internet_wifi_connect_method"); + try { + return platform.invokeMethod(hmg_internet_wifi_connect_method, [patientId]); + } on PlatformException catch (e) { + print(e); + return Future.error(e); + } + } + + Future connectHMGGuestWifi() { + print("Invoking platform method: $hmg_guest_wifi_connect_method"); + try { + return platform.invokeMethod(hmg_guest_wifi_connect_method); + } on PlatformException catch (e) { + print(e); + return Future.error(e); + } + } + + Future isHMGNetworkAvailable(String ssid) { + print("Invoking platform method: $is_hmg_network_available_method"); + try { + return platform.invokeMethod(is_hmg_network_available_method, ssid); + } on PlatformException catch (e) { + print(e); + return Future.error(e); + } + } + + Future enableWifiIfNot() async { + print("Invoking platform method: $enable_wifi_if_not"); + try { + return platform.invokeMethod(enable_wifi_if_not); + } on PlatformException catch (e) { + print(e); + return Future.error(e); + } + } + + void showLoading(String message, bool show) async { + print("Invoking platform method: $show_loading_method"); + try { + var result = await platform.invokeMethod(show_loading_method, [message, show]); + } on PlatformException catch (e) { + print(e); + } + } + + // GEO Fences + void registerHmgGeofences() async { + var result = await platform.invokeMethod(register_Hmg_Geofences); + } + + void unRegisterHmgGeofences() async { + var result = await platform.invokeMethod(un_register_Hmg_Geofences); + } +} diff --git a/lib/uitl/app_toast.dart b/lib/uitl/app_toast.dart index 8e45e3ce..5c917009 100644 --- a/lib/uitl/app_toast.dart +++ b/lib/uitl/app_toast.dart @@ -64,7 +64,7 @@ class AppToast { FlutterFlexibleToast.showToast( message: message, toastLength: toastLength, - timeInSeconds: timeInSeconds, + timeInSeconds: timeInSeconds=2, fontSize: fontSize, toastGravity: toastGravity, backgroundColor: Colors.green, @@ -87,7 +87,7 @@ class AppToast { static void showErrorToast({ @required String message, Toast toastLength = Toast.LENGTH_LONG, - int timeInSeconds, + int timeInSeconds=2, double fontSize = 16, ToastGravity toastGravity = ToastGravity.TOP, Color textColor = Colors.white, diff --git a/lib/uitl/date_uitl.dart b/lib/uitl/date_uitl.dart index 0b2b45d9..460a4066 100644 --- a/lib/uitl/date_uitl.dart +++ b/lib/uitl/date_uitl.dart @@ -19,24 +19,26 @@ class DateUtil { return DateTime.now(); } - static DateTime convertStringToDateNoTimeZone(String date) { + static DateTime convertStringToDateTime(String date) { if (date != null) { - const start = "/Date("; - const end = ")/"; - final startIndex = date.indexOf(start); - final endIndex = date.indexOf(end, startIndex + start.length); - return DateTime.fromMillisecondsSinceEpoch( - int.parse( - date.substring(startIndex + start.length, endIndex), - ), - ); + try { + var dateT = date.split('/'); + var year = dateT[2].substring(0, 4); + var dateP = + DateTime(int.parse(year), int.parse(dateT[1]), int.parse(dateT[0])); + return dateP; + } catch (e) { + print(e); + } + + return DateTime.now(); } else return DateTime.now(); } static String convertDateToString(DateTime date) { const start = "/Date("; - const end = "+0300)/"; + const end = "+0300)"; int milliseconds = date.millisecondsSinceEpoch; return start + "$milliseconds" + end; @@ -251,6 +253,18 @@ class DateUtil { else return ""; } + /// get data formatted like Apr 26,2020 + /// [dateTime] convert DateTime to data formatted Arabic + static String getMonthDayYearDateFormattedAr(DateTime dateTime) { + if (dateTime != null) + return getMonthArabic(dateTime.month) + + " " + + dateTime.day.toString() + + ", " + + dateTime.year.toString(); + else + return ""; + } /// get data formatted like Thursday, Apr 26,2020 /// [dateTime] convert DateTime to date formatted @@ -276,6 +290,24 @@ class DateUtil { return ""; } + static String getMonthDayYearLangDateFormatted( + DateTime dateTime, String lang) { + if (dateTime != null) + return lang == 'en' + ? getMonth(dateTime.month) + + " " + + dateTime.day.toString() + + " " + + dateTime.year.toString() + : dateTime.day.toString() + + " " + + getMonthArabic(dateTime.month) + + " " + + dateTime.year.toString(); + else + return ""; + } + /// get data formatted like 26/4/2020 /// [dateTime] convert DateTime to data formatted static String getDayMonthYearDateFormatted(DateTime dateTime) { @@ -325,6 +357,11 @@ class DateUtil { return ""; } + static String getFormattedDate(DateTime dateTime, String formattedString){ + return DateFormat(formattedString) + .format(dateTime); + } + static convertISODateToJsonDate(String isoDate) { return "/Date(" + DateFormat('mm-dd-yyy') diff --git a/lib/uitl/location_util.dart b/lib/uitl/location_util.dart index 5c2d3a3c..c3799425 100644 --- a/lib/uitl/location_util.dart +++ b/lib/uitl/location_util.dart @@ -20,7 +20,8 @@ class LocationUtils { Geolocator.checkPermission().then((permission) { if (permission == LocationPermission.always || permission == LocationPermission.whileInUse) { - Geolocator.getLastKnownPosition().then((value) => setLocation(value)); + Geolocator.getLastKnownPosition() + .then((value) => setLocation(value)); } if (permission == LocationPermission.denied || @@ -57,9 +58,12 @@ class LocationUtils { } void setLocation(Position position) { - print(position); - this.sharedPref.setDouble(USER_LAT, position.latitude ?? 0.0); - this.sharedPref.setDouble(USER_LONG, position.longitude ?? 0.0); + this + .sharedPref + .setDouble(USER_LAT, position != null ? position.latitude : 0.0); + this + .sharedPref + .setDouble(USER_LONG, position != null ? position.longitude : 0.0); } void setZeroLocation() { diff --git a/lib/uitl/translations_delegate_base.dart b/lib/uitl/translations_delegate_base.dart index 674dca5b..06c6628c 100644 --- a/lib/uitl/translations_delegate_base.dart +++ b/lib/uitl/translations_delegate_base.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'package:diplomaticquarterapp/config/localized_values.dart'; +import 'package:diplomaticquarterapp/pages/symptom-checker/select-gender.dart'; import 'package:flutter/foundation.dart' show SynchronousFuture; import 'package:flutter/material.dart'; @@ -13,6 +14,10 @@ class TranslationBase { return Localizations.of(context, TranslationBase); } + String by(String key) { + return localizedValues[key][locale.languageCode]; + } + String get dashboardScreenToolbarTitle => localizedValues['dashboardScreenToolbarTitle'][locale.languageCode]; @@ -221,6 +226,8 @@ class TranslationBase { String get upcomingPaymentPending => localizedValues['upcoming-payment-pending'][locale.languageCode]; + String get upcomingConfirmMore => + localizedValues['book-success-confirm-more-24-1-2'][locale.languageCode]; String get upcomingPaymentNow => localizedValues['upcoming-payment-now'][locale.languageCode]; @@ -455,6 +462,7 @@ class TranslationBase { String get viewAllHabibMedicalService => localizedValues['ViewAllHabibMedicalService'][locale.languageCode]; String get viewAll => localizedValues['viewAll'][locale.languageCode]; + String get view => localizedValues['view'][locale.languageCode]; String get contactUs => localizedValues['ContactUs'][locale.languageCode]; String get viewAllWaysReachUs => localizedValues['ViewAllWaysReachUs'][locale.languageCode]; @@ -692,6 +700,72 @@ class TranslationBase { localizedValues['ServiceInformationButton'][locale.languageCode]; String get serviceInformationTitle => localizedValues['ServiceInformationTitle'][locale.languageCode]; + String get infoLab => localizedValues['info-lab'][locale.languageCode]; + String get infoRadiology => + localizedValues['info-radiology'][locale.languageCode]; + String get orders => localizedValues['orders'][locale.languageCode]; + String get lakum => localizedValues['lakum'][locale.languageCode]; + String get wishlist => localizedValues['wishlist'][locale.languageCode]; + String get reviews => localizedValues['reviews'][locale.languageCode]; + String get myPrescriptions => + localizedValues['myPrescriptions'][locale.languageCode]; + String get medicationRefill => + localizedValues['medicationRefill'][locale.languageCode]; + String get pillReminder => + localizedValues['pillReminder'][locale.languageCode]; + String get shippingAddresses => + localizedValues['shippingAddresses'][locale.languageCode]; + String get reachUs => localizedValues['reachUs'][locale.languageCode]; + String get ourLocations => + localizedValues['ourLocations'][locale.languageCode]; + String get edit => localizedValues['edit'][locale.languageCode]; + String get delete => localizedValues['delete'][locale.languageCode]; + String get addAddress => localizedValues['addAddress'][locale.languageCode]; + String get addNewAddress => + localizedValues['addNewAddress'][locale.languageCode]; + String get order => localizedValues['order'][locale.languageCode]; + String get delivered => localizedValues['delivered'][locale.languageCode]; + String get processing => localizedValues['processing'][locale.languageCode]; + String get pending => localizedValues['pending'][locale.languageCode]; + String get cancelled => localizedValues['cancelled'][locale.languageCode]; + String get writeReview => localizedValues['writeReview'][locale.languageCode]; + String get shareReview => localizedValues['shareReview'][locale.languageCode]; + String get backMyAccount => + localizedValues['backMyAccount'][locale.languageCode]; + String get reviewSuccessful => + localizedValues['reviewSuccessful'][locale.languageCode]; + String get reviewShared => + localizedValues['reviewShared'][locale.languageCode]; + String get reviewComment => + localizedValues['reviewComment'][locale.languageCode]; + String get shippedMethod => + localizedValues['shippedMethod'][locale.languageCode]; + String get orderDetail => localizedValues['orderDetail'][locale.languageCode]; + String get subtotal => localizedValues['subtotal'][locale.languageCode]; + String get shipping => localizedValues['shipping'][locale.languageCode]; + String get shipBy => localizedValues['shipBy'][locale.languageCode]; + String get lakumPoints => localizedValues['lakumPoints'][locale.languageCode]; + String get use => localizedValues['use'][locale.languageCode]; + String get proceedPay => localizedValues['proceedPay'][locale.languageCode]; + String get vat => localizedValues['vat'][locale.languageCode]; + String get inclusiveVat => + localizedValues['inclusiveVat'][locale.languageCode]; + String get items => localizedValues['items'][locale.languageCode]; + String get checkOut => localizedValues['checkOut'][locale.languageCode]; + String get total => localizedValues['total'][locale.languageCode]; + String get sar => localizedValues['sar'][locale.languageCode]; + String get payOnline => localizedValues['payOnline'][locale.languageCode]; + String get cancelOrder => localizedValues['cancelOrder'][locale.languageCode]; + String get confirmAddress => + localizedValues['confirmAddress'][locale.languageCode]; + String get confirmLocation => + localizedValues['confirmLocation'][locale.languageCode]; + String get confirmDeleteMsg => + localizedValues['confirmDeleteMsg'][locale.languageCode]; + String get confirmDelete => + localizedValues['confirmDelete'][locale.languageCode]; + String get confirmCancellation => + localizedValues['confirmCancellation'][locale.languageCode]; String get serviceInformation => localizedValues['ServiceInformation'][locale.languageCode]; String get homeHealthCare => @@ -711,17 +785,30 @@ class TranslationBase { String get orderDate => localizedValues['orderDate'][locale.languageCode]; String get itemsNo => localizedValues['itemsNo'][locale.languageCode]; String get noOrder => localizedValues['noOrder'][locale.languageCode]; - String get infoLab => localizedValues['info-lab'][locale.languageCode]; - String get infoRadiology => - localizedValues['info-radiology'][locale.languageCode]; - // pharmacy module - String get medicationRefill => - localizedValues['medicationRefill'][locale.languageCode]; String get offersAndPromotions => localizedValues['offersAndPromotions'][locale.languageCode]; - String get myPrescriptions => - localizedValues['myPrescriptions'][locale.languageCode]; + String get review => localizedValues['review'][locale.languageCode]; + String get deliveredOrder => + localizedValues['deliveredOrder'][locale.languageCode]; + String get pendingOrder => + localizedValues['pendingOrder'][locale.languageCode]; + String get processingOrder => + localizedValues['processingOrder'][locale.languageCode]; + String get cancelledOrder => + localizedValues['cancelledOrder'][locale.languageCode]; + String get compare => localizedValues['compare'][locale.languageCode]; + String get medicationsRefill => + localizedValues['medicationsRefill'][locale.languageCode]; + String get myPrescription => + localizedValues['myPrescription'][locale.languageCode]; + String get quantity => localizedValues['quantity'][locale.languageCode]; + String get conditionsHMG => + localizedValues['conditionsHMG'][locale.languageCode]; + String get conditions => localizedValues['conditions'][locale.languageCode]; + + // pharmacy module + String get searchAndScanMedication => localizedValues['searchAndScanMedication'][locale.languageCode]; String get shopByBrands => @@ -731,6 +818,32 @@ class TranslationBase { String get bestSellers => localizedValues['bestSellers'][locale.languageCode]; String get deleteAllItems => localizedValues['deleteAllItems'][locale.languageCode]; + String get selectAddress => + localizedValues['selectAddress'][locale.languageCode]; + String get shippingAddress => + localizedValues['shippingAddress'][locale.languageCode]; + String get changeAddress => + localizedValues['changeAddress'][locale.languageCode]; + String get selectPaymentOption => + localizedValues['selectPaymentOption'][locale.languageCode]; + String get changeMethod => + localizedValues['changeMethod'][locale.languageCode]; + String get reviewOrder => localizedValues['reviewOrder'][locale.languageCode]; + String get orderSummary => + localizedValues['orderSummary'][locale.languageCode]; + String get active => localizedValues['active'][locale.languageCode]; + String get inactive => localizedValues['inactive'][locale.languageCode]; + String get balance => localizedValues['balance'][locale.languageCode]; + String get gained => localizedValues['gained'][locale.languageCode]; + String get consumed => localizedValues['consumed'][locale.languageCode]; + String get transferred => localizedValues['transferred'][locale.languageCode]; + String get checkBeneficiary => + localizedValues['checkBeneficiary'][locale.languageCode]; + String get beneficiaryName => + localizedValues['beneficiaryName'][locale.languageCode]; + String get accountActivation => + localizedValues['accountActivation'][locale.languageCode]; + String get acceptLbl => localizedValues['acceptLbl'][locale.languageCode]; String get termsService => localizedValues['TermsService'][locale.languageCode]; @@ -756,6 +869,11 @@ class TranslationBase { String get selectAge => localizedValues['select-age'][locale.languageCode]; String get iAm => localizedValues['i-am'][locale.languageCode]; String get yearOld => localizedValues['years-old'][locale.languageCode]; + String get categorise => localizedValues['categorise'][locale.languageCode]; + String get cart => localizedValues['cart'][locale.languageCode]; + String get wishList => localizedValues['wishList'][locale.languageCode]; + String get searchProductHere => + localizedValues['searchProductHere'][locale.languageCode]; String get email => localizedValues['email'][locale.languageCode]; String get book => localizedValues['Book'][locale.languageCode]; String get appointmentLabel => @@ -832,10 +950,8 @@ class TranslationBase { localizedValues['accessibility'][locale.languageCode]; String get selectClinic => localizedValues['selectClinic'][locale.languageCode]; - String get reviews => localizedValues['reviews'][locale.languageCode]; String get orderStatus => localizedValues['orderStatus'][locale.languageCode]; - String get cancelOrder => localizedValues['CancelOrder'][locale.languageCode]; String get findUs => localizedValues['FindUs'][locale.languageCode]; String get feedback => localizedValues['Feedback'][locale.languageCode]; String get liveChat => localizedValues['LiveChat'][locale.languageCode]; @@ -901,6 +1017,14 @@ class TranslationBase { localizedValues['blood-instruction'][locale.languageCode]; String get bloodTermsNcondition => localizedValues['view-terms'][locale.languageCode]; + String get wantToConnectWithHmgNetwork => + localizedValues['wantConnectHmgNetwork'][locale.languageCode]; + String get failedToAccessHmgServices => + localizedValues['failedToAccessHmgServices'][locale.languageCode]; + String get enablingWifi => + localizedValues['enablingWifi'][locale.languageCode]; + String get offerAndPackages => + localizedValues['offerAndPackages'][locale.languageCode]; String get invoiceNo => localizedValues['InvoiceNo'][locale.languageCode]; String get specialResult => localizedValues['SpecialResult'][locale.languageCode]; @@ -912,6 +1036,7 @@ class TranslationBase { String get range => localizedValues['range'][locale.languageCode]; String get outpatient => localizedValues['out-patient'][locale.languageCode]; String get inPatient => localizedValues['in-patient'][locale.languageCode]; + String get liveCare => localizedValues['liveCare'][locale.languageCode]; String get report => localizedValues['report'][locale.languageCode]; String get openRad => localizedValues['open-rad'][locale.languageCode]; String get sendCopyRad => localizedValues['send-copy'][locale.languageCode]; @@ -930,7 +1055,6 @@ class TranslationBase { String get addChild => localizedValues['add-child'][locale.languageCode]; String get childName => localizedValues['child-name'][locale.languageCode]; String get childDob => localizedValues['childDob'][locale.languageCode]; - String get delete => localizedValues['delete'][locale.languageCode]; String get deletedChildMes => localizedValues['deleted-child-mes'][locale.languageCode]; String get visit => localizedValues['visit'][locale.languageCode]; @@ -971,7 +1095,6 @@ class TranslationBase { localizedValues['info-ambulance'][locale.languageCode]; String get transportHeading => localizedValues['RRT-transport-heading'][locale.languageCode]; - String get sar => localizedValues['sar'][locale.languageCode]; String get directionHeading => localizedValues['RRT-direction-heading'][locale.languageCode]; String get toHospital => localizedValues['to-hospital'][locale.languageCode]; @@ -999,7 +1122,7 @@ class TranslationBase { String get selectAmbulate => localizedValues['select-ambulate'][locale.languageCode]; String get wheelchair => localizedValues['wheelchair'][locale.languageCode]; - String get walker => localizedValues['walker"'][locale.languageCode]; + String get walker => localizedValues['walker'][locale.languageCode]; String get stretcher => localizedValues['stretcher'][locale.languageCode]; String get none => localizedValues['none'][locale.languageCode]; String get RRTSummary => localizedValues['RRT-Summary'][locale.languageCode]; @@ -1012,6 +1135,8 @@ class TranslationBase { localizedValues['info-my-appointments'][locale.languageCode]; String get infoTodo => localizedValues['info-todo'][locale.languageCode]; String get familyInfo => localizedValues['family-info'][locale.languageCode]; + String get profileUpdate => + localizedValues['update-succ'][locale.languageCode]; String get dentalComplaints => localizedValues['dental-complains'][locale.languageCode]; String get emptyResult => @@ -1052,9 +1177,89 @@ class TranslationBase { String get requested => localizedValues['requested'][locale.languageCode]; String get ready => localizedValues['ready'][locale.languageCode]; String get completed => localizedValues['completed'][locale.languageCode]; - String get cancelled => localizedValues['cancelled'][locale.languageCode]; String get requestMedicalReport => localizedValues['request-medical-report'][locale.languageCode]; + String get insurCards => localizedValues['insur-cards'][locale.languageCode]; + String get labResult => localizedValues['labResult'][locale.languageCode]; + String get details => localizedValues['details'][locale.languageCode]; + String get age => localizedValues['age'][locale.languageCode]; + String get activeInsurence => + localizedValues['active-insurence'][locale.languageCode]; + String get notActive => localizedValues['not-active'][locale.languageCode]; + String get cardDetail => localizedValues['card-detail'][locale.languageCode]; + String get dr => localizedValues['Dr'][locale.languageCode]; + String get sendSuc => localizedValues['sendSuc'][locale.languageCode]; + String get instructionsPharmacies => + localizedValues['instructions-pharmacies'][locale.languageCode]; + String get selectHospitalDec => + localizedValues['select-hospital'][locale.languageCode]; + String get start => localizedValues['start'][locale.languageCode]; + String get infoChat => localizedValues['info-chat'][locale.languageCode]; + + String get noRecords => localizedValues['empty'][locale.languageCode]; + String get lastVisit => localizedValues['last-visit'][locale.languageCode]; + String get tapTitle => localizedValues['tap-title'][locale.languageCode]; + String get later => localizedValues['later'][locale.languageCode]; + + String get lastAppointment => + localizedValues['last-appointment'][locale.languageCode]; + String get rateClinic => localizedValues['rate-clinic'][locale.languageCode]; + String get fetchData => localizedValues['fetch-data'][locale.languageCode]; + + String get sendConfEmail => + localizedValues['send-email'][locale.languageCode]; + String get noDataAvailable => + localizedValues['noDataAvailable'][locale.languageCode]; + String get theName => localizedValues['thename'][locale.languageCode]; + String get noSearchResult => + localizedValues['noSearchResult'][locale.languageCode]; + String get selectFileSouse => + localizedValues['selectFileSouse'][locale.languageCode]; + String get rate => localizedValues['rate'][locale.languageCode]; + String get bookedSuccess => + localizedValues['booked-success'][locale.languageCode]; + String get appoReminder30 => + localizedValues['appo-reminder-select-option-30'][locale.languageCode]; + String get appoReminder60 => + localizedValues['appo-reminder-select-option-60'][locale.languageCode]; + String get appoReminder90 => + localizedValues['appo-reminder-select-option-90'][locale.languageCode]; + String get appoReminder120 => + localizedValues['appo-reminder-select-option-120'][locale.languageCode]; + String get gallery => localizedValues['gallery'][locale.languageCode]; + String get camera => localizedValues['camera'][locale.languageCode]; + String get medReport => localizedValues['med-report'][locale.languageCode]; + String get newMedReport => + localizedValues['new-med-report'][locale.languageCode]; + String get requestReport => + localizedValues['requestReport'][locale.languageCode]; + String get confirmMsgReport => + localizedValues['confirm-msg-report'][locale.languageCode]; + String get successSendReport => + localizedValues['successSendReport'][locale.languageCode]; + String get pulseTitle => localizedValues['pulseTitle'][locale.languageCode]; + String get systolicLng => + localizedValues['systolic-lng'][locale.languageCode]; + String get diastolicLng => + localizedValues['diastolic-lng'][locale.languageCode]; + String get policyHolder => + localizedValues['policy-holder'][locale.languageCode]; + String get policyNo => localizedValues['policy-no'][locale.languageCode]; + String get expiryDateTitle => + localizedValues['expiry-date'][locale.languageCode]; + String get classTitle => localizedValues['class'][locale.languageCode]; + String get approval => localizedValues['approval'][locale.languageCode]; + String get agree => localizedValues['agree'][locale.languageCode]; + String get disagree => localizedValues['disagree'][locale.languageCode]; + String get requestSent => + localizedValues['request-sent'][locale.languageCode]; + String get attachInsuraceImage => + localizedValues['attach-insurace-image'][locale.languageCode]; + String get infoInsurCards => + localizedValues['info-insur-cards'][locale.languageCode]; + String get scanNow => localizedValues['scan-now'][locale.languageCode]; + String get pharmacyServiceTermsCondition => + localizedValues['pharmacyServiceTermsCondition'][locale.languageCode]; String get referralStatus => localizedValues['referralStatus'][locale.languageCode]; @@ -1085,10 +1290,37 @@ class TranslationBase { String get help => localizedValues['help'][locale.languageCode]; String get habibRobotText => localizedValues['habibRobotText'][locale.languageCode]; - String get selectAddress => - localizedValues['selectAddress'][locale.languageCode]; - String get addNewAddress => - localizedValues['addNewAddress'][locale.languageCode]; + + String get topBrands => localizedValues['topBrands'][locale.languageCode]; + String get notifyMe => localizedValues['notifyMe'][locale.languageCode]; + String get specification => + localizedValues['specification'][locale.languageCode]; + String get availability => + localizedValues['availability'][locale.languageCode]; + String get quantitySize => + localizedValues['quantitySize'][locale.languageCode]; + String get addToCart => localizedValues['addToCart'][locale.languageCode]; + String get buyNow => localizedValues['buyNow'][locale.languageCode]; + String get quantityShortcut => + localizedValues['quantityShortcut'][locale.languageCode]; + + String get year => localizedValues['Year'][locale.languageCode]; + String get month => localizedValues['Month'][locale.languageCode]; + String get point => localizedValues['point'][locale.languageCode]; + String get riyal => localizedValues['riyal'][locale.languageCode]; + String get termOfService => + localizedValues['termOfService'][locale.languageCode]; + String get shoppingCart => + localizedValues['shoppingCart'][locale.languageCode]; + String get covidTest => localizedValues['covidTest'][locale.languageCode]; + String get driveThru => localizedValues['driveThru'][locale.languageCode]; + String get NearestErDesc => + localizedValues['NearestErDesc'][locale.languageCode]; + String get NearestEr => localizedValues['NearestEr'][locale.languageCode]; + String get infoCMC => localizedValues['infoCMC'][locale.languageCode]; + String get instructionAgree => + localizedValues['instructionAgree'][locale.languageCode]; + String get reqId => localizedValues['reqId'][locale.languageCode]; } class TranslationBaseDelegate extends LocalizationsDelegate { diff --git a/lib/uitl/utils.dart b/lib/uitl/utils.dart index 34c0e58d..58ef9421 100644 --- a/lib/uitl/utils.dart +++ b/lib/uitl/utils.dart @@ -32,6 +32,7 @@ import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import '../Constants.dart'; import 'app_shared_preferences.dart'; import 'app_toast.dart'; @@ -214,7 +215,7 @@ class Utils { toAnimate: false, position: BadgePosition.topEnd(), shape: BadgeShape.circle, - badgeColor: Color(0xFF40ACC9).withOpacity(1.0), + badgeColor: secondaryColor.withOpacity(1.0), borderRadius: BorderRadius.circular(8), badgeContent: Container( padding: EdgeInsets.all(2.0), diff --git a/lib/widgets/Loader/gif_loader_container.dart b/lib/widgets/Loader/gif_loader_container.dart index 06c151c9..b7a20339 100644 --- a/lib/widgets/Loader/gif_loader_container.dart +++ b/lib/widgets/Loader/gif_loader_container.dart @@ -36,7 +36,7 @@ class _GifLoaderContainerState extends State child: GifImage( controller: controller1, image: AssetImage( - "assets/images/progress-loading.gif"), //NetworkImage("http://img.mp.itc.cn/upload/20161107/5cad975eee9e4b45ae9d3c1238ccf91e.jpg"), + "assets/images/progress-loading-red.gif"), //NetworkImage("http://img.mp.itc.cn/upload/20161107/5cad975eee9e4b45ae9d3c1238ccf91e.jpg"), ), )); } diff --git a/lib/widgets/avatar/large_avatar.dart b/lib/widgets/avatar/large_avatar.dart index ed904d03..fcfcaa94 100644 --- a/lib/widgets/avatar/large_avatar.dart +++ b/lib/widgets/avatar/large_avatar.dart @@ -37,7 +37,7 @@ class LargeAvatar extends StatelessWidget { borderRadius: BorderRadius.all(Radius.circular(radius)), child: Image.network( url.trim(), - fit: BoxFit.cover, + fit: BoxFit.fill, width: width, height: height, ), diff --git a/lib/widgets/bottom_navigation/bottom_nav_bar.dart b/lib/widgets/bottom_navigation/bottom_nav_bar.dart index a6b61717..53822f1d 100644 --- a/lib/widgets/bottom_navigation/bottom_nav_bar.dart +++ b/lib/widgets/bottom_navigation/bottom_nav_bar.dart @@ -1,7 +1,10 @@ +import 'package:diplomaticquarterapp/core/service/AuthenticatedUserObject.dart'; import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; -import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/locator.dart'; +import 'package:diplomaticquarterapp/models/Appointments/toDoCountProviderModel.dart'; import 'package:diplomaticquarterapp/pages/BookAppointment/BookingOptions.dart'; import 'package:diplomaticquarterapp/pages/ToDoList/ToDo.dart'; +import 'package:diplomaticquarterapp/uitl/app_toast.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:eva_icons_flutter/eva_icons_flutter.dart'; import 'package:flutter/cupertino.dart'; @@ -25,6 +28,7 @@ class BottomNavBar extends StatefulWidget { class _BottomNavBarState extends State { int _index = 0; + ToDoCountProviderModel model; var event = RobotProvider(); _changeIndex(int index) async { widget.changeIndex(index); @@ -35,6 +39,7 @@ class _BottomNavBarState extends State { @override Widget build(BuildContext context) { + model = Provider.of(context); ProjectViewModel projectViewModel = Provider.of(context); return BottomAppBar( elevation: 4, @@ -116,6 +121,7 @@ class _BottomNavBarState extends State { } Future navigateToToDoList(context) async { - Navigator.push(context, MaterialPageRoute(builder: (context) => ToDo())); + Navigator.push(context, + MaterialPageRoute(builder: (context) => ToDo(isShowAppBar: false))); } } diff --git a/lib/widgets/bottom_navigation/bottom_navigation_item.dart b/lib/widgets/bottom_navigation/bottom_navigation_item.dart index 31ed59dc..391b6a3d 100644 --- a/lib/widgets/bottom_navigation/bottom_navigation_item.dart +++ b/lib/widgets/bottom_navigation/bottom_navigation_item.dart @@ -8,6 +8,8 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import '../../Constants.dart'; + class BottomNavigationItem extends StatelessWidget { final IconData icon; final IconData activeIcon; @@ -49,7 +51,7 @@ class BottomNavigationItem extends StatelessWidget { Container( child: Icon(currentIndex == index ? activeIcon : icon, color: currentIndex == index - ? Theme.of(context).primaryColor + ? secondaryColor : Theme.of(context).dividerColor, size: 22.0), ), @@ -60,7 +62,7 @@ class BottomNavigationItem extends StatelessWidget { name, textAlign: TextAlign.center, color: currentIndex == index - ? Theme.of(context).primaryColor + ? secondaryColor : Colors.grey, fontSize: 11, ), @@ -69,7 +71,7 @@ class BottomNavigationItem extends StatelessWidget { ), ], ) - : authenticatedUserObject.isLogin + : (authenticatedUserObject.isLogin && model.isShowBadge) ? Stack( alignment: AlignmentDirectional.center, children: [ @@ -80,8 +82,7 @@ class BottomNavigationItem extends StatelessWidget { toAnimate: false, position: BadgePosition.topEnd(), shape: BadgeShape.circle, - badgeColor: Colors - .red[800].withOpacity(1.0), + badgeColor: secondaryColor.withOpacity(1.0), borderRadius: BorderRadius.circular(8), badgeContent: Container( padding: EdgeInsets.all(2.0), @@ -102,7 +103,7 @@ class BottomNavigationItem extends StatelessWidget { child: Icon( currentIndex == index ? activeIcon : icon, color: currentIndex == index - ? Theme.of(context).primaryColor + ? secondaryColor : Theme.of(context).dividerColor, size: 22.0), ), @@ -135,7 +136,7 @@ class BottomNavigationItem extends StatelessWidget { child: Icon( currentIndex == index ? activeIcon : icon, color: currentIndex == index - ? Theme.of(context).primaryColor + ? secondaryColor : Theme.of(context).dividerColor, size: 22.0), ), @@ -146,7 +147,7 @@ class BottomNavigationItem extends StatelessWidget { name, textAlign: TextAlign.center, color: currentIndex == index - ? Theme.of(context).primaryColor + ? secondaryColor : Colors.grey, fontSize: 11, ), diff --git a/lib/widgets/bottom_options/BottomSheet.dart b/lib/widgets/bottom_options/BottomSheet.dart index f8a99c17..7bbadd8c 100644 --- a/lib/widgets/bottom_options/BottomSheet.dart +++ b/lib/widgets/bottom_options/BottomSheet.dart @@ -1,13 +1,14 @@ import 'dart:convert'; import 'dart:io'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:feather_icons_flutter/feather_icons_flutter.dart'; import 'package:flutter/material.dart'; import 'package:image_picker/image_picker.dart'; class ImageOptions { - static showImageOptions(BuildContext context, Function(String) image) { + static showImageOptions(BuildContext context, Function(String,File) image,) { showModalBottomSheet( backgroundColor: Colors.transparent, context: context, @@ -15,10 +16,10 @@ class ImageOptions { return _BottomSheet( children: [ _BottomSheetItem( - title: "Select file source", + title: TranslationBase.of(context).selectFileSouse, ), _BottomSheetItem( - title: "Gallery", + title: TranslationBase.of(context).gallery, icon: FeatherIcons.image, onTap: () async { File _image = @@ -27,12 +28,12 @@ class ImageOptions { final bytes = File(fileName).readAsBytesSync(); String base64Encode = base64.encode(bytes); if (base64Encode != null) { - image(base64Encode); + image(base64Encode,_image); } }, ), _BottomSheetItem( - title: "Camera", + title: TranslationBase.of(context).camera, icon: FeatherIcons.camera, onTap: () async { File _image = @@ -41,13 +42,15 @@ class ImageOptions { final bytes = File(fileName).readAsBytesSync(); String base64Encode = base64.encode(bytes); if (base64Encode != null) { - image(base64Encode); + image(base64Encode,_image); } }, ), _BottomSheetItem( - title: "Cancel", - onTap: (){}, + title: TranslationBase.of(context).cancel, + onTap: (){ + + }, ) ], ); diff --git a/lib/widgets/buttons/borderedButton.dart b/lib/widgets/buttons/borderedButton.dart index 5e05448e..b0bbdaf0 100644 --- a/lib/widgets/buttons/borderedButton.dart +++ b/lib/widgets/buttons/borderedButton.dart @@ -4,55 +4,91 @@ import 'package:flutter/material.dart'; class BorderedButton extends StatelessWidget { final String text; final Function handler; - final Color color; + final Color textColor; final bool hasBorder; final Color borderColor; final Color backgroundColor; final double vPadding; final double hPadding; + final double radius; + final double lPadding; + final double tPadding; + final double rPadding; + final double bPadding; + final double fontSize; + final Widget icon; + final FontWeight fontWeight; + final bool hasShadow; BorderedButton( this.text, { this.handler, - this.color, + this.textColor, this.hasBorder = false, this.borderColor, this.backgroundColor, this.vPadding = 0, this.hPadding = 0, + this.radius = 4.0, + this.lPadding = 4.0, + this.tPadding = 0.0, + this.rPadding = 4.0, + this.bPadding = 0.0, + this.fontSize = 0, + this.icon, + this.fontWeight, + this.hasShadow = false, }); @override Widget build(BuildContext context) { - return Container( - padding: EdgeInsets.symmetric(horizontal: 4, vertical: 4), - child: ButtonTheme( - //adds padding inside the button - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - //limits the touch area to the button area - minWidth: 0, - //wraps child's width - height: 0, - //wraps child's height - child: RaisedButton( - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - padding: EdgeInsets.symmetric(horizontal: 12, vertical: vPadding), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(4.0), - side: BorderSide(color: hasBorder ? borderColor : Colors.white, width: 0.8),), - color: backgroundColor ?? Colors.white, - textColor: color ?? Color(0xffc4aa54), - disabledTextColor: color ?? Colors.black, - disabledColor: backgroundColor ?? Colors.white, - onPressed: handler, - child: Text( - text, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: SizeConfig.textMultiplier * 1.6, - fontWeight: FontWeight.normal), + return GestureDetector( + onTap: () { + handler(); + }, + child: Container( + decoration: BoxDecoration( + shape: BoxShape.rectangle, + color: backgroundColor ?? Colors.white, + borderRadius: BorderRadius.circular(radius), + border: Border.fromBorderSide(BorderSide( + color: hasBorder ? borderColor : Colors.white, + width: 0.8, + )), + boxShadow: [ + BoxShadow( + color: !hasShadow ? Colors.transparent : Colors.grey.withOpacity(0.5), + // spreadRadius: 5, + blurRadius: 15.0, + offset: Offset(0.0, 0.75) // changes position of shadow + ), + ]), + child: Container( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + icon != null ? icon : Container(), + Container( + padding: (hPadding > 0 || vPadding > 0) + ? EdgeInsets.symmetric( + vertical: vPadding, horizontal: hPadding) + : EdgeInsets.fromLTRB( + lPadding, tPadding, rPadding, bPadding), + child: Text( + text, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: fontSize == 0 + ? SizeConfig.textMultiplier * 1.6 + : fontSize, + fontWeight: + fontWeight != null ? fontWeight : FontWeight.normal, + color: textColor ?? Color(0xffc4aa54)), + ), + ), + ], ), - ), //your original button + ), ), ); } diff --git a/lib/widgets/buttons/button.dart b/lib/widgets/buttons/button.dart index 457a1d42..5d7c9257 100644 --- a/lib/widgets/buttons/button.dart +++ b/lib/widgets/buttons/button.dart @@ -1,7 +1,9 @@ +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/services/permission/permission_service.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:hexcolor/hexcolor.dart'; +import 'package:provider/provider.dart'; /// Button widget /// [label] button label @@ -80,6 +82,7 @@ class _ButtonState extends State

K04Z4L1gtSmk28`uh?Eh}TROKKmy2fv(Jm;&|+$bG1BQ{$U}y&iaErVbwlepR8!(Pw@qqk?&)^-?es8 zaLfZmXGGI4BU=x1yZAWMlnimXX;c0ZX05Xq1H8b)wcfRLR&q*N@Efi5Eh)N;@Q-}(yj k{NaWa$;$lydNMX1ku`k|M(C0AgOGqnURGJAOv)tSKbpsu8~^|S literal 0 HcmV?d00001 diff --git a/assets/images/pharmacy_module/payment/sadad.png b/assets/images/pharmacy_module/payment/sadad.png new file mode 100644 index 0000000000000000000000000000000000000000..35e0426c4a68703441198afd5e961e7e8ddfa3fb GIT binary patch literal 23578 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 literal 0 HcmV?d00001 diff --git a/assets/images/pharmacy_module/payment_image.png b/assets/images/pharmacy_module/payment_image.png new file mode 100644 index 0000000000000000000000000000000000000000..ebf7a9297a1ed077d17cc8327e4f452017d7d71d GIT binary patch literal 4982 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 F{|9iKfB*mh literal 0 HcmV?d00001 diff --git a/assets/images/progress-loading-red.gif b/assets/images/progress-loading-red.gif new file mode 100644 index 0000000000000000000000000000000000000000..517c3dab1055feb0aac5b16ea0d1dcd886e9bc58 GIT binary patch literal 142880 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Â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